5

I'm trying to implement a file storage mechanism which holds a number of variably-sized records in a single file with the guarantee that the set of records will always be recoverable into a consistent state, even if the system failed at a hardware level.

So far, every scheme I've come up with pivots on writing data sequentially. Some piece of data would be appended to the end of each record which confirms that the write succeeded. However, if the data is not necessarily written to the disk sequentially when flushed then it would be possible for the confirmation data to be written before the content data.

There are two obvious ways around this, but both are undesirable:

  1. Flush the content, then write the confirmation and flush it. Adding the extra flush may degrade performance.
  2. Include a checksum in the confirmation (would require reading the content to confirm that it is valid).

I'm using C# on Windows (32 and 64-bit) and .Net 4.0's memory mapped file implementation

Kennet Belenky
  • 2,755
  • 18
  • 20
  • The second idea (verifying the data, the timestamp, the sequence number, and the checksum) seems legit. However, in general, you should be looking at high availability clusters, with separate machines across a network. All records or journal writes need to be replicated over the network to two or more machines. You cannot extract any guarantee from a single machine, period. – rwong Oct 13 '14 at 21:15

2 Answers2

1

This is too low level and OS specific for C#. try using Windows APIs from C, and read very carefully the API specifiations.

ruslik
  • 14,714
  • 1
  • 39
  • 40
0

Have you tried using the FileOptions.WriteThrough on the underlying filestream? That might help since it disables buffering. Other ideas would be to keep a separate file containing the confirmations as the last written offset, if it doesnt match your filesize (due to power outage for example ) you can simply truncate it do that size

Homde
  • 4,246
  • 4
  • 34
  • 50
  • 1
    Those are good ideas in terms of fault recovery. Unfortunately they don't apply to memory mapped files. MM Files always have WriteThrough disabled because they use the OS's underlying page manager to handle buffering. Keeping a confirmation log is also a good idea but it has other problems. It would then require two flushes per file operation (one for the MM file, one for the log). Even more problematic, with MM files you don't know when a flush is completed. At best you can instruct the OS to start a flush, but you don't get confirmation upon completion. That makes a deterministic log a no-go – Kennet Belenky Nov 22 '10 at 00:37
  • @Kennet Belenky: The thing about flushing is strange, compare with [Java](http://docs.oracle.com/javase/1.4.2/docs/api/java/nio/MappedByteBuffer.html). Maybe you could use a normal FileOutputStream for the log (the log is short so there won't be much speed difference)? IIUYC losing an unconfirmed record is not that bad, so you could flush the log more rarely. – maaartinus Aug 25 '12 at 03:37
  • @maaartinus Java's API is definitely easier to reason under, but it's not perfect either. It's nice that it provides the guarantee that the flush is complete upon return. However, it would be even nicer if it provided you with an async notification so you could go about your business. The 10ms seek time of a spinning-disk flush is a long time to sit idle. – Kennet Belenky Aug 28 '12 at 17:11
  • @Kennet Belenky: I can't recall anything in Java suitable for this async notification. Using `Callable` with an `ExecutorService` is verbose (as many things in Java) but trivial for anything you don't want to make you sit idle. – maaartinus Aug 28 '12 at 17:57