2009年7月23日星期四

DISCUZ 每日会员数不自动更新 的研究



Normal
0



7.8 磅
0
2

false
false
false

EN-US
ZH-CN
X-NONE




















MicrosoftInternetExplorer4





























































































































































/* Style Definitions */
table.MsoNormalTable
{mso-style-name:普通表格;
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-priority:99;
mso-style-qformat:yes;
mso-style-parent:"";
mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
mso-para-margin:0cm;
mso-para-margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:10.5pt;
mso-bidi-font-size:11.0pt;
font-family:"Calibri","sans-serif";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-fareast-font-family:宋体;
mso-fareast-theme-font:minor-fareast;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;
mso-bidi-font-family:"Times New Roman";
mso-bidi-theme-font:minor-bidi;
mso-font-kerning:1.0pt;}






症状:



Discuz 6.1 计划任务每日会员数不自动更新,需要后台更新数据缓存后才更新
如直接后台计划任务中相关计划中的“执行”按钮可以正常更新。



 



测试分析:



后台discuz自带的计划任务中建立一个测试任务test,该任务中直接运行相关更新函数:
updatecache('settings');仍然无效



查看cdb_caches中的settings变量中的totalmembers数值已更新,但缓存文件forumdata/cache/cache_settings.php中的totalmembers数值未更新。



分析程序include/cache.func.php中的updatecache函数先通过getcachearray函数取得所有需要更新的数值,并插入数据库,然后再从数据库中取得所有需要更新的变量的值,通过writetocache函数写入相关缓存文件中。



既然是这样,为何数据库中的值正确,但文件中却不正确呢?百思不得其解。发现文件建立时间已经更新,排除了文件权限问题。



再通过插入file_put_contents函数,让相关变量写入指定文件中来调试:



if ($script == "settings")



    file_put_contents("temp/updatecache_$script.txt",$cachedata);



writetocache($script, $cachenames, $cachedata);



 



function writetocache($script, $cachenames, $cachedata = '', $prefix = 'cache_')
{



if ($script == "settings")



    file_put_contents("temp/writecache_settings.txt", $cachedata);



……



……



}



 



如此测试发现 updatecache_settings.txt文件中数值正确,但writecache_settings.txt中不正确,这就更加奇怪了,为何调用writetocache前数值还是对的,进入writetocache函数后数值就变了?不可能啊!



只有一种可能:writecache_settings.txt文件又被覆盖了。



再次尝试在文件名后加上随机数发现果然有两个writecache_settings.txt,一个正确,一个不正确。



于是再次查看程序,发现include/cron.func.php中的runcron函数中在include $cronfile后有着这么一段:



$nextrun = $db->result_first("SELECT
nextrun FROM {$tablepre}crons WHERE available>'0' ORDER BY nextrun LIMIT
1");



    if(!$nextrun ===
FALSE) {



       require_once DISCUZ_ROOT.'./include/cache.func.php';



       $_DCACHE['settings']['cronnextrun']
= $nextrun;



       updatesettings();



}



查看updatesettings()函数:



function updatesettings() {



    global $_DCACHE;



    if(isset($_DCACHE['settings'])
&& is_array($_DCACHE['settings'])) {



       writetocache('settings',
'', '$_DCACHE[\'settings\'] = '.arrayeval($_DCACHE['settings']).";\n\n");



    }



}



果然,再次把$_DCACHE['settings']写入缓存文件中,而$_DCACHE['settings']在刚才并没有被更新,终于找到问题所在。



 



解决:



cache.func.php中的getcachearray函数中加入:



switch($cachename) {



       case 'settings':



           ……



           ……



           $_DCACHE['settings'] = $data;



           Break;



 



并且记得在该函数头部global $_DCACHE;



让程序在取得所有数据后 更新缓存变量$_DCACHE,以便runcron函数中调用updatesettings函数时能够将更新过的$_DCACHE写入缓存文件中。



 



测试ok,问题解决。

没有评论: