changeset 17:4580bb12db30

Separate command execution from command logging.
author Dan Creswell <dan.creswell@gmail.com>
date Sun, 05 Jul 2009 16:26:25 +0100
parents 46ac1a45718a
children 62b11f04d859
files src/org/dancres/blitz/txn/NullBatcher.java src/org/dancres/blitz/txn/PersistentPersonality.java src/org/dancres/blitz/txn/TimeBarrierPersonality.java src/org/dancres/blitz/txn/TxnManager.java src/org/dancres/blitz/txn/batch/ConcurrentWriteBatcher.java src/org/dancres/blitz/txn/batch/WriteBatcher.java src/org/prevayler/implementation/PrevaylerCore.java src/org/prevayler/implementation/SnapshotPrevaylerImpl.java
diffstat 8 files changed, 333 insertions(+), 306 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/org/dancres/blitz/txn/NullBatcher.java	Sun Jul 05 16:26:25 2009 +0100
@@ -0,0 +1,35 @@
+package org.dancres.blitz.txn;
+
+import java.io.IOException;
+import java.io.Serializable;
+import org.prevayler.Command;
+import org.prevayler.PrevalentSystem;
+import org.prevayler.implementation.SnapshotPrevayler;
+import org.prevayler.implementation.PrevaylerCore;
+import org.prevayler.implementation.Snapshotter;
+
+public class NullBatcher implements SnapshotPrevayler {
+    private PrevaylerCore thePrevayler;
+
+    NullBatcher(PrevaylerCore aPrevayler) {
+        thePrevayler = aPrevayler;
+    }
+    public Snapshotter takeSnapshot() throws IOException {
+        return thePrevayler.takeSnapshot();
+    }
+
+    public PrevalentSystem system() {
+        return thePrevayler.system();
+    }
+
+    public Serializable executeCommand(Command aCommand) throws Exception {
+        thePrevayler.logCommand(aCommand);
+        return aCommand.execute(system());
+    }
+
+    public Serializable executeCommand(Command aCommand, boolean sync) throws Exception {
+        thePrevayler.logCommand(aCommand, sync);
+        return aCommand.execute(system());
+    }
+
+}
--- a/src/org/dancres/blitz/txn/PersistentPersonality.java	Sun Jul 05 16:25:18 2009 +0100
+++ b/src/org/dancres/blitz/txn/PersistentPersonality.java	Sun Jul 05 16:26:25 2009 +0100
@@ -3,7 +3,7 @@
 import java.util.logging.Level;
 
 import org.prevayler.implementation.SnapshotPrevayler;
-import org.prevayler.implementation.SnapshotPrevaylerImpl;
+import org.prevayler.implementation.PrevaylerCore;
 
 import org.prevayler.PrevalentSystem;
 
@@ -32,11 +32,11 @@
         TxnManager.theLogger.log(Level.INFO, "Reset log stream: " +
                           theModel.shouldResetLogStream());
         TxnManager.theLogger.log(Level.INFO, "Write barrier window: " +
-                          theModel.getBatchWriteWindowSize());
+                          theModel.getBatchWriteWindowSizeMs() + ", " + theModel.getBatchWriteWindowSizeNs());
 
         if (theModel.useConcurrentWriteBatcher())
                 TxnManager.theLogger.log(Level.INFO,
-                                         "*** Using concurrent batcher ***");
+                                         "*** Concurrent batching enabled ***");
 
         if (theModel.shouldCleanLogs()) {
             TxnManager.theLogger.log(Level.WARNING,
@@ -58,26 +58,25 @@
         PersistentReboot myReboot = new PersistentReboot(theModel);
         myReboot.execute();
 
-        SnapshotPrevayler myPrevayler =
-            new SnapshotPrevaylerImpl(aSystem,
+        PrevaylerCore myPrevayler =
+            new PrevaylerCore(aSystem,
                                       theLogDir,
                                       theModel.shouldResetLogStream(),
                                       theModel.shouldCleanLogs(),
                                       theModel.getLogBufferSize());
 
-        if (theModel.getBatchWriteWindowSize() != 0) {
-            int myWindowSize = theModel.getBatchWriteWindowSize();
+        if ((theModel.getBatchWriteWindowSizeMs() != 0) ||
+            (theModel.getBatchWriteWindowSizeNs() != 0)) {
+            long myWindowSizeMs = theModel.getBatchWriteWindowSizeMs();
+            int myWindowSizeNs = theModel.getBatchWriteWindowSizeNs();
 
             if (theModel.useConcurrentWriteBatcher()) {
-                myPrevayler =
-                    new ConcurrentWriteBatcher(myPrevayler, myWindowSize);
+                return new ConcurrentWriteBatcher(myPrevayler, myWindowSizeMs, myWindowSizeNs);
             } else {
-                myPrevayler =
-                    new WriteBatcher(myPrevayler, myWindowSize);
+                return new WriteBatcher(myPrevayler, myWindowSizeMs, myWindowSizeNs);
             }
-        }
-
-        return myPrevayler;
+        } else
+            return new NullBatcher(myPrevayler);
     }
 
     public void destroy() {
--- a/src/org/dancres/blitz/txn/TimeBarrierPersonality.java	Sun Jul 05 16:25:18 2009 +0100
+++ b/src/org/dancres/blitz/txn/TimeBarrierPersonality.java	Sun Jul 05 16:26:25 2009 +0100
@@ -4,7 +4,6 @@
 
 import org.prevayler.implementation.SnapshotPrevayler;
 import org.prevayler.implementation.BufferingPrevaylerImpl;
-import org.prevayler.implementation.SnapshotPrevaylerImpl;
 
 import org.prevayler.PrevalentSystem;
 
--- a/src/org/dancres/blitz/txn/TxnManager.java	Sun Jul 05 16:25:18 2009 +0100
+++ b/src/org/dancres/blitz/txn/TxnManager.java	Sun Jul 05 16:26:25 2009 +0100
@@ -129,7 +129,8 @@
         thePrevayler = myPersonality.getPrevayler(new TxnManagerState());
 
         theLogger.log(Level.INFO, "Log Recovery complete...");
-
+        theLogger.log(Level.INFO, "Using prevayler: " + thePrevayler.getClass());
+        
         theManagerState = (TxnManagerState) thePrevayler.system();
 
         theCheckpointTrigger =
@@ -483,7 +484,7 @@
             // System.err.println("Bypass");
             return aCommand.execute(theManagerState);
         } else {
-            // System.err.println("Full log");
+            // System.err.println("Full log: " + thePrevayler.getClass());
             return thePrevayler.executeCommand(aCommand);
         }
     }
--- a/src/org/dancres/blitz/txn/batch/ConcurrentWriteBatcher.java	Sun Jul 05 16:25:18 2009 +0100
+++ b/src/org/dancres/blitz/txn/batch/ConcurrentWriteBatcher.java	Sun Jul 05 16:26:25 2009 +0100
@@ -7,11 +7,11 @@
 
 import java.util.logging.Level;
 
-import org.prevayler.Prevayler;
 import org.prevayler.PrevalentSystem;
 import org.prevayler.Command;
 
 import org.prevayler.implementation.SnapshotPrevayler;
+import org.prevayler.implementation.PrevaylerCore;
 import org.prevayler.implementation.Snapshotter;
 
 /**
@@ -32,7 +32,7 @@
    bunch is being written.</p>
  */
 public class ConcurrentWriteBatcher implements SnapshotPrevayler {
-    private SnapshotPrevayler thePrevayler;
+    private PrevaylerCore thePrevayler;
 
     private boolean amFirst = true;
 
@@ -40,13 +40,16 @@
 
     // Might be able to buff up to 60ms which gives average of 30 but
     // we'll see.
-    private long theWindowTime = 20;
+    private long theWindowTimeMs = 20;
+    private int theWindowTimeNs = 0;
 
-    public ConcurrentWriteBatcher(SnapshotPrevayler aPrevayler,
-        long aWindowTime) {
+
+    public ConcurrentWriteBatcher(PrevaylerCore aPrevayler,
+        long aWindowTimeMs, int aWindowTimeNs) {
         
         thePrevayler = aPrevayler;
-        theWindowTime = aWindowTime;
+        theWindowTimeMs = aWindowTimeMs;
+        theWindowTimeNs = aWindowTimeNs;
     }
 
     /**
@@ -66,7 +69,7 @@
     }
 
     private Serializable write(Command aComm) throws Exception {
-        WriteRequest myReq = new WriteRequest(aComm);
+        WriteRequest myReq = new WriteRequest(aComm, system());
 
         boolean wasFirst = false;
 
@@ -79,7 +82,7 @@
                 wasFirst = true;
 
                 try {
-                    wait(theWindowTime);
+                    wait(theWindowTimeMs, theWindowTimeNs);
                 } catch (InterruptedException anIE) {
                 }
 
@@ -101,7 +104,7 @@
         return myReq.getResult();
     }
 
-	public Snapshotter takeSnapshot() throws IOException {
+    public Snapshotter takeSnapshot() throws IOException {
         return thePrevayler.takeSnapshot();
     }
 
@@ -122,20 +125,21 @@
     }
 
     private static class WriteRequest {
+        private PrevalentSystem theSystem;
         private Command theCommand;
 
         private Exception theException;
-        private Serializable theResult;
 
         private boolean isDone;
 
-        WriteRequest(Command aCommand) {
+        WriteRequest(Command aCommand, PrevalentSystem aSystem) {
             theCommand = aCommand;
+            theSystem = aSystem;
         }
 
-        void execute(Prevayler aPrev, boolean doSync) {
+        void execute(PrevaylerCore aPrev, boolean doSync) {
             try {
-                theResult = aPrev.executeCommand(theCommand, doSync);
+                aPrev.logCommand(theCommand, doSync);
             } catch (Exception anE) {
                 theException = anE;
             } finally {
@@ -154,11 +158,13 @@
                     } catch (InterruptedException anIE) {
                     }
                 }
+            }
 
-                if (theException != null)
-                    throw theException;
-                else
-                    return theResult;
+            if (theException != null)
+                throw theException;
+            else {
+                Serializable myResult = theCommand.execute(theSystem);
+                return myResult;
             }
         }
     }
--- a/src/org/dancres/blitz/txn/batch/WriteBatcher.java	Sun Jul 05 16:25:18 2009 +0100
+++ b/src/org/dancres/blitz/txn/batch/WriteBatcher.java	Sun Jul 05 16:26:25 2009 +0100
@@ -16,6 +16,7 @@
 import org.prevayler.implementation.Snapshotter;
 
 import org.dancres.blitz.Logging;
+import org.prevayler.implementation.PrevaylerCore;
 
 /**
    <p>Batches commands issued in the same time period together in an attempt
@@ -34,7 +35,7 @@
     static Logger theLogger =
         Logging.newLogger("org.dancres.blitz.txn.LogBatcher");
 
-    private SnapshotPrevayler thePrevayler;
+    private PrevaylerCore thePrevayler;
 
     private boolean amFirst = true;
 
@@ -42,11 +43,13 @@
 
     // Might be able to buff up to 60ms which gives average of 30 but
     // we'll see.
-    private long theWindowTime = 20;
+    private long theWindowTimeMs = 0;
+    private int theWindowTimeNs = 0;
 
-    public WriteBatcher(SnapshotPrevayler aPrevayler, long aWindowTime) {
+    public WriteBatcher(PrevaylerCore aPrevayler, long aWindowTimeMs, int aWindowTimeNs) {
         thePrevayler = aPrevayler;
-        theWindowTime = aWindowTime;
+        theWindowTimeMs = aWindowTimeMs;
+        theWindowTimeNs = aWindowTimeNs;
     }
 
     /**
@@ -66,7 +69,7 @@
     }
 
     private Serializable write(Command aComm) throws Exception {
-        WriteRequest myReq = new WriteRequest(aComm);
+        WriteRequest myReq = new WriteRequest(system(), aComm);
 
         synchronized(this) {
             if (amFirst) {
@@ -74,7 +77,7 @@
                 amFirst = false;
 
                 try {
-                    wait(theWindowTime);
+                    wait(theWindowTimeMs, theWindowTimeNs);
                 } catch (InterruptedException anIE) {
                 }
 
@@ -113,19 +116,20 @@
 
     private static class WriteRequest {
         private Command theCommand;
+        private PrevalentSystem theSystem;
 
         private Exception theException;
-        private Serializable theResult;
 
         private boolean isDone;
 
-        WriteRequest(Command aCommand) {
+        WriteRequest(PrevalentSystem aSystem, Command aCommand) {
             theCommand = aCommand;
+            theSystem = aSystem;
         }
 
-        void execute(Prevayler aPrev, boolean doSync) {
+        void execute(PrevaylerCore aPrev, boolean doSync) {
             try {
-                theResult = aPrev.executeCommand(theCommand, doSync);
+                aPrev.logCommand(theCommand, doSync);
             } catch (Exception anE) {
                 theException = anE;
             } finally {
@@ -148,7 +152,7 @@
                 if (theException != null)
                     throw theException;
                 else
-                    return theResult;
+                    return theCommand.execute(theSystem);
             }
         }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/org/prevayler/implementation/PrevaylerCore.java	Sun Jul 05 16:26:25 2009 +0100
@@ -0,0 +1,244 @@
+/*
+  The copyright of all source code included in this Prevayler distribution is
+  held by Klaus Wuestefeld, except the files that specifically state otherwise.
+  All rights are reserved. "PREVAYLER" is a trademark of Klaus Wuestefeld.
+
+
+  BSD License:
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions are met:
+
+  - Redistributions of source code must retain the above copyright notice, this
+  list of conditions and the following disclaimer.
+
+  - Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+ 
+  - Neither the name of Prevayler nor the names of its contributors may be used
+  to endorse or promote products derived from this software without specific
+  prior written permission.
+
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.prevayler.implementation;
+
+import java.io.*;
+
+import java.rmi.RMISecurityManager;
+
+import org.prevayler.*;
+
+/** Provides transparent persistence for business objects.
+ * This applies to any deterministic system implementing the PrevalentSystem interface.
+ * All commands to the system must be represented as objects implementing the Command interface and must be executed
+ * using Prevayler.executeCommand(Command).
+ * Take a look at the demo application included with the Prevayler distribution for examples.
+ */
+public class PrevaylerCore {
+
+    private final PrevalentSystem system;
+    private final SystemClock clock;
+    private final CommandOutputStream output;
+
+    /** Returns a new Prevayler for the given PrevalentSystem.
+     * "PrevalenceBase" shall be the directory where the snapshot and log files shall be created and read.
+     * @param newSystem The newly started, "empty" PrevalentSystem that will be used as a starting point for every
+     * system startup, until the first snapshot is taken.
+     * @param shouldReset Whether to issue resets in the underlying OOS
+     */
+    public PrevaylerCore(PrevalentSystem newSystem,
+            boolean shouldReset, boolean shouldClean,
+            int aBufferSize)
+            throws IOException, ClassNotFoundException {
+
+        this(newSystem, "PrevalenceBase", shouldReset, shouldClean,
+                aBufferSize);
+    }
+
+    /** Returns a new Prevayler for the given PrevalentSystem.
+     * @param newSystem The newly started, "empty" PrevalentSystem that will be used as a starting point for every
+     * system startup, until the first snapshot is taken.
+     * @param directory The full path of the directory where the snapshot and log files shall be created and read.
+     * @param shouldReset Whether to issue resets in the underlying OOS
+     */
+    public PrevaylerCore(PrevalentSystem newSystem, String directory,
+            boolean shouldReset, boolean shouldClean,
+            int aBufferSize)
+            throws IOException, ClassNotFoundException {
+
+        newSystem.clock(new SystemClock());
+        CommandInputStream input = new CommandInputStream(directory);
+
+        PrevalentSystem savedSystem = input.readLastSnapshot();
+        system = (savedSystem == null)
+                ? newSystem
+                : savedSystem;
+
+        recoverCommands(input);
+
+        output = input.commandOutputStream(shouldReset, shouldClean,
+                aBufferSize);
+        clock = (SystemClock) system.clock();
+        clock.resume();
+    }
+
+    public PrevaylerCore(PrevalentSystem newSystem, String directory)
+            throws IOException, ClassNotFoundException {
+
+        clock = null;
+        output = null;
+
+        newSystem.clock(new SystemClock());
+        CommandInputStream input = new CommandInputStream(directory);
+
+        PrevalentSystem savedSystem = input.readLastSnapshot();
+
+        if (savedSystem != null) {
+            system = savedSystem;
+        } else {
+            system = newSystem;
+        }
+
+        System.out.println("System base clock: " + system.clock().time().getTime());
+        Serializable[] myUserData = system.getSnapshotContributions();
+
+        for (int i = 0; i < myUserData.length; i++) {
+            System.out.println(myUserData[i].toString());
+        }
+
+        debugCommands(input);
+    }
+
+    /**
+    Returns the underlying PrevalentSystem.
+     */
+    public PrevalentSystem system() {
+        return system;
+    }
+
+    /** Logs the received command for crash or shutdown recovery and executes it on the underlying PrevalentSystem.
+     * @see system()
+     * @return The serializable object that was returned by the execution of command.
+     * @throws IOException if there is trouble writing the command to the log.
+     * @throws Exception if command.execute() throws an exception.
+     */
+    public void logCommand(Command command) throws Exception {
+        synchronized (this) {
+            output.writeCommand(command);
+        }
+    }
+
+    public void logCommand(Command command, boolean doSync) throws Exception {
+        synchronized (this) {
+            output.writeCommand(command, doSync);
+        }
+    }
+
+    /**
+     * This method prepares a snapshot of the system and returns it in a
+     * Snapshotter instance which can be used to save the snapshot to disk
+     * once dirty state has been sync'd to disk.  If your application has no
+     * additional state, you can simply invoke on the Snapshotter immediately.
+     * @return Snapshotter to be used to save an appropriate snapshot post
+     * sync'ing of dirty state to disk.
+     * @see system()
+     * @throws IOException if there is trouble preparing the snapshot file.
+     */
+    public synchronized Snapshotter takeSnapshot() throws IOException {
+        clock.pause();
+        try {
+            return output.writeSnapshot(system);
+        } finally {
+            clock.resume();
+        }
+    }
+
+    private void debugCommands(CommandInputStream input) throws IOException, ClassNotFoundException {
+        Command command;
+        
+        while (true) {
+            try {
+                command = input.readCommand();
+            } catch (EOFException eof) {
+                break;
+            }
+
+            try {
+                System.out.println(command);
+                System.out.println();
+                // command.execute(system);
+            } catch (Exception e) {
+                //Don't do anything at all. Commands may throw exceptions normally.
+                System.err.println("Command threw exception");
+                e.printStackTrace(System.err);
+            }
+        }
+    }
+
+    private void recoverCommands(CommandInputStream input) throws IOException, ClassNotFoundException {
+        Command command;
+        while (true) {
+            try {
+                command = input.readCommand();
+            } catch (EOFException eof) {
+                break;
+            }
+
+            try {
+                command.execute(system);
+            } catch (Exception e) {
+                //Don't do anything at all. Commands may throw exceptions normally.
+                System.err.println("Command threw exception");
+                e.printStackTrace(System.err);
+            }
+        }
+    }
+
+    public static void main(String anArgs[]) {
+        try {
+            System.setSecurityManager(new RMISecurityManager());
+
+            new PrevaylerCore(new DebugSystem(), anArgs[0]);
+        } catch (Exception anE) {
+            System.err.println("Whoops");
+            anE.printStackTrace(System.err);
+        }
+    }
+
+    static class DebugSystem implements org.prevayler.PrevalentSystem {
+
+        private org.prevayler.AlarmClock theClock;
+
+        public void clock(org.prevayler.AlarmClock clock) {
+            theClock = clock;
+        }
+
+        public org.prevayler.AlarmClock clock() {
+            return theClock;
+        }
+
+        public void add(SnapshotContributor aContributor) {
+        }
+
+        public void remove(SnapshotContributor aContributor) {
+        }
+
+        public Serializable[] getSnapshotContributions() {
+            return new Serializable[0];
+        }
+    }
+}
--- a/src/org/prevayler/implementation/SnapshotPrevaylerImpl.java	Sun Jul 05 16:25:18 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,261 +0,0 @@
-/*
-  The copyright of all source code included in this Prevayler distribution is
-  held by Klaus Wuestefeld, except the files that specifically state otherwise.
-  All rights are reserved. "PREVAYLER" is a trademark of Klaus Wuestefeld.
-
-
-  BSD License:
-
-  Redistribution and use in source and binary forms, with or without
-  modification, are permitted provided that the following conditions are met:
-
-  - Redistributions of source code must retain the above copyright notice, this
-  list of conditions and the following disclaimer.
-
-  - Redistributions in binary form must reproduce the above copyright notice,
-  this list of conditions and the following disclaimer in the documentation
-  and/or other materials provided with the distribution.
- 
-  - Neither the name of Prevayler nor the names of its contributors may be used
-  to endorse or promote products derived from this software without specific
-  prior written permission.
-
-
-  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
-  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
-  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
-  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
-  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
-  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-  POSSIBILITY OF SUCH DAMAGE.
-*/
-
-package org.prevayler.implementation;
-
-import java.util.Date;
-import java.io.*;
-
-import java.rmi.RMISecurityManager;
-
-import org.prevayler.*;
-
-/** Provides transparent persistence for business objects.
-* This applies to any deterministic system implementing the PrevalentSystem interface.
-* All commands to the system must be represented as objects implementing the Command interface and must be executed using Prevayler.executeCommand(Command).
-* Take a look at the demo application included with the Prevayler distribution for examples.
-*/
-public class SnapshotPrevaylerImpl implements SnapshotPrevayler {
-
-	private final PrevalentSystem system;
-	private final SystemClock clock;
-	private final CommandOutputStream output;
-
-
-	/** Returns a new Prevayler for the given PrevalentSystem.
-	* "PrevalenceBase" shall be the directory where the snapshot and log files shall be created and read.
-	* @param newSystem The newly started, "empty" PrevalentSystem that will be used as a starting point for every system startup, until the first snapshot is taken.
-    * @param shouldReset Whether to issue resets in the underlying OOS
-	*/
-	public SnapshotPrevaylerImpl(PrevalentSystem newSystem,
-                                 boolean shouldReset, boolean shouldClean,
-                                 int aBufferSize)
-        throws IOException, ClassNotFoundException {
-
-		this(newSystem, "PrevalenceBase", shouldReset, shouldClean,
-             aBufferSize);
-	}
-
-
-	/** Returns a new Prevayler for the given PrevalentSystem.
-	* @param newSystem The newly started, "empty" PrevalentSystem that will be used as a starting point for every system startup, until the first snapshot is taken.
-	* @param directory The full path of the directory where the snapshot and log files shall be created and read.
-    * @param shouldReset Whether to issue resets in the underlying OOS
-	*/
-	public SnapshotPrevaylerImpl(PrevalentSystem newSystem, String directory,
-                                 boolean shouldReset, boolean shouldClean,
-                                 int aBufferSize)
-        throws IOException, ClassNotFoundException {
-
-		newSystem.clock(new SystemClock());
-		CommandInputStream input = new CommandInputStream(directory);
-
-		PrevalentSystem savedSystem = input.readLastSnapshot();
-		system = (savedSystem == null)
-		    ? newSystem
-		    : savedSystem;
-
-		recoverCommands(input);
-
-		output = input.commandOutputStream(shouldReset, shouldClean,
-                                           aBufferSize);
-		clock = (SystemClock)system.clock();
-		clock.resume();
-	}
-
-    public SnapshotPrevaylerImpl(PrevalentSystem newSystem, String directory)
-        throws IOException, ClassNotFoundException {
-
-        clock = null;
-        output = null;
-
-		newSystem.clock(new SystemClock());
-		CommandInputStream input = new CommandInputStream(directory);
-
-		PrevalentSystem savedSystem = input.readLastSnapshot();
-
-        if (savedSystem != null)
-            system = savedSystem;
-        else
-            system = newSystem;
-
-        System.out.println("System base clock: " + system.clock().time().getTime());
-        Serializable[] myUserData = system.getSnapshotContributions();
-
-        for (int i = 0; i < myUserData.length; i++) {
-            System.out.println(myUserData[i].toString());
-        }
-
-		debugCommands(input);
-    }
-
-	/**
-       Returns the underlying PrevalentSystem.
-	*/
-	public PrevalentSystem system() {
-		return system;
-	}
-
-	/** Logs the received command for crash or shutdown recovery and executes it on the underlying PrevalentSystem.
-	* @see system()
-	* @return The serializable object that was returned by the execution of command.
-	* @throws IOException if there is trouble writing the command to the log.
-	* @throws Exception if command.execute() throws an exception.
-	*/
-	public Serializable executeCommand(Command command) throws Exception {
-
-        synchronized(this) {
-            try {
-                clock.pause();  //To be deterministic, the system must know exactly at what time the command is being executed.
-                output.writeCommand(new ClockRecoveryCommand(command, clock.time()));
-            } finally {
-                clock.resume();
-            }
-        }
-
-        return command.execute(system);
-	}
-
-	public Serializable executeCommand(Command command,
-                                       boolean doSync)
-        throws Exception {
-
-        synchronized(this) {
-            try {
-                clock.pause();
-                output.writeCommand(new ClockRecoveryCommand(command,
-                                                             clock.time()),
-                                    doSync);
-            } finally {
-                clock.resume();
-            }
-        }
-
-        return command.execute(system);
-	}
-
-    /**
-     * This method prepares a snapshot of the system and returns it in a
-     * Snapshotter instance which can be used to save the snapshot to disk
-     * once dirty state has been sync'd to disk.  If your application has no
-     * additional state, you can simply invoke on the Snapshotter immediately.
-    * @return Snapshotter to be used to save an appropriate snapshot post
-    * sync'ing of dirty state to disk.
-	* @see system()
-	* @throws IOException if there is trouble preparing the snapshot file.
-	*/
-	public synchronized Snapshotter takeSnapshot() throws IOException {
-		clock.pause();
-		try {
-			return output.writeSnapshot(system);
-		} finally {
-			clock.resume();
-		}
-	}
-
-	private void debugCommands(CommandInputStream input) throws IOException, ClassNotFoundException {
-		Command command;
-		while(true) {
-			try {
-				command = input.readCommand();
-			} catch (EOFException eof) {
-				break;
-			}
-
-			try {
-                System.out.println(command);
-                System.out.println();
-                // command.execute(system);
-			} catch (Exception e) {
-				//Don't do anything at all. Commands may throw exceptions normally.
-                System.err.println("Command threw exception");
-                e.printStackTrace(System.err);
-			}
-		}
-	}
-
-	private void recoverCommands(CommandInputStream input) throws IOException, ClassNotFoundException {
-		Command command;
-		while(true) {
-			try {
-				command = input.readCommand();
-			} catch (EOFException eof) {
-				break;
-			}
-
-			try {
-				command.execute(system);
-			} catch (Exception e) {
-				//Don't do anything at all. Commands may throw exceptions normally.
-                System.err.println("Command threw exception");
-                e.printStackTrace(System.err);
-			}
-		}
-	}
-
-    public static void main(String anArgs[]) {
-        try {
-            System.setSecurityManager(new RMISecurityManager());
-
-            new SnapshotPrevaylerImpl(new DebugSystem(), anArgs[0]);
-        } catch (Exception anE) {
-            System.err.println("Whoops");
-            anE.printStackTrace(System.err);
-        }
-    }
-
-    static class DebugSystem implements org.prevayler.PrevalentSystem {
-        private org.prevayler.AlarmClock theClock;
-
-        public void clock(org.prevayler.AlarmClock clock) {
-            theClock = clock;
-        }
-
-        public org.prevayler.AlarmClock clock() {
-            return theClock;
-        }
-
-        public void add(SnapshotContributor aContributor) {
-        }
-
-        public void remove(SnapshotContributor aContributor) {
-        }
-
-        public Serializable[] getSnapshotContributions() {
-            return new Serializable[0];
-        }
-    }
-}