Mercurial > hg > blitz_condensed
comparison src/org/dancres/blitz/remote/txn/LoopBackMgr.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.remote.txn; | |
2 | |
3 import java.rmi.RemoteException; | |
4 import java.util.HashMap; | |
5 import java.util.logging.Logger; | |
6 import java.util.logging.Level; | |
7 | |
8 import net.jini.core.transaction.server.ServerTransaction; | |
9 import net.jini.core.transaction.server.TransactionManager; | |
10 import net.jini.core.transaction.*; | |
11 import net.jini.core.lease.LeaseDeniedException; | |
12 import net.jini.config.ConfigurationException; | |
13 | |
14 import org.dancres.blitz.txn.TxnManager; | |
15 import org.dancres.blitz.txn.TxnState; | |
16 import org.dancres.blitz.util.Time; | |
17 import org.dancres.blitz.lease.LeaseBounds; | |
18 import org.dancres.blitz.lease.Reapable; | |
19 import org.dancres.blitz.lease.ReapFilter; | |
20 import org.dancres.blitz.lease.LeaseReaper; | |
21 import org.dancres.blitz.Logging; | |
22 import org.dancres.blitz.config.ConfigurationFactory; | |
23 | |
24 /** | |
25 */ | |
26 public class LoopBackMgr implements Reapable { | |
27 | |
28 private static Logger theLogger = | |
29 Logging.newLogger("org.dancres.blitz.remote.txn.LoopBackMgr"); | |
30 | |
31 /** | |
32 * This will need updating based on reading the log or reading | |
33 * from checkpoint or both! NO IT WON'T we simply won't log these - they | |
34 * either complete or they don't - they're one operation wonders which | |
35 * don't need logging. | |
36 */ | |
37 private long theNextKey = 0; | |
38 private long theMagic = System.currentTimeMillis(); | |
39 | |
40 private LeaseReaper theReaper; | |
41 | |
42 /** | |
43 * Keeps track of transactions we have active in the core. We hold lease | |
44 * state here. | |
45 */ | |
46 private HashMap theActiveTxns = new HashMap(); | |
47 | |
48 private TransactionManager theStub; | |
49 | |
50 private static LoopBackMgr theMgr; | |
51 | |
52 static void init(TransactionManager aStub) { | |
53 theMgr = new LoopBackMgr(aStub); | |
54 } | |
55 | |
56 static LoopBackMgr get() { | |
57 return theMgr; | |
58 } | |
59 | |
60 private LoopBackMgr(TransactionManager aStub) { | |
61 try { | |
62 long myReapInterval = | |
63 ((Long) ConfigurationFactory.getEntry("loopbackTxnReapInterval", | |
64 long.class, | |
65 new Long(5 * 60 * 1000))).longValue(); | |
66 theReaper = new LeaseReaper("LoopbackTxn", null, myReapInterval); | |
67 | |
68 theReaper.add(this); | |
69 | |
70 } catch (ConfigurationException aCE) { | |
71 theLogger.log(Level.SEVERE, "Failed to load config", aCE); | |
72 } | |
73 | |
74 theStub = aStub; | |
75 } | |
76 | |
77 private long nextId() { | |
78 synchronized (this) { | |
79 return theNextKey++; | |
80 } | |
81 } | |
82 | |
83 public TxnTicket create(long aLeaseTime) | |
84 throws LeaseDeniedException, RemoteException { | |
85 | |
86 long myLeaseTime = | |
87 Time.getAbsoluteTime(LeaseBounds.boundTxn(aLeaseTime)); | |
88 | |
89 long myId = nextId(); | |
90 | |
91 SpaceTxnUID myUID = new SpaceTxnUID(myId, theMagic); | |
92 | |
93 TxnDetails myDetails = new TxnDetails(myLeaseTime); | |
94 | |
95 ServerTransaction myTxn = new ServerTransaction(theStub, myId); | |
96 | |
97 try { | |
98 // Insert the transaction | |
99 // | |
100 TxnManager.get().getTxnFor(myTxn, false); | |
101 } catch (Exception anE) { | |
102 theLogger.log(Level.SEVERE, "Failed to allocate loopback txn", anE); | |
103 throw new LeaseDeniedException("Couldn't allocate txn"); | |
104 } | |
105 | |
106 synchronized(this) { | |
107 theActiveTxns.put(myUID, myDetails); | |
108 } | |
109 | |
110 return new TxnTicket(myUID, myLeaseTime); | |
111 } | |
112 | |
113 private SpaceTxnUID validateTxn(long anId) | |
114 throws UnknownTransactionException { | |
115 | |
116 SpaceTxnUID myUID = new SpaceTxnUID(anId, theMagic); | |
117 | |
118 synchronized (this) { | |
119 TxnDetails myDetails = (TxnDetails) theActiveTxns.get(myUID); | |
120 | |
121 if ((myDetails == null) || | |
122 (myDetails.hasExpired(System.currentTimeMillis()))) | |
123 throw new UnknownTransactionException(); | |
124 } | |
125 | |
126 return myUID; | |
127 } | |
128 | |
129 public void commit(long id) | |
130 throws UnknownTransactionException, CannotCommitException, | |
131 RemoteException { | |
132 | |
133 SpaceTxnUID myUID = validateTxn(id); | |
134 | |
135 TxnManager myMgr = TxnManager.get(); | |
136 | |
137 TxnState myState = myMgr.getTxnFor(theStub, id); | |
138 | |
139 try { | |
140 myMgr.prepareAndCommit(myState); | |
141 } finally { | |
142 synchronized (this) { | |
143 theActiveTxns.remove(myUID); | |
144 } | |
145 } | |
146 } | |
147 | |
148 public void commit(long id, long waitFor) | |
149 throws UnknownTransactionException, CannotCommitException, | |
150 TimeoutExpiredException, RemoteException { | |
151 | |
152 commit(id); | |
153 } | |
154 | |
155 public void abort(long id) | |
156 throws UnknownTransactionException, CannotAbortException, | |
157 RemoteException { | |
158 | |
159 SpaceTxnUID myUID = validateTxn(id); | |
160 | |
161 TxnManager myMgr = TxnManager.get(); | |
162 | |
163 TxnState myState = myMgr.getTxnFor(theStub, id); | |
164 | |
165 try { | |
166 myMgr.abort(myState); | |
167 } finally { | |
168 synchronized(this) { | |
169 theActiveTxns.remove(myUID); | |
170 } | |
171 } | |
172 } | |
173 | |
174 public void abort(long id, long waitFor) | |
175 throws UnknownTransactionException, CannotAbortException, | |
176 TimeoutExpiredException, RemoteException { | |
177 | |
178 abort(id); | |
179 } | |
180 | |
181 boolean renew(SpaceTxnUID aUID, long anExpiry) { | |
182 synchronized (this) { | |
183 TxnDetails myHolder = (TxnDetails) theActiveTxns.get(aUID); | |
184 | |
185 if (myHolder != null) { | |
186 return myHolder.testAndSetExpiry(System.currentTimeMillis(), | |
187 anExpiry); | |
188 } | |
189 | |
190 return false; | |
191 } | |
192 } | |
193 | |
194 boolean cancel(SpaceTxnUID aUID) { | |
195 return (delete(aUID) != null); | |
196 } | |
197 | |
198 | |
199 public TxnDetails delete(SpaceTxnUID aUID) { | |
200 | |
201 synchronized (this) { | |
202 TxnDetails myHolder = (TxnDetails) theActiveTxns.remove(aUID); | |
203 | |
204 if (myHolder != null) { | |
205 try { | |
206 TxnState myState = | |
207 TxnManager.get().getTxnFor(theStub, aUID.getId()); | |
208 | |
209 TxnManager.get().abort(myState); | |
210 } catch (Exception anE) { | |
211 // Nothing we cn do | |
212 } | |
213 | |
214 return myHolder; | |
215 } | |
216 | |
217 return null; | |
218 } | |
219 } | |
220 | |
221 public void reap(ReapFilter aFilter) { | |
222 /* | |
223 No reap filters will be configured so we can ignore those - see | |
224 initialization in constructor | |
225 */ | |
226 long myTime = System.currentTimeMillis(); | |
227 | |
228 Object[] myKeys; | |
229 | |
230 synchronized (this) { | |
231 myKeys = theActiveTxns.keySet().toArray(); | |
232 } | |
233 | |
234 for (int i = 0; i < myKeys.length; i++) { | |
235 TxnDetails myHolder = | |
236 (TxnDetails) theActiveTxns.get(myKeys[i]); | |
237 | |
238 if (myHolder.hasExpired(myTime)) { | |
239 delete((SpaceTxnUID) myKeys[i]); | |
240 } | |
241 } | |
242 } | |
243 | |
244 public String toString() { | |
245 return "LoopBackMgr"; | |
246 } | |
247 | |
248 public int hashCode() { | |
249 return 4095; | |
250 } | |
251 | |
252 public boolean equals(Object anObject) { | |
253 if (anObject instanceof LoopBackMgr) | |
254 return true; | |
255 else | |
256 return false; | |
257 } | |
258 } |