1 5 package org.prevayler.implementation; 6 7 import java.io.IOException ; 8 import java.util.Date ; 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 _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 37 public PrevaylerImpl(SnapshotManager snapshotManager, TransactionPublisher transactionPublisher) throws IOException , ClassNotFoundException { 38 _snapshotManager = snapshotManager; 39 _prevalentSystem = _snapshotManager.recoveredPrevalentSystem(); 40 _systemVersion = _snapshotManager.recoveredVersion(); 41 42 _publisher = transactionPublisher; 43 _clock = _publisher.clock(); 44 45 _ignoreRuntimeExceptions = true; _publisher.addSubscriber(subscriber(), _systemVersion + 1); 47 _ignoreRuntimeExceptions = false; 48 } 49 50 51 public Object 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 execute(Query sensitiveQuery) throws Exception { 68 synchronized (_prevalentSystem) { 69 return sensitiveQuery.query(_prevalentSystem, clock().time()); 70 } 71 } 72 73 74 public Object execute(TransactionWithQuery transactionWithQuery) throws Exception { 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 { 83 synchronized (_prevalentSystem) { 84 _snapshotManager.writeSnapshot(_prevalentSystem, _systemVersion); 85 } 86 } 87 88 89 public void close() throws IOException { _publisher.close(); } 90 91 92 private Object deepCopy(Object transaction) { 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 executionTime) { 101 synchronized (_prevalentSystem) { 102 _systemVersion++; 103 try { 104 transaction.executeOn(_prevalentSystem, executionTime); 105 } catch (RuntimeException rx) { 106 if (!_ignoreRuntimeExceptions) throw rx; 107 } 108 } 109 } 110 111 }; 112 } 113 114 } 115 | Popular Tags |