Question

I have an application that stores data in XML file every 500 ms using XElement object's .Save("path") method. The problem is : when a sudden shutdown is occurred the content of the file is deleted so on the next run of the application the file can not be used.

How to prevent that / make sure the data will not be lost? P.S: I'm using .NET 2010 C# under windows 7

I've made an experiment: instead of writing to the same data.xml file I've created (by copying from the original file) a new file each time and when the power was off while copying from data.xml file it would corrupt all previously created files?!?!?

Was it helpful?

Solution

Let's assume your file is data.xml. Instead of writing to data.xml all the time, write to a temporary file data.xml.tmp, and when finished, rename it to data.xml. But renaming will not work if you already have a data.xml file, so you will need to delete it first and then rename the temporary file.

That way, data.xml will contain the last safe data. If you have a sudden shutdown, the incomplete file will be the temporary data.xml.tmp. If your program tries to read the file later on and there is no data.xml file, that means the shutdown happened between the delete and rename operations, so you will have to read the temporary file instead. We know it is safe because otherwise there would be a data.xml file.

OTHER TIPS

You can use a 2-phase commit:

  1. Write the new XML to a file with a different name
  2. Delete the old file
  3. Rename to new file to the old name

This way, there will always be at least one complete file.
If you restart, and the standard name doesn't exist, check for the different name.

This one could be a life savior but with little more efforts. There should be a separate process which does

  • Take backup to its stash automatically whenever the file gets updated.
  • It internally maintains two versions in a linked list.
  • If the file gets updated, then the latest shall be updated to HEAD using linkedList.AddFirst() and the least version pointed by TAIL could be removed by linkedList.RemoveLast().
  • And of course, it should scan and load the stash about the latest version available in the stash during startup.

In the hard shutdown scenario, when the system starts up next time, this process should check whether the file is valid / corrupted. If corrupted, then restore the latest from HEAD and subscribe for FileChanged notification using a simple FileSystemWatcher.

This approach is well tested.

Problems seen

  • What if the Hard shutdown happens while updating the HEAD? -- Well, there is another version we have it in the stash next to HEAD
  • What if the Hard shutdown happens while updating the HEAD when the stash is empty? -- We know that the file was valid while updating HEAD. The process shall try copying again at next startup since it is not corrupted.
  • What if the stash is empty and the file has been corrupted? -- This is the death pit and no solution is available for this. But this scenario occurs only when you deploy this recovery process after the file corruption happened.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top