1 21 22 package org.apache.derby.impl.services.locks; 23 24 import org.apache.derby.iapi.services.locks.Lockable; 25 import org.apache.derby.iapi.services.locks.Latch; 26 27 import org.apache.derby.iapi.services.sanity.SanityManager; 28 29 import java.util.Dictionary ; 30 import java.util.Stack ; 31 import java.util.List ; 32 import java.util.ListIterator ; 33 34 43 44 public class LockControl implements Control { 45 46 private final Lockable ref; 47 48 58 private Lock firstGrant; 59 private List granted; 60 private List waiting; 61 private Lock lastPossibleSkip; 62 63 protected LockControl(Lock firstLock, Lockable ref) { 64 super(); 65 this.ref = ref; 66 67 69 firstGrant = firstLock; 70 } 71 72 private LockControl(LockControl copyFrom) 74 { 75 super(); 76 77 this.ref = copyFrom.ref; 78 this.firstGrant = copyFrom.firstGrant; 79 80 if (copyFrom.granted != null) 81 this.granted = new java.util.LinkedList (copyFrom.granted); 82 83 if (copyFrom.waiting != null) 84 this.waiting = new java.util.LinkedList (copyFrom.waiting); 85 86 this.lastPossibleSkip = copyFrom.lastPossibleSkip; 87 } 88 89 public LockControl getLockControl() { 90 return this; 91 } 92 93 95 public boolean isEmpty() { 96 97 if (!isUnlocked()) 99 return false; 100 101 return (waiting == null) || waiting.isEmpty(); 102 } 103 104 107 void grant(Lock lockItem) { 108 109 lockItem.grant(); 110 111 List lgranted = granted; 112 113 if (lgranted == null) { 114 if (firstGrant == null) { 115 firstGrant = lockItem; 117 } else { 118 lgranted = granted = new java.util.LinkedList (); 120 lgranted.add(firstGrant); 121 lgranted.add(lockItem); 122 firstGrant = null; 123 } 124 } else { 125 lgranted.add(lockItem); 127 } 128 } 129 130 132 public boolean unlock(Latch lockInGroup, int unlockCount) { 133 134 136 if (unlockCount == 0) 137 unlockCount = lockInGroup.getCount(); 138 139 List lgranted = granted; 140 141 for (int index = 0; unlockCount > 0; ) { 143 144 Lock lockInSet; 145 146 if (firstGrant != null) { 147 if (SanityManager.DEBUG) { 148 SanityManager.ASSERT(lockInGroup.equals(firstGrant)); 149 } 150 lockInSet = firstGrant; 151 } else { 152 index = lgranted.indexOf(lockInGroup); 154 155 if (SanityManager.DEBUG) { 156 SanityManager.ASSERT(index != -1); 157 } 158 lockInSet = (Lock) lgranted.get(index); 159 } 160 161 unlockCount -= lockInSet.unlock(unlockCount); 162 163 if (lockInSet.getCount() != 0) { 164 if (SanityManager.DEBUG) { 165 if (unlockCount != 0) 166 SanityManager.THROWASSERT("locked item didn't reduce unlock count to zero " + unlockCount); 167 } 168 continue; 169 } 170 171 if (firstGrant == lockInSet) { 172 if (SanityManager.DEBUG) { 173 if (unlockCount != 0) 174 SanityManager.THROWASSERT("item is still locked! " + unlockCount); 175 } 176 firstGrant = null; 177 } 178 else { 179 lgranted.remove(index); 180 } 181 } 182 183 return true; 184 } 185 186 192 193 public boolean isGrantable( 194 boolean noWaitersBeforeMe, 195 Object compatabilitySpace, 196 Object qualifier) 197 { 198 if (isUnlocked()) 199 return true; 200 201 boolean grantLock = false; 202 203 Lockable lref = ref; 204 List lgranted = granted; 205 206 { 207 boolean selfCompatible = lref.lockerAlwaysCompatible(); 210 211 int index = 0; 212 int endIndex = firstGrant == null ? lgranted.size() : 0; 213 do { 214 215 Lock gl = firstGrant == null ? (Lock) lgranted.get(index) : firstGrant; 216 217 boolean sameSpace = 218 (gl.getCompatabilitySpace().equals(compatabilitySpace)); 219 220 if (sameSpace && selfCompatible) 221 { 222 225 grantLock = true; 226 continue; 227 } 228 else if (!lref.requestCompatible(qualifier, gl.getQualifier())) 229 { 230 233 grantLock = false; 234 break; 235 } 236 else 237 { 238 241 if (sameSpace || noWaitersBeforeMe) 242 { 243 grantLock = true; 244 } 245 } 246 } while (++index < endIndex); 247 } 248 249 return(grantLock); 250 } 251 252 269 270 public Lock addLock(LockSet ls, Object compatabilitySpace, Object qualifier) { 271 272 if (SanityManager.DEBUG) { 273 274 if (!(!isUnlocked() || (firstWaiter() != null))) 275 SanityManager.THROWASSERT("entered in totally unlocked mode " + isUnlocked() + " " + (firstWaiter() != null)); 276 } 277 278 boolean grantLock = false; 283 boolean otherWaiters = (firstWaiter() != null); 284 285 Lock lockItem = null; 286 Lockable lref = ref; 287 288 boolean spaceHasALock = false; 294 boolean noGrantAtAll = false; 295 if (!grantLock && !isUnlocked()) { 296 297 boolean selfCompatible = lref.lockerAlwaysCompatible(); 298 299 int index = 0; 300 int endIndex = firstGrant == null ? granted.size() : 0; 301 do { 302 303 Lock gl = firstGrant == null ? (Lock) granted.get(index) : firstGrant; 304 305 306 boolean sameSpace = (gl.getCompatabilitySpace().equals(compatabilitySpace)); 307 308 if (sameSpace && selfCompatible) { 311 312 spaceHasALock = true; 313 314 if (noGrantAtAll) 315 break; 316 317 if (qualifier == gl.getQualifier()) 318 lockItem = gl; 319 320 grantLock = true; 321 continue; 322 } 323 324 if (!lref.requestCompatible(qualifier, gl.getQualifier())) { 327 grantLock = false; 328 lockItem = null; 329 330 if (spaceHasALock) 333 break; 334 335 noGrantAtAll = true; 336 } 337 338 341 if (!noGrantAtAll && (sameSpace || !otherWaiters)) { 342 grantLock = true; 343 } 344 } while (++index < endIndex); 345 } 346 347 if (lockItem != null) { 348 if (SanityManager.DEBUG) { 349 if (!grantLock) { 350 SanityManager.THROWASSERT("lock is not granted !" + lockItem); 351 } 352 } 353 354 lockItem.count++; 356 return lockItem; 357 } 358 359 if (grantLock) { 360 lockItem = new Lock(compatabilitySpace, lref, qualifier); 361 grant(lockItem); 362 return lockItem; 363 } 364 365 ActiveLock waitingLock = new ActiveLock(compatabilitySpace, lref, qualifier); 366 367 if (spaceHasALock) { 370 waitingLock.canSkip = true; 371 } 372 373 if (waiting == null) 374 waiting = new java.util.LinkedList (); 375 376 addWaiter(waiting, waitingLock, ls); 378 379 if (waitingLock.canSkip) { 380 lastPossibleSkip = waitingLock; 381 } 382 383 return waitingLock; 384 } 385 386 protected boolean isUnlocked() { 387 388 if (firstGrant != null) 390 return false; 391 392 List lgranted = granted; 393 394 return (lgranted == null) || lgranted.isEmpty(); 395 } 396 397 401 public ActiveLock firstWaiter() { 402 if ((waiting == null) || waiting.isEmpty()) 403 return null; 404 return (ActiveLock) waiting.get(0); 405 } 406 407 408 411 ActiveLock getNextWaiter(ActiveLock item, boolean remove, LockSet ls) { 412 413 ActiveLock nextWaitingLock = null; 414 415 if (remove && (waiting.get(0) == item)) 416 { 417 popFrontWaiter(waiting, ls); 420 421 nextWaitingLock = firstWaiter(); 422 } 423 else if ((lastPossibleSkip != null) && (lastPossibleSkip != item)) 424 { 425 428 431 int itemIndex = waiting.indexOf(item); 432 int removeIndex = remove ? itemIndex : -1; 433 434 435 436 438 441 if (itemIndex != waiting.size() - 1) { 442 443 for (ListIterator li = waiting.listIterator(itemIndex + 1); li.hasNext();) { 444 ActiveLock al = (ActiveLock) li.next(); 446 447 if (al.canSkip) { 448 nextWaitingLock = al; 449 break; 450 } 451 } 452 } 453 454 if (remove) { 455 removeWaiter(waiting, removeIndex, ls); 456 } 457 458 } else { 459 if (remove) { 460 int count = removeWaiter(waiting, item, ls); 461 462 if (SanityManager.DEBUG) { 463 if (count != 1) 464 { 465 SanityManager.THROWASSERT( 466 "count = " + count + "item = " + item + 467 "waiting = " + waiting); 468 } 469 } 470 } 471 } 472 473 if (remove && (item == lastPossibleSkip)) 474 lastPossibleSkip = null; 475 476 if (nextWaitingLock != null) { 477 if (!nextWaitingLock.setPotentiallyGranted()) 478 nextWaitingLock = null; 479 } 480 481 return nextWaitingLock; 482 } 483 484 487 public Lockable getLockable() { 488 return ref; 489 } 490 public Lock getFirstGrant() { 491 return firstGrant; 492 } 493 public List getGranted() { 494 return granted; 495 } 496 public List getWaiting() { 497 return waiting; 498 } 499 500 503 504 protected void giveUpWait(Object item, LockSet ls) { 505 506 int count = removeWaiter(waiting, item, ls); 507 if (item == lastPossibleSkip) 508 lastPossibleSkip = null; 509 510 if (SanityManager.DEBUG) { 511 if (count != 1) 512 { 513 SanityManager.THROWASSERT( 514 "count = " + count + "item = " + item + 515 "waiting = " + waiting); 516 } 517 } 518 } 519 520 523 524 533 public void addWaiters(Dictionary waiters) { 534 535 if ((waiting == null) || waiting.isEmpty()) 536 return; 537 538 Object previous = this; 539 for (ListIterator li = waiting.listIterator(); li.hasNext(); ) { 540 541 ActiveLock waitingLock = ((ActiveLock) li.next()); 542 543 Object waiter = waitingLock.getCompatabilitySpace(); 544 545 waiters.put(waiter, waitingLock); 546 waiters.put(waitingLock, previous); 547 previous = waitingLock; 548 } 549 } 550 551 555 List getGrants() { 556 557 List ret; 558 559 if (firstGrant != null) { 560 ret = new java.util.LinkedList (); 561 ret.add(firstGrant); 562 } 563 else 564 { 565 ret = new java.util.LinkedList (granted); 566 } 567 568 return ret; 569 } 570 571 574 public final Lock getLock(Object compatabilitySpace, Object qualifier) { 575 576 if (isUnlocked()) 577 return null; 578 579 List lgranted = granted; 580 581 582 int index = 0; 583 int endIndex = firstGrant == null ? lgranted.size() : 0; 584 do { 585 586 Lock gl = firstGrant == null ? (Lock) lgranted.get(index) : firstGrant; 587 588 if (!gl.getCompatabilitySpace().equals(compatabilitySpace)) 589 continue; 590 591 if (gl.getQualifier() == qualifier) 592 return gl; 593 594 } while (++index < endIndex); 595 return null; 596 } 597 598 602 603 public Control shallowClone() 604 { 605 return new LockControl(this); 606 } 607 609 616 private void addWaiter(List waiting, 617 Lock lockItem, 618 LockSet ls) { 619 620 waiting.add(lockItem); 622 623 ls.oneMoreWaiter(); 625 } 626 627 635 private Object popFrontWaiter(List waiting, LockSet ls) { 636 ls.oneLessWaiter(); 638 639 return waiting.remove(0); 641 } 642 643 644 654 private Object removeWaiter(List waiting, 655 int index, 656 LockSet ls) { 657 ls.oneLessWaiter(); 659 660 return waiting.remove(index); 662 } 663 664 673 private int removeWaiter(List waiting, 674 Object item, 675 LockSet ls) { 676 ls.oneLessWaiter(); 678 679 return waiting.remove(item) ? 1 : 0; 681 } 682 } 683 684 685 | Popular Tags |