001: /*-
002: * See the file LICENSE for redistribution information.
003: *
004: * Copyright (c) 2002,2008 Oracle. All rights reserved.
005: *
006: * $Id: LockType.java,v 1.18.2.3 2008/01/07 15:14:17 cwl Exp $
007: */
008:
009: package com.sleepycat.je.txn;
010:
011: /**
012: * LockType is a type safe enumeration of all lock types. Methods on LockType
013: * objects can be used to determine whether a type conflicts with another
014: * type or can be upgraded to another type.
015: */
016: public class LockType {
017:
018: /**
019: * Lock types. Indexes must be kept manually synchronized in the matrixes
020: * below.
021: */
022: public static final LockType READ = new LockType(0, false, "READ");
023: public static final LockType WRITE = new LockType(1, true, "WRITE");
024: public static final LockType RANGE_READ = new LockType(2, false,
025: "RANGE_READ");
026: public static final LockType RANGE_WRITE = new LockType(3, true,
027: "RANGE_WRITE");
028: public static final LockType RANGE_INSERT = new LockType(4, false,
029: "RANGE_INSERT");
030:
031: /**
032: * NONE is used for requesting a dirty read and does not appear in the
033: * conflict or upgrade matrices.
034: */
035: public static final LockType NONE = new LockType(5, false, "NONE");
036:
037: /**
038: * RESTART is used for waiting for a restart and does not appear in the
039: * conflict or upgrade matrices.
040: */
041: public static final LockType RESTART = new LockType(6, false,
042: "RESTART");
043:
044: /**
045: * Whenever the conflict matrix is changed be sure to update this. For
046: * every type that can cause a RESTART result call setCausesRestart. This
047: * could have been determined programmatically but I chose to maintain it
048: * manually to avoid extra code size.
049: */
050: static {
051: RANGE_READ.setCausesRestart();
052: RANGE_WRITE.setCausesRestart();
053: }
054:
055: /**
056: * Lock conflict matrix.
057: * @see #getConflict
058: */
059: private static LockConflict[][] conflictMatrix = { { // READ is held and there is a request for:
060: LockConflict.ALLOW, // READ
061: LockConflict.BLOCK, // WRITE
062: LockConflict.ALLOW, // RANGE_READ
063: LockConflict.BLOCK, // RANGE_WRITE
064: LockConflict.ALLOW, // RANGE_INSERT
065: }, { // WRITE is held and there is a request for:
066: LockConflict.BLOCK, // READ
067: LockConflict.BLOCK, // WRITE
068: LockConflict.BLOCK, // RANGE_READ
069: LockConflict.BLOCK, // RANGE_WRITE
070: LockConflict.ALLOW, // RANGE_INSERT
071: }, { // RANGE_READ is held and there is a request for:
072: LockConflict.ALLOW, // READ
073: LockConflict.BLOCK, // WRITE
074: LockConflict.ALLOW, // RANGE_READ
075: LockConflict.BLOCK, // RANGE_WRITE
076: LockConflict.BLOCK, // RANGE_INSERT
077: }, { // RANGE_WRITE is held and there is a request for:
078: LockConflict.BLOCK, // READ
079: LockConflict.BLOCK, // WRITE
080: LockConflict.BLOCK, // RANGE_READ
081: LockConflict.BLOCK, // RANGE_WRITE
082: LockConflict.BLOCK, // RANGE_INSERT
083: }, { // RANGE_INSERT is held and there is a request for:
084: LockConflict.ALLOW, // READ
085: LockConflict.ALLOW, // WRITE
086: LockConflict.RESTART, // RANGE_READ
087: LockConflict.RESTART, // RANGE_WRITE
088: LockConflict.ALLOW, // RANGE_INSERT
089: }, };
090:
091: /**
092: * Lock upgrade matrix.
093: * @see #getUpgrade
094: */
095: private static LockUpgrade[][] upgradeMatrix = { { // READ is held and there is a request for:
096: LockUpgrade.EXISTING, // READ
097: LockUpgrade.WRITE_PROMOTE, // WRITE
098: LockUpgrade.RANGE_READ_IMMED, // RANGE_READ
099: LockUpgrade.RANGE_WRITE_PROMOTE, // RANGE_WRITE
100: LockUpgrade.ILLEGAL, // RANGE_INSERT
101: }, { // WRITE is held and there is a request for:
102: LockUpgrade.EXISTING, // READ
103: LockUpgrade.EXISTING, // WRITE
104: LockUpgrade.RANGE_WRITE_IMMED, // RANGE_READ
105: LockUpgrade.RANGE_WRITE_IMMED, // RANGE_WRITE
106: LockUpgrade.ILLEGAL, // RANGE_INSERT
107: }, { // RANGE_READ is held and there is a request for:
108: LockUpgrade.EXISTING, // READ
109: LockUpgrade.RANGE_WRITE_PROMOTE, // WRITE
110: LockUpgrade.EXISTING, // RANGE_READ
111: LockUpgrade.RANGE_WRITE_PROMOTE, // RANGE_WRITE
112: LockUpgrade.ILLEGAL, // RANGE_INSERT
113: }, { // RANGE_WRITE is held and there is a request for:
114: LockUpgrade.EXISTING, // READ
115: LockUpgrade.EXISTING, // WRITE
116: LockUpgrade.EXISTING, // RANGE_READ
117: LockUpgrade.EXISTING, // RANGE_WRITE
118: LockUpgrade.ILLEGAL, // RANGE_INSERT
119: }, { // RANGE_INSERT is held and there is a request for:
120: LockUpgrade.ILLEGAL, // READ
121: LockUpgrade.ILLEGAL, // WRITE
122: LockUpgrade.ILLEGAL, // RANGE_READ
123: LockUpgrade.ILLEGAL, // RANGE_WRITE
124: LockUpgrade.EXISTING, // RANGE_INSERT
125: }, };
126:
127: private int index;
128: private boolean write;
129: private String name;
130: private boolean causesRestart;
131:
132: /**
133: * No lock types can be defined outside this class.
134: */
135: private LockType(int index, boolean write, String name) {
136: this .index = index;
137: this .write = write;
138: this .name = name;
139: }
140:
141: /**
142: * Returns true if this is a WRITE or RANGE_WRITE lock. For RANGE_INSERT,
143: * false is returned because RANGE_INSERT is used to lock the key following
144: * the insertion key, not the insertion key itself.
145: */
146: public final boolean isWriteLock() {
147: return write;
148: }
149:
150: /**
151: * Specifies that when this type is requested it can result in
152: * LockGrantType.RESTART.
153: */
154: private void setCausesRestart() {
155: causesRestart = true;
156: }
157:
158: /**
159: * Returns whether when this type is requested it can result in
160: * LockGrantType.RESTART.
161: */
162: final boolean getCausesRestart() {
163: return causesRestart;
164: }
165:
166: /**
167: * Returns the LockConfict that results when this lock type is held and the
168: * given lock type is requested by another locker.
169: */
170: LockConflict getConflict(LockType requestedType) {
171: return conflictMatrix[index][requestedType.index];
172: }
173:
174: /**
175: * Returns the LockUpgrade that results when this lock type is held and the
176: * given lock type is requested by the same locker.
177: *
178: * <p>For the returned LockUpgrade object, getIllegal will never return
179: * true because this method fires an assertion if getIllegal returns true.
180: */
181: LockUpgrade getUpgrade(LockType requestedType) {
182: LockUpgrade upgrade = upgradeMatrix[index][requestedType.index];
183: assert !upgrade.getIllegal() : toString() + " to "
184: + requestedType;
185: return upgrade;
186: }
187:
188: public String toString() {
189: return name;
190: }
191: }
|