这个函数的功能是设置DNSHandler的handler为DNSHandler::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;
//设置DNSHandler的handler为DNSHandler::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();
//超时了,重新想所有down的DNSserver发起链接
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();
//设置HostDBContinuation的handler为HostDBContinuation::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;
}