1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 2002, 2014 Oracle and/or its affiliates.  All rights reserved.
5  *
6  */
7 
8 package com.sleepycat.je.txn;
9 
10 /**
11  * LockUpgrade is a type safe enumeration of lock upgrade types.  Methods on
12  * LockUpgrade objects are used to determine whether an upgrade is needed and,
13  * if so, how it should be handled.
14  */
15 public class LockUpgrade {
16 
17     /*
18      * Due to static initialization circularities between LockUpgrade and
19      * LockType, the LockUpgrade.upgrade field of each of these LockUpgrades
20      * will get filled in by a piece of static code in EnvironmentImpl.
21      * [#16496]
22      */
23     public static final LockUpgrade ILLEGAL =
24         new LockUpgrade(null, false, true);
25 
26     public static final LockUpgrade EXISTING =
27         new LockUpgrade(null, false, false);
28 
29     public static final LockUpgrade WRITE_PROMOTE =
30         new LockUpgrade(null /*LockType.WRITE*/, true, false);
31 
32     public static final LockUpgrade RANGE_READ_IMMED =
33         new LockUpgrade(null /*LockType.RANGE_READ*/, false, false);
34 
35     public static final LockUpgrade RANGE_WRITE_IMMED =
36         new LockUpgrade(null /*LockType.RANGE_WRITE*/, false, false);
37 
38     public static final LockUpgrade RANGE_WRITE_PROMOTE =
39         new LockUpgrade(null /*LockType.RANGE_WRITE*/, true, false);
40 
41     private LockType upgrade;
42     private boolean promotion;
43     private boolean illegal;
44 
45     /**
46      * No upgrade types can be defined outside this class.
47      */
LockUpgrade(LockType upgrade, boolean promotion, boolean illegal)48     private LockUpgrade(LockType upgrade, boolean promotion, boolean illegal) {
49         this.upgrade = upgrade;
50         this.promotion = promotion;
51         this.illegal = illegal;
52     }
53 
54     /**
55      * This method is called to determine whether the upgrade is illegal.
56      * If true is returned, an internal error has occurred.  This should never
57      * happen since RANGE_INSERT should never be requested along with other
58      * locks by the same locker; a separate locker is used for RANGE_INSERT
59      * locks.
60      */
getIllegal()61     boolean getIllegal() {
62         return illegal;
63     }
64 
65     /**
66      * This method is called first to determine whether an upgrade to a new
67      * lock type is needed, and what the new lock type should be.  If null is
68      * returned, the existing lock should be unchanged and no upgrade is
69      * needed.  If non-null is returned, an upgrade to the returned type should
70      * be performed; in this case, call getPromotion to determine how to do the
71      * upgrade.
72      */
getUpgrade()73     LockType getUpgrade() {
74         return upgrade;
75     }
76 
77     /**
78      * @hidden
79      */
setUpgrade(LockType upgrade)80     public void setUpgrade(LockType upgrade) {
81         this.upgrade = upgrade;
82     }
83 
84     /**
85      * This method is called when getUpgrade returns non-null to determine
86      * whether the upgrade is a true promotion or can be granted immediately.
87      * A true promotion is a change from read to write locking, and may require
88      * waiting if the write lock conflicts with a lock held by another locker.
89      * An upgrade that is not a promotion is just a type change, and never
90      * causes a lock conflict.
91      */
getPromotion()92     boolean getPromotion() {
93         return promotion;
94     }
95 }
96