开发者

transactional open/write/replace in .NET?

开发者 https://www.devze.com 2023-04-06 22:05 出处:网络
I am thinking maybe i should res开发者_如何学运维trict it to 8k. I\'d like to open a file and write from start to end everytime. However if for some reason (say power outage) it doesnt complete i do n

I am thinking maybe i should res开发者_如何学运维trict it to 8k. I'd like to open a file and write from start to end everytime. However if for some reason (say power outage) it doesnt complete i do not want corrupt data. Is there a way i can do a transactional file open/write/close so it doesnt replace the previous file unless its a success?

When i google i get many results on database transactions and ado instead of files


  1. Write to a temporary file,
  2. Delete the old file
  3. Rename the remporary file only if the write succeeds.

To prevent data loss if you lose power after step two but before step three, you need one more step:

  • At program startup, check for temporary files that have their main files deleted but have not yet been renamed. If you find any, perform step three again for those files.


NTFS in Windows Vista and later is transactional.

I do not believe that you can access it from the pure managed code - you'll need to P/Invoke into Win32 API.

A good place to start would be CreateTransaction, CommitTransaction, RollbackTransaction, CreateFileTransacted (and other *Transacted) Win32 API functions.


Slight variation on Mark Byer's solution which I use all the time:

  1. Write new contents to a temp file IN THE SAME DIRECTORY as the file you want to replace.
  2. If the write is successful, rename[1] it to the desired file.

Rename is atomic so if it succeeds, then the system is not left in an undefined state. If it fails, then, again, the system is still in a pristine state AND you have a backup of the content you wanted to replace it with (in the temp file) on system restart.

My typical naming convention is along the lines of:

/path/to/original/content.data

/path/to/original/.#content.data

If the system shuts down somewhere in that process, on restart of your app, you can scan for .#content.data and either present that to the user as what they had been entering when the system went down or use some custom magic to decide whether or not it is "complete" to decide whether or not to rename it over content.data.

I don't know what kind of data you are writing so I can't help you decide what that "magic" would be, but if it's an xml file, for example, you could parse it for correctness and if you don't get an unexpected end-of-file, then you probably have a complete file.

FWIW, restricting yourself to 8k writes isn't going to save you because you are now depending on implementation details in the underlying OS and FS which could change in the next version or be different in a previous version.

Links:

  1. http://83.139.107.116:8080/1.1/handlers/monodoc.ashx?link=M%3aMono.Unix.Native.Stdlib.rename(System.String%2cSystem.String)
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号