KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sleepycat > je > txn > TxnManager


1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 2002,2006 Oracle. All rights reserved.
5  *
6  * $Id: TxnManager.java,v 1.59 2006/10/30 21:14:27 bostic Exp $
7  */

8
9 package com.sleepycat.je.txn;
10
11 import java.util.Collections JavaDoc;
12 import java.util.HashMap JavaDoc;
13 import java.util.HashSet JavaDoc;
14 import java.util.Iterator JavaDoc;
15 import java.util.Map JavaDoc;
16 import java.util.Set JavaDoc;
17
18 import javax.transaction.xa.Xid JavaDoc;
19
20 import com.sleepycat.je.DatabaseException;
21 import com.sleepycat.je.LockStats;
22 import com.sleepycat.je.StatsConfig;
23 import com.sleepycat.je.Transaction;
24 import com.sleepycat.je.TransactionConfig;
25 import com.sleepycat.je.TransactionStats;
26 import com.sleepycat.je.dbi.EnvironmentImpl;
27 import com.sleepycat.je.dbi.MemoryBudget;
28 import com.sleepycat.je.latch.Latch;
29 import com.sleepycat.je.latch.LatchSupport;
30 import com.sleepycat.je.utilint.DbLsn;
31
32 /**
33  * Class to manage transactions. Basically a Set of all transactions with add
34  * and remove methods and a latch around the set.
35  */

36 public class TxnManager {
37
38     /*
39      * All NullTxns share the same id so as not to eat from the id number
40      * space.
41      */

42     static final long NULL_TXN_ID = -1;
43     private static final String JavaDoc DEBUG_NAME = TxnManager.class.getName();
44     
45     private LockManager lockManager;
46     private EnvironmentImpl env;
47     private Latch allTxnLatch;
48     private Set JavaDoc allTxns;
49     /* Maps Xids to Txns. */
50     private Map JavaDoc allXATxns;
51     /* Maps Threads to Txns when there are thread implied transactions. */
52     private Map JavaDoc thread2Txn;
53     private long lastUsedTxnId;
54     private int nActiveSerializable;
55     
56     /* Locker Stats */
57     private int numCommits;
58     private int numAborts;
59     private int numXAPrepares;
60     private int numXACommits;
61     private int numXAAborts;
62
63     public TxnManager(EnvironmentImpl env)
64         throws DatabaseException {
65
66         if (EnvironmentImpl.getFairLatches()) {
67             lockManager = new LatchedLockManager(env);
68         } else {
69         if (env.isNoLocking()) {
70         lockManager = new DummyLockManager(env);
71         } else {
72         lockManager = new SyncedLockManager(env);
73         }
74         }
75
76         this.env = env;
77         allTxns = new HashSet JavaDoc();
78         allTxnLatch = LatchSupport.makeLatch(DEBUG_NAME, env);
79         allXATxns = Collections.synchronizedMap(new HashMap JavaDoc());
80         thread2Txn = Collections.synchronizedMap(new HashMap JavaDoc());
81
82         numCommits = 0;
83         numAborts = 0;
84         numXAPrepares = 0;
85         numXACommits = 0;
86         numXAAborts = 0;
87         lastUsedTxnId = 0;
88     }
89
90     /**
91      * Set the txn id sequence.
92      */

93     synchronized public void setLastTxnId(long lastId) {
94         this.lastUsedTxnId = lastId;
95     }
96
97     /**
98      * Get the last used id, for checkpoint info.
99      */

100     public synchronized long getLastTxnId() {
101         return lastUsedTxnId;
102     }
103
104     /**
105      * Get the next transaction id to use.
106      */

107     synchronized long incTxnId() {
108         return ++lastUsedTxnId;
109     }
110     
111     /**
112      * Create a new transaction.
113      * @param parent for nested transactions, not yet supported
114      * @param txnConfig specifies txn attributes
115      * @return the new txn
116      */

117     public Txn txnBegin(Transaction parent, TransactionConfig txnConfig)
118         throws DatabaseException {
119
120         if (parent != null) {
121             throw new DatabaseException
122         ("Nested transactions are not supported yet.");
123         }
124         
125         return new Txn(env, txnConfig);
126     }
127
128     /**
129      * Give transactions and environment access to lock manager.
130      */

131     public LockManager getLockManager() {
132         return lockManager;
133     }
134
135     /**
136      * Called when txn is created.
137      */

138     void registerTxn(Txn txn)
139         throws DatabaseException {
140
141         allTxnLatch.acquire();
142         allTxns.add(txn);
143         if (txn.isSerializableIsolation()) {
144             nActiveSerializable++;
145         }
146         allTxnLatch.release();
147     }
148
149     /**
150      * Called when txn ends.
151      */

152     void unRegisterTxn(Txn txn, boolean isCommit)
153         throws DatabaseException {
154
155         allTxnLatch.acquire();
156     try {
157         allTxns.remove(txn);
158         /* Remove any accumulated MemoryBudget delta for the Txn. */
159         env.getMemoryBudget().
160         updateMiscMemoryUsage(txn.getAccumulatedDelta() -
161                       txn.getInMemorySize());
162         if (isCommit) {
163         numCommits++;
164         } else {
165         numAborts++;
166         }
167         if (txn.isSerializableIsolation()) {
168         nActiveSerializable--;
169         }
170     } finally {
171         allTxnLatch.release();
172     }
173     }
174
175     /**
176      * Called when txn is created.
177      */

178     public void registerXATxn(Xid JavaDoc xid, Txn txn, boolean isPrepare)
179         throws DatabaseException {
180
181     if (!allXATxns.containsKey(xid)) {
182         allXATxns.put(xid, txn);
183         env.getMemoryBudget().updateMiscMemoryUsage
184         (MemoryBudget.HASHMAP_ENTRY_OVERHEAD);
185     }
186
187     if (isPrepare) {
188         numXAPrepares++;
189     }
190     }
191
192     /**
193      * Called when txn ends.
194      */

195     void unRegisterXATxn(Xid JavaDoc xid, boolean isCommit)
196         throws DatabaseException {
197
198     if (allXATxns.remove(xid) == null) {
199         throw new DatabaseException
200         ("XA Transaction " + xid +
201          " can not be unregistered.");
202     }
203     env.getMemoryBudget().updateMiscMemoryUsage
204         (0 - MemoryBudget.HASHMAP_ENTRY_OVERHEAD);
205     if (isCommit) {
206         numXACommits++;
207     } else {
208         numXAAborts++;
209     }
210     }
211
212     /**
213      * Retrieve a Txn object from an Xid.
214      */

215     public Txn getTxnFromXid(Xid JavaDoc xid)
216     throws DatabaseException {
217
218     return (Txn) allXATxns.get(xid);
219     }
220
221     /**
222      * Called when txn is assoc'd with this thread.
223      */

224     public void setTxnForThread(Transaction txn) {
225
226     Thread JavaDoc curThread = Thread.currentThread();
227     thread2Txn.put(curThread, txn);
228     }
229
230     /**
231      * Called when txn is assoc'd with this thread.
232      */

233     public Transaction unsetTxnForThread()
234         throws DatabaseException {
235
236     Thread JavaDoc curThread = Thread.currentThread();
237     return (Transaction) thread2Txn.remove(curThread);
238     }
239
240     /**
241      * Retrieve a Txn object for this Thread.
242      */

243     public Transaction getTxnForThread()
244     throws DatabaseException {
245
246     return (Transaction) thread2Txn.get(Thread.currentThread());
247     }
248
249     public Xid JavaDoc[] XARecover()
250     throws DatabaseException {
251
252     Set JavaDoc xidSet = allXATxns.keySet();
253     Xid JavaDoc[] ret = new Xid JavaDoc[xidSet.size()];
254     ret = (Xid JavaDoc[]) xidSet.toArray(ret);
255
256     return ret;
257     }
258
259     /**
260      * Returns whether there are any active serializable transactions,
261      * excluding the transaction given (if non-null). This is intentionally
262      * returned without latching, since latching would not make the act of
263      * reading an integer more atomic than it already is.
264      */

265     public boolean
266         areOtherSerializableTransactionsActive(Locker excludeLocker) {
267         int exclude =
268             (excludeLocker != null &&
269              excludeLocker.isSerializableIsolation()) ?
270             1 : 0;
271         return (nActiveSerializable - exclude > 0);
272     }
273
274     /**
275      * Get the earliest LSN of all the active transactions, for checkpoint.
276      */

277     public long getFirstActiveLsn()
278         throws DatabaseException {
279
280         /*
281          * Note that the latching hierarchy calls for getting allTxnLatch
282          * first, then synchronizing on individual txns.
283          */

284     long firstActive = DbLsn.NULL_LSN;
285         allTxnLatch.acquire();
286     try {
287         Iterator JavaDoc iter = allTxns.iterator();
288         while(iter.hasNext()) {
289         long txnFirstActive = ((Txn) iter.next()).getFirstActiveLsn();
290         if (firstActive == DbLsn.NULL_LSN) {
291             firstActive = txnFirstActive;
292         } else if (txnFirstActive != DbLsn.NULL_LSN) {
293             if (DbLsn.compareTo(txnFirstActive, firstActive) < 0) {
294             firstActive = txnFirstActive;
295             }
296         }
297         }
298     } finally {
299         allTxnLatch.release();
300     }
301         return firstActive;
302     }
303
304     /*
305      * Statistics
306      */

307
308     /**
309      * Collect transaction related stats.
310      */

311     public TransactionStats txnStat(StatsConfig config)
312         throws DatabaseException {
313
314         TransactionStats stats = new TransactionStats();
315         allTxnLatch.acquire();
316     try {
317         stats.setNCommits(numCommits);
318         stats.setNAborts(numAborts);
319         stats.setNXAPrepares(numXAPrepares);
320         stats.setNXACommits(numXACommits);
321         stats.setNXAAborts(numXAAborts);
322         stats.setNActive(allTxns.size());
323         TransactionStats.Active[] activeSet =
324         new TransactionStats.Active[stats.getNActive()];
325         stats.setActiveTxns(activeSet);
326         Iterator JavaDoc iter = allTxns.iterator();
327         int i = 0;
328         while (iter.hasNext()) {
329         Locker txn = (Locker) iter.next();
330         activeSet[i] = new TransactionStats.Active
331             (txn.toString(), txn.getId(), 0);
332         i++;
333         }
334         if (config.getClear()) {
335         numCommits = 0;
336         numAborts = 0;
337         numXACommits = 0;
338         numXAAborts = 0;
339         }
340     } finally {
341         allTxnLatch.release();
342     }
343         return stats;
344     }
345
346     /**
347      * Collect lock related stats.
348      */

349     public LockStats lockStat(StatsConfig config)
350         throws DatabaseException {
351
352         return lockManager.lockStat(config);
353     }
354 }
355
Popular Tags