package com.sleepycat.je.txn;
import com.sleepycat.je.Database;
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.DbInternal;
import com.sleepycat.je.Environment;
import com.sleepycat.je.Transaction;
import com.sleepycat.je.TransactionConfig;
import com.sleepycat.je.dbi.DatabaseImpl;
import com.sleepycat.je.dbi.EnvironmentImpl;
import de.ovgu.cide.jakutil.*;
/**
* Factory of static methods for creating Locker objects.
*/
public class LockerFactory {
/**
* Get a locker for a writable operation, checking whether the db and
* environment is transactional or not. Must return a non null locker.
*/
public static Locker getWritableLocker( Environment env, Transaction userTxn, boolean dbIsTransactional) throws DatabaseException {
return getWritableLocker(env,userTxn,dbIsTransactional,false,null);
}
/**
* Get a locker for a writable operation, also specifying whether to retain
* non-transactional locks when a new locker must be created.
* @param retainNonTxnLocks is true for DbTree operations, so that the
* handle lock may be transferred out of the locker when the operation is
* complete.
*/
public static Locker getWritableLocker( Environment env, Transaction userTxn, boolean dbIsTransactional, boolean retainNonTxnLocks, TransactionConfig autoCommitConfig) throws DatabaseException {
EnvironmentImpl envImpl=DbInternal.envGetEnvironmentImpl(env);
boolean envIsTransactional=envImpl.isTransactional();
if (userTxn == null) {
Transaction xaLocker=env.getThreadTransaction();
if (xaLocker != null) {
return DbInternal.getLocker(xaLocker);
}
}
if (dbIsTransactional && userTxn == null) {
if (autoCommitConfig == null) {
autoCommitConfig=DbInternal.getDefaultTxnConfig(env);
}
return new AutoTxn(envImpl,autoCommitConfig);
}
else if (userTxn == null) {
if (retainNonTxnLocks) {
return new BasicLocker(envImpl);
}
else {
return new ThreadLocker(envImpl);
}
}
else {
if (!envIsTransactional) {
throw new DatabaseException("A Transaction cannot be used because the" + " environment was opened" + " non-transactionally");
}
if (!dbIsTransactional) {
throw new DatabaseException("A Transaction cannot be used because the" + " database was opened" + " non-transactionally");
}
Locker locker=DbInternal.getLocker(userTxn);
if (locker.isReadCommittedIsolation() && !retainNonTxnLocks) {
return new ReadCommittedLocker(envImpl,locker);
}
else {
return locker;
}
}
}
/**
* Get a locker for a read or cursor operation.
* See getWritableLocker for an explanation of retainNonTxnLocks.
*/
public static Locker getReadableLocker( Environment env, Transaction userTxn, boolean dbIsTransactional, boolean retainNonTxnLocks, boolean readCommittedIsolation) throws DatabaseException {
if (userTxn != null && !dbIsTransactional) {
throw new DatabaseException("A Transaction cannot be used because the" + " database was opened" + " non-transactionally");
}
Locker locker=null;
if (userTxn != null) {
locker=DbInternal.getLocker(userTxn);
if (locker.isReadCommittedIsolation()) {
readCommittedIsolation=true;
}
}
return getReadableLocker(env,locker,retainNonTxnLocks,readCommittedIsolation);
}
/**
* Get a locker for this database handle for a read or cursor operation.
* See getWritableLocker for an explanation of retainNonTxnLocks.
*/
public static Locker getReadableLocker( Environment env, Database dbHandle, Locker locker, boolean retainNonTxnLocks, boolean readCommittedIsolation) throws DatabaseException {
DatabaseImpl dbImpl=DbInternal.dbGetDatabaseImpl(dbHandle);
if (!dbImpl.isTransactional() && locker != null && locker.isTransactional()) {
throw new DatabaseException("A Transaction cannot be used because the" + " database was opened" + " non-transactionally");
}
if (locker != null && !locker.isTransactional() && !retainNonTxnLocks) {
locker=null;
}
if (locker != null && locker.isReadCommittedIsolation()) {
readCommittedIsolation=true;
}
return getReadableLocker(env,locker,retainNonTxnLocks,readCommittedIsolation);
}
/**
* Get a locker for a read or cursor operation.
* See getWritableLocker for an explanation of retainNonTxnLocks.
*/
private static Locker getReadableLocker( Environment env, Locker locker, boolean retainNonTxnLocks, boolean readCommittedIsolation) throws DatabaseException {
EnvironmentImpl envImpl=DbInternal.envGetEnvironmentImpl(env);
if (locker == null) {
Transaction xaTxn=env.getThreadTransaction();
if (xaTxn != null) {
return DbInternal.getLocker(xaTxn);
}
}
if (locker == null) {
if (retainNonTxnLocks) {
locker=new BasicLocker(envImpl);
}
else {
locker=new ThreadLocker(envImpl);
}
}
else {
if (readCommittedIsolation && !retainNonTxnLocks) {
locker=new ReadCommittedLocker(envImpl,locker);
}
}
return locker;
}
}