注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

Koala++'s blog

计算广告学 RTB

 
 
 

日志

 
 

Larbin[3]sequencer源代码分析  

2010-04-19 12:08:26|  分类: Larbin |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

       main函数里的input函数是一个提供给用户查看当前爬虫信息和输入一些参数的微型服务器,这个暂时跳过,看sequencer函数,sequencersequencer.c中实现:

/** start the sequencer

 */

void sequencer() {

    bool testPriority = true;

    if (space == 0) {

       space = global::inter->putAll();

    }

    int still = space;

    if (still > maxPerCall)

       still = maxPerCall;

    while (still) {

       if (canGetUrl(&testPriority)) {

           space--;

           still--;

       } else {

           still = 0;

       }

    }

}

       这里是最多处理maxPerCallURLcanGetUrl的代码如下:

/* Get the next url

 * here is defined how priorities are handled

 */

static bool canGetUrl(bool *testPriority) {

    url *u;

    if (global::readPriorityWait) {

       global::readPriorityWait--;

       u = global::URLsPriorityWait->get();

       global::namedSiteList[u->hostHashCode()].putPriorityUrlWait(u);

       return true;

    } else if ( *testPriority

          && (u = global::URLsPriority->tryGet()) != NULL) {

       // We've got one url (priority)

       global::namedSiteList[u->hostHashCode()].putPriorityUrl(u);

       return true;

    } else {

       *testPriority = false;

       // Try to get an ordinary url

       if (global::readWait) {

           global::readWait--;

           u = global::URLsDiskWait->get();

           global::namedSiteList[u->hostHashCode()].putUrlWait(u);

           return true;

       } else {

           u = global::URLsDisk->tryGet();

           if (u != NULL) {

              global::namedSiteList[u->hostHashCode()].putUrl(u);

              return true;

           } else {

              return false;

           }

       }

    }

}

       关于这个函数,“执着的小雨”的Blog介绍了:下面是贴过来的:

Larbin[3]sequencer - quweiprotoss - Koala++s blog

“为什么diskpriority的队列都是成对出现的,是因为可以认为每个sitenamedSiteList当中都有一个小的队列来保存它的url,这个url的个数是有个限制的,当超过这个限制的时候就不能再把该site下的url放入,但也不能丢弃,而是放入wait队列。larbin会控制一段时间在disk队列中取url,一段时间在diskWait当中取urldiskpriority的区别只是优先级的区别。namedSiteLIst的作用可以任务是实现了DNS缓存;IPSiteList是控制了polite访问。”

       readPriorityWait的值是在main.cc中的cron函数中:

// see if we should read again urls in fifowait

if ((global::now % 300) == 0) {

    global::readPriorityWait = global::URLsPriorityWait->getLength();

    global::readWait = global::URLsDiskWait->getLength();

}

if ((global::now % 300) == 150) {

    global::readPriorityWait = 0;

    global::readWait = 0;

}

       这里global::now % 300是判断这次是对wait里的url里进行处理,还是对不是wait里的进行处理,这里的%300等于0150的概率都是1/300,所以大约300次换一次。readPriorityWaitURLsPriorityWait中的长度,也就是url的数量,readWait亦然。

       canGetUrl中,在对于每个站点,将相应的URL放进去。putPriorityUrlWaitputPriorityUrlputUrlWaitputUrlsite.h中的定义如下:

/** Put an url in the fifo

 * If there are too much, put it back in UrlsInternal

 * Never fill totally the fifo => call at least with 1 */

void putGenericUrl(url *u, int limit, bool prio);

inline void putUrl(url *u) {

    putGenericUrl(u, 15, false);

}

inline void putUrlWait(url *u) {

    putGenericUrl(u, 10, false);

}

inline void putPriorityUrl(url *u) {

    putGenericUrl(u, 5, true);

}

inline void putPriorityUrlWait(url *u) {

    putGenericUrl(u, 1, true);

}

       可以看出最终调用的都是putGenericUrl

/* Put an url in the fifo if their are not too many */

void NamedSite::putGenericUrl(url *u, int limit, bool prio) {

    if (nburls > maxUrlsBySite - limit) {

       // Already enough Urls in memory for this Site

       // first check if it can already be forgotten

       if (!strcmp(name, u->getHost())) {

           if (dnsState == errorDns) {

              nburls++;

              forgetUrl(u, noDNS);

              return;

           }

           if (dnsState == noConnDns) {

              nburls++;

              forgetUrl(u, noConnection);

              return;

           }

           if (u->getPort() == port && dnsState == doneDns && !testRobots(

                  u->getFile())) {

              nburls++;

              forgetUrl(u, forbiddenRobots);

              return;

           }

       }

       // else put it back in URLsDisk

       refUrl();

       global::inter->getOne();

       if (prio) {

           global::URLsPriorityWait->put(u);

       } else {

           global::URLsDiskWait->put(u);

       }

    }

       如果已经有足够多的url在内存里,执行这里if中的代码,strcmp(name,u->getHost())是判断这个主机是不是已经就进行过dns方面的判断,也就是说对于一个站点,只做一次dns解析的判断,以后就按这个结果进行处理,dnsStatenoDnsnoConnDns,还有robots.txt不允许的情况,如果没有问题,就把它放到URLsDisk中。

else {

    nburls++;

    if (dnsState == waitDns || strcmp(name, u->getHost()) || port

           != u->getPort() || global::now > dnsTimeout) {

       // dns not done or other site

       putInFifo(u);

       addNamedUrl();

       // Put Site in fifo if not yet in

       if (!isInFifo) {

           isInFifo = true;

           global::dnsSites->put(this);

       }

    } else

       switch (dnsState) {

       case doneDns:

           transfer(u);

           break;

       case errorDns:

           forgetUrl(u, noDNS);

           break;

       default: // noConnDns

           forgetUrl(u, noConnection);

       }

}

       如果需要判断dns能不能解析,就将它放到dnsSites里,这个会在fetchDns中判断。或是如果还能放到内存里,并且又是doneDns,表示可以解析,就调用transfer

void NamedSite::transfer(url *u) {

    if (testRobots(u->getFile())) {

       if (global::proxyAddr == NULL) {

           memcpy(&u->addr, &addr, sizeof(struct in_addr));

       }

       global::IPSiteList[ipHash].putUrl(u);

    } else {

       forgetUrl(u, forbiddenRobots);

    }

}

       这里是将url放入到IPSiteList的相应ipHash中。

 

 

 

 

 

 

  评论这张
 
阅读(2538)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017