An Abstraction Layer
In order to make file access safer, the CKPTFile controls all access to the array. Instead of accessing the underlying array directly, you must go through the CKPTFile interface.
The underlying array is itself behind another abstraction barrierin this case, it's hidden inside a MappedByteBuffer object. The CPKTFile uses the MappedByteBuffer to read and write the file (see Figure 4).
The get() methods read from the CKPTFile and the put() methods write to it. The get methods have a simple implementationthey just call the get() methods of the MappedByteBuffer. The put() methods are a little more complicated, and this is where we get to the heart of our implementation.
The Atomicity Architecture
The whole point of the CKPTFile class is to make it possible to checkpoint the file. This has the effect of turning the set of writes between two checkpoints into a kind of de facto transaction (see Figure 5). If the writes between two checkpoints are a transaction, then we want to carry out this transaction in its entirety or not at all. This means that in the event only some of the writes are completed, the file should be restored to its original state.
Figure 6 shows a hypothetical example in which a file is written and checkpointed. The first checkpoint occurs after a set of writes has been performed and completes successfully. The second set of writes begins, but before the second checkpoint can happen, the system crashes, leaving the file in an inconsistent state. The only thing to do in this scenario is repair the file so that it reverts to the state it was in just after the last checkpoint. How do you do that? The answer is surprisingly simple: get it from another file.