Code Critique: Transactional File

time to read 2 min | 333 words

Update: To clarify, the only purpose of this code is to give atomic writes, it either complete successfully or it is rolled back.

Okay, this looks like it is too simple to work, thoughts?

/// <summary>
/// Allow to overwrite a file in a transactional manner.
/// That is, either we completely succeed or completely fail in writing to the file.
/// Read will correct previous failed transaction if a previous write has failed.
/// Assumptions:
///  * You want to always rewrite the file, rathar than edit it.
///  * The underlying file system has at least transactional metadata.
///  * Thread safety is provided by the calling code.
/// 
/// Write implementation:
///  - Rename file to "[file].old_copy" (overwrite if needed
///  - Create new file stream with the file name and pass it to the client
///  - After client is done, flush & close the stream
///  - Delete old file
/// 
/// Read implementation:
///  - If old file exists, remove new file and rename old file
/// 
/// </summary>
public static class TransactionalFile
{
	public static void Read(string name, Action<Stream> action)
	{
		if (File.Exists(name + ".old_copy"))
		{
			File.Delete(name);
			File.Move(name + ".old_copy", name);
		}

		using (
			var stream = new FileStream(name, FileMode.Open, FileAccess.Read, FileShare.None, 0x1000,
										FileOptions.SequentialScan))
		{
			action(stream);
		}
	}

	public static void Write(string name, Action<Stream> action)
	{
		File.Delete(name + ".old_copy");

		if (File.Exists(name))
			File.Move(name, name + ".old_copy");

		using (
			var stream = new FileStream(name, FileMode.CreateNew, FileAccess.Write, FileShare.None, 0x1000,
			                            FileOptions.WriteThrough | FileOptions.SequentialScan))
		{
			action(stream);
			stream.Flush();
		}

		File.Delete(name + ".old_copy");
	}
}