关于Discuz!NT不定期出现“此文档已具有DocumentElement节点”错误分析

官方的缓存机制确实设计的不错,尤其和memcached分布式缓存两者的完美结合,很方便以后论坛的分布式部署

不过遗憾的有两点
1、官方准备分离memcached,可惜缓存在设计时耦合度过高,现在分离了却产生了循环引用的尴尬境地
2、官方自身的缓存在创建内部XmlDocument的时候没有检验是否已经存在节点,使得很多用户莫名其妙的出现“此文档已具有DocumentElement节点” 的怪毛病

今晚正好闲下来,就来分析了一下官方在缓存初始化的时候部分代码

下面我给大家演示一下为什么会出现这样的问题





两次操作都是追加根节点,都是失败的,哪怕是节点名不同,因为xml有且只能有一个根节点



创建了节点,但是作为子节点加入了进来,这样是没有问题的



既然这样我们要怎样来保证创建的是根节点呢?
方法如下
在创建内存XML时先卸除所有节点并判断有无节点
修改如下

  1. cs = new DefaultCacheStrategy();
  2. // 判断是否有节点,如果有则全部删除,防止出现“此文档已具有DocumentDelement节点”
  3. if (rootXml.HasChildNodes)
  4. {
  5. rootXml.RemoveAll();
  6. }
  7. objectXmlMap = rootXml.CreateElement("Cache");
  8. //建立内部XML文档.
  9. rootXml.AppendChild(objectXmlMap);
  10.                
  11. cacheConfigTimer.AutoReset = true;
  12. cacheConfigTimer.Enabled = true;
  13. cacheConfigTimer.Elapsed += new System.Timers.ElapsedEventHandler(Timer_Elapsed);
  14. cacheConfigTimer.Start();
复制代码

注意:重点在于
if (rootXml.HasChildNodes)
{
rootXml.RemoveAll();
}

这样可以清除所有节点

希望官方能在检验上更加严格点,从理论上来说官方这样创建是不应该出现重复创建根节点的,但实际是难以预料的,所以还是要实行更严格的检验

附加中有个实例,大家可以下载下来调试一下,这样便会明白为什么会出现这样的情况,只有在重复根节点是会出现这样的毛病

附件: Sample.rar (2010/4/15 21:25:33, 17.47 K)

posted @ 2010-06-07 15:14  肚肚  阅读(795)  评论(0编辑  收藏  举报