package com.sleepycat.je.txn;
import de.ovgu.cide.jakutil.*;
/**
* LockType is a type safe enumeration of all lock types. Methods on LockType
* objects can be used to determine whether a type conflicts with another
* type or can be upgraded to another type.
*/
public class LockType {
/**
* Lock types. Indexes must be kept manually synchronized in the matrixes
* below.
*/
public static final LockType READ=new LockType(0,false,"READ");
public static final LockType WRITE=new LockType(1,true,"WRITE");
public static final LockType RANGE_READ=new LockType(2,false,"RANGE_READ");
public static final LockType RANGE_WRITE=new LockType(3,true,"RANGE_WRITE");
public static final LockType RANGE_INSERT=new LockType(4,false,"RANGE_INSERT");
/**
* NONE is used for requesting a dirty read and does not appear in the
* conflict or upgrade matrices.
*/
public static final LockType NONE=new LockType(5,false,"NONE");
/**
* RESTART is used for waiting for a restart and does not appear in the
* conflict or upgrade matrices.
*/
public static final LockType RESTART=new LockType(6,false,"RESTART");
/**
* Whenever the conflict matrix is changed be sure to update this. For
* every type that can cause a RESTART result call setCausesRestart. This
* could have been determined programmatically but I chose to maintain it
* manually to avoid extra code size.
*/
static {
RANGE_READ.setCausesRestart();
RANGE_WRITE.setCausesRestart();
}
/**
* Lock conflict matrix.
* @see #getConflict
*/
private static LockConflict[][] conflictMatrix={{LockConflict.ALLOW,LockConflict.BLOCK,LockConflict.ALLOW,LockConflict.BLOCK,LockConflict.ALLOW},{LockConflict.BLOCK,LockConflict.BLOCK,LockConflict.BLOCK,LockConflict.BLOCK,LockConflict.ALLOW},{LockConflict.ALLOW,LockConflict.BLOCK,LockConflict.ALLOW,LockConflict.BLOCK,LockConflict.BLOCK},{LockConflict.BLOCK,LockConflict.BLOCK,LockConflict.BLOCK,LockConflict.BLOCK,LockConflict.BLOCK},{LockConflict.ALLOW,LockConflict.ALLOW,LockConflict.RESTART,LockConflict.RESTART,LockConflict.ALLOW}};
/**
* Lock upgrade matrix.
* @see #getUpgrade
*/
private static LockUpgrade[][] upgradeMatrix={{LockUpgrade.EXISTING,LockUpgrade.WRITE_PROMOTE,LockUpgrade.RANGE_READ_IMMED,LockUpgrade.RANGE_WRITE_PROMOTE,LockUpgrade.ILLEGAL},{LockUpgrade.EXISTING,LockUpgrade.EXISTING,LockUpgrade.RANGE_WRITE_IMMED,LockUpgrade.RANGE_WRITE_IMMED,LockUpgrade.ILLEGAL},{LockUpgrade.EXISTING,LockUpgrade.RANGE_WRITE_PROMOTE,LockUpgrade.EXISTING,LockUpgrade.RANGE_WRITE_PROMOTE,LockUpgrade.ILLEGAL},{LockUpgrade.EXISTING,LockUpgrade.EXISTING,LockUpgrade.EXISTING,LockUpgrade.EXISTING,LockUpgrade.ILLEGAL},{LockUpgrade.ILLEGAL,LockUpgrade.ILLEGAL,LockUpgrade.ILLEGAL,LockUpgrade.ILLEGAL,LockUpgrade.EXISTING}};
private int index;
private boolean write;
private String name;
private boolean causesRestart;
/**
* No lock types can be defined outside this class.
*/
private LockType( int index, boolean write, String name){
this.index=index;
this.write=write;
this.name=name;
}
/**
* Returns true if this is a WRITE or RANGE_WRITE lock. For RANGE_INSERT,
* false is returned because RANGE_INSERT is used to lock the key following
* the insertion key, not the insertion key itself.
*/
public final boolean isWriteLock(){
return write;
}
/**
* Specifies that when this type is requested it can result in
* LockGrantType.RESTART.
*/
private void setCausesRestart(){
causesRestart=true;
}
/**
* Returns whether when this type is requested it can result in
* LockGrantType.RESTART.
*/
final boolean getCausesRestart(){
return causesRestart;
}
/**
* Returns the LockConfict that results when this lock type is held and the
* given lock type is requested by another locker.
*/
LockConflict getConflict( LockType requestedType){
return conflictMatrix[index][requestedType.index];
}
/**
* Returns the LockUpgrade that results when this lock type is held and the
* given lock type is requested by the same locker.
* <p>For the returned LockUpgrade object, getIllegal will never return
* true because this method fires an assertion if getIllegal returns true.
*/
LockUpgrade getUpgrade( LockType requestedType){
LockUpgrade upgrade=upgradeMatrix[index][requestedType.index];
assert !upgrade.getIllegal() : toString() + " to " + requestedType;
return upgrade;
}
public String toString(){
return name;
}
}