KickJava   Java API By Example, From Geeks To Geeks.

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


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

8
9 package com.sleepycat.je.txn;
10
11 import com.sleepycat.je.Database;
12 import com.sleepycat.je.DatabaseException;
13 import com.sleepycat.je.DbInternal;
14 import com.sleepycat.je.Environment;
15 import com.sleepycat.je.Transaction;
16 import com.sleepycat.je.TransactionConfig;
17 import com.sleepycat.je.dbi.DatabaseImpl;
18 import com.sleepycat.je.dbi.EnvironmentImpl;
19
20 /**
21  * Factory of static methods for creating Locker objects.
22  */

23 public class LockerFactory {
24
25     /**
26      * Get a locker for a writable operation, checking whether the db and
27      * environment is transactional or not. Must return a non null locker.
28      */

29     public static Locker getWritableLocker(Environment env,
30                                            Transaction userTxn,
31                                            boolean dbIsTransactional)
32         throws DatabaseException {
33
34         return getWritableLocker(env, userTxn, dbIsTransactional, false, null);
35     }
36
37     /**
38      * Get a locker for a writable operation, also specifying whether to retain
39      * non-transactional locks when a new locker must be created.
40      *
41      * @param retainNonTxnLocks is true for DbTree operations, so that the
42      * handle lock may be transferred out of the locker when the operation is
43      * complete.
44      */

45     public static Locker getWritableLocker(Environment env,
46                                            Transaction userTxn,
47                                            boolean dbIsTransactional,
48                                            boolean retainNonTxnLocks,
49                                            TransactionConfig autoCommitConfig)
50         throws DatabaseException {
51
52         EnvironmentImpl envImpl = DbInternal.envGetEnvironmentImpl(env);
53         boolean envIsTransactional = envImpl.isTransactional();
54
55     if (userTxn == null) {
56         Transaction xaLocker = env.getThreadTransaction();
57         if (xaLocker != null) {
58         return DbInternal.getLocker(xaLocker);
59         }
60     }
61
62         if (dbIsTransactional && userTxn == null) {
63
64             if (autoCommitConfig == null) {
65                 autoCommitConfig = DbInternal.getDefaultTxnConfig(env);
66             }
67             return new AutoTxn(envImpl, autoCommitConfig);
68
69         } else if (userTxn == null) {
70
71             if (retainNonTxnLocks) {
72                 return new BasicLocker(envImpl);
73             } else {
74                 return new ThreadLocker(envImpl);
75             }
76
77         } else {
78
79             /*
80              * The user provided a transaction, the environment and the
81              * database had better be opened transactionally.
82              */

83             if (!envIsTransactional) {
84                 throw new DatabaseException
85             ("A Transaction cannot be used because the"+
86              " environment was opened" +
87              " non-transactionally");
88             }
89             if (!dbIsTransactional) {
90                 throw new DatabaseException
91             ("A Transaction cannot be used because the" +
92              " database was opened" +
93              " non-transactionally");
94             }
95
96             /*
97              * Use the locker for the given transaction. For read-comitted,
98              * wrap the given transactional locker in a special locker for that
99              * isolation level. But if retainNonTxnLocks we cannot use
100              * read-committed, since retainNonTxnLocks is used for handle locks
101              * that must be retained across operations.
102              */

103             Locker locker = DbInternal.getLocker(userTxn);
104             if (locker.isReadCommittedIsolation() && !retainNonTxnLocks) {
105                 return new ReadCommittedLocker(envImpl, locker);
106             } else {
107                 return locker;
108             }
109         }
110     }
111    
112     /**
113      * Get a locker for a read or cursor operation.
114      * See getWritableLocker for an explanation of retainNonTxnLocks.
115      */

116     public static Locker getReadableLocker(Environment env,
117                                            Transaction userTxn,
118                                            boolean dbIsTransactional,
119                                            boolean retainNonTxnLocks,
120                                            boolean readCommittedIsolation)
121         throws DatabaseException {
122
123         if (userTxn != null && !dbIsTransactional) {
124             throw new DatabaseException
125                 ("A Transaction cannot be used because the" +
126                  " database was opened" +
127                  " non-transactionally");
128         }
129
130         Locker locker = null;
131     if (userTxn != null) {
132
133             /*
134              * Use the locker for the given transaction. Request read-comitted
135              * if that isolation level is configured for the transaction, or if
136              * true is passed for the parameter (this is the case when
137              * read-committed is configured for the cursor).
138              */

139             locker = DbInternal.getLocker(userTxn);
140             if (locker.isReadCommittedIsolation()) {
141                 readCommittedIsolation = true;
142             }
143         }
144
145         return getReadableLocker
146         (env, locker, retainNonTxnLocks, readCommittedIsolation);
147     }
148
149     /**
150      * Get a locker for this database handle for a read or cursor operation.
151      * See getWritableLocker for an explanation of retainNonTxnLocks.
152      */

153     public static Locker getReadableLocker(Environment env,
154                                            Database dbHandle,
155                                            Locker locker,
156                                            boolean retainNonTxnLocks,
157                                            boolean readCommittedIsolation)
158         throws DatabaseException {
159         
160         DatabaseImpl dbImpl = DbInternal.dbGetDatabaseImpl(dbHandle);
161         if (!dbImpl.isTransactional() &&
162             locker != null &&
163             locker.isTransactional()) {
164             throw new DatabaseException
165                 ("A Transaction cannot be used because the" +
166                  " database was opened" +
167                  " non-transactionally");
168         }
169
170         /*
171          * Don't reuse a non-transactional locker unless retaining
172          * non-transactional locks was requested.
173          */

174         if (locker != null &&
175             !locker.isTransactional() &&
176             !retainNonTxnLocks) {
177             locker = null;
178         }
179
180         /*
181          * Request read-comitted if that isolation level is configured for the
182          * locker being reused, or if true is passed for the parameter (this is
183          * the case when read-committed is configured for the cursor).
184          */

185         if (locker != null && locker.isReadCommittedIsolation()) {
186             readCommittedIsolation = true;
187         }
188
189         return getReadableLocker
190             (env, locker, retainNonTxnLocks, readCommittedIsolation);
191     }
192
193     /**
194      * Get a locker for a read or cursor operation.
195      * See getWritableLocker for an explanation of retainNonTxnLocks.
196      */

197     private static Locker getReadableLocker(Environment env,
198                                             Locker locker,
199                                             boolean retainNonTxnLocks,
200                                             boolean readCommittedIsolation)
201         throws DatabaseException {
202
203         EnvironmentImpl envImpl = DbInternal.envGetEnvironmentImpl(env);
204
205     if (locker == null) {
206         Transaction xaTxn = env.getThreadTransaction();
207         if (xaTxn != null) {
208         return DbInternal.getLocker(xaTxn);
209         }
210     }
211
212         if (locker == null) {
213
214             /*
215              * A non-transactional locker is requested. If we're retaining
216              * non-transactional locks across operations, use a BasicLocker
217              * since the locker may be used across threads; this is used when
218              * acquiring handle locks internally (open, close, remove, etc).
219              * Otherwise, use a ThreadLocker to avoid self-deadlocks within the
220              * same thread; this used for ordinary user operations.
221              */

222             if (retainNonTxnLocks) {
223                 locker = new BasicLocker(envImpl);
224             } else {
225                 locker = new ThreadLocker(envImpl);
226             }
227         } else {
228
229             /*
230              * Use the given locker. For read-committed, wrap the given
231              * transactional locker in a special locker for that isolation
232              * level. But if retainNonTxnLocks we cannot use read-committed,
233              * since retainNonTxnLocks is used for handle locks that must be
234              * retained across operations.
235              */

236             if (readCommittedIsolation && !retainNonTxnLocks) {
237                 locker = new ReadCommittedLocker(envImpl, locker);
238             }
239         }
240         return locker;
241     }
242 }
243
Popular Tags