comparison src/org/dancres/blitz/EntryViewImpl.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 net.jini.core.transaction.Transaction;
6 import net.jini.core.transaction.TransactionException;
7 import net.jini.core.transaction.UnknownTransactionException;
8
9 import org.dancres.blitz.entry.*;
10 import org.dancres.blitz.mangler.MangledEntry;
11 import org.dancres.blitz.txn.TxnManager;
12 import org.dancres.blitz.txn.TxnState;
13 import org.dancres.blitz.txnlock.LockMgr;
14 import org.dancres.blitz.txnlock.TxnLock;
15 import org.dancres.blitz.txnlock.TxnLocks;
16 import org.dancres.blitz.notify.EventQueue;
17
18 /**
19 <p>This class supports both iteration using the old JavaSpaceAdmin interface
20 and the new JavaSpace05 interface. The key differences amount to the
21 the number of templates that can be passed and whether or not locks are
22 held on the transaction.</p>
23
24 <p>For JavaSpace05, there are multiple templates and we hold locks on the
25 transaction.</p>
26 */
27 class EntryViewImpl implements EntryView {
28 private TxnState theTxn;
29
30 private TransactionException theException;
31 private int theStatus = ACTIVE;
32
33 private static final int ACTIVE = -1;
34 private static final int DECEASED = -2;
35
36 private UIDSet theUIDs;
37
38 private NewView theDynamicView;
39
40 private EntryRx theBuffer;
41
42 private boolean shouldUpdate;
43
44 EntryViewImpl(Transaction aTxn, MangledEntry[] aTemplates,
45 boolean holdLocks, boolean doUpdate, long aLimit)
46 throws TransactionException, IOException {
47
48 shouldUpdate = doUpdate;
49
50 theTxn = TxnManager.get().resolve(aTxn);
51
52 /*
53 Basic process is to assemble a set of fully matching Entry UID's which we
54 then step through ascertaining whether these UID's are still valid and possibly
55 asserting locks transactionally.
56
57 Full matching is done in each view and the matching tuples are then
58 logged/merged in the UIDSet
59
60 These tuple ids are then scanned through using EntryReposImpl::find to load
61 the entry, verify it's valid etc after which we may or may not maintain a
62 transaction lock (these steps are done in EntryRx).
63 */
64 theUIDs = new UIDSet(aLimit);
65
66 theBuffer = new EntryRx(theTxn, holdLocks);
67 theDynamicView = new NewView(this, aTemplates, theUIDs);
68
69 if (shouldUpdate)
70 EventQueue.get().insert(theDynamicView.getSearchTask());
71
72 /*
73 For each template do a full tree search and assemble all matches
74 */
75 for (int i = 0; i < aTemplates.length; i++) {
76 if (theUIDs.isFull())
77 break;
78
79 DiskView myFixedView = new DiskView(aTemplates[i], theUIDs);
80
81 EntryRepository myRepos =
82 EntryRepositoryFactory.get().find(aTemplates[i].getType());
83
84 if (myRepos != null) {
85 myRepos.find(aTemplates[i], myFixedView);
86
87 // Try subtypes
88 String[] mySubtypes = myRepos.getSubtypes();
89
90 for (int j = 0; j < mySubtypes.length; j++) {
91 myRepos = EntryRepositoryFactory.get().find(mySubtypes[j]);
92
93 if (myRepos != null) {
94 myRepos.find(aTemplates[i], myFixedView);
95 }
96 }
97 }
98 }
99 }
100
101 TxnState getTxn() {
102 return theTxn;
103 }
104
105 void resolved() {
106 setStatus(DECEASED,
107 new TransactionException(
108 "Transaction closed with view active"));
109 }
110
111 private void setStatus(int aStatus, TransactionException aTE) {
112 // Make sure we only do this once
113 //
114 synchronized(this) {
115 if (theStatus == DECEASED)
116 return;
117
118 theStatus = aStatus;
119 theException = aTE;
120 }
121
122 if (shouldUpdate)
123 theDynamicView.getSearchTask().taint();
124
125 if (theTxn.isNull()) {
126 try {
127 TxnManager.get().prepareAndCommit(theTxn);
128 } catch (UnknownTransactionException aUTE) {
129 /*
130 Don't care much...if we got here, we're defining state
131 and everyone else will fail at the status test above
132 */
133 synchronized(this) {
134 theException = aUTE;
135 }
136 }
137 }
138 }
139
140 public void close() {
141 setStatus(DECEASED, null);
142 }
143
144 public EntryChit next() throws TransactionException, IOException {
145 synchronized(this) {
146 if (theStatus == DECEASED) {
147 if (theException != null)
148 throw theException;
149 else
150 throw new TransactionException("No longer active");
151 }
152 }
153
154 SpaceEntryUID myUID;
155
156 while ((myUID = theUIDs.pop()) != null) {
157 EntryRepository myRepos =
158 EntryRepositoryFactory.get().get(myUID.getType());
159
160 myRepos.find(theBuffer, myUID.getOID(), null);
161
162 MangledEntry myEntry = theBuffer.getEntry();
163
164 if (myEntry != null)
165 return new EntryChit(myEntry, myUID);
166 }
167
168 return null;
169 }
170
171 /**
172 Used to receive the entry requested by id from the EntryRepository
173 It performs the appropriate locking checks and updates the transaction
174 if we're holding locks
175 */
176 private static class EntryRx implements SearchVisitor {
177 private MangledEntry theEntry;
178
179 private TxnState theTxn;
180 private boolean keepLock;
181
182 private TransactionException theFailure;
183
184 EntryRx(TxnState aTxn, boolean holdLock) {
185 theTxn = aTxn;
186 keepLock = holdLock;
187 }
188
189 public int offer(SearchOffer anOffer) {
190 OpInfo myInfo = anOffer.getInfo();
191
192 // Try the lock
193 LockMgr myMgr = TxnLocks.getLockMgr(myInfo.getType());
194 TxnLock myLock = myMgr.getLock(myInfo.getOID());
195
196 int myResult;
197
198 synchronized(myLock) {
199 myResult = myLock.acquire(theTxn, TxnLock.READ,
200 null, null, false);
201 }
202
203 if (myResult == TxnLock.SUCCESS) {
204 if (keepLock) {
205 /*
206 Need to track the lock under the transaction
207 */
208 try {
209 theTxn.add(new EntryTxnOp(TxnLock.READ, myInfo,
210 myLock));
211 } catch (TransactionException aTE) {
212 myLock.release(theTxn, TxnLock.READ);
213 theFailure = aTE;
214 return STOP;
215 }
216 } else {
217 /*
218 No need to track this lock, we were just testing so
219 we can release it now
220 */
221 myLock.release(theTxn, TxnLock.READ);
222 }
223
224 theEntry = anOffer.getEntry();
225 }
226
227 return STOP;
228 }
229
230 public boolean isDeleter() {
231 return false;
232 }
233
234 MangledEntry getEntry() throws TransactionException {
235 /*
236 If we're running under an external (non-null) transaction
237 we may have failed whilst attempting to lock (we would have
238 failed to record the lock in the transaction).
239 */
240 if (theFailure != null)
241 throw theFailure;
242
243 MangledEntry myResult = theEntry;
244 theEntry = null;
245
246 return myResult;
247 }
248 }
249 }