views:

374

answers:

5

I understand that .NET FileStream's Flush method only writes the current buffer to disk, but dependent on Windows' disk driver and the hard disk firmware this is no guarantee that the data is actually physically written to disk.

Is there a .NET or Win32 method that can give me this guarantee? So if there is power loss one nanosecond after the call to this method comes back, I can still be sure that everything is OK?

+2  A: 

Well, you could close the file... that would probably do it. In reality, with HAL abstraction, virtualization, and disk hardware now having more processing power and cache memory than computers did a few years ago, you're going to have to live with hoping the disk does its job.

The transactional file system never really materialized ;-p Of course, you could perhaps look at using a database as a back end, and use the transaction system of that?

Aside: note that not all streams even guarantee to Flush() - for example, GZipStream etc retain a working buffer of uncommitted data even after a flush - the only way to get it to flush everything is to Close() it.

Marc Gravell
Technically, with writing to a database, theres no guarantee that a power outage or other catastrophic failure won't lose the write or corrupt the database somehow, although its far more likely to survive than a simple filesystem write.
cletus
yes, but you can wrap the "mark this as done" and "here's the results" in the same transaction
Marc Gravell
+6  A: 

Under Windows, look at FlushFileBuffers (Win32 API).

Thank you :) I have quickly done a performance test and FileStream.Flush() is way too fast to be true. FlushFileBuffers on FileStream's SafeFileHandle is as slow as I would expect it (100 times slower than Flush() in my test)
Stefan Schultze
+1  A: 

There's simply too many levels of abstraction to be absolutely sure that the data is written to the disc, right down to the hardware level.

Not brilliantly performant or foolproof, but how about re-opening the file once it is written in a seperate process and checking the size or contents?

Ayresome
+1  A: 

maybe you have a look at this article:

http://msdn.microsoft.com/en-us/magazine/cc163388.aspx

A: 

Stefan S. said:

I understand that .NET FileStream's Flush method only writes the current buffer to disk

No, .NET FileStream's Flush only writes the .NET buffers to the OS cache, it does not flush the OS cache to disk. Sadly the MSDN doc on this class doesn't say that. For .NET < 4.0, you'll have to call Flush + Win32's FlushFilebuffers:

using System.Runtime.InteropServices;
. . .

// start of class:
[DllImport("kernel32", SetLastError=true)]
private static extern bool FlushFileBuffers(IntPtr handle);
. . .

stream.Flush();     // Flush .NET buffers to OS file cache.
#pragma warning disable 618,612 // disable stream.Handle deprecation warning.
if (!FlushFileBuffers(stream.Handle))   // Flush OS file cache to disk.
#pragma warning restore 618,612
{
  Int32 err = Marshal.GetLastWin32Error();
  throw new Win32Exception(err, "Win32 FlushFileBuffers returned error for " + stream.Name);
}

For .NET 4.0, just use the new flush(true) method.

jimvfr