1 8 9 package com.sleepycat.je; 10 11 import java.util.HashSet ; 12 import java.util.Set ; 13 import java.util.logging.Level ; 14 15 import com.sleepycat.je.dbi.GetMode; 16 import com.sleepycat.je.dbi.CursorImpl; 17 import com.sleepycat.je.dbi.CursorImpl.SearchMode; 18 import com.sleepycat.je.log.LogUtils; 19 import com.sleepycat.je.txn.Locker; 20 import com.sleepycat.je.utilint.DatabaseUtil; 21 22 26 public class SecondaryCursor extends Cursor { 27 28 private SecondaryDatabase secondaryDb; 29 private Database primaryDb; 30 31 35 SecondaryCursor(SecondaryDatabase dbHandle, 36 Transaction txn, 37 CursorConfig cursorConfig) 38 throws DatabaseException { 39 40 super(dbHandle, txn, cursorConfig); 41 secondaryDb = dbHandle; 42 primaryDb = dbHandle.getPrimaryDatabase(); 43 } 44 45 48 private SecondaryCursor(SecondaryCursor cursor, boolean samePosition) 49 throws DatabaseException { 50 51 super(cursor, samePosition); 52 secondaryDb = cursor.secondaryDb; 53 primaryDb = cursor.primaryDb; 54 } 55 56 60 public Database getPrimaryDatabase() { 61 return primaryDb; 62 } 63 64 68 public Cursor dup(boolean samePosition) 69 throws DatabaseException { 70 71 checkState(true); 72 return new SecondaryCursor(this, samePosition); 73 } 74 75 79 public SecondaryCursor dupSecondary(boolean samePosition) 80 throws DatabaseException { 81 82 return (SecondaryCursor) dup(samePosition); 83 } 84 85 89 public OperationStatus delete() 90 throws DatabaseException { 91 92 checkState(true); 93 checkUpdatesAllowed("delete"); 94 trace(Level.FINEST, "SecondaryCursor.delete: ", null); 95 96 97 DatabaseEntry key = new DatabaseEntry(); 98 DatabaseEntry pKey = new DatabaseEntry(); 99 OperationStatus status = getCurrentInternal(key, pKey, 100 LockMode.RMW); 101 102 103 if (status == OperationStatus.SUCCESS) { 104 status = 105 primaryDb.deleteInternal(cursorImpl.getLocker(), pKey, null); 106 if (status != OperationStatus.SUCCESS) { 107 SecondaryDatabase secDb = (SecondaryDatabase) getDatabase(); 108 throw secDb.secondaryCorruptException(); 109 } 110 } 111 return status; 112 } 113 114 118 public OperationStatus put(DatabaseEntry key, DatabaseEntry data) 119 throws DatabaseException { 120 121 throw SecondaryDatabase.notAllowedException(); 122 } 123 124 128 public OperationStatus putNoOverwrite(DatabaseEntry key, 129 DatabaseEntry data) 130 throws DatabaseException { 131 132 throw SecondaryDatabase.notAllowedException(); 133 } 134 135 139 public OperationStatus putNoDupData(DatabaseEntry key, DatabaseEntry data) 140 throws DatabaseException { 141 142 throw SecondaryDatabase.notAllowedException(); 143 } 144 145 149 public OperationStatus putCurrent(DatabaseEntry data) 150 throws DatabaseException { 151 152 throw SecondaryDatabase.notAllowedException(); 153 } 154 155 159 public OperationStatus getCurrent(DatabaseEntry key, 160 DatabaseEntry data, 161 LockMode lockMode) 162 throws DatabaseException { 163 164 return getCurrent(key, new DatabaseEntry(), data, lockMode); 165 } 166 167 171 public OperationStatus getCurrent(DatabaseEntry key, 172 DatabaseEntry pKey, 173 DatabaseEntry data, 174 LockMode lockMode) 175 throws DatabaseException { 176 177 checkState(true); 178 checkArgsNoValRequired(key, pKey, data); 179 trace(Level.FINEST, "SecondaryCursor.getCurrent: ", lockMode); 180 181 return getCurrentInternal(key, pKey, data, lockMode); 182 } 183 184 188 public OperationStatus getFirst(DatabaseEntry key, 189 DatabaseEntry data, 190 LockMode lockMode) 191 throws DatabaseException { 192 193 return getFirst(key, new DatabaseEntry(), data, lockMode); 194 } 195 196 200 public OperationStatus getFirst(DatabaseEntry key, 201 DatabaseEntry pKey, 202 DatabaseEntry data, 203 LockMode lockMode) 204 throws DatabaseException { 205 206 checkState(false); 207 checkArgsNoValRequired(key, pKey, data); 208 trace(Level.FINEST, "SecondaryCursor.getFirst: ", lockMode); 209 210 return position(key, pKey, data, lockMode, true); 211 } 212 213 217 public OperationStatus getLast(DatabaseEntry key, 218 DatabaseEntry data, 219 LockMode lockMode) 220 throws DatabaseException { 221 222 return getLast(key, new DatabaseEntry(), data, lockMode); 223 } 224 225 229 public OperationStatus getLast(DatabaseEntry key, 230 DatabaseEntry pKey, 231 DatabaseEntry data, 232 LockMode lockMode) 233 throws DatabaseException { 234 235 checkState(false); 236 checkArgsNoValRequired(key, pKey, data); 237 trace(Level.FINEST, "SecondaryCursor.getLast: ", lockMode); 238 239 return position(key, pKey, data, lockMode, false); 240 } 241 242 246 public OperationStatus getNext(DatabaseEntry key, 247 DatabaseEntry data, 248 LockMode lockMode) 249 throws DatabaseException { 250 251 return getNext(key, new DatabaseEntry(), data, lockMode); 252 } 253 254 258 public OperationStatus getNext(DatabaseEntry key, 259 DatabaseEntry pKey, 260 DatabaseEntry data, 261 LockMode lockMode) 262 throws DatabaseException { 263 264 checkState(false); 265 checkArgsNoValRequired(key, pKey, data); 266 trace(Level.FINEST, "SecondaryCursor.getNext: ", lockMode); 267 268 if (cursorImpl.isNotInitialized()) { 269 return position(key, pKey, data, lockMode, true); 270 } else { 271 return retrieveNext(key, pKey, data, lockMode, GetMode.NEXT); 272 } 273 } 274 275 279 public OperationStatus getNextDup(DatabaseEntry key, 280 DatabaseEntry data, 281 LockMode lockMode) 282 throws DatabaseException { 283 284 return getNextDup(key, new DatabaseEntry(), data, lockMode); 285 } 286 287 291 public OperationStatus getNextDup(DatabaseEntry key, 292 DatabaseEntry pKey, 293 DatabaseEntry data, 294 LockMode lockMode) 295 throws DatabaseException { 296 297 checkState(true); 298 checkArgsNoValRequired(key, pKey, data); 299 trace(Level.FINEST, "SecondaryCursor.getNextDup: ", lockMode); 300 301 return retrieveNext(key, pKey, data, lockMode, GetMode.NEXT_DUP); 302 } 303 304 308 public OperationStatus getNextNoDup(DatabaseEntry key, 309 DatabaseEntry data, 310 LockMode lockMode) 311 throws DatabaseException { 312 313 return getNextNoDup(key, new DatabaseEntry(), data, lockMode); 314 } 315 316 320 public OperationStatus getNextNoDup(DatabaseEntry key, 321 DatabaseEntry pKey, 322 DatabaseEntry data, 323 LockMode lockMode) 324 throws DatabaseException { 325 326 checkState(false); 327 checkArgsNoValRequired(key, pKey, data); 328 trace(Level.FINEST, "SecondaryCursor.getNextNoDup: ", null, null, 329 lockMode); 330 331 if (cursorImpl.isNotInitialized()) { 332 return position(key, pKey, data, lockMode, true); 333 } else { 334 return retrieveNext(key, pKey, data, lockMode, 335 GetMode.NEXT_NODUP); 336 } 337 } 338 339 343 public OperationStatus getPrev(DatabaseEntry key, 344 DatabaseEntry data, 345 LockMode lockMode) 346 throws DatabaseException { 347 348 return getPrev(key, new DatabaseEntry(), data, lockMode); 349 } 350 351 355 public OperationStatus getPrev(DatabaseEntry key, 356 DatabaseEntry pKey, 357 DatabaseEntry data, 358 LockMode lockMode) 359 throws DatabaseException { 360 361 checkState(false); 362 checkArgsNoValRequired(key, pKey, data); 363 trace(Level.FINEST, "SecondaryCursor.getPrev: ", lockMode); 364 365 if (cursorImpl.isNotInitialized()) { 366 return position(key, pKey, data, lockMode, false); 367 } else { 368 return retrieveNext(key, pKey, data, lockMode, GetMode.PREV); 369 } 370 } 371 372 376 public OperationStatus getPrevDup(DatabaseEntry key, 377 DatabaseEntry data, 378 LockMode lockMode) 379 throws DatabaseException { 380 381 return getPrevDup(key, new DatabaseEntry(), data, lockMode); 382 } 383 384 388 public OperationStatus getPrevDup(DatabaseEntry key, 389 DatabaseEntry pKey, 390 DatabaseEntry data, 391 LockMode lockMode) 392 throws DatabaseException { 393 394 checkState(true); 395 checkArgsNoValRequired(key, pKey, data); 396 trace(Level.FINEST, "SecondaryCursor.getPrevDup: ", lockMode); 397 398 return retrieveNext(key, pKey, data, lockMode, GetMode.PREV_DUP); 399 } 400 401 405 public OperationStatus getPrevNoDup(DatabaseEntry key, 406 DatabaseEntry data, 407 LockMode lockMode) 408 throws DatabaseException { 409 410 return getPrevNoDup(key, new DatabaseEntry(), data, lockMode); 411 } 412 413 417 public OperationStatus getPrevNoDup(DatabaseEntry key, 418 DatabaseEntry pKey, 419 DatabaseEntry data, 420 LockMode lockMode) 421 throws DatabaseException { 422 423 checkState(false); 424 checkArgsNoValRequired(key, pKey, data); 425 trace(Level.FINEST, "SecondaryCursor.getPrevNoDup: ", lockMode); 426 427 if (cursorImpl.isNotInitialized()) { 428 return position(key, pKey, data, lockMode, false); 429 } else { 430 return retrieveNext(key, pKey, data, lockMode, 431 GetMode.PREV_NODUP); 432 } 433 } 434 435 439 public OperationStatus getSearchKey(DatabaseEntry key, 440 DatabaseEntry data, 441 LockMode lockMode) 442 throws DatabaseException { 443 444 return getSearchKey(key, new DatabaseEntry(), data, lockMode); 445 } 446 447 451 public OperationStatus getSearchKey(DatabaseEntry key, 452 DatabaseEntry pKey, 453 DatabaseEntry data, 454 LockMode lockMode) 455 throws DatabaseException { 456 457 checkState(false); 458 DatabaseUtil.checkForNullDbt(key, "key", true); 459 DatabaseUtil.checkForNullDbt(pKey, "pKey", false); 460 DatabaseUtil.checkForNullDbt(data, "data", false); 461 trace(Level.FINEST, "SecondaryCursor.getSearchKey: ", key, null, 462 lockMode); 463 464 return search(key, pKey, data, lockMode, SearchMode.SET); 465 } 466 467 471 public OperationStatus getSearchKeyRange(DatabaseEntry key, 472 DatabaseEntry data, 473 LockMode lockMode) 474 throws DatabaseException { 475 476 return getSearchKeyRange(key, new DatabaseEntry(), data, lockMode); 477 } 478 479 483 public OperationStatus getSearchKeyRange(DatabaseEntry key, 484 DatabaseEntry pKey, 485 DatabaseEntry data, 486 LockMode lockMode) 487 throws DatabaseException { 488 489 checkState(false); 490 DatabaseUtil.checkForNullDbt(key, "key", true); 491 DatabaseUtil.checkForNullDbt(pKey, "pKey", false); 492 DatabaseUtil.checkForNullDbt(data, "data", false); 493 trace(Level.FINEST, "SecondaryCursor.getSearchKeyRange: ", key, data, 494 lockMode); 495 496 return search(key, pKey, data, lockMode, SearchMode.SET_RANGE); 497 } 498 499 503 public OperationStatus getSearchBoth(DatabaseEntry key, 504 DatabaseEntry data, 505 LockMode lockMode) 506 throws DatabaseException { 507 508 throw SecondaryDatabase.notAllowedException(); 509 } 510 511 515 public OperationStatus getSearchBoth(DatabaseEntry key, 516 DatabaseEntry pKey, 517 DatabaseEntry data, 518 LockMode lockMode) 519 throws DatabaseException { 520 521 checkState(false); 522 DatabaseUtil.checkForNullDbt(key, "key", true); 523 DatabaseUtil.checkForNullDbt(pKey, "pKey", true); 524 DatabaseUtil.checkForNullDbt(data, "data", false); 525 trace(Level.FINEST, "SecondaryCursor.getSearchBoth: ", key, data, 526 lockMode); 527 528 return search(key, pKey, data, lockMode, SearchMode.BOTH); 529 } 530 531 535 public OperationStatus getSearchBothRange(DatabaseEntry key, 536 DatabaseEntry data, 537 LockMode lockMode) 538 throws DatabaseException { 539 540 throw SecondaryDatabase.notAllowedException(); 541 } 542 543 547 public OperationStatus getSearchBothRange(DatabaseEntry key, 548 DatabaseEntry pKey, 549 DatabaseEntry data, 550 LockMode lockMode) 551 throws DatabaseException { 552 553 checkState(false); 554 DatabaseUtil.checkForNullDbt(key, "key", true); 555 DatabaseUtil.checkForNullDbt(pKey, "pKey", true); 556 DatabaseUtil.checkForNullDbt(data, "data", false); 557 trace(Level.FINEST, "SecondaryCursor.getSearchBothRange: ", key, data, 558 lockMode); 559 560 return search(key, pKey, data, lockMode, SearchMode.BOTH_RANGE); 561 } 562 563 566 private OperationStatus getCurrentInternal(DatabaseEntry key, 567 DatabaseEntry pKey, 568 DatabaseEntry data, 569 LockMode lockMode) 570 throws DatabaseException { 571 572 OperationStatus status = getCurrentInternal(key, pKey, lockMode); 573 if (status == OperationStatus.SUCCESS) { 574 575 579 status = readPrimaryAfterGet(key, pKey, data, lockMode); 580 } 581 return status; 582 } 583 584 587 OperationStatus search(DatabaseEntry key, 588 DatabaseEntry pKey, 589 DatabaseEntry data, 590 LockMode lockMode, 591 SearchMode searchMode) 592 throws DatabaseException { 593 594 597 while (true) { 598 OperationStatus status = search(key, pKey, lockMode, searchMode); 599 if (status != OperationStatus.SUCCESS) { 600 return status; 601 } 602 status = readPrimaryAfterGet(key, pKey, data, lockMode); 603 if (status == OperationStatus.SUCCESS) { 604 return status; 605 } 606 } 607 } 608 609 612 OperationStatus position(DatabaseEntry key, 613 DatabaseEntry pKey, 614 DatabaseEntry data, 615 LockMode lockMode, 616 boolean first) 617 throws DatabaseException { 618 619 622 while (true) { 623 OperationStatus status = position(key, pKey, lockMode, first); 624 if (status != OperationStatus.SUCCESS) { 625 return status; 626 } 627 status = readPrimaryAfterGet(key, pKey, data, lockMode); 628 if (status == OperationStatus.SUCCESS) { 629 return status; 630 } 631 } 632 } 633 634 637 OperationStatus retrieveNext(DatabaseEntry key, 638 DatabaseEntry pKey, 639 DatabaseEntry data, 640 LockMode lockMode, 641 GetMode getMode) 642 throws DatabaseException { 643 644 647 while (true) { 648 OperationStatus status = retrieveNext(key, pKey, lockMode, 649 getMode); 650 if (status != OperationStatus.SUCCESS) { 651 return status; 652 } 653 status = readPrimaryAfterGet(key, pKey, data, lockMode); 654 if (status == OperationStatus.SUCCESS) { 655 return status; 656 } 657 } 658 } 659 660 678 private OperationStatus readPrimaryAfterGet(DatabaseEntry key, 679 DatabaseEntry pKey, 680 DatabaseEntry data, 681 LockMode lockMode) 682 throws DatabaseException { 683 684 690 DatabaseEntry copyToPartialEntry = null; 691 boolean readUncommitted = isReadUncommittedMode(lockMode); 692 if (readUncommitted && data.getPartial()) { 693 if (data.getPartialLength() == 0) { 694 695 data.setData(LogUtils.ZERO_LENGTH_BYTE_ARRAY); 696 return OperationStatus.SUCCESS; 697 } else { 698 699 copyToPartialEntry = data; 700 data = new DatabaseEntry(); 701 } 702 } 703 704 Locker locker = cursorImpl.getLocker(); 705 Cursor cursor = null; 706 try { 707 cursor = new Cursor(primaryDb, locker, null); 708 OperationStatus status = 709 cursor.search(pKey, data, lockMode, SearchMode.SET); 710 if (status != OperationStatus.SUCCESS) { 711 712 718 if (readUncommitted) { 719 status = getCurrentInternal(key, pKey, lockMode); 720 if (status == OperationStatus.KEYEMPTY) { 721 return status; 722 } 723 } 724 725 726 SecondaryDatabase secDb = (SecondaryDatabase) getDatabase(); 727 throw secDb.secondaryCorruptException(); 728 } 729 730 735 if (readUncommitted) { 736 SecondaryConfig config = 737 secondaryDb.getPrivateSecondaryConfig(); 738 739 744 if (config.getImmutableSecondaryKey()) { 745 746 } else if (config.getKeyCreator() != null) { 747 748 752 DatabaseEntry secKey = new DatabaseEntry(); 753 if (!config.getKeyCreator().createSecondaryKey 754 (secondaryDb, pKey, data, secKey) || 755 !secKey.equals(key)) { 756 return OperationStatus.KEYEMPTY; 757 } 758 } else if (config.getMultiKeyCreator() != null) { 759 760 764 Set results = new HashSet (); 765 config.getMultiKeyCreator().createSecondaryKeys 766 (secondaryDb, pKey, data, results); 767 if (!results.contains(key)) { 768 return OperationStatus.KEYEMPTY; 769 } 770 } 771 } 772 773 777 if (copyToPartialEntry != null) { 778 CursorImpl.setDbt(copyToPartialEntry, data.getData()); 779 } 780 return OperationStatus.SUCCESS; 781 } finally { 782 if (cursor != null) { 783 cursor.close(); 784 } 785 } 786 } 787 788 792 private void checkArgsNoValRequired(DatabaseEntry key, 793 DatabaseEntry pKey, 794 DatabaseEntry data) { 795 DatabaseUtil.checkForNullDbt(key, "key", false); 796 DatabaseUtil.checkForNullDbt(pKey, "pKey", false); 797 DatabaseUtil.checkForNullDbt(data, "data", false); 798 } 799 } 800 | Popular Tags |