KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > prevayler > implementation > PrevaylerImpl


1 //Prevayler(TM) - The Free-Software Prevalence Layer.
2
//Copyright (C) 2001-2003 Klaus Wuestefeld
3
//This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
4

5 package org.prevayler.implementation;
6
7 import java.io.IOException JavaDoc;
8 import java.util.Date JavaDoc;
9
10 import org.prevayler.Clock;
11 import org.prevayler.Prevayler;
12 import org.prevayler.Query;
13 import org.prevayler.Transaction;
14 import org.prevayler.TransactionWithQuery;
15 import org.prevayler.implementation.publishing.TransactionPublisher;
16 import org.prevayler.implementation.publishing.TransactionSubscriber;
17 import org.prevayler.implementation.snapshot.SnapshotManager;
18
19
20 public class PrevaylerImpl implements Prevayler {
21
22     private final Object JavaDoc _prevalentSystem;
23     private long _systemVersion = 0;
24
25     private final Clock _clock;
26
27     private final SnapshotManager _snapshotManager;
28
29     private final TransactionPublisher _publisher;
30     private boolean _ignoreRuntimeExceptions;
31
32
33     /** Creates a new Prevayler
34      * @param snapshotManager The SnapshotManager that will be used for reading and writing snapshot files.
35      * @param transactionPublisher The TransactionPublisher that will be used for publishing transactions executed with this PrevaylerImpl.
36      */

37     public PrevaylerImpl(SnapshotManager snapshotManager, TransactionPublisher transactionPublisher) throws IOException JavaDoc, ClassNotFoundException JavaDoc {
38         _snapshotManager = snapshotManager;
39         _prevalentSystem = _snapshotManager.recoveredPrevalentSystem();
40         _systemVersion = _snapshotManager.recoveredVersion();
41
42         _publisher = transactionPublisher;
43         _clock = _publisher.clock();
44
45         _ignoreRuntimeExceptions = true; //During pending transaction recovery (rolling forward), RuntimeExceptions are ignored because they were already thrown and handled during the first transaction execution.
46
_publisher.addSubscriber(subscriber(), _systemVersion + 1);
47         _ignoreRuntimeExceptions = false;
48     }
49
50
51     public Object JavaDoc prevalentSystem() { return _prevalentSystem; }
52
53
54     public Clock clock() { return _clock; }
55
56
57     public void execute(Transaction transaction) {
58         publish((Transaction)deepCopy(transaction));
59     }
60
61
62     private void publish(Transaction transaction) {
63         _publisher.publish(transaction);
64     }
65
66
67     public Object JavaDoc execute(Query sensitiveQuery) throws Exception JavaDoc {
68         synchronized (_prevalentSystem) {
69             return sensitiveQuery.query(_prevalentSystem, clock().time());
70         }
71     }
72
73
74     public Object JavaDoc execute(TransactionWithQuery transactionWithQuery) throws Exception JavaDoc {
75         TransactionWithQuery copy = (TransactionWithQuery)deepCopy(transactionWithQuery);
76         TransactionWithQueryExecuter executer = new TransactionWithQueryExecuter(copy);
77         publish(executer);
78         return executer.result();
79     }
80
81
82     public void takeSnapshot() throws IOException JavaDoc {
83         synchronized (_prevalentSystem) {
84             _snapshotManager.writeSnapshot(_prevalentSystem, _systemVersion);
85         }
86     }
87
88
89     public void close() throws IOException JavaDoc { _publisher.close(); }
90
91
92     private Object JavaDoc deepCopy(Object JavaDoc transaction) { //TODO Optimizations: 1) Publish the byte array of the serialized transaction (this will save the Censor and the Logger from having to serialize the transaction again). This is also a step towards transaction multiplexing (useful to avoid hickups due to very large transactions). The Censor can use the actual given transaction if it is Immutable instead of deserializing a new one from the byte array. 2) Make the baptism fail-fast feature optional (default is on). If it is off, the given transaction can be used instead of deserializing a new one from the byte array.
93
return _snapshotManager.deepCopy(transaction, "Unable to produce a deep copy of the transaction. Deep copies of transactions are executed instead of the transactions themselves so that the behaviour of the system during transaction execution is exactly the same as during transaction recovery from the log.");
94     }
95
96
97     private TransactionSubscriber subscriber() {
98         return new TransactionSubscriber() {
99     
100             public void receive(Transaction transaction, Date JavaDoc executionTime) {
101                 synchronized (_prevalentSystem) {
102                     _systemVersion++;
103                     try {
104                         transaction.executeOn(_prevalentSystem, executionTime);
105                     } catch (RuntimeException JavaDoc rx) {
106                         if (!_ignoreRuntimeExceptions) throw rx;
107                     }
108                 }
109             }
110     
111         };
112     }
113
114 }
115
Popular Tags