Mercurial > hg > blitz_condensed
comparison src/org/prevayler/implementation/PrevaylerCore.java @ 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 | src/org/prevayler/implementation/SnapshotPrevaylerImpl.java@3dc0c5604566 |
children | a77f0a9ed93c |
comparison
equal
deleted
inserted
replaced
16:46ac1a45718a | 17:4580bb12db30 |
---|---|
1 /* | |
2 The copyright of all source code included in this Prevayler distribution is | |
3 held by Klaus Wuestefeld, except the files that specifically state otherwise. | |
4 All rights are reserved. "PREVAYLER" is a trademark of Klaus Wuestefeld. | |
5 | |
6 | |
7 BSD License: | |
8 | |
9 Redistribution and use in source and binary forms, with or without | |
10 modification, are permitted provided that the following conditions are met: | |
11 | |
12 - Redistributions of source code must retain the above copyright notice, this | |
13 list of conditions and the following disclaimer. | |
14 | |
15 - Redistributions in binary form must reproduce the above copyright notice, | |
16 this list of conditions and the following disclaimer in the documentation | |
17 and/or other materials provided with the distribution. | |
18 | |
19 - Neither the name of Prevayler nor the names of its contributors may be used | |
20 to endorse or promote products derived from this software without specific | |
21 prior written permission. | |
22 | |
23 | |
24 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
25 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
26 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
27 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | |
28 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
29 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
30 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
31 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
32 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
33 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
34 POSSIBILITY OF SUCH DAMAGE. | |
35 */ | |
36 | |
37 package org.prevayler.implementation; | |
38 | |
39 import java.io.*; | |
40 | |
41 import java.rmi.RMISecurityManager; | |
42 | |
43 import org.prevayler.*; | |
44 | |
45 /** Provides transparent persistence for business objects. | |
46 * This applies to any deterministic system implementing the PrevalentSystem interface. | |
47 * All commands to the system must be represented as objects implementing the Command interface and must be executed | |
48 * using Prevayler.executeCommand(Command). | |
49 * Take a look at the demo application included with the Prevayler distribution for examples. | |
50 */ | |
51 public class PrevaylerCore { | |
52 | |
53 private final PrevalentSystem system; | |
54 private final SystemClock clock; | |
55 private final CommandOutputStream output; | |
56 | |
57 /** Returns a new Prevayler for the given PrevalentSystem. | |
58 * "PrevalenceBase" shall be the directory where the snapshot and log files shall be created and read. | |
59 * @param newSystem The newly started, "empty" PrevalentSystem that will be used as a starting point for every | |
60 * system startup, until the first snapshot is taken. | |
61 * @param shouldReset Whether to issue resets in the underlying OOS | |
62 */ | |
63 public PrevaylerCore(PrevalentSystem newSystem, | |
64 boolean shouldReset, boolean shouldClean, | |
65 int aBufferSize) | |
66 throws IOException, ClassNotFoundException { | |
67 | |
68 this(newSystem, "PrevalenceBase", shouldReset, shouldClean, | |
69 aBufferSize); | |
70 } | |
71 | |
72 /** Returns a new Prevayler for the given PrevalentSystem. | |
73 * @param newSystem The newly started, "empty" PrevalentSystem that will be used as a starting point for every | |
74 * system startup, until the first snapshot is taken. | |
75 * @param directory The full path of the directory where the snapshot and log files shall be created and read. | |
76 * @param shouldReset Whether to issue resets in the underlying OOS | |
77 */ | |
78 public PrevaylerCore(PrevalentSystem newSystem, String directory, | |
79 boolean shouldReset, boolean shouldClean, | |
80 int aBufferSize) | |
81 throws IOException, ClassNotFoundException { | |
82 | |
83 newSystem.clock(new SystemClock()); | |
84 CommandInputStream input = new CommandInputStream(directory); | |
85 | |
86 PrevalentSystem savedSystem = input.readLastSnapshot(); | |
87 system = (savedSystem == null) | |
88 ? newSystem | |
89 : savedSystem; | |
90 | |
91 recoverCommands(input); | |
92 | |
93 output = input.commandOutputStream(shouldReset, shouldClean, | |
94 aBufferSize); | |
95 clock = (SystemClock) system.clock(); | |
96 clock.resume(); | |
97 } | |
98 | |
99 public PrevaylerCore(PrevalentSystem newSystem, String directory) | |
100 throws IOException, ClassNotFoundException { | |
101 | |
102 clock = null; | |
103 output = null; | |
104 | |
105 newSystem.clock(new SystemClock()); | |
106 CommandInputStream input = new CommandInputStream(directory); | |
107 | |
108 PrevalentSystem savedSystem = input.readLastSnapshot(); | |
109 | |
110 if (savedSystem != null) { | |
111 system = savedSystem; | |
112 } else { | |
113 system = newSystem; | |
114 } | |
115 | |
116 System.out.println("System base clock: " + system.clock().time().getTime()); | |
117 Serializable[] myUserData = system.getSnapshotContributions(); | |
118 | |
119 for (int i = 0; i < myUserData.length; i++) { | |
120 System.out.println(myUserData[i].toString()); | |
121 } | |
122 | |
123 debugCommands(input); | |
124 } | |
125 | |
126 /** | |
127 Returns the underlying PrevalentSystem. | |
128 */ | |
129 public PrevalentSystem system() { | |
130 return system; | |
131 } | |
132 | |
133 /** Logs the received command for crash or shutdown recovery and executes it on the underlying PrevalentSystem. | |
134 * @see system() | |
135 * @return The serializable object that was returned by the execution of command. | |
136 * @throws IOException if there is trouble writing the command to the log. | |
137 * @throws Exception if command.execute() throws an exception. | |
138 */ | |
139 public void logCommand(Command command) throws Exception { | |
140 synchronized (this) { | |
141 output.writeCommand(command); | |
142 } | |
143 } | |
144 | |
145 public void logCommand(Command command, boolean doSync) throws Exception { | |
146 synchronized (this) { | |
147 output.writeCommand(command, doSync); | |
148 } | |
149 } | |
150 | |
151 /** | |
152 * This method prepares a snapshot of the system and returns it in a | |
153 * Snapshotter instance which can be used to save the snapshot to disk | |
154 * once dirty state has been sync'd to disk. If your application has no | |
155 * additional state, you can simply invoke on the Snapshotter immediately. | |
156 * @return Snapshotter to be used to save an appropriate snapshot post | |
157 * sync'ing of dirty state to disk. | |
158 * @see system() | |
159 * @throws IOException if there is trouble preparing the snapshot file. | |
160 */ | |
161 public synchronized Snapshotter takeSnapshot() throws IOException { | |
162 clock.pause(); | |
163 try { | |
164 return output.writeSnapshot(system); | |
165 } finally { | |
166 clock.resume(); | |
167 } | |
168 } | |
169 | |
170 private void debugCommands(CommandInputStream input) throws IOException, ClassNotFoundException { | |
171 Command command; | |
172 | |
173 while (true) { | |
174 try { | |
175 command = input.readCommand(); | |
176 } catch (EOFException eof) { | |
177 break; | |
178 } | |
179 | |
180 try { | |
181 System.out.println(command); | |
182 System.out.println(); | |
183 // command.execute(system); | |
184 } catch (Exception e) { | |
185 //Don't do anything at all. Commands may throw exceptions normally. | |
186 System.err.println("Command threw exception"); | |
187 e.printStackTrace(System.err); | |
188 } | |
189 } | |
190 } | |
191 | |
192 private void recoverCommands(CommandInputStream input) throws IOException, ClassNotFoundException { | |
193 Command command; | |
194 while (true) { | |
195 try { | |
196 command = input.readCommand(); | |
197 } catch (EOFException eof) { | |
198 break; | |
199 } | |
200 | |
201 try { | |
202 command.execute(system); | |
203 } catch (Exception e) { | |
204 //Don't do anything at all. Commands may throw exceptions normally. | |
205 System.err.println("Command threw exception"); | |
206 e.printStackTrace(System.err); | |
207 } | |
208 } | |
209 } | |
210 | |
211 public static void main(String anArgs[]) { | |
212 try { | |
213 System.setSecurityManager(new RMISecurityManager()); | |
214 | |
215 new PrevaylerCore(new DebugSystem(), anArgs[0]); | |
216 } catch (Exception anE) { | |
217 System.err.println("Whoops"); | |
218 anE.printStackTrace(System.err); | |
219 } | |
220 } | |
221 | |
222 static class DebugSystem implements org.prevayler.PrevalentSystem { | |
223 | |
224 private org.prevayler.AlarmClock theClock; | |
225 | |
226 public void clock(org.prevayler.AlarmClock clock) { | |
227 theClock = clock; | |
228 } | |
229 | |
230 public org.prevayler.AlarmClock clock() { | |
231 return theClock; | |
232 } | |
233 | |
234 public void add(SnapshotContributor aContributor) { | |
235 } | |
236 | |
237 public void remove(SnapshotContributor aContributor) { | |
238 } | |
239 | |
240 public Serializable[] getSnapshotContributions() { | |
241 return new Serializable[0]; | |
242 } | |
243 } | |
244 } |