package com.sleepycat.je.txn; import com.sleepycat.je.DatabaseException; import com.sleepycat.je.dbi.CursorImpl; import com.sleepycat.je.dbi.DatabaseImpl; import com.sleepycat.je.dbi.EnvironmentImpl; import com.sleepycat.je.tree.BIN; import com.sleepycat.je.tree.Key; import de.ovgu.cide.jakutil.*; /** * Extends BuddyLocker to acquire write locks using the buddy locker (the * transaction locker). This is used for ReadCommitted (Degree 2) isolation. */ public class ReadCommittedLocker extends BuddyLocker { /** * Creates a ReadCommittedLocker. * @param buddy is a transactional locker that will be used for acquiring * write locks. */ public ReadCommittedLocker( EnvironmentImpl env, Locker buddy) throws DatabaseException { super(env,(buddy instanceof ReadCommittedLocker) ? ((ReadCommittedLocker)buddy).getBuddy() : buddy); assert getBuddy().isTransactional(); } /** * Creates a new instance of this txn for the same environment. No * transactional locks are held by this object, so no locks are retained. * newNonTxnLocker is also called for the BuddyLocker. */ public Locker newNonTxnLocker() throws DatabaseException { return new ReadCommittedLocker(envImpl,getBuddy().newNonTxnLocker()); } /** * Forwards write locks to the buddy locker (the transaction locker). * @see Locker#lockInternal * @Override */ LockResult lockInternal( long nodeId, LockType lockType, boolean noWait, DatabaseImpl database) throws DatabaseException { if (lockType.isWriteLock()) { return getBuddy().lockInternal(nodeId,lockType,noWait,database); } else { return super.lockInternal(nodeId,lockType,noWait,database); } } /** * Releases the lock from this locker, or if not owned by this locker then * releases it from the buddy locker. */ public void releaseLock( long nodeId) throws DatabaseException { if (!lockManager.release(nodeId,this)) { lockManager.release(nodeId,getBuddy()); } } /** * Forwards this method to the transactional buddy. Since the buddy * handles write locks, it knows whether this transaction created the node. */ public boolean createdNode( long nodeId) throws DatabaseException { return getBuddy().createdNode(nodeId); } /** * Forwards this method to the transactional buddy. The buddy handles * write locks and therefore handles abort information. */ public long getAbortLsn( long nodeId) throws DatabaseException { return getBuddy().getAbortLsn(nodeId); } /** * @return the WriteLockInfo for this node. */ public WriteLockInfo getWriteLockInfo( long nodeId) throws DatabaseException { return getBuddy().getWriteLockInfo(nodeId); } /** * Forwards this method to the transactional buddy. The buddy Txn tracks * cursors. */ public void registerCursor( CursorImpl cursor) throws DatabaseException { getBuddy().registerCursor(cursor); } /** * Forwards this method to the transactional buddy. The buddy Txn tracks * cursors. */ public void unRegisterCursor( CursorImpl cursor) throws DatabaseException { getBuddy().unRegisterCursor(cursor); } /** * Is always transactional because the buddy locker is transactional. */ public boolean isTransactional(){ return true; } /** * Is always read-committed isolation. */ public boolean isReadCommittedIsolation(){ return true; } }