1 5 package com.tc.object.msg; 6 7 import com.tc.bytes.TCByteBuffer; 8 import com.tc.io.TCByteBufferOutput; 9 import com.tc.io.TCSerializable; 10 import com.tc.net.protocol.tcm.MessageChannel; 11 import com.tc.net.protocol.tcm.MessageMonitor; 12 import com.tc.net.protocol.tcm.TCMessageHeader; 13 import com.tc.net.protocol.tcm.TCMessageType; 14 import com.tc.object.lockmanager.api.LockContext; 15 import com.tc.object.lockmanager.api.LockID; 16 import com.tc.object.lockmanager.api.LockLevel; 17 import com.tc.object.lockmanager.api.ThreadID; 18 import com.tc.object.lockmanager.api.WaitContext; 19 import com.tc.object.session.SessionID; 20 import com.tc.object.tx.WaitInvocation; 21 import com.tc.object.tx.WaitInvocationFactory; 22 23 import java.io.IOException ; 24 import java.util.Collection ; 25 import java.util.HashSet ; 26 import java.util.Iterator ; 27 import java.util.Set ; 28 29 34 public class LockRequestMessage extends DSOMessageBase { 35 36 private static final WaitInvocationFactory waitInvocationFactory = new WaitInvocationFactory(); 37 38 private final static byte LOCK_ID = 1; 39 private final static byte LOCK_LEVEL = 2; 40 private final static byte THREAD_ID = 3; 41 private final static byte REQUEST_TYPE = 4; 42 private final static byte WITH_WAIT = 5; 43 private final static byte WAIT_MILLIS = 6; 44 private final static byte WAIT_NANOS = 7; 45 private final static byte NOTIFY_ALL = 8; 46 private static final byte WAIT_ARG_COUNT = 9; 47 private static final byte WAIT_CONTEXT = 10; 48 private static final byte LOCK_CONTEXT = 11; 49 private static final byte PENDING_LOCK_CONTEXT = 12; 50 51 private final static byte UNITIALIZED_REQUEST_TYPE = -1; 53 private final static byte OBTAIN_LOCK_REQUEST_TYPE = 1; 54 private final static byte RELEASE_LOCK_REQUEST_TYPE = 2; 55 private final static byte RECALL_COMMIT_LOCK_REQUEST_TYPE = 3; 56 private final static byte QUERY_LOCK_REQUEST_TYPE = 4; 57 private final static byte TRY_OBTAIN_LOCK_REQUEST_TYPE = 5; 58 private final static byte INTERRUPT_WAIT_REQUEST_TYPE = 6; 59 60 public final static int UNITIALIZED_WAIT_TIME = -1; 61 62 private final Set lockContexts = new HashSet (); 63 private final Set waitContexts = new HashSet (); 64 private final Set pendingLockContexts = new HashSet (); 65 66 private LockID lockID = LockID.NULL_ID; 67 private int lockLevel = LockLevel.NIL_LOCK_LEVEL; 68 private ThreadID threadID = ThreadID.NULL_ID; 69 private byte requestType = UNITIALIZED_REQUEST_TYPE; 70 private boolean withWait; 71 private long waitMillis = UNITIALIZED_WAIT_TIME; 72 private int waitNanos = UNITIALIZED_WAIT_TIME; 73 private boolean notifyAll; 74 private int waitArgCount = -1; 75 76 public LockRequestMessage(MessageMonitor monitor, TCByteBufferOutput out, MessageChannel channel, TCMessageType type) { 77 super(monitor, out, channel, type); 78 } 79 80 public LockRequestMessage(SessionID sessionID, MessageMonitor monitor, MessageChannel channel, 81 TCMessageHeader header, TCByteBuffer[] data) { 82 super(sessionID, monitor, channel, header, data); 83 } 84 85 protected void dehydrateValues() { 86 putNVPair(LOCK_ID, lockID.asString()); 87 putNVPair(LOCK_LEVEL, lockLevel); 88 putNVPair(THREAD_ID, threadID.toLong()); 89 90 putNVPair(REQUEST_TYPE, requestType); 91 92 putNVPair(WITH_WAIT, withWait); 93 94 if (withWait) { 95 putNVPair(WAIT_ARG_COUNT, this.waitArgCount); 96 putNVPair(WAIT_MILLIS, waitMillis); 97 putNVPair(WAIT_NANOS, waitNanos); 98 } 99 100 putNVPair(NOTIFY_ALL, notifyAll); 101 102 for (Iterator i = lockContexts.iterator(); i.hasNext();) { 103 putNVPair(LOCK_CONTEXT, (TCSerializable) i.next()); 104 } 105 106 for (Iterator i = waitContexts.iterator(); i.hasNext();) { 107 putNVPair(WAIT_CONTEXT, (TCSerializable) i.next()); 108 } 109 110 for (Iterator i = pendingLockContexts.iterator(); i.hasNext();) { 111 putNVPair(PENDING_LOCK_CONTEXT, (TCSerializable) i.next()); 112 } 113 114 } 115 116 private static boolean isValidRequestType(byte type) { 117 if ((type == RELEASE_LOCK_REQUEST_TYPE) || (type == OBTAIN_LOCK_REQUEST_TYPE) 118 || (type == RECALL_COMMIT_LOCK_REQUEST_TYPE) || (type == QUERY_LOCK_REQUEST_TYPE) 119 || (type == TRY_OBTAIN_LOCK_REQUEST_TYPE) || (type == INTERRUPT_WAIT_REQUEST_TYPE)) { return true; } 120 121 return false; 122 } 123 124 private static String getRequestTypeDescription(byte type) { 125 switch (type) { 126 case RELEASE_LOCK_REQUEST_TYPE: 127 return "Lock Release"; 128 case OBTAIN_LOCK_REQUEST_TYPE: 129 return "Obtain Lock"; 130 case RECALL_COMMIT_LOCK_REQUEST_TYPE: 131 return "Recall Lock Commit"; 132 case QUERY_LOCK_REQUEST_TYPE: 133 return "Query Lock"; 134 case TRY_OBTAIN_LOCK_REQUEST_TYPE: 135 return "Try Obtain Lock"; 136 case INTERRUPT_WAIT_REQUEST_TYPE: 137 return "Interrupt Wait"; 138 default: 139 return "UNKNOWN (" + type + ")"; 140 } 141 } 142 143 protected String describePayload() { 144 StringBuffer rv = new StringBuffer (); 145 146 rv.append("Request Type: ").append(getRequestTypeDescription(this.requestType)).append('\n'); 147 rv.append(lockID).append(' ').append(threadID).append(' ').append("Lock Type: ").append( 148 LockLevel 149 .toString(lockLevel)) 150 .append('\n'); 151 152 if (isWaitRelease()) { 153 rv.append("Wait millis: ").append(waitMillis).append(", nanos: ").append(waitNanos).append('\n'); 154 } 155 if (waitContexts.size() > 0) { 156 rv.append("Wait contexts size = ").append(waitContexts.size()).append('\n'); 157 } 158 if (lockContexts.size() > 0) { 159 rv.append("Lock contexts size = ").append(lockContexts.size()).append('\n'); 160 } 161 if (pendingLockContexts.size() > 0) { 162 rv.append("Pending Lock contexts size = ").append(pendingLockContexts.size()).append('\n'); 163 } 164 165 return rv.toString(); 166 } 167 168 protected boolean hydrateValue(byte name) throws IOException { 169 switch (name) { 170 case LOCK_ID: 171 lockID = new LockID(getStringValue()); 173 return true; 174 case LOCK_LEVEL: 175 lockLevel = getIntValue(); 176 return true; 177 case THREAD_ID: 178 threadID = new ThreadID(getLongValue()); 179 return true; 180 case WITH_WAIT: 181 withWait = getBooleanValue(); 182 return true; 183 case REQUEST_TYPE: 184 final byte req = getByteValue(); 185 if (!isValidRequestType(req)) { return false; } 186 requestType = req; 187 return true; 188 case WAIT_MILLIS: 189 waitMillis = getLongValue(); 190 return true; 191 case WAIT_NANOS: 192 waitNanos = getIntValue(); 193 return true; 194 case NOTIFY_ALL: 195 notifyAll = getBooleanValue(); 196 return true; 197 case WAIT_ARG_COUNT: 198 waitArgCount = getIntValue(); 199 return true; 200 case LOCK_CONTEXT: 201 lockContexts.add(getObject(new LockContext())); 202 return true; 203 case WAIT_CONTEXT: 204 waitContexts.add(getObject(new WaitContext())); 205 return true; 206 case PENDING_LOCK_CONTEXT: 207 pendingLockContexts.add(getObject(new LockContext())); 208 return true; 209 default: 210 return false; 211 } 212 } 213 214 public LockID getLockID() { 215 return lockID; 216 } 217 218 public ThreadID getThreadID() { 219 return threadID; 220 } 221 222 public int getLockLevel() { 223 return lockLevel; 224 } 225 226 public boolean isNotifyAll() { 227 return notifyAll; 228 } 229 230 public void addLockContext(LockContext ctxt) { 231 synchronized (lockContexts) { 232 lockContexts.add(ctxt); 233 } 234 } 235 236 public Collection getLockContexts() { 237 synchronized (lockContexts) { 238 return new HashSet (lockContexts); 239 } 240 } 241 242 public void addWaitContext(WaitContext ctxt) { 243 synchronized (waitContexts) { 244 waitContexts.add(ctxt); 245 } 246 } 247 248 public Collection getWaitContexts() { 249 synchronized (waitContexts) { 250 return new HashSet (waitContexts); 251 } 252 } 253 254 public void addPendingLockContext(LockContext ctxt) { 255 synchronized (pendingLockContexts) { 256 pendingLockContexts.add(ctxt); 257 } 258 } 259 260 public Collection getPendingLockContexts() { 261 synchronized (pendingLockContexts) { 262 return new HashSet (pendingLockContexts); 263 } 264 } 265 266 public boolean isInterruptWaitRequest() { 267 if (!isValidRequestType(requestType)) { throw new AssertionError ("Invalid request type: " + requestType); } 268 return requestType == INTERRUPT_WAIT_REQUEST_TYPE; 269 } 270 271 public boolean isQueryLockRequest() { 272 if (!isValidRequestType(requestType)) { throw new AssertionError ("Invalid request type: " + requestType); } 273 return requestType == QUERY_LOCK_REQUEST_TYPE; 274 } 275 276 public boolean isTryObtainLockRequest() { 277 if (!isValidRequestType(requestType)) { throw new AssertionError ("Invalid request type: " + requestType); } 278 return requestType == TRY_OBTAIN_LOCK_REQUEST_TYPE; 279 } 280 281 public boolean isObtainLockRequest() { 282 if (!isValidRequestType(requestType)) { throw new AssertionError ("Invalid request type: " + requestType); } 283 return requestType == OBTAIN_LOCK_REQUEST_TYPE; 284 } 285 286 public boolean isReleaseLockRequest() { 287 if (!isValidRequestType(requestType)) { throw new AssertionError ("Invalid request type: " + requestType); } 288 return requestType == RELEASE_LOCK_REQUEST_TYPE; 289 } 290 291 public boolean isRecallCommitLockRequest() { 292 if (!isValidRequestType(requestType)) { throw new AssertionError ("Invalid request type: " + requestType); } 293 return requestType == RECALL_COMMIT_LOCK_REQUEST_TYPE; 294 } 295 296 public WaitInvocation getWaitInvocation() { 297 if (!this.withWait) { throw new IllegalStateException ("not a wait request"); } 298 return waitInvocationFactory.newWaitInvocation(this.waitArgCount, this.waitMillis, this.waitNanos); 299 } 300 301 public boolean isWaitRelease() { 302 return this.withWait; 303 } 304 305 public void initializeInterruptWait(LockID lid, ThreadID id) { 306 initialize(lid, id, LockLevel.NIL_LOCK_LEVEL, INTERRUPT_WAIT_REQUEST_TYPE, false, false, UNITIALIZED_WAIT_TIME, 307 UNITIALIZED_WAIT_TIME, -1); 308 } 309 310 public void initializeQueryLock(LockID lid, ThreadID id) { 311 initialize(lid, id, LockLevel.NIL_LOCK_LEVEL, QUERY_LOCK_REQUEST_TYPE, false, false, UNITIALIZED_WAIT_TIME, 312 UNITIALIZED_WAIT_TIME, -1); 313 } 314 315 public void initializeObtainLock(LockID lid, ThreadID id, int type) { 316 initialize(lid, id, type, OBTAIN_LOCK_REQUEST_TYPE, false, false, UNITIALIZED_WAIT_TIME, UNITIALIZED_WAIT_TIME, -1); 317 } 318 319 public void initializeTryObtainLock(LockID lid, ThreadID id, int type) { 320 initialize(lid, id, type, TRY_OBTAIN_LOCK_REQUEST_TYPE, false, false, UNITIALIZED_WAIT_TIME, UNITIALIZED_WAIT_TIME, 321 -1); 322 } 323 324 public void initializeLockRelease(LockID lid, ThreadID id) { 325 initialize(lid, id, LockLevel.NIL_LOCK_LEVEL, RELEASE_LOCK_REQUEST_TYPE, false, false, UNITIALIZED_WAIT_TIME, 326 UNITIALIZED_WAIT_TIME, -1); 327 } 328 329 public void initializeLockReleaseWait(LockID lid, ThreadID id, WaitInvocation call) { 330 initialize(lid, id, LockLevel.NIL_LOCK_LEVEL, RELEASE_LOCK_REQUEST_TYPE, true, false, call.getMillis(), call 331 .getNanos(), call.getSignature().getArgCount()); 332 } 333 334 public void initializeLockRecallCommit(LockID lid) { 335 initialize(lid, ThreadID.VM_ID, LockLevel.NIL_LOCK_LEVEL, RECALL_COMMIT_LOCK_REQUEST_TYPE, false, false, 336 UNITIALIZED_WAIT_TIME, UNITIALIZED_WAIT_TIME, -1); 337 } 338 339 private void initialize(LockID lid, ThreadID id, int level, byte reqType, boolean wait, boolean all, long millis, 340 int nanos, int waitArgs) { 341 this.lockID = lid; 342 this.lockLevel = level; 343 this.threadID = id; 344 345 if (!isValidRequestType(reqType)) { throw new IllegalArgumentException ("Invalid request type: " + reqType); } 346 this.requestType = reqType; 347 348 if (this.requestType == RELEASE_LOCK_REQUEST_TYPE || this.requestType == RECALL_COMMIT_LOCK_REQUEST_TYPE) { 349 if (this.lockLevel != LockLevel.NIL_LOCK_LEVEL) { 350 throw new IllegalArgumentException ("Cannot specify a lock level for release or recall commit(yet)"); 352 } 353 } 354 355 this.withWait = wait; 356 this.notifyAll = all; 357 358 if (wait) { 359 if ((waitArgs < 0) || (waitArgs > 2)) { throw new IllegalArgumentException ( 360 "Wait argument count must be 0, 1 or 2"); } 361 362 if (requestType != RELEASE_LOCK_REQUEST_TYPE) { throw new IllegalArgumentException ( 363 "Can't include withWait option for non lock release requests"); } 364 365 this.waitArgCount = waitArgs; 366 this.waitMillis = millis; 367 this.waitNanos = nanos; 368 } 369 } 370 371 } 372 | Popular Tags |