1 7 package org.jboss.cache.lock; 8 9 import org.apache.commons.logging.Log; 10 import org.apache.commons.logging.LogFactory; 11 import org.jboss.cache.Fqn; 12 import org.jboss.cache.Node; 13 import org.jboss.cache.NodeSPI; 14 15 import java.util.ArrayList ; 16 import java.util.Collection ; 17 import java.util.HashSet ; 18 import java.util.Iterator ; 19 import java.util.Set ; 20 import java.util.concurrent.TimeUnit ; 21 import java.util.concurrent.locks.Lock ; 22 23 64 public class IdentityLock implements NodeLock 65 { 66 67 70 private boolean PRINT_LOCK_DETAILS = Boolean.getBoolean("print_lock_details"); 71 72 private static final Log log = LogFactory.getLog(IdentityLock.class); 73 private static boolean trace = log.isTraceEnabled(); 74 private final LockStrategy lock_; 75 private final LockMap map_; 76 private final boolean mustReacquireRead_; 77 private NodeSPI node; 78 79 82 public IdentityLock(NodeSPI node) 83 { 84 this(LockStrategyFactory.getLockStrategy(), node); 85 log.trace("Using default lock level"); 86 } 87 88 93 public IdentityLock(IsolationLevel level, NodeSPI node) 94 { 95 this(LockStrategyFactory.getLockStrategy(level), node); 96 } 97 98 private IdentityLock(LockStrategy strategy, NodeSPI node) 99 { 100 lock_ = strategy; 101 mustReacquireRead_ = strategy instanceof LockStrategyReadCommitted; 102 map_ = new LockMap(); 103 this.node = node; 104 } 105 106 109 public Node getNode() 110 { 111 return node; 112 } 113 114 117 public Fqn getFqn() 118 { 119 if (node == null) 120 { 121 return null; 122 } 123 return node.getFqn(); 124 } 125 126 132 public Set getReaderOwners() 133 { 134 return map_.readerOwners(); 135 } 136 137 142 public Object getWriterOwner() 143 { 144 return map_.writerOwner(); 145 } 146 147 159 public boolean acquireWriteLock(Object caller, long timeout) throws LockingException, TimeoutException, InterruptedException 160 { 161 if (trace) 162 { 163 log.trace(new StringBuffer ("acquiring WL: fqn=").append(getFqn()).append(", caller=").append(caller). 164 append(", lock=").append(toString(PRINT_LOCK_DETAILS))); 165 } 166 boolean flag = acquireWriteLock0(caller, timeout); 167 if (trace) 168 { 169 log.trace(new StringBuffer ("acquired WL: fqn=").append(getFqn()).append(", caller=").append(caller). 170 append(", lock=").append(toString(PRINT_LOCK_DETAILS))); 171 } 172 return flag; 173 } 174 175 private boolean acquireWriteLock0(Object caller, long timeout) throws LockingException, TimeoutException, InterruptedException 176 { 177 if (caller == null) 178 { 179 throw new IllegalArgumentException ("acquireWriteLock(): null caller"); 180 } 181 182 if (map_.isOwner(caller, LockMap.OWNER_WRITE)) 183 { 184 if (trace) 185 { 186 log.trace("acquireWriteLock(): caller already owns lock for " + getFqn() + " (caller=" + caller + ')'); 187 } 188 return false; } 190 191 if (map_.isOwner(caller, LockMap.OWNER_READ)) 193 { 194 Lock wLock; 196 try 197 { 198 if (trace) 199 { 200 log.trace("upgrading RL to WL for " + caller + ", timeout=" + timeout + ", locks: " + map_.printInfo()); 201 } 202 wLock = lock_.upgradeLockAttempt(timeout); 203 } 204 catch (UpgradeException ue) 205 { 206 String errStr = "acquireWriteLock(): lock upgrade failed for " + getFqn() + " (caller=" + caller + ')'; 207 log.error(errStr, ue); 208 throw new UpgradeException(errStr, ue); 209 } 210 if (wLock == null) 211 { 212 release(caller); map_.removeReader(caller); 214 String errStr = "upgrade lock for " + getFqn() + " could not be acquired after " + timeout + " ms." + 215 " Lock map ownership " + map_.printInfo() + " (caller=" + caller + ')'; 216 log.error(errStr); 217 throw new UpgradeException(errStr); 218 } 219 try 220 { 221 if (trace) 222 { 223 log.trace("upgrading lock for " + getFqn()); 224 } 225 map_.upgrade(caller); 226 } 227 catch (OwnerNotExistedException ex) 228 { 229 throw new UpgradeException("Can't upgrade lock to WL for " + getFqn() + ", error in LockMap.upgrade(): " + ex); 230 } 231 } 232 else 233 { 234 boolean rc = lock_.writeLock().tryLock(timeout, TimeUnit.MILLISECONDS); 236 237 if (!rc) 239 { 240 String errStr = "write lock for " + getFqn() + " could not be acquired after " + timeout + " ms. " + 241 "Locks: " + map_.printInfo() + " (caller=" + caller + ", lock info: " + toString(true) + ')'; 242 log.error(errStr); 243 throw new TimeoutException(errStr); 244 } 245 map_.setWriterIfNotNull(caller); 246 } 247 return true; 248 } 249 250 259 public boolean acquireReadLock(Object caller, long timeout) throws LockingException, TimeoutException, InterruptedException 260 { 261 if (trace) 262 { 263 log.trace(new StringBuffer ("acquiring RL: fqn=").append(getFqn()).append(", caller=").append(caller). 264 append(", lock=").append(toString(PRINT_LOCK_DETAILS))); 265 } 266 boolean flag = acquireReadLock0(caller, timeout); 267 if (trace) 268 { 269 log.trace(new StringBuffer ("acquired RL: fqn=").append(getFqn()).append(", caller=").append(caller). 270 append(", lock=").append(toString(PRINT_LOCK_DETAILS))); 271 } 272 return flag; 273 } 274 275 private boolean acquireReadLock0(Object caller, long timeout) 276 throws LockingException, TimeoutException, InterruptedException 277 { 278 boolean rc; 279 280 if (caller == null) 281 { 282 throw new IllegalArgumentException ("owner is null"); 283 } 284 285 boolean hasRead = false; 286 boolean hasRequired = false; 287 if (mustReacquireRead_) 288 { 289 hasRequired = map_.isOwner(caller, LockMap.OWNER_WRITE); 290 if (!hasRequired) 291 { 292 hasRead = map_.isOwner(caller, LockMap.OWNER_READ); 293 } 294 } 295 else if (map_.isOwner(caller, LockMap.OWNER_ANY)) 296 { 297 hasRequired = true; 298 } 299 300 if (hasRequired) 301 { 302 if (trace) 303 { 304 StringBuffer sb = new StringBuffer (64); 305 sb.append("acquireReadLock(): caller ").append(caller).append(" already owns lock for ").append(getFqn()); 306 log.trace(sb.toString()); 307 } 308 return false; } 310 311 rc = lock_.readLock().tryLock(timeout, TimeUnit.MILLISECONDS); 312 313 if (!rc) 315 { 316 StringBuffer sb = new StringBuffer (); 317 sb.append("read lock for ").append(getFqn()).append(" could not be acquired by ").append(caller); 318 sb.append(" after ").append(timeout).append(" ms. " + "Locks: ").append(map_.printInfo()); 319 sb.append(", lock info: ").append(toString(true)); 320 log.error(sb.toString()); 321 throw new TimeoutException(sb.toString()); 322 } 323 324 if (!hasRead) 326 { 327 map_.addReader(caller); } 329 return true; 330 } 331 332 337 public void release(Object caller) 338 { 339 if (caller == null) 340 { 341 throw new IllegalArgumentException ("IdentityLock.release(): null owner object."); 342 } 343 344 if (map_.isOwner(caller, LockMap.OWNER_READ)) 346 { 347 map_.removeReader(caller); 348 lock_.readLock().unlock(); 349 } 350 else if (map_.isOwner(caller, LockMap.OWNER_WRITE)) 351 { 352 map_.removeWriter(); 353 lock_.writeLock().unlock(); 354 } 355 } 356 357 360 public void releaseAll() 361 { 362 try 363 { 364 if ((map_.writerOwner()) != null) 365 { 366 lock_.writeLock().unlock(); 368 } 369 370 map_.releaseReaderOwners(lock_); 371 } 372 finally 373 { 374 map_.removeAll(); 375 } 376 } 377 378 381 public void releaseForce() 382 { 383 releaseAll(); 384 } 385 386 389 public boolean isReadLocked() 390 { 391 return map_.isReadLocked(); 392 } 393 394 397 public boolean isWriteLocked() 398 { 399 return map_.writerOwner() != null; 400 } 401 402 405 public boolean isLocked() 406 { 407 return isReadLocked() || isWriteLocked(); 408 } 409 410 415 public boolean isOwner(Object o) 416 { 417 return map_.isOwner(o, LockMap.OWNER_ANY); 418 } 419 420 public String toString() 421 { 422 return toString(false); 423 } 424 425 public String toString(boolean print_lock_details) 426 { 427 StringBuffer sb = new StringBuffer (); 428 toString(sb, print_lock_details); 429 return sb.toString(); 430 } 431 432 public void toString(StringBuffer sb) 433 { 434 toString(sb, false); 435 } 436 437 public void toString(StringBuffer sb, boolean print_lock_details) 438 { 439 boolean printed_read_owners = false; 440 Collection read_owners = lock_ != null ? getReaderOwners() : null; 441 if (read_owners != null && read_owners.size() > 0) 442 { 443 Iterator iter = read_owners.iterator(); 448 read_owners = new ArrayList (read_owners.size()); 449 while (iter.hasNext()) 450 { 451 read_owners.add(iter.next()); 452 } 453 454 sb.append("read owners=").append(read_owners); 455 printed_read_owners = true; 456 } 457 else 458 { 459 read_owners = null; 460 } 461 462 Object write_owner = lock_ != null ? getWriterOwner() : null; 463 if (write_owner != null) 464 { 465 if (printed_read_owners) 466 { 467 sb.append(", "); 468 } 469 sb.append("write owner=").append(write_owner); 470 } 471 if (read_owners == null && write_owner == null) 472 { 473 sb.append("<unlocked>"); 474 } 475 if (print_lock_details) 476 { 477 sb.append(" (").append(lock_.toString()).append(')'); 478 } 479 } 480 481 public boolean acquire(Object caller, long timeout, NodeLock.LockType lock_type) throws LockingException, TimeoutException, InterruptedException 482 { 483 try 484 { 485 if (lock_type == NodeLock.LockType.NONE) 486 { 487 return true; 488 } 489 else if (lock_type == NodeLock.LockType.READ) 490 { 491 return acquireReadLock(caller, timeout); 492 } 493 else 494 { 495 return acquireWriteLock(caller, timeout); 496 } 497 } 498 catch (UpgradeException e) 499 { 500 StringBuffer buf = new StringBuffer ("failure upgrading lock: fqn=").append(getFqn()).append(", caller=").append(caller). 501 append(", lock=").append(toString(true)); 502 if (trace) 503 { 504 log.trace(buf.toString()); 505 } 506 throw new UpgradeException(buf.toString(), e); 507 } 508 catch (LockingException e) 509 { 510 StringBuffer buf = new StringBuffer ("failure acquiring lock: fqn=").append(getFqn()).append(", caller=").append(caller). 511 append(", lock=").append(toString(true)); 512 if (trace) 513 { 514 log.trace(buf.toString()); 515 } 516 throw new LockingException(buf.toString(), e); 517 } 518 catch (TimeoutException e) 519 { 520 StringBuffer buf = new StringBuffer ("failure acquiring lock: fqn=").append(getFqn()).append(", caller=").append(caller). 521 append(", lock=").append(toString(true)); 522 if (trace) 523 { 524 log.trace(buf.toString()); 525 } 526 throw new TimeoutException(buf.toString(), e); 527 } 528 } 529 530 public Set acquireAll(Object caller, long timeout, LockType lock_type) 531 throws LockingException, TimeoutException, InterruptedException 532 { 533 boolean acquired; 534 Set retval = new HashSet (); 535 536 if (lock_type == LockType.NONE) 537 { 538 return retval; 539 } 540 acquired = acquire(caller, timeout, lock_type); 541 if (acquired) 542 { 543 retval.add(this); 544 } 545 546 for (NodeSPI n : node.getChildrenDirect()) 547 { 548 retval.addAll(n.getLock().acquireAll(caller, timeout, lock_type)); 549 } 550 return retval; 551 } 552 553 public void releaseAll(Object owner) 554 { 555 for (NodeSPI n : node.getChildrenDirect()) 556 { 557 n.getLock().releaseAll(owner); 558 } 559 release(owner); 560 } 561 562 private void printIndent(StringBuffer sb, int indent) 563 { 564 if (sb != null) 565 { 566 for (int i = 0; i < indent; i++) 567 { 568 sb.append(" "); 569 } 570 } 571 } 572 573 public void printLockInfo(StringBuffer sb, int indent) 574 { 575 boolean locked = isLocked(); 576 577 printIndent(sb, indent); 578 sb.append(Fqn.SEPARATOR).append(node.getFqn().getLastElement()); 579 if (locked) 580 { 581 sb.append("\t("); 582 toString(sb); 583 sb.append(")"); 584 } 585 586 for (NodeSPI n : node.getChildrenDirect()) 587 { 588 sb.append("\n"); 589 n.getLock().printLockInfo(sb, indent + 4); 590 } 591 } 592 593 } 594 | Popular Tags |