comparison src/org/dancres/blitz/txn/TxnId.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.txn;
2
3 import java.io.Serializable;
4 import java.io.IOException;
5
6 import java.rmi.RemoteException;
7 import java.rmi.MarshalledObject;
8
9 import java.util.Map;
10 import java.util.HashMap;
11
12 import net.jini.security.ProxyPreparer;
13
14 import net.jini.core.transaction.server.TransactionManager;
15 import net.jini.core.transaction.TransactionException;
16
17 import net.jini.config.ConfigurationException;
18
19 import org.dancres.blitz.entry.OpInfo;
20
21 import org.dancres.blitz.config.ConfigurationFactory;
22
23 /**
24 <p> A reference to transactional state being held within the transaction
25 manager. </p>
26
27 <p> This class uses txnPreparer to do initial preparation of the
28 passed RemoteEventListener when constructed from scratch (i.e. it's a new
29 registration). It uses recoveredTxnPreparer in those cases where it
30 has been de-serialized from storage and is about to be used for the first
31 time post a restart </p>
32 */
33 public final class TxnId implements Serializable {
34 private static final ProxyPreparer RECOVERY_PREPARER;
35 private static final ProxyPreparer PREPARER;
36
37 static {
38 try {
39 RECOVERY_PREPARER =
40 ConfigurationFactory.getPreparer("recoveredTxnPreparer");
41
42 PREPARER =
43 ConfigurationFactory.getPreparer("txnPreparer");
44 } catch (ConfigurationException aCE) {
45 throw new RuntimeException("TxnId has problems with preparers",
46 aCE);
47 }
48 }
49
50 private MarshalledObject theMarshalledMgr;
51 private long theId;
52
53 private transient TransactionManager theManager;
54 private transient boolean isPrepared;
55
56 private static final LocalTxnManager LOCAL_TXN_MGR =
57 new LocalTxnManager();
58
59 private static final Map theMarshalledTxnMgrCache = new HashMap();
60
61 /**
62 Repeatedly marshalling the same txn mgr for writing to disk and
63 such like is costly so we marshall them once and then cache them
64 forever on the basis that we'll never see enough transaction manager
65 refs to make the memory consumption substantial
66
67 @todo Broken references may be a problem....
68 */
69 private static MarshalledObject getMarshalledMgr(TransactionManager aMgr)
70 throws RemoteException {
71
72 try {
73 synchronized(theMarshalledTxnMgrCache) {
74 MarshalledObject myMarshalledMgr =
75 (MarshalledObject) theMarshalledTxnMgrCache.get(aMgr);
76
77 if (myMarshalledMgr == null) {
78 myMarshalledMgr = new MarshalledObject(aMgr);
79 theMarshalledTxnMgrCache.put(aMgr, myMarshalledMgr);
80 }
81
82 return myMarshalledMgr;
83 }
84 } catch (IOException anIOE) {
85 throw new RemoteException("Failed to marshall txnmgr", anIOE);
86 }
87
88 }
89
90 static TxnId newNullTxn() throws RemoteException {
91 return new TxnId(LOCAL_TXN_MGR.nextId());
92 }
93
94 /**
95 Only to be used for local(null) transactions. That's because we do
96 no preparation on the txn manager reference (there's no point).
97 */
98 private TxnId(long anId) throws RemoteException {
99 theManager = LOCAL_TXN_MGR;
100 theMarshalledMgr = null;
101 isPrepared = true;
102 theId = anId;
103 }
104
105 /**
106 Use this for transactions which have a remote transaction manager
107 */
108 TxnId(TransactionManager aMgr, long anId) throws RemoteException {
109 theId = anId;
110
111 theManager = (TransactionManager) PREPARER.prepareProxy(aMgr);
112
113 theMarshalledMgr = getMarshalledMgr(aMgr);
114
115 isPrepared = true;
116 }
117
118 boolean isNull() {
119 try {
120 return (getManager() instanceof LocalTxnManager);
121 } catch (RemoteException anRE) {
122 // This will only happen if we've tried to unpack a remote
123 // object reference which implicitly means it's not null
124 //
125 return false;
126 }
127 }
128
129 public synchronized TransactionManager getManager()
130 throws RemoteException {
131
132 // This flag is only set in the constructor for non-null txns or by us.
133 if (!isPrepared) {
134 Object myManager = null;
135
136 try {
137 // Only null if it was a local txn mgr.....
138 //
139 if (theMarshalledMgr == null)
140 myManager = LOCAL_TXN_MGR;
141 else {
142 myManager = theMarshalledMgr.get();
143 myManager = RECOVERY_PREPARER.prepareProxy(myManager);
144 }
145 } catch (IOException anIOE) {
146 throw new RemoteException("Failed to unmarshall txnmgr",
147 anIOE);
148 } catch (ClassNotFoundException aCNFE) {
149 throw new RemoteException("Failed to unmarshall txnmgr",
150 aCNFE);
151 }
152
153 theManager = (TransactionManager) myManager;
154 isPrepared = true;
155 }
156
157 return theManager;
158 }
159
160 public long getId() {
161 return theId;
162 }
163
164 public String toString() {
165 try {
166 return getManager() + "->" + theId;
167 } catch (RemoteException anRE) {
168 return "Broken_Codebase->" + theId;
169 }
170 }
171
172 public boolean equals(Object anObject) {
173 if (anObject instanceof TxnId) {
174 TxnId myOther = (TxnId) anObject;
175
176 if (myOther.theId != theId)
177 return false;
178
179 try {
180 TransactionManager myMgr = getManager();
181 TransactionManager myOtherMgr = myOther.getManager();
182
183 return myMgr.equals(myOtherMgr);
184 } catch (RemoteException anRE) {
185 // Likely to happen if codebase of txnmgr ref is broken
186 return false;
187 }
188 }
189
190 return false;
191 }
192
193 public int hashCode() {
194 return (int) (theId ^ (theId >>> 32));
195 }
196 }
197