2013-04-02 2 views
0

스레드를 사용하여 일련의 플러그인을 실행하는 프로그램이 있습니다. 이 과정에서 플러그인의 런타임을 XDocument에 기록하여 플러그인이 마지막으로 실행 된 이후의 시간을 프로그램이 알 수 있도록합니다. 그래도 문제가 있습니다. 약 하루에 한 번 (예측할 수없는 시간에) 나는 다음과 같은 오류를 얻을하여 XDocument를로드 할 때 :

[04/01/2013 08:17:10.083] Unexpected end of file has occurred. The following elements are not closed: Database, DatabaseList. Line 4043, position 1.XDocument가 불완전한 파일을 저장하는 이유는 무엇입니까?

가 좀 추적 문을 실행하고 약 44 플러그인 왼쪽으로 시간이 그 전에, 서비스가 실패했음을 발견 XDocument가 파일의 끝 부분을 쓰지 않고 닫히는 것 같았습니다. 그것은 하드 디스크의 XML 파일에 쓰고 읽습니다. 그러나 Linq를 사용하여 데이터에서 복잡한 연산을 수행하기 때문에 메모리의 XDocument에 대한 모든 연산을 수행합니다.

왜 이런 일이 일어날 지 알고 있습니까? 실행중인 프로세스 중에 문제가 발생하면 실제 파일을 파손시키지 않도록 XDocument를로드하려면 어떻게해야합니까?

편집 : 여기에 XDocument (이름 XDoc)를 사용하는 코드의 예는 다음과 같습니다

private void RunPlugin(object oQueuedPlugin) 
    { 
     PluginState oPluginState = (PluginState)oQueuedPlugin; 
     PluginResponse oResponse = new PluginResponse(); 
     XElement xPlugin; 

     lock (xDoc) 
     { 
      xPlugin = GetPluginNode(oPluginState.ClientFusionDatabase.Name, oPluginState.Plugin.Name); 
     } 

     if (xPlugin == null) 
     { 
      API.Log.Write("ActivityTrace.ShowXMLLog", "XML for " + oPluginState.ClientFusionDatabase.Name + " was null."); 
      XElement NewPlugin = new XElement("Plugin", 
       new XAttribute("PluginName", oPluginState.Plugin.Name), 
       new XAttribute("Running", "true"), 
       new XAttribute("LastStart", DateTime.Now.ToString()), 
       new XAttribute("LastSuccess", ""), 
       new XAttribute("LastExitStatus","")); 

      lock (xDoc) 
      { 
       var Location = from database in xDoc.Root.Elements("Database") 
           where database.Attribute("DatabaseName").Value == oPluginState.ClientFusionDatabase.Name 
           select database; 

       Location.FirstOrDefault().Add(NewPlugin); 
       xDoc.Save(XmlLogFilePath); 
      } 

      oResponse = oPluginState.Plugin.Run(oPluginState.ClientFusionDatabase); 
      if (oResponse == null) 
      { 
       API.Log.Write("ActivityTrace.ShowNullReturnLog", oPluginState.ClientFusionDatabase.Name + "- " + oPluginState.Plugin.Name + " returned null."); 
      } 

      lock (xDoc) 
      { 
       NewPlugin.Attribute("Running").Value = "false"; 
       NewPlugin.Attribute("LastExitStatus").Value = oResponse.ResponseType.ToString(); 
       if (oResponse.ResponseType == PluginResponseTypes.Success || oResponse.ResponseType == PluginResponseTypes.Warning) 
        NewPlugin.Attribute("LastSuccess").Value = DateTime.Now.ToString(); 
       xDoc.Save(XmlLogFilePath); 
      } 

      API.Log.Write("ActivityTrace.ShowXMLLog","Completed " + oPluginState.ClientFusionDatabase.Name + "- " + oPluginState.Plugin.Name + " with XML " + NewPlugin.ToString()); 
      API.Log.Write(oPluginState.Plugin.Name, "(" + oPluginState.ClientFusionDatabase.Connection.Database + " = " + (oResponse.ResponseType + ") ").PadRight(9) + "EXIT MESSAGE: " + (string.IsNullOrEmpty(oResponse.Message) ? "None" : oResponse.Message)); 
     } 
     else 
     { 
      DateTime dLastRun = (DateTime)xPlugin.Attribute("LastStart"); 
      bool bRunning = (bool)xPlugin.Attribute("Running"); 

      if ((DateTime.Now - dLastRun) > oPluginState.Plugin.Interval && !bRunning) 
      { 
       lock (xDoc) 
       { 
        xPlugin.Attribute("LastStart").Value = DateTime.Now.ToString(); 
        xPlugin.Attribute("Running").Value = "true"; 
        xDoc.Save(XmlLogFilePath); 
       } 
       oResponse = oPluginState.Plugin.Run(oPluginState.ClientFusionDatabase); 

       lock (xDoc) 
       { 
        xPlugin.Attribute("Running").Value = "false"; 
        xPlugin.Attribute("LastExitStatus").Value = oResponse.ResponseType.ToString(); 
        if (oResponse.ResponseType == PluginResponseTypes.Success || oResponse.ResponseType == PluginResponseTypes.Warning) 
         xPlugin.Attribute("LastSuccess").Value = DateTime.Now.ToString(); 
        xDoc.Save(XmlLogFilePath); 
       } 

       API.Log.Write(oPluginState.Plugin.Name, "(" + oPluginState.ClientFusionDatabase.Connection.Database + " = " + (oResponse.ResponseType + ") ").PadRight(9) + "EXIT MESSAGE: " + (string.IsNullOrEmpty(oResponse.Message) ? "None" : oResponse.Message)); 
      } 
      else if (bRunning) 
       API.Log.Write(oPluginState.Plugin.Name, "(" + oPluginState.ClientFusionDatabase.Connection.Database + " = " + ("SKIPPED) ").PadRight(9) + "REASON: Plugin already running"); 
     } 

     oPluginState.Complete = true; 
    } 

문제는 플러그인 중 하나 이상은하지에 발생하는, 제대로 오류를 처리되지 않는 것입니다 응답을 반환하고 프로그램을 중단하십시오.

+2

코드 예제를 게시하고 입력 할 수 없습니까? –

+1

당신의 이야기에서 나는 당신의 서비스가 망가지는 것을 얻었습니까? 그렇다면 모든 개체가 제대로 처리되지 않고 디스크에 변경 내용을 기록 할 것으로 예상 할 수 없습니다. – Virtlink

+0

몇 가지를 추가하려고합니다. 거기에 매달려. – ijb109

답변

1

전체 내용을 구문 분석하고 메모리에로드하지 않고 XML 파일을 읽으려면 XmlReader class을 사용할 수 있습니다. 그런 다음 XML 파일을 작성하려면 XmlWriter class을 사용할 수 있습니다. 각각의 MSDN 페이지에 몇 가지 예가 있습니다.

그러나 LINQ의 모든 이점을 잃어 버리면 상당히 다르게 작동합니다. 디스크에서만 XML 파일 작업을하는 동안 LINQ와 XDocument의 이점을 결합 할 수있는 방법은 없습니다.

서비스가 중단되면 XmlWriter이 버퍼를 디스크로 비우고 불완전한 XML 파일을 남기지 않고 폐기되지 않을 수 있습니다. 대신 서비스가 중단되는 버그를 해결해야합니다.

관련 문제