1 21 22 package org.apache.derby.impl.store.access.btree.index; 23 24 import org.apache.derby.iapi.services.sanity.SanityManager; 25 26 import org.apache.derby.iapi.error.StandardException; 27 28 import org.apache.derby.iapi.store.access.conglomerate.TransactionManager; 29 30 import org.apache.derby.iapi.store.access.ConglomerateController; 31 32 import org.apache.derby.iapi.store.access.RowUtil; 33 import org.apache.derby.iapi.store.access.TransactionController; 34 35 import org.apache.derby.iapi.store.raw.FetchDescriptor; 36 import org.apache.derby.iapi.store.raw.LockingPolicy; 37 import org.apache.derby.iapi.store.raw.Page; 38 import org.apache.derby.iapi.store.raw.RecordHandle; 39 import org.apache.derby.iapi.store.raw.Transaction; 40 41 import org.apache.derby.iapi.types.DataValueDescriptor; 42 43 import org.apache.derby.iapi.types.RowLocation; 44 45 import org.apache.derby.impl.store.access.btree.BTree; 46 import org.apache.derby.impl.store.access.btree.BTreeLockingPolicy; 47 import org.apache.derby.impl.store.access.btree.ControlRow; 48 import org.apache.derby.impl.store.access.btree.LeafControlRow; 49 import org.apache.derby.impl.store.access.btree.OpenBTree; 50 import org.apache.derby.impl.store.access.btree.BTreeRowPosition; 51 import org.apache.derby.impl.store.access.btree.WaitError; 52 53 61 class B2IRowLocking3 implements BTreeLockingPolicy 62 { 63 64 68 69 73 protected ConglomerateController base_cc; 74 75 79 protected OpenBTree open_btree; 80 81 85 private LockingPolicy scan_locking_policy; 86 87 90 private Transaction rawtran; 91 92 96 B2IRowLocking3( 97 Transaction rawtran, 98 int lock_level, 99 LockingPolicy locking_policy, 100 ConglomerateController base_cc, 101 OpenBTree open_btree) 102 { 103 this.rawtran = rawtran; 104 this.base_cc = base_cc; 105 this.open_btree = open_btree; 106 this.scan_locking_policy = 107 rawtran.newLockingPolicy( 108 LockingPolicy.MODE_RECORD, 109 TransactionController.ISOLATION_READ_COMMITTED, true); 110 } 111 112 116 117 private boolean _lockScan( 118 RecordHandle rh, 119 boolean forUpdate, 120 boolean wait) 121 throws StandardException 122 { 123 boolean ret_val = true; 124 125 127 if (!forUpdate) 128 { 129 ret_val = 130 scan_locking_policy.lockRecordForRead( 131 rawtran, open_btree.getContainerHandle(), 132 rh, wait, false); 133 } 134 else 135 { 136 ret_val = 137 scan_locking_policy.lockRecordForWrite( 138 rawtran, rh, false, wait); 139 } 140 141 return(ret_val); 142 } 143 144 180 private boolean lockPreviousToFirstKey( 181 LeafControlRow current_leaf, 182 LeafControlRow aux_leaf, 183 int lock_operation, 184 int lock_duration) 185 throws StandardException 186 { 187 190 boolean ret_status = 192 base_cc.lockRow( 193 BTree.ROOTPAGEID, 194 RecordHandle.PREVIOUS_KEY_HANDLE, 195 lock_operation, 196 false , 197 lock_duration); 198 199 if (!ret_status) 200 { 201 current_leaf.release(); 202 current_leaf = null; 203 204 if (aux_leaf != null) 205 { 206 aux_leaf.release(); 207 aux_leaf = null; 208 } 209 210 base_cc.lockRow( 212 BTree.ROOTPAGEID, 213 RecordHandle.PREVIOUS_KEY_HANDLE, 214 lock_operation, 215 true , 216 lock_duration); 217 } 218 219 return(ret_status); 220 } 221 222 223 265 private boolean lockRowOnPage( 266 BTree btree, 267 LeafControlRow current_leaf, 268 LeafControlRow aux_leaf, 269 int current_slot, 270 boolean check_changed_rowloc, 271 FetchDescriptor lock_fetch_desc, 272 DataValueDescriptor[] lock_template, 273 RowLocation lock_row_loc, 274 int lock_operation, 275 int lock_duration) 276 throws StandardException 277 { 278 if (SanityManager.DEBUG) 279 { 280 SanityManager.ASSERT(current_leaf != null); 281 282 if (current_slot <= 0 || 283 current_slot >= current_leaf.getPage().recordCount()) 284 { 285 SanityManager.THROWASSERT( 286 "current_slot = " + current_slot + 287 "; current_leaf.getPage().recordCount() = " + 288 current_leaf.getPage().recordCount()); 289 } 290 291 292 if (!(btree instanceof B2I)) 293 { 294 SanityManager.THROWASSERT( 295 "btree not instance of B2I, it is " + 296 btree.getClass().getName()); 297 } 298 299 SanityManager.ASSERT(lock_template != null, "template is null"); 300 301 SanityManager.ASSERT( 305 lock_row_loc == lock_template[lock_template.length - 1], 306 "row_loc is not the object in last column of lock_template."); 307 } 308 309 RecordHandle rec_handle = 311 current_leaf.getPage().fetchFromSlot( 312 (RecordHandle) null, current_slot, 313 lock_template, lock_fetch_desc, true); 314 315 boolean ret_status = 317 base_cc.lockRow( 318 lock_row_loc, 319 lock_operation, 320 false , lock_duration); 321 322 if (!ret_status) 323 { 324 326 if (current_leaf != null) 327 { 328 current_leaf.release(); 329 current_leaf = null; 330 } 331 if (aux_leaf != null) 332 { 333 aux_leaf.release(); 334 aux_leaf = null; 335 } 336 337 base_cc.lockRow( 338 lock_row_loc, 339 lock_operation, 340 true , lock_duration); 341 } 342 343 return(ret_status); 344 } 345 346 private boolean searchLeftAndLockPreviousKey( 347 B2I b2i, 348 LeafControlRow current_leaf, 349 int current_slot, 350 FetchDescriptor lock_fetch_desc, 351 DataValueDescriptor[] lock_template, 352 RowLocation lock_row_loc, 353 OpenBTree open_btree, 354 int lock_operation, 355 int lock_duration) 356 throws StandardException 357 { 358 boolean latches_released = false; 359 LeafControlRow prev_leaf; 360 LeafControlRow prev_prev_leaf; 361 362 try 363 { 364 367 prev_leaf = 368 (LeafControlRow) current_leaf.getLeftSibling(open_btree); 369 370 } 371 catch (WaitError e) 372 { 373 long previous_pageno = current_leaf.getleftSiblingPageNumber(); 374 375 current_leaf.release(); 378 current_leaf = null; 379 380 prev_leaf = (LeafControlRow) 382 ControlRow.Get(open_btree, previous_pageno); 383 384 latches_released = true; 385 } 386 387 while (true) 388 { 389 try 390 { 391 394 if (prev_leaf.getPage().recordCount() > 1) 395 { 396 399 boolean ret_status = 400 lockRowOnPage( 401 b2i, 402 prev_leaf, 403 current_leaf, 404 prev_leaf.getPage().recordCount() - 1, 405 false, 406 lock_fetch_desc, 407 lock_template, 408 lock_row_loc, 409 lock_operation, 410 lock_duration); 411 412 if (!ret_status) 413 { 414 prev_leaf = null; 415 current_leaf = null; 416 latches_released = true; 417 } 418 419 break; 420 } 421 else if (prev_leaf.isLeftmostLeaf()) 422 { 423 boolean ret_status = 426 lockPreviousToFirstKey( 427 prev_leaf, current_leaf, 428 lock_operation, lock_duration); 429 430 if (!ret_status) 431 { 432 prev_leaf = null; 433 current_leaf = null; 434 latches_released = true; 435 } 436 437 break; 438 } 439 440 448 prev_prev_leaf = 449 (LeafControlRow) prev_leaf.getLeftSibling(open_btree); 450 prev_leaf.release(); 451 prev_leaf = prev_prev_leaf; 452 prev_prev_leaf = null; 453 } 454 catch (WaitError e) 455 { 456 long previous_pageno = prev_leaf.getleftSiblingPageNumber(); 457 458 current_leaf.release(); 461 current_leaf = null; 462 prev_leaf.release(); 463 prev_leaf = null; 464 465 prev_leaf = (LeafControlRow) 467 ControlRow.Get(open_btree, previous_pageno); 468 469 latches_released = true; 470 } 471 } 472 if (prev_leaf != null) 473 prev_leaf.release(); 474 475 return(!latches_released); 476 477 } 478 479 483 484 517 protected boolean _lockScanRow( 518 OpenBTree open_btree, 519 BTree btree, 520 BTreeRowPosition pos, 521 boolean request_row_lock, 522 boolean request_scan_lock, 523 FetchDescriptor lock_fetch_desc, 524 DataValueDescriptor[] lock_template, 525 RowLocation lock_row_loc, 526 boolean previous_key_lock, 527 boolean forUpdate, 528 int lock_operation) 529 throws StandardException 530 { 531 boolean latch_released = false; 532 B2I b2i = (B2I) btree; 533 534 if (request_row_lock) 535 { 536 541 if (pos.current_slot == 0) 542 { 543 547 552 latch_released = 553 !lockNonScanPreviousRow( 554 btree, 555 pos.current_leaf, 556 1 , 557 lock_fetch_desc, 558 lock_template, 559 lock_row_loc, 560 open_btree, 561 lock_operation, 562 TransactionManager.LOCK_COMMIT_DURATION); 563 564 if (SanityManager.DEBUG) 566 { 567 latch_released = 568 OpenBTree.test_errors( 569 open_btree, 570 "B2iRowLocking3_1_lockScanRow", false, 571 this, pos.current_leaf, latch_released); 572 } 573 } 574 else 575 { 576 578 latch_released = 579 !lockRowOnPage( 580 btree, 581 pos.current_leaf, 582 (LeafControlRow) null , 583 pos.current_slot, 584 true, 585 lock_fetch_desc, 586 lock_template, 587 lock_row_loc, 588 lock_operation, 589 TransactionManager.LOCK_COMMIT_DURATION); 590 591 if (SanityManager.DEBUG) 593 { 594 latch_released = 595 OpenBTree.test_errors( 596 open_btree, 597 "B2iRowLocking3_2_lockScanRow", false, 598 this, pos.current_leaf, latch_released); 599 } 600 } 601 } 602 603 if (request_scan_lock && !latch_released) 604 { 605 607 611 612 latch_released = 613 !lockScan( 614 pos.current_leaf, 615 (LeafControlRow) null, false, 617 ConglomerateController.LOCK_READ); 619 if (SanityManager.DEBUG) 621 { 622 623 latch_released = 624 OpenBTree.test_errors( 625 open_btree, 626 "B2iRowLocking3_3_lockScanRow", true, 627 this, pos.current_leaf, latch_released); 628 } 629 } 630 631 return(!latch_released); 632 } 633 634 638 639 640 649 650 660 public boolean lockScan( 661 LeafControlRow current_leaf, 662 ControlRow aux_control_row, 663 boolean forUpdate, 664 int lock_operation) 665 throws StandardException 666 { 667 RecordHandle scan_lock_rh = 670 current_leaf.getPage().makeRecordHandle( 671 RecordHandle.RECORD_ID_PROTECTION_HANDLE); 672 673 boolean ret_status = 675 _lockScan(scan_lock_rh, forUpdate, false ); 676 677 if (!ret_status) 678 { 679 current_leaf.release(); 680 current_leaf = null; 681 682 if (aux_control_row != null) 683 { 684 aux_control_row.release(); 685 aux_control_row = null; 686 } 687 688 _lockScan(scan_lock_rh, forUpdate, true ); 691 692 697 if (!forUpdate) 698 { 699 scan_locking_policy.unlockRecordAfterRead( 700 rawtran, open_btree.getContainerHandle(), 701 scan_lock_rh, false, true); 702 } 703 else 704 { 705 } 710 } 711 712 return(ret_status); 713 } 714 715 728 public boolean lockScanForReclaimSpace( 729 LeafControlRow current_leaf) 730 throws StandardException 731 { 732 RecordHandle scan_lock_rh = 735 current_leaf.getPage().makeRecordHandle( 736 RecordHandle.RECORD_ID_PROTECTION_HANDLE); 737 738 return( 740 _lockScan(scan_lock_rh, true , false )); 741 } 742 743 750 public boolean lockScanCommittedDeletedRow( 751 OpenBTree open_btree, 752 LeafControlRow leaf, 753 DataValueDescriptor[] template, 754 FetchDescriptor lock_fetch_desc, 755 int slot_no) 756 throws StandardException 757 { 758 if (SanityManager.DEBUG) 759 { 760 SanityManager.ASSERT(leaf != null); 761 762 if (slot_no <= 0 || slot_no >= leaf.getPage().recordCount()) 763 { 764 SanityManager.THROWASSERT( 765 "slot_no = " + slot_no + 766 "; leaf.getPage().recordCount() = " + 767 leaf.getPage().recordCount()); 768 } 769 770 SanityManager.ASSERT(template != null, "template is null"); 771 } 772 773 RowLocation row_loc = (RowLocation) 774 template[((B2I) open_btree.getConglomerate()).rowLocationColumn]; 775 776 leaf.getPage().fetchFromSlot( 778 (RecordHandle) null, slot_no, template, lock_fetch_desc, true); 779 780 return( 782 base_cc.lockRow(row_loc, 783 ConglomerateController.LOCK_UPD, 784 false , 785 TransactionManager.LOCK_COMMIT_DURATION)); 786 } 787 788 817 public boolean lockScanRow( 818 OpenBTree open_btree, 819 BTree btree, 820 BTreeRowPosition pos, 821 boolean request_scan_lock, 822 FetchDescriptor lock_fetch_desc, 823 DataValueDescriptor[] lock_template, 824 RowLocation lock_row_loc, 825 boolean previous_key_lock, 826 boolean forUpdate, 827 int lock_operation) 828 throws StandardException 829 { 830 return( 831 _lockScanRow( 832 open_btree, 833 btree, 834 pos, 835 true, request_scan_lock, 837 lock_fetch_desc, 838 lock_template, 839 lock_row_loc, 840 previous_key_lock, 841 forUpdate, 842 lock_operation)); 843 } 844 845 852 public void unlockScanRecordAfterRead( 853 BTreeRowPosition pos, 854 boolean forUpdate) 855 throws StandardException 856 { 857 return; 858 } 859 860 868 public void unlockScan( 869 long page_number) 870 { 871 try 874 { 875 RecordHandle scan_lock_rh = 876 open_btree.makeRecordHandle( 877 page_number, RecordHandle.RECORD_ID_PROTECTION_HANDLE); 878 879 scan_locking_policy.unlockRecordAfterRead( 880 rawtran, open_btree.getContainerHandle(), 881 scan_lock_rh, false, true); 882 } 883 catch (StandardException se) 884 { 885 if (SanityManager.DEBUG) 886 SanityManager.THROWASSERT("error from make RecordHandle."); 887 } 888 889 } 890 891 898 899 906 public boolean lockNonScanPreviousRow( 907 BTree btree, 908 LeafControlRow current_leaf, 909 int current_slot, 910 FetchDescriptor lock_fetch_desc, 911 DataValueDescriptor[] lock_template, 912 RowLocation lock_row_loc, 913 OpenBTree open_btree, 914 int lock_operation, 915 int lock_duration) 916 throws StandardException 917 { 918 boolean ret_status; 919 920 if (SanityManager.DEBUG) 921 { 922 SanityManager.ASSERT(btree instanceof B2I); 923 } 924 925 if (current_slot > 1) 926 { 927 929 931 ret_status = 932 lockRowOnPage( 933 btree, 934 current_leaf, (LeafControlRow) null, 935 current_slot - 1, 936 false, 937 lock_fetch_desc, 938 lock_template, 939 lock_row_loc, 940 lock_operation, lock_duration); 941 } 942 else 943 { 944 if (SanityManager.DEBUG) 947 SanityManager.ASSERT(current_slot == 1); 948 949 if (current_leaf.isLeftmostLeaf()) 950 { 951 ret_status = 954 lockPreviousToFirstKey( 955 current_leaf, (LeafControlRow) null, 956 lock_operation, lock_duration); 957 } 958 else 959 { 960 963 970 ret_status = this.searchLeftAndLockPreviousKey( 974 (B2I) btree, 975 current_leaf, current_slot, 976 lock_fetch_desc, lock_template, lock_row_loc, 977 open_btree, lock_operation, lock_duration); 978 } 979 } 980 981 return(ret_status); 982 } 983 984 991 public boolean lockNonScanRow( 992 BTree btree, 993 LeafControlRow current_leaf, 994 LeafControlRow aux_leaf, 995 DataValueDescriptor[] current_row, 996 int lock_operation) 997 throws StandardException 998 { 999 if (SanityManager.DEBUG) 1000 { 1001 SanityManager.ASSERT(btree instanceof B2I); 1002 } 1003 B2I b2i = (B2I) btree; 1004 1005 boolean ret_status = 1007 base_cc.lockRow( 1008 (RowLocation) current_row[b2i.rowLocationColumn], 1009 lock_operation, 1010 false , 1011 TransactionManager.LOCK_COMMIT_DURATION); 1012 1013 if (!ret_status) 1014 { 1015 1017 if (current_leaf != null) 1018 { 1019 current_leaf.release(); 1020 current_leaf = null; 1021 } 1022 if (aux_leaf != null) 1023 { 1024 aux_leaf.release(); 1025 aux_leaf = null; 1026 } 1027 1028 base_cc.lockRow( 1029 (RowLocation) current_row[b2i.rowLocationColumn], 1030 lock_operation, 1031 true , 1032 TransactionManager.LOCK_COMMIT_DURATION); 1033 } 1034 1035 return(ret_status); 1036 } 1037 1038 public boolean lockNonScanRowOnPage( 1039 BTree btree, 1040 LeafControlRow current_leaf, 1041 int current_slot, 1042 FetchDescriptor lock_fetch_desc, 1043 DataValueDescriptor[] lock_template, 1044 RowLocation lock_row_loc, 1045 int lock_operation) 1046 throws StandardException 1047 { 1048 return( 1049 lockRowOnPage( 1050 btree, 1051 current_leaf, 1052 null, 1053 current_slot, 1054 false, 1055 lock_fetch_desc, 1056 lock_template, 1057 lock_row_loc, 1058 lock_operation, 1059 TransactionManager.LOCK_COMMIT_DURATION)); 1060 } 1061} 1062 | Popular Tags |