1 8 9 package com.sleepycat.je.txn; 10 11 import java.util.ArrayList ; 12 import java.util.Collections ; 13 import java.util.HashSet ; 14 import java.util.Iterator ; 15 import java.util.List ; 16 import java.util.Set ; 17 18 import com.sleepycat.je.DatabaseException; 19 import com.sleepycat.je.dbi.MemoryBudget; 20 21 25 public class Lock { 26 private static final int REMOVE_LOCKINFO_OVERHEAD = 27 0 - MemoryBudget.LOCKINFO_OVERHEAD; 28 29 51 private LockInfo firstOwner; 52 private Set ownerSet; 53 private LockInfo firstWaiter; 54 private List waiterList; 55 private Long nodeId; 56 57 60 Lock(Long nodeId) { 61 this.nodeId = nodeId; 62 } 63 64 65 public Lock() { 66 } 67 68 Long getNodeId() { 69 return nodeId; 70 } 71 72 78 private void addWaiterToEndOfList(LockInfo waiter, 79 MemoryBudget mb, 80 int lockTableIndex) { 81 82 if (waiterList == null) { 83 if (firstWaiter == null) { 84 firstWaiter = waiter; 85 } else { 86 waiterList = new ArrayList (); 87 waiterList.add(waiter); 88 } 89 } else { 90 waiterList.add(waiter); 91 } 92 mb.updateLockMemoryUsage 93 (MemoryBudget.LOCKINFO_OVERHEAD, lockTableIndex); 94 } 95 96 99 private void addWaiterToHeadOfList(LockInfo waiter, 100 MemoryBudget mb, 101 int lockTableIndex) { 102 103 if (firstWaiter != null) { 104 if (waiterList == null) { 105 waiterList = new ArrayList (); 106 } 107 waiterList.add(0, firstWaiter); 108 } 109 110 firstWaiter = waiter; 111 mb.updateLockMemoryUsage 112 (MemoryBudget.LOCKINFO_OVERHEAD, lockTableIndex); 113 } 114 115 118 List getWaitersListClone() { 119 List dumpWaiters = new ArrayList (); 120 if (firstWaiter != null) { 121 dumpWaiters.add(firstWaiter); 122 } 123 124 if (waiterList != null) { 125 dumpWaiters.addAll(waiterList); 126 } 127 128 return dumpWaiters; 129 } 130 131 134 void flushWaiter(Locker locker, MemoryBudget mb, int lockTableIndex) { 135 if ((firstWaiter != null) && (firstWaiter.getLocker() == locker)) { 136 firstWaiter = null; 137 mb.updateLockMemoryUsage 138 (REMOVE_LOCKINFO_OVERHEAD, lockTableIndex); 139 } else if (waiterList != null) { 140 Iterator iter = waiterList.iterator(); 141 while (iter.hasNext()) { 142 LockInfo info = (LockInfo) iter.next(); 143 if (info.getLocker() == locker) { 144 iter.remove(); 145 mb.updateLockMemoryUsage 146 (REMOVE_LOCKINFO_OVERHEAD, lockTableIndex); 147 return; 148 } 149 } 150 } 151 } 152 153 private void addOwner(LockInfo newLock, 154 MemoryBudget mb, 155 int lockTableIndex) { 156 if (firstOwner == null) { 157 firstOwner = newLock; 158 } else { 159 if (ownerSet == null) { 160 ownerSet = new HashSet (); 161 } 162 ownerSet.add(newLock); 163 } 164 mb.updateLockMemoryUsage 165 (MemoryBudget.LOCKINFO_OVERHEAD, lockTableIndex); 166 } 167 168 171 Set getOwnersClone() { 172 173 174 Set owners; 175 if (ownerSet != null) { 176 owners = new HashSet (ownerSet); 177 } else { 178 owners = new HashSet (); 179 } 180 if (firstOwner != null) { 181 owners.add(firstOwner); 182 } 183 return owners; 184 } 185 186 189 private boolean flushOwner(LockInfo oldOwner, 190 MemoryBudget mb, 191 int lockTableIndex) { 192 boolean removed = false; 193 if (oldOwner != null) { 194 if (firstOwner == oldOwner) { 195 firstOwner = null; 196 return true; 197 } 198 199 if (ownerSet != null) { 200 removed = ownerSet.remove(oldOwner); 201 } 202 } 203 204 if (removed) { 205 mb.updateLockMemoryUsage(REMOVE_LOCKINFO_OVERHEAD, lockTableIndex); 206 } 207 return removed; 208 } 209 210 213 private LockInfo flushOwner(Locker locker, 214 MemoryBudget mb, 215 int lockTableIndex) { 216 LockInfo flushedInfo = null; 217 if ((firstOwner != null) && 218 (firstOwner.getLocker() == locker)) { 219 flushedInfo = firstOwner; 220 firstOwner = null; 221 } else if (ownerSet != null) { 222 Iterator iter = ownerSet.iterator(); 223 while (iter.hasNext()) { 224 LockInfo o = (LockInfo) iter.next(); 225 if (o.getLocker() == locker) { 226 iter.remove(); 227 flushedInfo = o; 228 } 229 } 230 } 231 if (flushedInfo != null) { 232 mb.updateLockMemoryUsage(REMOVE_LOCKINFO_OVERHEAD, lockTableIndex); 233 } 234 235 return flushedInfo; 236 } 237 238 242 private LockInfo getOwnerLockInfo(Locker locker) { 243 if ((firstOwner != null) && (firstOwner.getLocker() == locker)) { 244 return firstOwner; 245 } 246 247 if (ownerSet != null) { 248 Iterator iter = ownerSet.iterator(); 249 while (iter.hasNext()) { 250 LockInfo o = (LockInfo) iter.next(); 251 if (o.getLocker() == locker) { 252 return o; 253 } 254 } 255 } 256 257 return null; 258 } 259 260 266 boolean isOwner(Locker locker, LockType lockType) { 267 LockInfo o = getOwnerLockInfo(locker); 268 if (o != null) { 269 LockType ownedLockType = o.getLockType(); 270 if (lockType == ownedLockType) { 271 return true; 272 } 273 LockUpgrade upgrade = ownedLockType.getUpgrade(lockType); 274 if (!upgrade.getPromotion()) { 275 return true; 276 } 277 } 278 return false; 279 } 280 281 285 boolean isOwnedWriteLock(Locker locker) { 286 LockInfo o = getOwnerLockInfo(locker); 287 return o != null && o.getLockType().isWriteLock(); 288 } 289 290 295 boolean isWaiter(Locker locker) { 296 297 if (firstWaiter != null) { 298 if (firstWaiter.getLocker() == locker) { 299 return true; 300 } 301 } 302 303 if (waiterList != null) { 304 Iterator iter = waiterList.iterator(); 305 while (iter.hasNext()) { 306 LockInfo info = (LockInfo) iter.next(); 307 if (info.getLocker() == locker) { 308 return true; 309 } 310 } 311 } 312 return false; 313 } 314 315 int nWaiters() { 316 int count = 0; 317 if (firstWaiter != null) { 318 count++; 319 } 320 if (waiterList != null) { 321 count += waiterList.size(); 322 } 323 return count; 324 } 325 326 int nOwners() { 327 int count = 0; 328 if (firstOwner != null) { 329 count++; 330 } 331 332 if (ownerSet != null) { 333 count += ownerSet.size(); 334 } 335 return count; 336 } 337 338 343 LockGrantType lock(LockType requestType, 344 Locker locker, 345 boolean nonBlockingRequest, 346 MemoryBudget mb, 347 int lockTableIndex) { 348 349 assert validateRequest(locker); 351 352 LockInfo newLock = new LockInfo(locker, requestType); 353 LockGrantType grant = 354 tryLock(newLock, nWaiters() == 0, mb, lockTableIndex); 355 356 357 if (grant == LockGrantType.WAIT_NEW || 358 grant == LockGrantType.WAIT_PROMOTION || 359 grant == LockGrantType.WAIT_RESTART) { 360 361 367 if (requestType.getCausesRestart() && 368 grant != LockGrantType.WAIT_RESTART) { 369 LockInfo waiter = null; 370 Iterator iter = null; 371 372 if (waiterList != null) { 373 iter = waiterList.iterator(); 374 } 375 376 if (firstWaiter != null) { 377 waiter = firstWaiter; 378 } else if ((iter != null) && (iter.hasNext())) { 379 waiter = (LockInfo) iter.next(); 380 } 381 382 while (waiter != null) { 383 384 388 Locker waiterLocker = waiter.getLocker(); 389 LockType waiterType = waiter.getLockType(); 390 if (waiterType != LockType.RESTART && 391 locker != waiterLocker && 392 !locker.sharesLocksWith(waiterLocker)) { 393 LockConflict conflict = 394 waiterType.getConflict(requestType); 395 if (conflict.getRestart()) { 396 grant = LockGrantType.WAIT_RESTART; 397 break; 398 } 399 } 400 401 402 if ((iter != null) && (iter.hasNext())) { 403 waiter = (LockInfo) iter.next(); 404 } else { 405 waiter = null; 406 } 407 } 408 } 409 410 411 if (nonBlockingRequest) { 412 grant = LockGrantType.DENIED; 413 } else { 414 if (grant == LockGrantType.WAIT_PROMOTION) { 415 addWaiterToHeadOfList(newLock, mb, lockTableIndex); 416 } else { 417 assert grant == LockGrantType.WAIT_NEW || 418 grant == LockGrantType.WAIT_RESTART; 419 420 427 if (grant == LockGrantType.WAIT_RESTART) { 428 newLock.setLockType(LockType.RESTART); 429 } 430 431 addWaiterToEndOfList(newLock, mb, lockTableIndex); 432 } 433 } 434 } 435 436 return grant; 437 } 438 439 446 Set release(Locker locker, MemoryBudget mb, int lockTableIndex) { 447 448 LockInfo removedLock = flushOwner(locker, mb, lockTableIndex); 449 if (removedLock == null) { 450 451 return null; 452 } 453 454 Set lockersToNotify = Collections.EMPTY_SET; 455 456 if (nWaiters() == 0) { 457 458 return lockersToNotify; 459 } 460 461 465 LockInfo waiter = null; 466 Iterator iter = null; 467 boolean isFirstWaiter = false; 468 469 if (waiterList != null) { 470 iter = waiterList.iterator(); 471 } 472 473 if (firstWaiter != null) { 474 waiter = firstWaiter; 475 isFirstWaiter = true; 476 } else if ((iter != null) && (iter.hasNext())) { 477 waiter = (LockInfo) iter.next(); 478 } 479 480 while (waiter != null) { 481 482 LockType waiterType = waiter.getLockType(); 483 Locker waiterLocker = waiter.getLocker(); 484 LockGrantType grant; 485 if (waiterType == LockType.RESTART) { 486 487 grant = rangeInsertConflict(waiterLocker) ? 488 LockGrantType.WAIT_NEW : LockGrantType.NEW; 489 } else { 490 491 grant = tryLock(waiter, true, mb, lockTableIndex); 492 } 493 494 if (grant == LockGrantType.NEW || 495 grant == LockGrantType.EXISTING || 496 grant == LockGrantType.PROMOTION) { 497 498 if (isFirstWaiter) { 499 firstWaiter = null; 500 } else { 501 iter.remove(); 502 } 503 if (lockersToNotify == Collections.EMPTY_SET) { 504 lockersToNotify = new HashSet (); 505 } 506 lockersToNotify.add(waiterLocker); 507 mb.updateLockMemoryUsage 508 (REMOVE_LOCKINFO_OVERHEAD, lockTableIndex); 509 } else { 510 assert grant == LockGrantType.WAIT_NEW || 511 grant == LockGrantType.WAIT_PROMOTION || 512 grant == LockGrantType.WAIT_RESTART; 513 514 break; 515 } 516 517 518 if ((iter != null) && (iter.hasNext())) { 519 waiter = (LockInfo) iter.next(); 520 isFirstWaiter = false; 521 } else { 522 waiter = null; 523 } 524 } 525 return lockersToNotify; 526 } 527 528 545 private LockGrantType tryLock(LockInfo newLock, 546 boolean firstWaiterInLine, 547 MemoryBudget mb, 548 int lockTableIndex) { 549 550 551 if (nOwners() == 0) { 552 addOwner(newLock, mb, lockTableIndex); 553 return LockGrantType.NEW; 554 } 555 556 Locker locker = newLock.getLocker(); 557 LockType requestType = newLock.getLockType(); 558 LockUpgrade upgrade = null; 559 LockInfo lockToUpgrade = null; 560 boolean ownerExists = false; 561 boolean ownerConflicts = false; 562 563 568 LockInfo owner = null; 569 Iterator iter = null; 570 571 if (ownerSet != null) { 572 iter = ownerSet.iterator(); 573 } 574 575 if (firstOwner != null) { 576 owner = firstOwner; 577 } else if ((iter != null) && (iter.hasNext())) { 578 owner = (LockInfo) iter.next(); 579 } 580 581 while (owner != null) { 582 Locker ownerLocker = owner.getLocker(); 583 LockType ownerType = owner.getLockType(); 584 if (locker == ownerLocker) { 585 586 592 assert (upgrade == null); upgrade = ownerType.getUpgrade(requestType); 594 if (upgrade.getUpgrade() == null) { 595 return LockGrantType.EXISTING; 596 } else { 597 lockToUpgrade = owner; 598 } 599 } else { 600 601 607 if (!locker.sharesLocksWith(ownerLocker)) { 608 LockConflict conflict = ownerType.getConflict(requestType); 609 if (conflict.getRestart()) { 610 return LockGrantType.WAIT_RESTART; 611 } else { 612 if (!conflict.getAllowed()) { 613 ownerConflicts = true; 614 } 615 ownerExists = true; 616 } 617 } 618 } 619 620 621 if ((iter != null) && (iter.hasNext())) { 622 owner = (LockInfo) iter.next(); 623 } else { 624 owner = null; 625 } 626 } 627 628 629 if (upgrade != null) { 630 631 LockType upgradeType = upgrade.getUpgrade(); 632 assert upgradeType != null; 633 if (!ownerConflicts) { 634 635 lockToUpgrade.setLockType(upgradeType); 636 return upgrade.getPromotion() ? 637 LockGrantType.PROMOTION : LockGrantType.EXISTING; 638 } else { 639 640 return LockGrantType.WAIT_PROMOTION; 641 } 642 } else { 643 644 if (!ownerConflicts && (!ownerExists || firstWaiterInLine)) { 645 646 addOwner(newLock, mb, lockTableIndex); 647 return LockGrantType.NEW; 648 } else { 649 650 return LockGrantType.WAIT_NEW; 651 } 652 } 653 } 654 655 660 private boolean rangeInsertConflict(Locker waiterLocker) { 661 662 LockInfo owner = null; 663 Iterator iter = null; 664 665 if (ownerSet != null) { 666 iter = ownerSet.iterator(); 667 } 668 669 if (firstOwner != null) { 670 owner = firstOwner; 671 } else if ((iter != null) && (iter.hasNext())) { 672 owner = (LockInfo) iter.next(); 673 } 674 675 while (owner != null) { 676 Locker ownerLocker = owner.getLocker(); 677 if (ownerLocker != waiterLocker && 678 !ownerLocker.sharesLocksWith(waiterLocker) && 679 owner.getLockType() == LockType.RANGE_INSERT) { 680 return true; 681 } 682 683 684 if ((iter != null) && (iter.hasNext())) { 685 owner = (LockInfo) iter.next(); 686 } else { 687 owner = null; 688 } 689 } 690 691 return false; 692 } 693 694 697 void demote(Locker locker) { 698 LockInfo owner = getOwnerLockInfo(locker); 699 if (owner != null) { 700 LockType type = owner.getLockType(); 701 if (type.isWriteLock()) { 702 owner.setLockType((type == LockType.RANGE_WRITE) ? 703 LockType.RANGE_READ : LockType.READ); 704 } 705 } 706 } 707 708 712 LockType transfer(Locker currentLocker, 713 Locker destLocker, 714 MemoryBudget mb, 715 int lockTableIndex) 716 throws DatabaseException { 717 718 722 LockType lockType = null; 723 int numRemovedLockInfos = 0; 724 725 if (firstOwner != null) { 726 if (firstOwner.getLocker() == destLocker) { 727 firstOwner = null; 728 numRemovedLockInfos++; 729 } else if (firstOwner.getLocker() == currentLocker) { 730 lockType = setNewLocker(firstOwner, destLocker); 731 } 732 } 733 734 if (ownerSet != null) { 735 Iterator iter = ownerSet.iterator(); 736 while (iter.hasNext()) { 737 LockInfo owner = (LockInfo) iter.next(); 738 if (owner.getLocker() == destLocker) { 739 iter.remove(); 740 numRemovedLockInfos++; 741 } else if (owner.getLocker() == currentLocker) { 742 lockType = setNewLocker(owner, destLocker); 743 } 744 } 745 } 746 747 748 if ((firstWaiter != null) && (firstWaiter.getLocker() == destLocker)) { 749 firstWaiter = null; 750 numRemovedLockInfos++; 751 } 752 if (waiterList != null) { 753 Iterator iter = waiterList.iterator(); 754 while (iter.hasNext()) { 755 LockInfo info = (LockInfo) iter.next(); 756 if (info.getLocker() == destLocker) { 757 iter.remove(); 758 numRemovedLockInfos++; 759 } 760 } 761 } 762 763 mb.updateLockMemoryUsage(0 - (numRemovedLockInfos * 764 MemoryBudget.LOCKINFO_OVERHEAD), 765 lockTableIndex); 766 return lockType; 767 } 768 769 private LockType setNewLocker(LockInfo owner, Locker destLocker) 770 throws DatabaseException { 771 772 owner.setLocker(destLocker); 773 destLocker.addLock(nodeId, this, owner.getLockType(), 774 LockGrantType.NEW); 775 return owner.getLockType(); 776 } 777 778 783 LockType transferMultiple(Locker currentLocker, 784 Locker[] destLockers, 785 MemoryBudget mb, 786 int lockTableIndex) 787 throws DatabaseException { 788 789 LockType lockType = null; 790 LockInfo oldOwner = null; 791 792 if (destLockers.length == 1) { 793 return transfer(currentLocker, destLockers[0], mb, lockTableIndex); 794 } else { 795 796 799 if (firstOwner != null) { 800 for (int i = 0; i < destLockers.length; i++) { 801 if (firstOwner.getLocker() == destLockers[i]) { 802 firstOwner = null; 803 break; 804 } 805 } 806 } 807 808 if (ownerSet != null) { 809 Iterator ownersIter = ownerSet.iterator(); 810 while (ownersIter.hasNext()) { 811 LockInfo o = (LockInfo) ownersIter.next(); 812 for (int i = 0; i < destLockers.length; i++) { 813 if (o.getLocker() == destLockers[i]) { 814 ownersIter.remove(); 815 break; 816 } 817 } 818 } 819 } 820 821 824 if (firstOwner != null) { 825 oldOwner = cloneLockInfo(firstOwner, 826 currentLocker, 827 destLockers, 828 mb, 829 lockTableIndex); 830 } 831 832 if ((ownerSet != null) && (oldOwner == null)) { 833 Iterator ownersIter = ownerSet.iterator(); 834 while (ownersIter.hasNext()) { 835 LockInfo o = (LockInfo) ownersIter.next(); 836 oldOwner = cloneLockInfo(o, 837 currentLocker, 838 destLockers, 839 mb, 840 lockTableIndex); 841 if (oldOwner != null) { 842 break; 843 } 844 } 845 } 846 847 850 if (firstWaiter != null) { 851 for (int i = 0; i < destLockers.length; i++) { 852 if (firstWaiter.getLocker() == destLockers[i]) { 853 firstWaiter = null; 854 break; 855 } 856 } 857 } 858 859 if (waiterList != null) { 860 Iterator iter = waiterList.iterator(); 861 while (iter.hasNext()) { 862 LockInfo o = (LockInfo) iter.next(); 863 for (int i = 0; i < destLockers.length; i++) { 864 if (o.getLocker() == destLockers[i]) { 865 iter.remove(); 866 break; 867 } 868 } 869 } 870 } 871 } 872 873 boolean removed = flushOwner(oldOwner, mb, lockTableIndex); 874 assert removed; 875 return lockType; 876 } 877 878 882 private LockInfo cloneLockInfo(LockInfo oldOwner, 883 Locker currentLocker, 884 Locker[] destLockers, 885 MemoryBudget mb, 886 int lockTableIndex) 887 throws DatabaseException { 888 889 if (oldOwner.getLocker() == currentLocker) { 890 try { 891 LockType lockType = oldOwner.getLockType(); 892 for (int i = 0; i < destLockers.length; i++) { 893 LockInfo clonedLockInfo = (LockInfo) oldOwner.clone(); 894 clonedLockInfo.setLocker(destLockers[i]); 895 destLockers[i].addLock(nodeId, this, lockType, 896 LockGrantType.NEW); 897 addOwner(clonedLockInfo, mb, lockTableIndex); 898 } 899 return oldOwner; 900 } catch (CloneNotSupportedException e) { 901 throw new DatabaseException(e); 902 } 903 } else { 904 return null; 905 } 906 } 907 908 912 Locker getWriteOwnerLocker() { 913 914 LockInfo owner = null; 915 Iterator iter = null; 916 917 if (ownerSet != null) { 918 iter = ownerSet.iterator(); 919 } 920 921 if (firstOwner != null) { 922 owner = firstOwner; 923 } else if ((iter != null) && (iter.hasNext())) { 924 owner = (LockInfo) iter.next(); 925 } 926 927 while (owner != null) { 928 929 if (owner.getLockType().isWriteLock()) { 930 return owner.getLocker(); 931 } 932 933 934 if ((iter != null) && (iter.hasNext())) { 935 owner = (LockInfo) iter.next(); 936 } else { 937 owner = null; 938 } 939 } 940 941 return null; 942 } 943 944 947 private boolean validateRequest(Locker locker) { 948 if (firstWaiter != null) { 949 if (firstWaiter.getLocker() == locker) { 950 assert false : "locker " + locker + 951 " is already on waiters list."; 952 } 953 } 954 955 if (waiterList != null) { 956 Iterator iter = waiterList.iterator(); 957 while (iter.hasNext()) { 958 LockInfo o = (LockInfo) iter.next(); 959 if (o.getLocker() == locker) { 960 assert false : "locker " + locker + 961 " is already on waiters list."; 962 } 963 } 964 } 965 return true; 966 } 967 968 971 public String toString() { 972 StringBuffer sb = new StringBuffer (); 973 sb.append(" NodeId:").append(nodeId); 974 sb.append(" Owners:"); 975 if (nOwners() == 0) { 976 sb.append(" (none)"); 977 } else { 978 if (firstOwner != null) { 979 sb.append(firstOwner); 980 } 981 982 if (ownerSet != null) { 983 Iterator iter = ownerSet.iterator(); 984 while (iter.hasNext()) { 985 LockInfo info = (LockInfo) iter.next(); 986 sb.append(info); 987 } 988 } 989 } 990 991 sb.append(" Waiters:"); 992 if (nWaiters() == 0) { 993 sb.append(" (none)"); 994 } else { 995 sb.append(getWaitersListClone()); 996 } 997 return sb.toString(); 998 } 999 } 1000 | Popular Tags |