Mercurial > hg > blitz_condensed
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 } |