Skip to content

Instantly share code, notes, and snippets.

@klauswuestefeld
Created July 25, 2011 04:55
Show Gist options
  • Save klauswuestefeld/1103582 to your computer and use it in GitHub Desktop.
Save klauswuestefeld/1103582 to your computer and use it in GitHub Desktop.
PrevaylerJr - "To serve the persistence needs of 99% of information systems in the world using 23 semicolons."
import java.io.*;
public class PrevaylerJr {
public static interface Command extends Serializable {
Object executeOn(Object system);
}
private final Object _system;
private final ObjectOutputStream _journal;
public PrevaylerJr(Serializable initialState, File storageFile) throws Exception {
File tempFile = new File(storageFile.getAbsolutePath() + ".tmp");
_system = restoreState(initialState, storageFile, tempFile);
_journal = new ObjectOutputStream(new FileOutputStream(tempFile));
writeToJournal(_system);
if (storageFile.delete() && tempFile.renameTo(storageFile))
return;
throw new IOException("Unable to rename " + tempFile + " to " + storageFile);
}
synchronized
public Object executeTransaction(Command transaction) throws Exception {
writeToJournal(transaction);
return transaction.executeOn(_system);
}
synchronized
public Object executeQuery(Command query) {
return query.executeOn(_system);
}
private Object restoreState(Object initialState, File storageFile, File tempFile) {
Object state = initialState;
try {
File fileToRead = storageFile.exists() ? storageFile : tempFile;
ObjectInputStream input = new ObjectInputStream(new FileInputStream(fileToRead));
state = restoreImage(input);
restoreCommands(state, input);
} catch (Exception endOfStreamReached) {}
return state;
}
private Serializable restoreImage(ObjectInputStream input) throws IOException, ClassNotFoundException {
return (Serializable) input.readObject();
}
private void restoreCommands(Object state, ObjectInputStream input) throws IOException, ClassNotFoundException {
while (true)
((Command) input.readObject()).executeOn(state);
}
private void writeToJournal(Object object) throws IOException {
_journal.writeObject(object);
_journal.flush();
}
}
@klauswuestefeld
Copy link
Author

Applying transactions to the system before they are written will cause queries to see unwritten changes. So, unless you sequence all queries with disk writes, you lose the D in ACID.
Recovering the system after a transaction exception, even if done with the RoyalFoodTaster pattern, is a huge hiccup in the system. If there is a silly transaction throwing a frequent but unimportant exception, sysadmins will hate you for this feature.
Throwing an exception is just one particular kind of bug a transaction can cause. All other bugs will not be caught, just as they won't be caught in any DBMS.

@beothorn
Copy link

Is there a reason to use Object instead of Serializable on lines 67,41 and 11?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment