1 8 9 package com.sleepycat.collections; 10 11 import java.util.ArrayList ; 12 import java.util.List ; 13 import java.util.WeakHashMap ; 14 15 import com.sleepycat.compat.DbCompat; 16 import com.sleepycat.je.Cursor; 17 import com.sleepycat.je.CursorConfig; 18 import com.sleepycat.je.Database; 19 import com.sleepycat.je.DatabaseException; 20 import com.sleepycat.je.Environment; 21 import com.sleepycat.je.EnvironmentConfig; 22 import com.sleepycat.je.LockMode; 23 import com.sleepycat.je.Transaction; 24 import com.sleepycat.je.TransactionConfig; 25 import com.sleepycat.util.RuntimeExceptionWrapper; 26 27 36 public class CurrentTransaction { 37 38 39 40 private static WeakHashMap envMap = new WeakHashMap (); 41 42 private LockMode writeLockMode; 43 private boolean cdbMode; 44 private boolean txnMode; 45 private boolean lockingMode; 46 private Environment env; 47 private ThreadLocal localTrans = new ThreadLocal (); 48 private ThreadLocal localCdbCursors; 49 50 60 public static CurrentTransaction getInstance(Environment env) { 61 62 CurrentTransaction currentTxn = getInstanceInternal(env); 63 return currentTxn.isTxnMode() ? currentTxn : null; 64 } 65 66 72 static CurrentTransaction getInstanceInternal(Environment env) { 73 synchronized (envMap) { 74 CurrentTransaction myEnv = (CurrentTransaction) envMap.get(env); 75 if (myEnv == null) { 76 myEnv = new CurrentTransaction(env); 77 envMap.put(env, myEnv); 78 } 79 return myEnv; 80 } 81 } 82 83 private CurrentTransaction(Environment env) { 84 this.env = env; 85 try { 86 EnvironmentConfig config = env.getConfig(); 87 txnMode = config.getTransactional(); 88 lockingMode = DbCompat.getInitializeLocking(config); 89 if (txnMode || lockingMode) { 90 writeLockMode = LockMode.RMW; 91 } else { 92 writeLockMode = LockMode.DEFAULT; 93 } 94 cdbMode = DbCompat.getInitializeCDB(config); 95 if (cdbMode) { 96 localCdbCursors = new ThreadLocal (); 97 } 98 } catch (DatabaseException e) { 99 throw new RuntimeExceptionWrapper(e); 100 } 101 } 102 103 106 final boolean isLockingMode() { 107 108 return lockingMode; 109 } 110 111 114 final boolean isTxnMode() { 115 116 return txnMode; 117 } 118 119 122 final boolean isCdbMode() { 123 124 return cdbMode; 125 } 126 127 133 final LockMode getWriteLockMode() { 134 135 return writeLockMode; 136 } 137 138 141 public final Environment getEnvironment() { 142 143 return env; 144 } 145 146 150 public final Transaction getTransaction() { 151 152 Trans trans = (Trans) localTrans.get(); 153 return (trans != null) ? trans.txn : null; 154 } 155 156 161 boolean isAutoCommitAllowed() 162 throws DatabaseException { 163 164 return getTransaction() == null && 165 DbCompat.getThreadTransaction(env) == null; 166 } 167 168 185 public final Transaction beginTransaction(TransactionConfig config) 186 throws DatabaseException { 187 188 Trans trans = (Trans) localTrans.get(); 189 if (trans != null) { 190 if (trans.txn != null) { 191 if (!DbCompat.NESTED_TRANSACTIONS) { 192 throw new IllegalStateException ( 193 "Nested transactions are not supported"); 194 } 195 Transaction parentTxn = trans.txn; 196 trans = new Trans(trans, config); 197 trans.txn = env.beginTransaction(parentTxn, config); 198 localTrans.set(trans); 199 } else { 200 trans.txn = env.beginTransaction(null, config); 201 trans.config = config; 202 } 203 } else { 204 trans = new Trans(null, config); 205 trans.txn = env.beginTransaction(null, config); 206 localTrans.set(trans); 207 } 208 return trans.txn; 209 } 210 211 226 public final Transaction commitTransaction() 227 throws DatabaseException, IllegalStateException { 228 229 Trans trans = (Trans) localTrans.get(); 230 if (trans != null && trans.txn != null) { 231 Transaction parent = closeTxn(trans); 232 trans.txn.commit(); 233 return parent; 234 } else { 235 throw new IllegalStateException ("No transaction is active"); 236 } 237 } 238 239 254 public final Transaction abortTransaction() 255 throws DatabaseException, IllegalStateException { 256 257 Trans trans = (Trans) localTrans.get(); 258 if (trans != null && trans.txn != null) { 259 Transaction parent = closeTxn(trans); 260 trans.txn.abort(); 261 return parent; 262 } else { 263 throw new IllegalStateException ("No transaction is active"); 264 } 265 } 266 267 271 final boolean isReadUncommitted() { 272 273 Trans trans = (Trans) localTrans.get(); 274 if (trans != null && trans.config != null) { 275 return trans.config.getReadUncommitted(); 276 } else { 277 return false; 278 } 279 } 280 281 private Transaction closeTxn(Trans trans) { 282 283 localTrans.set(trans.parent); 284 return (trans.parent != null) ? trans.parent.txn : null; 285 } 286 287 private static class Trans { 288 289 private Trans parent; 290 private Transaction txn; 291 private TransactionConfig config; 292 293 private Trans(Trans parent, TransactionConfig config) { 294 295 this.parent = parent; 296 this.config = config; 297 } 298 } 299 300 304 Cursor openCursor(Database db, CursorConfig cursorConfig, 305 boolean writeCursor, Transaction txn) 306 throws DatabaseException { 307 308 if (cdbMode) { 309 CdbCursors cdbCursors = null; 310 WeakHashMap cdbCursorsMap = (WeakHashMap ) localCdbCursors.get(); 311 if (cdbCursorsMap == null) { 312 cdbCursorsMap = new WeakHashMap (); 313 localCdbCursors.set(cdbCursorsMap); 314 } else { 315 cdbCursors = (CdbCursors) cdbCursorsMap.get(db); 316 } 317 if (cdbCursors == null) { 318 cdbCursors = new CdbCursors(); 319 cdbCursorsMap.put(db, cdbCursors); 320 } 321 322 328 List cursors; 329 CursorConfig cdbConfig; 330 if (writeCursor) { 331 if (cdbCursors.readCursors.size() > 0) { 332 333 339 throw new IllegalStateException ( 340 "cannot open CDB write cursor when read cursor is open"); 341 } 342 cursors = cdbCursors.writeCursors; 343 cdbConfig = new CursorConfig(); 344 DbCompat.setWriteCursor(cdbConfig, true); 345 } else { 346 cursors = cdbCursors.readCursors; 347 cdbConfig = null; 348 } 349 Cursor cursor; 350 if (cursors.size() > 0) { 351 Cursor other = ((Cursor) cursors.get(0)); 352 cursor = other.dup(false); 353 } else { 354 cursor = db.openCursor(null, cdbConfig); 355 } 356 cursors.add(cursor); 357 return cursor; 358 } else { 359 return db.openCursor(txn, cursorConfig); 360 } 361 } 362 363 375 Cursor dupCursor(Cursor cursor, boolean writeCursor, boolean samePosition) 376 throws DatabaseException { 377 378 if (cdbMode) { 379 WeakHashMap cdbCursorsMap = (WeakHashMap ) localCdbCursors.get(); 380 if (cdbCursorsMap != null) { 381 Database db = cursor.getDatabase(); 382 CdbCursors cdbCursors = (CdbCursors) cdbCursorsMap.get(db); 383 if (cdbCursors != null) { 384 List cursors = writeCursor ? cdbCursors.writeCursors 385 : cdbCursors.readCursors; 386 if (cursors.contains(cursor)) { 387 Cursor newCursor = cursor.dup(samePosition); 388 cursors.add(newCursor); 389 return newCursor; 390 } 391 } 392 } 393 throw new IllegalStateException ("cursor to dup not tracked"); 394 } else { 395 return cursor.dup(samePosition); 396 } 397 } 398 399 406 void closeCursor(Cursor cursor) 407 throws DatabaseException { 408 409 if (cursor == null) { 410 return; 411 } 412 if (cdbMode) { 413 WeakHashMap cdbCursorsMap = (WeakHashMap ) localCdbCursors.get(); 414 if (cdbCursorsMap != null) { 415 Database db = cursor.getDatabase(); 416 CdbCursors cdbCursors = (CdbCursors) cdbCursorsMap.get(db); 417 if (cdbCursors != null) { 418 if (cdbCursors.readCursors.remove(cursor) || 419 cdbCursors.writeCursors.remove(cursor)) { 420 cursor.close(); 421 return; 422 } 423 } 424 } 425 throw new IllegalStateException ( 426 "closing CDB cursor that was not known to be open"); 427 } else { 428 cursor.close(); 429 } 430 } 431 432 436 boolean isCDBCursorOpen(Database db) 437 throws DatabaseException { 438 439 if (cdbMode) { 440 WeakHashMap cdbCursorsMap = (WeakHashMap ) localCdbCursors.get(); 441 if (cdbCursorsMap != null) { 442 CdbCursors cdbCursors = (CdbCursors) cdbCursorsMap.get(db); 443 444 if (cdbCursors != null && 445 (cdbCursors.readCursors.size() > 0 || 446 cdbCursors.writeCursors.size() > 0)) { 447 return true; 448 } 449 } 450 } 451 return false; 452 } 453 454 static final class CdbCursors { 455 456 List writeCursors = new ArrayList (); 457 List readCursors = new ArrayList (); 458 } 459 } 460 | Popular Tags |