# HG changeset patch # User Dan Creswell # Date 1246807585 -3600 # Node ID 4580bb12db30ca52afe044245cca1ff1e9dc09f7 # Parent 46ac1a45718a59678b1c67f51cc7285896fdb5de Separate command execution from command logging. diff -r 46ac1a45718a -r 4580bb12db30 src/org/dancres/blitz/txn/NullBatcher.java --- /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()); + } + +} diff -r 46ac1a45718a -r 4580bb12db30 src/org/dancres/blitz/txn/PersistentPersonality.java --- 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() { diff -r 46ac1a45718a -r 4580bb12db30 src/org/dancres/blitz/txn/TimeBarrierPersonality.java --- 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; diff -r 46ac1a45718a -r 4580bb12db30 src/org/dancres/blitz/txn/TxnManager.java --- 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); } } diff -r 46ac1a45718a -r 4580bb12db30 src/org/dancres/blitz/txn/batch/ConcurrentWriteBatcher.java --- 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.

*/ 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; } } } diff -r 46ac1a45718a -r 4580bb12db30 src/org/dancres/blitz/txn/batch/WriteBatcher.java --- 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; /**

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); } } } diff -r 46ac1a45718a -r 4580bb12db30 src/org/prevayler/implementation/PrevaylerCore.java --- /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]; + } + } +} diff -r 46ac1a45718a -r 4580bb12db30 src/org/prevayler/implementation/SnapshotPrevaylerImpl.java --- 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]; - } - } -}