comparison src/org/dancres/blitz/EntryTxnOp.java @ 0:3dc0c5604566

Initial checkin of blitz 2.0 fcs - no installer yet.
author Dan Creswell <dan.creswell@gmail.com>
date Sat, 21 Mar 2009 11:00:06 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:3dc0c5604566
1 package org.dancres.blitz;
2
3 import java.io.IOException;
4
5 import org.dancres.blitz.mangler.MangledEntry;
6
7 import org.dancres.blitz.entry.OpInfo;
8
9 import org.dancres.blitz.txn.TxnOp;
10 import org.dancres.blitz.txn.TxnState;
11
12 import org.dancres.blitz.txnlock.*;
13
14 import org.dancres.blitz.notify.QueueEvent;
15 import org.dancres.blitz.notify.EventQueue;
16
17 /**
18 Each operation against an Entry is represented by an instance of this class.
19 These are stored in <code>TxnState</code> instances and constitute part of
20 the record of operations performed by a particular transaction.
21
22 @see org.dancres.blitz.txn.TxnState
23
24 @todo As postEvent happens before txnlock is released one can get
25 temporary conflicts which could be alleviated if txnlock was released first
26 but to do this would mean needing a snapshot of txnlock state from before
27 the release was performed.
28 */
29 class EntryTxnOp implements TxnOp {
30 static final long serialVersionUID = -347168809827671347L;
31
32 /**
33 Required when we figure out what lock type to assert.
34 Lock is transient because it's a memory only structure so we will
35 have to recover it if necessary.
36 */
37 private int theOp;
38 private OpInfo theInfo;
39
40 private transient TxnLock theTxnLock;
41
42 EntryTxnOp(OpInfo anInfo) {
43 theInfo = anInfo;
44 }
45
46 EntryTxnOp(int anOp, OpInfo anInfo, TxnLock aLock) {
47 theOp = anOp;
48 theInfo = anInfo;
49 theTxnLock = aLock;
50 }
51
52 public void restore(TxnState aState) throws IOException {
53 if (theInfo.isDebugOp())
54 return;
55
56 theInfo.restore();
57
58 LockMgr myMgr = TxnLocks.getLockMgr(theInfo.getType());
59 theTxnLock = myMgr.getLock(theInfo.getOID());
60
61 synchronized(theTxnLock) {
62 theTxnLock.acquire(aState, theOp, null, null, true);
63 }
64 }
65
66 public void commit(TxnState aState) throws IOException {
67 if (theInfo.isDebugOp())
68 return;
69
70 MangledEntry myEntry = theInfo.commit(aState);
71
72 postEvent(aState, myEntry, true);
73
74 theTxnLock.release(aState, theOp);
75 }
76
77 public void abort(TxnState aState) throws IOException {
78 if (theInfo.isDebugOp())
79 return;
80
81 MangledEntry myEntry = theInfo.abort(aState);
82
83 postEvent(aState, myEntry, false);
84
85 theTxnLock.release(aState, theOp);
86 }
87
88 public String toString() {
89 return theInfo.toString();
90 }
91
92 private void postEvent(TxnState aState, MangledEntry anEntry,
93 boolean isCommit) {
94
95 // No Entry means no Event - if Entry is present, we then need to
96 // figure out whether or not we generate an event based on commit/abort
97 // and the kind of operation
98 if (anEntry == null)
99 return;
100
101 switch (theOp) {
102 case TxnLock.READ : {
103 if (theTxnLock.hasOnly(aState.getId(), TxnLock.READ)) {
104 // Entry still exists and we are the last outstanding
105 // read - which means we resolve a conflict
106 QueueEvent myEvent =
107 new QueueEvent(QueueEvent.ENTRY_NOT_CONFLICTED, aState,
108 new QueueEvent.Context(anEntry,
109 theInfo.getOID()));
110
111 EventQueue.get().add(myEvent);
112 }
113
114 break;
115 }
116
117 case TxnLock.DELETE : {
118 if (!isCommit) {
119 // We're aborting a take, if we wrote this Entry
120 // we shouldn't generate an Event
121 if (!theTxnLock.hasWriter(aState.getId())) {
122 QueueEvent myEvent =
123 new QueueEvent(QueueEvent.ENTRY_VISIBLE, aState,
124 new QueueEvent.Context(anEntry,
125 theInfo.getOID()));
126
127 EventQueue.get().add(myEvent);
128 }
129 }
130 break;
131 }
132
133 /**
134 * If we've been doing a write, the Entry is pinned and cannot
135 * be flushed from cache thus even if it becomes lease expired
136 * it will be present in cache when we query it.
137 */
138 case TxnLock.WRITE : {
139 if (isCommit) {
140 // If we're commiting a write, an Entry became visible
141 QueueEvent myEvent =
142 new QueueEvent(QueueEvent.ENTRY_WRITTEN,
143 aState,
144 new QueueEvent.Context(anEntry, theInfo.getOID()));
145 EventQueue.get().add(myEvent);
146 }
147 break;
148 }
149 }
150 }
151 }