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 import java.util.Collections; 11 import java.util.HashSet; 12 import java.util.List; 13 import java.util.Set; 14 15 import com.sleepycat.je.DatabaseException; 16 import com.sleepycat.je.dbi.MemoryBudget; 17 18 /** 19 * Implements a lightweight Lock with no waiters and only a single Owner. If, 20 * during an operation (lock) more than one owner or waiter is required, then 21 * this will mutate to a LockImpl, perform the requested operation, and return 22 * the new LockImpl to the caller. 23 * 24 * public for Sizeof. 25 */ 26 public class ThinLockImpl extends LockInfo implements Lock { 27 28 /** 29 * Create a Lock. Public for Sizeof. 30 */ ThinLockImpl()31 public ThinLockImpl() { 32 super(null, null); 33 } 34 getWaitersListClone()35 public List<LockInfo> getWaitersListClone() { 36 return Collections.emptyList(); 37 } 38 flushWaiter(Locker locker, MemoryBudget mb, int lockTableIndex)39 public void flushWaiter(Locker locker, 40 MemoryBudget mb, 41 int lockTableIndex) { 42 43 /* Do nothing. */ 44 return; 45 } 46 getOwnersClone()47 public Set<LockInfo> getOwnersClone() { 48 49 Set<LockInfo> ret = new HashSet<LockInfo>(); 50 if (locker != null) { 51 ret.add(this); 52 } 53 return ret; 54 } 55 isOwner(Locker locker, LockType lockType)56 public boolean isOwner(Locker locker, LockType lockType) { 57 58 if (locker == this.locker) { 59 if (lockType == this.lockType) { 60 return true; 61 } 62 63 if (this.lockType != null) { 64 LockUpgrade upgrade = this.lockType.getUpgrade(lockType); 65 if (!upgrade.getPromotion()) { 66 return true; 67 } 68 } 69 } else { 70 return false; 71 } 72 return false; 73 } 74 isOwnedWriteLock(Locker locker)75 public boolean isOwnedWriteLock(Locker locker) { 76 77 if (locker != this.locker) { 78 return false; 79 } 80 81 if (this.lockType != null) { 82 return this.lockType.isWriteLock(); 83 } else { 84 return false; 85 } 86 } 87 getOwnedLockType(Locker locker)88 public LockType getOwnedLockType(Locker locker) { 89 if (locker != this.locker) { 90 return null; 91 } 92 return this.lockType; 93 } 94 isWaiter(Locker locker)95 public boolean isWaiter(Locker locker) { 96 97 /* There can never be waiters on Thin Locks. */ 98 return false; 99 } 100 nWaiters()101 public int nWaiters() { 102 return 0; 103 } 104 nOwners()105 public int nOwners() { 106 return (locker == null ? 0 : 1); 107 } 108 lock(LockType requestType, Locker locker, boolean nonBlockingRequest, boolean jumpAheadOfWaiters, MemoryBudget mb, int lockTableIndex)109 public LockAttemptResult lock(LockType requestType, 110 Locker locker, 111 boolean nonBlockingRequest, 112 boolean jumpAheadOfWaiters, 113 MemoryBudget mb, 114 int lockTableIndex) 115 throws DatabaseException { 116 117 if (this.locker != null && 118 this.locker != locker) { 119 /* Lock is already held by someone else so mutate. */ 120 Lock newLock = new LockImpl(new LockInfo(this)); 121 return newLock.lock(requestType, locker, nonBlockingRequest, 122 jumpAheadOfWaiters, mb, lockTableIndex); 123 } 124 125 LockGrantType grant = null; 126 if (this.locker == null) { 127 this.locker = locker; 128 this.lockType = requestType; 129 grant = LockGrantType.NEW; 130 } else { 131 132 /* The requestor holds this lock. Check for upgrades. */ 133 LockUpgrade upgrade = lockType.getUpgrade(requestType); 134 if (upgrade.getUpgrade() == null) { 135 grant = LockGrantType.EXISTING; 136 } else { 137 LockType upgradeType = upgrade.getUpgrade(); 138 assert upgradeType != null; 139 this.lockType = upgradeType; 140 grant = (upgrade.getPromotion() ? 141 LockGrantType.PROMOTION : 142 LockGrantType.EXISTING); 143 } 144 } 145 return new LockAttemptResult(this, grant, false); 146 } 147 release(Locker locker, MemoryBudget mb, int lockTableIndex)148 public Set<Locker> release(Locker locker, 149 MemoryBudget mb, 150 int lockTableIndex) { 151 152 if (locker == this.locker) { 153 this.locker = null; 154 this.lockType = null; 155 return Collections.emptySet(); 156 } else { 157 return null; 158 } 159 } 160 stealLock(Locker locker, MemoryBudget mb, int lockTableIndex)161 public void stealLock(Locker locker, MemoryBudget mb, int lockTableIndex) { 162 if (this.locker != locker && 163 this.locker.getPreemptable()) { 164 this.locker.setPreempted(); 165 this.locker = null; 166 } 167 } 168 demote(Locker locker)169 public void demote(Locker locker) { 170 171 if (this.lockType.isWriteLock()) { 172 this.lockType = (lockType == LockType.RANGE_WRITE) ? 173 LockType.RANGE_READ : LockType.READ; 174 } 175 } 176 getWriteOwnerLocker()177 public Locker getWriteOwnerLocker() { 178 179 if (lockType != null && 180 lockType.isWriteLock()) { 181 return locker; 182 } else { 183 return null; 184 } 185 } 186 isThin()187 public boolean isThin() { 188 return true; 189 } 190 191 @Override toString()192 public String toString() { 193 194 StringBuilder sb = new StringBuilder(); 195 sb.append(" ThinLockAddr:").append(System.identityHashCode(this)); 196 sb.append(" Owner:"); 197 if (nOwners() == 0) { 198 sb.append(" (none)"); 199 } else { 200 sb.append(locker); 201 } 202 203 sb.append(" Waiters: (none)"); 204 return sb.toString(); 205 } 206 } 207