关于Discuz!NT不定期出现“此文档已具有DocumentElement节点”错误分析
官方的缓存机制确实设计的不错,尤其和memcached分布式缓存两者的完美结合,很方便以后论坛的分布式部署
不过遗憾的有两点
1、官方准备分离memcached,可惜缓存在设计时耦合度过高,现在分离了却产生了循环引用的尴尬境地
2、官方自身的缓存在创建内部XmlDocument的时候没有检验是否已经存在节点,使得很多用户莫名其妙的出现“此文档已具有DocumentElement节点” 的怪毛病
今晚正好闲下来,就来分析了一下官方在缓存初始化的时候部分代码
下面我给大家演示一下为什么会出现这样的问题
两次操作都是追加根节点,都是失败的,哪怕是节点名不同,因为xml有且只能有一个根节点
创建了节点,但是作为子节点加入了进来,这样是没有问题的
既然这样我们要怎样来保证创建的是根节点呢?
方法如下
在创建内存XML时先卸除所有节点并判断有无节点
修改如下
- cs = new DefaultCacheStrategy();
- // 判断是否有节点,如果有则全部删除,防止出现“此文档已具有DocumentDelement节点”
- if (rootXml.HasChildNodes)
- {
- rootXml.RemoveAll();
- }
- objectXmlMap = rootXml.CreateElement("Cache");
- //建立内部XML文档.
- rootXml.AppendChild(objectXmlMap);
- cacheConfigTimer.AutoReset = true;
- cacheConfigTimer.Enabled = true;
- cacheConfigTimer.Elapsed += new System.Timers.ElapsedEventHandler(Timer_Elapsed);
- cacheConfigTimer.Start();
注意:重点在于
if (rootXml.HasChildNodes)
{
rootXml.RemoveAll();
}
这样可以清除所有节点
希望官方能在检验上更加严格点,从理论上来说官方这样创建是不应该出现重复创建根节点的,但实际是难以预料的,所以还是要实行更严格的检验
附加中有个实例,大家可以下载下来调试一下,这样便会明白为什么会出现这样的情况,只有在重复根节点是会出现这样的毛病
附件: Sample.rar (2010/4/15 21:25:33, 17.47 K)