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