这个函数的功能是设置DNSHandlerhandlerDNSHandler::mainEvent,并定时调用该函数,然后打开到DNSserver的链接

main()--->DNSProcessor::start()--->DNSProcessor::open()--->DNSHandler::startEvent()

int

DNSHandler::startEvent(int/* event ATS_UNUSED */,Event *e)

{

Debug("dns","DNSHandler::startEvent: on thread%d\n", e->ethread->id);

this->validate_ip();

if(!dns_handler_initialized) {

dns_handler_initialized = 1;

//设置DNSHandlerhandlerDNSHandler::mainEvent

SET_HANDLER(&DNSHandler::mainEvent);

//如果开启round_robin功能,想所有DNSserver发起链接

if(dns_ns_rr) {

intmax_nscount = m_res->nscount;

if(max_nscount > MAX_NAMED)

max_nscount = MAX_NAMED;

n_con= 0;

for(inti = 0; i < max_nscount; i++) {

ip_port_text_bufferbuff;

sockaddr*sa = &m_res->nsaddr_list[i].sa;

if(ats_is_ip(sa)) {

open_con(sa, false,n_con);

++n_con;

Debug("dns_pas","opened connection to %s, n_con =%d",

ats_ip_nptop(sa, buff,sizeof(buff)),

n_con

);

}

}

dns_ns_rr_init_down = 0;

//没有开启round_robin功能,指向一个DNSserver发起链接

}else{

open_con(0);

n_con= 1;

}

//定时调用DNSHandler::mainEvent

e->ethread->schedule_every(this,DNS_PERIOD);

returnEVENT_CONT;

}else{

ink_assert(false);         // I.e. this should neverreally happen

returnEVENT_DONE;

}

}

向一个DNSserver发起链接

main()--->DNSProcessor::start()--->DNSProcessor::open()--->DNSHandler::startEvent()--->DNSHandler::open_con()

void

DNSHandler::open_con(sockaddrconst*target, boolfailed, inticon)

{

ip_port_text_bufferip_text;

PollDescriptor*pd = get_PollDescriptor(dnsProcessor.thread);

if(!icon && target) {

ats_ip_copy(&ip,target);

}elseif(!target) {

target = &ip.sa;

}

Debug("dns","open_con: opening connection %s",ats_ip_nptop(target, ip_text, sizeofip_text));

if(con[icon].fd!= NO_FD) {  // Remove old FD from epollfd

con[icon].eio.stop();

con[icon].close();

}

//DNSserver发起链接

if(con[icon].connect(

target, DNSConnection::Options()

.setNonBlockingConnect(true)

.setNonBlockingIo(true)

.setUseTcp(false)

.setBindRandomPort(true)

.setLocalIpv6(&local_ipv6.sa)

.setLocalIpv4(&local_ipv4.sa)

)< 0) {

Debug("dns","opening connection %s FAILED for%d", ip_text, icon);

if(!failed) {

if(dns_ns_rr)

rr_failure(icon);

else

failover();

}

return;

}else{

ns_down[icon]= 0;

//NET模块能接受该DNS请求的响应,留到NET模块再做分析

if(con[icon].eio.start(pd,&con[icon],EVENTIO_READ) < 0) {

Error("[iocore_dns]open_con: Failed to add %d server to epolllist\n", icon);

}else{

con[icon].num= icon;

Debug("dns","opening connection %s SUCCEEDEDfor %d", ip_text, icon);

}

}

}

这个函数的功能一是接收DNS响应,二是从等待队列中取出DNS请求项并发送DNS请求

main()--->DNSProcessor::start()--->DNSProcessor::open()--->DNSHandler::startEvent()--->DNSHandler::mainEvent()

int

DNSHandler::mainEvent(intevent, Event*e)

{

//接收DNSserver的响应

recv_dns(event, e);

//下面判断正常的DNSserver是否满足设置为失败的条件以及失败的DNSserver是否满足重新发起链接的条件,如果满足则设置为失败以及重新发起链接,同样分两种模式处理

//round_robin模式时的处理

if(dns_ns_rr) {

ink_hrtimet = ink_get_hrtime();

//超时了,重新想所有downDNSserver发起链接

if(t - last_primary_retry> DNS_PRIMARY_RETRY_PERIOD) {

for(inti = 0; i < n_con;i++) {

if(ns_down[i]){

Debug("dns","mainEvent: nameserver= %d is down", i);

retry_named(i, t, true);

}

}

last_primary_retry= t;

}

//判断正常的DNSserver是否快失败了,如果是则设置为失败,否则看是否要重新发起链接

for(inti = 0; i < n_con;i++) {

if(!ns_down[i]&& failover_soon(i)) {

Debug("dns","mainEvent: nameserver= %d failoversoon", name_server);

if(failover_now(i))

rr_failure(i);

else{

Debug("dns","mainEvent: nameserver= %d no failovernow - retrying", i);

retry_named(i, t, false);

++failover_soon_number[i];

}

}

}

}else{

//round_robin模式时的处理

if(failover_soon(name_server)){

Debug("dns","mainEvent: will failoversoon");

if(failover_now(name_server)){

Debug("dns","mainEvent: failing over now toanother nameserver");

failover();

} else{

try_primary_named(false);

++failover_soon_number[name_server];

}

}elseif(name_server)    // not on the primary named

try_primary_named(true);

}

//把等待队列中的DNS请求项取出发送DNS请求

if(entries.head)

write_dns(this);


returnEVENT_CONT;

}

接收DNS响应

main()--->DNSProcessor::start()--->DNSProcessor::open()--->DNSHandler::startEvent()--->DNSHandler::mainEvent()--->DNSHandler::recv_dns()

DNSHandler::recv_dns(int/*event ATS_UNUSED */,Event* /*e ATS_UNUSED */)

{

DNSConnection*dnsc = NULL;

ip_text_bufferipbuff1, ipbuff2;

while((dnsc = (DNSConnection*) triggered.dequeue())){

while(1) {

IpEndpointfrom_ip;

socklen_tfrom_length = sizeof(from_ip);

if(!hostent_cache)

hostent_cache= dnsBufAllocator.alloc();

HostEnt*buf = hostent_cache;

//接收DNS响应

intres = socketManager.recvfrom(dnsc->fd,buf->buf,MAX_DNS_PACKET_LEN, 0, &from_ip.sa,&from_length);

//如果出错则把相应的DNSserver设置为down,如果是round_robin模式则直接设置为down即可,如果是非round_robin模式,要切换当前DNSserver,重新发起到新DNSserver的链接

if(res == -EAGAIN)

break;

if(res <= 0) {

Debug("dns","named error: %d",res);

if(dns_ns_rr)

rr_failure(dnsc->num);

elseif(dnsc->num== name_server)

failover();

break;

}

//判断本次响应是否和请求对应

if(!ats_ip_addr_eq(&dnsc->ip.sa,&from_ip.sa)){

Warning("unexpectedDNS response from %s (expected %s)",

ats_ip_ntop(&from_ip.sa,ipbuff1, sizeofipbuff1),

ats_ip_ntop(&dnsc->ip.sa,ipbuff2, sizeofipbuff2)

);

continue;

}

hostent_cache= 0;

buf->packet_size= res;

Debug("dns","received packet size = %d",res);

//round_robin模式时的处理

if(dns_ns_rr) {

Debug("dns","round-robin: nameserver%d DNS response code = %d",dnsc->num,get_rcode(buf));

//响应码是否正确,如果正确设置该DNSserver可可用

if(good_rcode(buf->buf)){

received_one(dnsc->num);

if(ns_down[dnsc->num]){

Warning("connectionto DNS server %s restored",

ats_ip_ntop(&m_res->nsaddr_list[dnsc->num].sa,ipbuff1, sizeofipbuff1)

);

ns_down[dnsc->num]= 0;

}

}

} else{

//round_robin模式时的处理

if(!dnsc->num){

Debug("dns","primary DNS response code = %d",get_rcode(buf));

if(good_rcode(buf->buf)){

if(name_server)

recover();

else

received_one(name_server);

}

}

}

Ptr<HostEnt>protect_hostent = make_ptr(buf);

//处理响应报文,下面分析完DNS请求的发送流程再分析接收DNS响应处理流程

if(dns_process(this,buf, res)) {

if(dnsc->num== name_server)

received_one(name_server);

}

}

}

}

分析完dns的启动后,下面该分析hostdb的启动了

main()--->HostDBProcessor::start()

int

HostDBProcessor::start(int,size_t)

{

hostDB.alloc_mutexes();

//调用hostDB.start启动hostdb

if(hostDB.start(0) < 0)

return-1;

......

hostdb_current_interval =(unsignedint)(ink_get_based_hrtime()/ HOST_DB_TIMEOUT_INTERVAL);

HostDBContinuation*b = hostDBContAllocator.alloc();

//设置HostDBContinuationhandlerHostDBContinuation::backgroundEvent并定时调用

SET_CONTINUATION_HANDLER(b,(HostDBContHandler)& HostDBContinuation::backgroundEvent);

b->mutex= new_ProxyMutex();

eventProcessor.schedule_every(b,HOST_DB_TIMEOUT_INTERVAL, ET_DNS);

//如果配置hostdb同步则进行同步处理

if(hostdb_sync_frequency > 0)

eventProcessor.schedule_imm(NEW(newHostDBSyncer));

return0;

}

这个函数找到hostdb存储的文件名host.db,并创建或打开该文件并初始化相关数据

main()--->HostDBProcessor::start()--->HostDBCache::start()

int

HostDBCache::start(intflags)

{

Store*hostDBStore;

Span*hostDBSpan;

charstorage_path[PATH_NAME_MAX + 1];

intstorage_size = 33554432; // 32MB default

boolreconfigure = ((flags & PROCESSOR_RECONFIGURE) ? true: false);

boolfix = ((flags & PROCESSOR_FIX) ? true: false);

......

if(storage_path[0] != '/'){

Layout::relative_to(storage_path,PATH_NAME_MAX, system_root_dir, storage_path);

}

Debug("hostdb","Storage path is %s",storage_path);

if(access(storage_path,R_OK) == -1) {

ink_strlcpy(storage_path,system_runtime_dir, sizeof(storage_path));

if(access(storage_path,R_OK) == -1) {

Warning("Unableto access() directory '%s': %d, %s",storage_path, errno, strerror(errno));

Warning("Please set 'proxy.config.hostdb.storage_path' or'proxy.config.local_state_dir' ");

}

}

hostDBStore = NEW(newStore);

hostDBSpan = NEW(newSpan);

hostDBSpan->init(storage_path,storage_size);

hostDBStore->add(hostDBSpan);

Debug("hostdb","Opening %s, size=%d",hostdb_filename, hostdb_size);

if(open(hostDBStore, "hostdb.config",hostdb_filename, hostdb_size, reconfigure, fix, false/* slient*/ ) < 0) {

Note("reconfiguringhost database");

charp[PATH_NAME_MAX + 1];

Layout::relative_to(p,PATH_NAME_MAX, system_runtime_dir, "hostdb.config");

if(unlink(p)< 0)

Debug("hostdb","unable to unlink %s",p);

deletehostDBStore;

hostDBStore = NEW(newStore);

hostDBSpan = NEW(newSpan);

hostDBSpan->init(storage_path,storage_size);

hostDBStore->add(hostDBSpan);

if(open(hostDBStore, "hostdb.config",hostdb_filename, hostdb_size, true,fix) < 0) {

Warning("couldnot initialize host database. Host database will be disabled");

hostdb_enable = 0;

deletehostDBStore;

return-1;

}

}

HOSTDB_SET_DYN_COUNT(hostdb_bytes_stat,totalsize);

deletehostDBStore;

return0;

}