1 8 9 package com.sleepycat.je.incomp; 10 11 import java.io.File ; 12 import java.io.IOException ; 13 14 import junit.framework.TestCase; 15 16 import com.sleepycat.je.CheckpointConfig; 17 import com.sleepycat.je.Cursor; 18 import com.sleepycat.je.Database; 19 import com.sleepycat.je.DatabaseConfig; 20 import com.sleepycat.je.DatabaseEntry; 21 import com.sleepycat.je.DatabaseException; 22 import com.sleepycat.je.DbInternal; 23 import com.sleepycat.je.Environment; 24 import com.sleepycat.je.EnvironmentConfig; 25 import com.sleepycat.je.OperationStatus; 26 import com.sleepycat.je.Transaction; 27 import com.sleepycat.je.config.EnvironmentParams; 28 import com.sleepycat.je.tree.BIN; 29 import com.sleepycat.je.tree.DBIN; 30 import com.sleepycat.je.tree.IN; 31 import com.sleepycat.je.util.TestUtils; 32 33 66 public class INCompressorTest extends TestCase { 67 private static final boolean DEBUG = false; 68 private static final int NUM_RECS = 257; 69 70 private File envHome; 71 private Environment env; 72 private Database db; 73 private IN in; 74 private BIN bin; 75 private DBIN dbin; 76 private boolean hasDups; 77 78 79 private DatabaseEntry entry0 = new DatabaseEntry(new byte[] {0}); 80 private DatabaseEntry entry1 = new DatabaseEntry(new byte[] {1}); 81 private DatabaseEntry entry2 = new DatabaseEntry(new byte[] {2}); 82 private DatabaseEntry keyFound = new DatabaseEntry(); 83 private DatabaseEntry dataFound = new DatabaseEntry(); 84 85 public INCompressorTest() { 86 envHome = new File (System.getProperty(TestUtils.DEST_DIR)); 87 } 88 89 public void setUp() 90 throws IOException { 91 92 TestUtils.removeLogFiles("Setup", envHome, false); 93 } 94 95 public void tearDown() 96 throws Exception { 97 98 if (env != null) { 99 try { env.close(); } catch (DatabaseException ignored) { } 100 } 101 TestUtils.removeLogFiles("TearDown", envHome, false); 102 env = null; 103 db = null; 104 in = null; 105 bin = null; 106 dbin = null; 107 entry0 = null; 108 entry1 = null; 109 entry2 = null; 110 keyFound = null; 111 dataFound = null; 112 } 113 114 public void testDeleteTransactional() 115 throws DatabaseException { 116 117 118 openAndInit(true, false); 119 OperationStatus status; 120 121 122 Transaction txn = env.beginTransaction(null, null); 123 Cursor cursor = db.openCursor(txn, null); 124 status = cursor.getFirst(keyFound, dataFound, null); 125 assertEquals(OperationStatus.SUCCESS, status); 126 checkBinEntriesAndCursors(bin, 2, 1); 127 128 129 status = cursor.delete(); 130 assertEquals(OperationStatus.SUCCESS, status); 131 env.compress(); 132 checkBinEntriesAndCursors(bin, 2, 1); 133 134 135 cursor.close(); 136 env.compress(); 137 checkBinEntriesAndCursors(bin, 2, 0); 138 139 140 txn.commit(); 141 checkBinEntriesAndCursors(bin, 2, 0); 142 143 144 env.compress(); 145 checkBinEntriesAndCursors(bin, 1, 0); 146 147 148 assertEquals(2, in.getNEntries()); 149 150 closeEnv(); 151 } 152 153 public void testDeleteNonTransactional() 154 throws DatabaseException { 155 156 157 openAndInit(false, false); 158 OperationStatus status; 159 160 161 Cursor cursor = db.openCursor(null, null); 162 status = cursor.getFirst(keyFound, dataFound, null); 163 assertEquals(OperationStatus.SUCCESS, status); 164 checkBinEntriesAndCursors(bin, 2, 1); 165 166 167 status = cursor.delete(); 168 assertEquals(OperationStatus.SUCCESS, status); 169 env.compress(); 170 checkBinEntriesAndCursors(bin, 2, 1); 171 172 173 cursor.close(); 174 checkBinEntriesAndCursors(bin, 2, 0); 175 176 177 env.compress(); 178 checkBinEntriesAndCursors(bin, 1, 0); 179 180 181 assertEquals(2, in.getNEntries()); 182 183 closeEnv(); 184 } 185 186 public void testDeleteDuplicate() 187 throws DatabaseException { 188 189 190 openAndInit(false, true); 191 OperationStatus status; 192 193 194 Cursor cursor = db.openCursor(null, null); 195 status = cursor.getFirst(keyFound, dataFound, null); 196 assertEquals(OperationStatus.SUCCESS, status); 197 checkBinEntriesAndCursors(dbin, 2, 1); 198 199 200 status = cursor.delete(); 201 assertEquals(OperationStatus.SUCCESS, status); 202 env.compress(); 203 checkBinEntriesAndCursors(dbin, 2, 1); 204 205 206 cursor.close(); 207 checkBinEntriesAndCursors(dbin, 2, 0); 208 209 210 env.compress(); 211 checkBinEntriesAndCursors(dbin, 1, 0); 212 213 214 assertEquals(2, in.getNEntries()); 215 checkBinEntriesAndCursors(bin, 2, 0); 216 217 closeEnv(); 218 } 219 220 public void testRemoveEmptyBIN() 221 throws DatabaseException { 222 223 224 openAndInit(false, false); 225 OperationStatus status; 226 227 228 Cursor cursor = db.openCursor(null, null); 229 status = cursor.getFirst(keyFound, dataFound, null); 230 assertEquals(OperationStatus.SUCCESS, status); 231 checkBinEntriesAndCursors(bin, 2, 1); 232 233 234 status = cursor.delete(); 235 assertEquals(OperationStatus.SUCCESS, status); 236 status = cursor.getNext(keyFound, dataFound, null); 237 assertEquals(OperationStatus.SUCCESS, status); 238 status = cursor.delete(); 239 assertEquals(OperationStatus.SUCCESS, status); 240 env.compress(); 241 checkBinEntriesAndCursors(bin, 2, 1); 242 243 244 cursor.close(); 245 checkBinEntriesAndCursors(bin, 2, 0); 246 247 248 env.compress(); 249 checkBinEntriesAndCursors(bin, 0, 0); 250 251 252 assertEquals(1, in.getNEntries()); 253 254 closeEnv(); 255 } 256 257 public void testRemoveEmptyDBIN() 258 throws DatabaseException { 259 260 261 openAndInit(false, true); 262 OperationStatus status; 263 264 265 Cursor cursor = db.openCursor(null, null); 266 status = cursor.getFirst(keyFound, dataFound, null); 267 assertEquals(OperationStatus.SUCCESS, status); 268 checkBinEntriesAndCursors(dbin, 2, 1); 269 270 271 status = cursor.delete(); 272 assertEquals(OperationStatus.SUCCESS, status); 273 status = cursor.getNext(keyFound, dataFound, null); 274 assertEquals(OperationStatus.SUCCESS, status); 275 status = cursor.delete(); 276 assertEquals(OperationStatus.SUCCESS, status); 277 env.compress(); 278 checkBinEntriesAndCursors(dbin, 2, 1); 279 280 281 cursor.close(); 282 checkBinEntriesAndCursors(dbin, 2, 0); 283 284 285 env.compress(); 286 checkBinEntriesAndCursors(dbin, 0, 0); 287 288 289 assertEquals(2, in.getNEntries()); 290 checkBinEntriesAndCursors(bin, 1, 0); 291 292 closeEnv(); 293 } 294 295 public void testRemoveEmptyDBINandBIN() 296 throws DatabaseException { 297 298 299 openAndInit(false, true); 300 OperationStatus status; 301 302 303 Cursor cursor = db.openCursor(null, null); 304 status = cursor.getSearchKey(entry1, dataFound, null); 305 assertEquals(OperationStatus.SUCCESS, status); 306 status = cursor.delete(); 307 assertEquals(OperationStatus.SUCCESS, status); 308 env.compress(); 309 checkBinEntriesAndCursors(bin, 2, 1); 310 checkBinEntriesAndCursors(dbin, 2, 0); 311 312 313 status = cursor.getFirst(keyFound, dataFound, null); 314 assertEquals(OperationStatus.SUCCESS, status); 315 env.compress(); 316 checkBinEntriesAndCursors(bin, 2, 1); 317 checkBinEntriesAndCursors(dbin, 2, 1); 318 319 320 status = cursor.delete(); 321 assertEquals(OperationStatus.SUCCESS, status); 322 status = cursor.getNext(keyFound, dataFound, null); 323 assertEquals(OperationStatus.SUCCESS, status); 324 status = cursor.delete(); 325 assertEquals(OperationStatus.SUCCESS, status); 326 env.compress(); 327 checkBinEntriesAndCursors(bin, 2, 1); 328 checkBinEntriesAndCursors(dbin, 2, 1); 329 330 331 cursor.close(); 332 checkBinEntriesAndCursors(bin, 2, 0); 333 checkBinEntriesAndCursors(dbin, 2, 0); 334 335 336 env.compress(); 337 344 env.compress(); 345 346 checkBinEntriesAndCursors(bin, 0, 0); 347 checkBinEntriesAndCursors(dbin, 0, 0); 348 349 350 assertEquals(1, in.getNEntries()); 351 352 closeEnv(); 353 } 354 355 public void testAbortInsert() 356 throws DatabaseException { 357 358 359 openAndInit(true, false); 360 361 362 Transaction txn = env.beginTransaction(null, null); 363 Cursor cursor = db.openCursor(txn, null); 364 cursor.put(entry2, entry0); 365 checkBinEntriesAndCursors(bin, 3, 1); 366 367 368 cursor.close(); 369 env.compress(); 370 checkBinEntriesAndCursors(bin, 3, 0); 371 372 373 txn.abort(); 374 checkBinEntriesAndCursors(bin, 3, 0); 375 376 377 env.compress(); 378 checkBinEntriesAndCursors(bin, 2, 0); 379 380 381 assertEquals(2, in.getNEntries()); 382 383 closeEnv(); 384 } 385 386 public void testAbortInsertDuplicate() 387 throws DatabaseException { 388 389 390 openAndInit(true, true); 391 392 393 Transaction txn = env.beginTransaction(null, null); 394 Cursor cursor = db.openCursor(txn, null); 395 cursor.put(entry0, entry2); 396 checkBinEntriesAndCursors(bin, 2, 1); 397 checkBinEntriesAndCursors(dbin, 3, 1); 398 399 400 cursor.close(); 401 env.compress(); 402 checkBinEntriesAndCursors(bin, 2, 0); 403 checkBinEntriesAndCursors(dbin, 3, 0); 404 405 406 txn.abort(); 407 checkBinEntriesAndCursors(bin, 2, 0); 408 checkBinEntriesAndCursors(dbin, 3, 0); 409 410 411 env.compress(); 412 checkBinEntriesAndCursors(bin, 2, 0); 413 checkBinEntriesAndCursors(dbin, 2, 0); 414 415 416 assertEquals(2, in.getNEntries()); 417 418 closeEnv(); 419 } 420 421 public void testRollBackInsert() 422 throws DatabaseException { 423 424 425 openAndInit(true, false); 426 427 428 Transaction txn = env.beginTransaction(null, null); 429 Cursor cursor = db.openCursor(txn, null); 430 cursor.put(entry2, entry0); 431 checkBinEntriesAndCursors(bin, 3, 1); 432 433 434 cursor.close(); 435 env.compress(); 436 checkBinEntriesAndCursors(bin, 3, 0); 437 438 439 CheckpointConfig config = new CheckpointConfig(); 440 config.setForce(true); 441 env.checkpoint(config); 442 443 444 txn.abort(); 445 checkBinEntriesAndCursors(bin, 3, 0); 446 447 451 db.close(); 452 DbInternal.envGetEnvironmentImpl(env).close(false); 453 env = null; 454 openEnv(true, false, null); 455 initInternalNodes(); 456 checkBinEntriesAndCursors(bin, 3, 0); 457 458 459 assertEquals(2, in.getNEntries()); 460 461 462 env.compress(); 463 checkBinEntriesAndCursors(bin, 2, 0); 464 465 closeEnv(); 466 } 467 468 public void testRollBackInsertDuplicate() 469 throws DatabaseException { 470 471 472 openAndInit(true, true); 473 474 475 Transaction txn = env.beginTransaction(null, null); 476 Cursor cursor = db.openCursor(txn, null); 477 cursor.put(entry0, entry2); 478 checkBinEntriesAndCursors(bin, 2, 1); 479 checkBinEntriesAndCursors(dbin, 3, 1); 480 481 482 cursor.close(); 483 env.compress(); 484 checkBinEntriesAndCursors(bin, 2, 0); 485 checkBinEntriesAndCursors(dbin, 3, 0); 486 487 488 CheckpointConfig config = new CheckpointConfig(); 489 config.setForce(true); 490 env.checkpoint(config); 491 492 493 txn.abort(); 494 checkBinEntriesAndCursors(bin, 2, 0); 495 checkBinEntriesAndCursors(dbin, 3, 0); 496 497 501 db.close(); 502 DbInternal.envGetEnvironmentImpl(env).close(false); 503 env = null; 504 openEnv(true, true, null); 505 initInternalNodes(); 506 checkBinEntriesAndCursors(bin, 2, 0); 507 checkBinEntriesAndCursors(dbin, 3, 0); 508 509 510 env.compress(); 511 checkBinEntriesAndCursors(bin, 2, 0); 512 checkBinEntriesAndCursors(dbin, 2, 0); 513 514 515 assertEquals(2, in.getNEntries()); 516 517 closeEnv(); 518 } 519 520 public void testRollForwardDelete() 521 throws DatabaseException { 522 523 524 openAndInit(false, false); 525 OperationStatus status; 526 527 528 CheckpointConfig config = new CheckpointConfig(); 529 config.setForce(true); 530 env.checkpoint(config); 531 532 533 Cursor cursor = db.openCursor(null, null); 534 status = cursor.getFirst(keyFound, dataFound, null); 535 assertEquals(OperationStatus.SUCCESS, status); 536 checkBinEntriesAndCursors(bin, 2, 1); 537 538 539 status = cursor.delete(); 540 assertEquals(OperationStatus.SUCCESS, status); 541 env.compress(); 542 checkBinEntriesAndCursors(bin, 2, 1); 543 544 545 cursor.close(); 546 checkBinEntriesAndCursors(bin, 2, 0); 547 548 552 db.close(); 553 DbInternal.envGetEnvironmentImpl(env).close(false); 554 openEnv(false, false, null); 555 initInternalNodes(); 556 checkBinEntriesAndCursors(bin, 2, 0); 557 558 559 env.compress(); 560 checkBinEntriesAndCursors(bin, 1, 0); 561 562 563 assertEquals(2, in.getNEntries()); 564 565 closeEnv(); 566 } 567 568 public void testRollForwardDeleteDuplicate() 569 throws DatabaseException { 570 571 572 openAndInit(false, true); 573 OperationStatus status; 574 575 576 CheckpointConfig config = new CheckpointConfig(); 577 config.setForce(true); 578 env.checkpoint(config); 579 580 581 Cursor cursor = db.openCursor(null, null); 582 status = cursor.getFirst(keyFound, dataFound, null); 583 assertEquals(OperationStatus.SUCCESS, status); 584 checkBinEntriesAndCursors(dbin, 2, 1); 585 586 587 status = cursor.delete(); 588 assertEquals(OperationStatus.SUCCESS, status); 589 env.compress(); 590 checkBinEntriesAndCursors(dbin, 2, 1); 591 592 593 cursor.close(); 594 checkBinEntriesAndCursors(dbin, 2, 0); 595 596 600 db.close(); 601 DbInternal.envGetEnvironmentImpl(env).close(false); 602 openEnv(false, true, null); 603 initInternalNodes(); 604 checkBinEntriesAndCursors(dbin, 2, 0); 605 606 607 env.compress(); 608 checkBinEntriesAndCursors(dbin, 1, 0); 609 610 611 assertEquals(2, in.getNEntries()); 612 checkBinEntriesAndCursors(bin, 2, 0); 613 614 closeEnv(); 615 } 616 617 621 public void testLazyPruning() 622 throws DatabaseException { 623 624 625 openAndInit(false, false); 626 627 deleteAndLazyCompress(false); 628 629 630 env.compress(); 631 checkINCompQueueSize(0); 632 assertEquals(1, in.getNEntries()); 633 634 closeEnv(); 635 } 636 637 641 public void testLazyPruningDups() 642 throws DatabaseException { 643 644 645 openAndInit(false, true); 646 647 deleteAndLazyCompress(true); 648 649 650 env.compress(); 651 652 env.compress(); 653 checkINCompQueueSize(0); 654 assertEquals(1, in.getNEntries()); 655 656 closeEnv(); 657 } 658 659 662 public void testEmptyInitialDBINScan() 663 throws DatabaseException { 664 665 666 openAndInit(false, true); 667 668 deleteAndLazyCompress(true); 669 670 676 Cursor cursor = db.openCursor(null, null); 677 OperationStatus status = cursor.getFirst(keyFound, dataFound, null); 678 assertEquals(OperationStatus.SUCCESS, status); 679 assertTrue(keyFound.getData()[0] == 64); 680 cursor.close(); 681 closeEnv(); 682 } 683 684 688 public void testEmptyInitialBINScan() 689 throws DatabaseException { 690 691 692 openAndInit(false, false); 693 694 deleteAndLazyCompress(false); 695 696 701 Cursor cursor = db.openCursor(null, null); 702 OperationStatus status = cursor.getFirst(keyFound, dataFound, null); 703 assertEquals(OperationStatus.SUCCESS, status); 704 assertTrue(keyFound.getData()[0] == 64); 705 cursor.close(); 706 closeEnv(); 707 } 708 709 713 public void testNodeNotEmpty() 714 throws DatabaseException { 715 716 717 openAndInit(false, false); 718 719 deleteAndLazyCompress(false); 720 721 725 assertEquals(OperationStatus.SUCCESS, db.put(null, entry0, entry0)); 726 checkBinEntriesAndCursors(bin, 1, 0); 727 728 env.compress(); 729 assertEquals(2, in.getNEntries()); 730 checkINCompQueueSize(0); 731 732 closeEnv(); 733 } 734 735 736 737 738 private void deleteAndLazyCompress(boolean doDups) 739 throws DatabaseException { 740 741 742 Cursor cursor = db.openCursor(null, null); 743 OperationStatus status = cursor.getFirst(keyFound, dataFound, null); 744 assertEquals(OperationStatus.SUCCESS, status); 745 checkBinEntriesAndCursors(bin, 2, 1); 746 747 status = cursor.delete(); 748 assertEquals(OperationStatus.SUCCESS, status); 749 status = cursor.getNext(keyFound, dataFound, null); 750 assertEquals(OperationStatus.SUCCESS, status); 751 status = cursor.delete(); 752 assertEquals(OperationStatus.SUCCESS, status); 753 if (doDups) { 754 status = cursor.getNext(keyFound, dataFound, null); 755 assertEquals(OperationStatus.SUCCESS, status); 756 status = cursor.delete(); 757 assertEquals(OperationStatus.SUCCESS, status); 758 } 759 cursor.close(); 760 761 764 checkINCompQueueSize(doDups ? 2 : 1); 765 CheckpointConfig config = new CheckpointConfig(); 766 config.setForce(true); 767 env.checkpoint(config); 768 checkBinEntriesAndCursors((doDups ? dbin : bin), 0, 0); 769 770 771 assertEquals(2, in.getNEntries()); 772 checkINCompQueueSize(1); 773 } 774 775 778 private void checkBinEntriesAndCursors(BIN checkBin, 779 int nEntries, 780 int nCursors) 781 throws DatabaseException { 782 783 assertEquals("nEntries", nEntries, checkBin.getNEntries()); 784 assertEquals("nCursors", nCursors, checkBin.nCursors()); 785 } 786 787 790 private void checkINCompQueueSize(int expected) 791 throws DatabaseException { 792 793 assertEquals(expected, 794 DbInternal.envGetEnvironmentImpl(env).getINCompressorQueueSize()); 795 } 796 797 805 private void openAndInit(boolean transactional, boolean dups) 806 throws DatabaseException { 807 808 openEnv(transactional, dups, null); 809 810 816 BIN firstBin = null; 817 OperationStatus status; 818 for (int i = 0;; i += 1) { 819 DatabaseEntry key = new DatabaseEntry(new byte[] { (byte) i }); 820 status = db.put(null, key, entry0); 821 assertEquals(OperationStatus.SUCCESS, status); 822 Cursor cursor = db.openCursor(null, null); 823 status = cursor.getLast(keyFound, dataFound, null); 824 assertEquals(OperationStatus.SUCCESS, status); 825 BIN b = DbInternal.getCursorImpl(cursor).getBIN(); 826 cursor.close(); 827 if (firstBin == null) { 828 firstBin = b; 829 } else if (firstBin != b) { 830 831 while (firstBin.getNEntries() > 2) { 832 cursor = db.openCursor(null, null); 833 keyFound.setData(entry2.getData()); 834 status = 835 cursor.getSearchKeyRange(keyFound, dataFound, null); 836 assertEquals(OperationStatus.SUCCESS, status); 837 cursor.close(); 838 status = db.delete(null, keyFound); 839 assertEquals(OperationStatus.SUCCESS, status); 840 env.compress(); 841 } 842 break; 843 } 844 } 845 846 847 if (dups) { 848 status = db.put(null, entry0, entry1); 849 assertEquals(OperationStatus.SUCCESS, status); 850 } 851 852 853 initInternalNodes(); 854 assertSame(bin, firstBin); 855 856 857 assertEquals(2, in.getNEntries()); 858 checkBinEntriesAndCursors(bin, 2, 0); 859 if (dups) { 860 checkBinEntriesAndCursors(dbin, 2, 0); 861 } else { 862 assertNull(dbin); 863 } 864 } 865 866 869 private void initInternalNodes() 870 throws DatabaseException { 871 872 873 Cursor cursor = db.openCursor(null, null); 874 OperationStatus status = cursor.getFirst(keyFound, dataFound, null); 875 assertEquals(OperationStatus.SUCCESS, status); 876 bin = DbInternal.getCursorImpl(cursor).getBIN(); 877 dbin = DbInternal.getCursorImpl(cursor).getDupBIN(); 878 cursor.close(); 879 880 881 bin.latch(); 882 in = DbInternal.dbGetDatabaseImpl(db) 883 .getTree() 884 .getParentINForChildIN(bin, true, true) 885 .parent; 886 assertNotNull(in); 887 in.releaseLatch(); 888 } 889 890 893 private void openEnv(boolean transactional, boolean dups, String nodeMax) 894 throws DatabaseException { 895 896 hasDups = dups; 897 898 EnvironmentConfig envConfig = TestUtils.initEnvConfig(); 899 envConfig.setTransactional(transactional); 900 envConfig.setConfigParam 901 (EnvironmentParams.ENV_RUN_INCOMPRESSOR.getName(), "false"); 902 if (nodeMax != null) { 903 envConfig.setConfigParam 904 (EnvironmentParams.NODE_MAX.getName(), nodeMax); 905 envConfig.setConfigParam 906 (EnvironmentParams.NODE_MAX_DUPTREE.getName(), nodeMax); 907 } 908 envConfig.setAllowCreate(true); 909 env = new Environment(envHome, envConfig); 910 911 912 DatabaseConfig dbConfig = new DatabaseConfig(); 913 dbConfig.setTransactional(transactional); 914 dbConfig.setSortedDuplicates(dups); 915 dbConfig.setAllowCreate(true); 916 db = env.openDatabase(null, "testDB", dbConfig); 917 } 918 919 922 private void closeEnv() 923 throws DatabaseException { 924 925 db.close(); 926 db = null; 927 env.close(); 928 env = null; 929 } 930 } 931 | Popular Tags |