package com.sleepycat.je.txn;
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.dbi.EnvironmentImpl;
import de.ovgu.cide.jakutil.*;
/**
* Extends BasicLocker to share locks with another specific locker.
* <p>In general, a BuddyLocker can be used whenever the primary (API) locker
* is in use, and we need to lock a node and release that lock before the
* primary locker transaction ends. In other words, for this particular lock
* we don't want to use two-phase locking. To accomplish that we use a
* separate BuddyLocker instance to hold the lock, while sharing locks with the
* primary locker. The BuddyLocker can be closed to release this particular
* lock, without releasing the other locks held by the primary locker.</p>
* <p>In particular, a BuddyLocker is used when acquiring a RANGE_INSERT lock.
* RANGE_INSERT only needs to be held until the point we have inserted the new
* node into the BIN. A separate locker is therefore used so we can release
* that lock separately when the insertion into the BIN is complete. But the
* RANGE_INSERT lock must not conflict with locks held by the primary locker.
* So a BuddyLocker is used that shares locks with the primary locker.</p>
*/
public class BuddyLocker extends BasicLocker {
private Locker buddy;
/**
* Creates a BuddyLocker.
*/
public BuddyLocker( EnvironmentImpl env, Locker buddy) throws DatabaseException {
super(env);
this.buddy=buddy;
}
/**
* Returns the buddy locker.
*/
Locker getBuddy(){
return buddy;
}
/**
* Forwards this call to the buddy locker.
*/
public Txn getTxnLocker(){
return buddy.getTxnLocker();
}
/**
* 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 BuddyLocker(envImpl,buddy.newNonTxnLocker());
}
/**
* Forwards this call to the base class and to the buddy locker.
*/
public void releaseNonTxnLocks() throws DatabaseException {
super.releaseNonTxnLocks();
buddy.releaseNonTxnLocks();
}
/**
* Returns whether this locker can share locks with the given locker.
*/
public boolean sharesLocksWith( Locker other){
if (super.sharesLocksWith(other)) {
return true;
}
else {
return buddy == other;
}
}
}