1 8 9 package com.sleepycat.je.cleaner; 10 11 import java.io.File ; 12 import java.io.IOException ; 13 import java.nio.ByteBuffer ; 14 import java.util.Enumeration ; 15 16 import junit.framework.Test; 17 import junit.framework.TestCase; 18 import junit.framework.TestSuite; 19 20 import com.sleepycat.bind.tuple.IntegerBinding; 21 import com.sleepycat.je.CheckpointConfig; 22 import com.sleepycat.je.Cursor; 23 import com.sleepycat.je.Database; 24 import com.sleepycat.je.DatabaseConfig; 25 import com.sleepycat.je.DatabaseEntry; 26 import com.sleepycat.je.DatabaseException; 27 import com.sleepycat.je.DbInternal; 28 import com.sleepycat.je.Environment; 29 import com.sleepycat.je.EnvironmentConfig; 30 import com.sleepycat.je.OperationStatus; 31 import com.sleepycat.je.Transaction; 32 import com.sleepycat.je.config.EnvironmentParams; 33 import com.sleepycat.je.log.FileHeader; 34 import com.sleepycat.je.log.FileManager; 35 import com.sleepycat.je.log.LogManager; 36 import com.sleepycat.je.log.LogSource; 37 import com.sleepycat.je.log.LogUtils; 38 import com.sleepycat.je.util.TestUtils; 39 import com.sleepycat.je.utilint.DbLsn; 40 41 public class UtilizationTest extends TestCase { 42 43 private static final String DB_NAME = "foo"; 44 45 private static final String OP_NONE = "op-none"; 46 private static final String OP_CHECKPOINT = "op-checkpoint"; 47 private static final String OP_RECOVER = "op-recover"; 48 private static final String [] OPERATIONS = { OP_NONE, 51 OP_CHECKPOINT, 52 OP_RECOVER, 53 OP_RECOVER }; 54 56 61 private static final boolean[] FETCH_OBSOLETE_SIZE = { false, 62 false, 63 false, 64 true }; 65 66 private static final CheckpointConfig forceConfig = new CheckpointConfig(); 67 static { 68 forceConfig.setForce(true); 69 } 70 71 private File envHome; 72 private Environment env; 73 private Database db; 74 private boolean dups = false; 75 private DatabaseEntry keyEntry = new DatabaseEntry(); 76 private DatabaseEntry dataEntry = new DatabaseEntry(); 77 private String operation; 78 private long lastFileSeen; 79 private boolean fetchObsoleteSize; 80 81 public static Test suite() { 82 TestSuite allTests = new TestSuite(); 83 for (int i = 0; i < OPERATIONS.length; i += 1) { 84 TestSuite suite = new TestSuite(UtilizationTest.class); 85 Enumeration e = suite.tests(); 86 while (e.hasMoreElements()) { 87 UtilizationTest test = (UtilizationTest) e.nextElement(); 88 test.init(OPERATIONS[i], FETCH_OBSOLETE_SIZE[i]); 89 allTests.addTest(test); 90 } 91 } 92 return allTests; 93 } 94 95 public UtilizationTest() { 96 envHome = new File (System.getProperty(TestUtils.DEST_DIR)); 97 } 98 99 private void init(String operation, boolean fetchObsoleteSize) { 100 this.operation = operation; 101 this.fetchObsoleteSize = fetchObsoleteSize; 102 } 103 104 public void setUp() 105 throws IOException , DatabaseException { 106 107 TestUtils.removeLogFiles("Setup", envHome, false); 108 TestUtils.removeFiles("Setup", envHome, FileManager.DEL_SUFFIX); 109 } 110 111 public void tearDown() 112 throws IOException , DatabaseException { 113 114 115 setName(operation + 116 (fetchObsoleteSize ? "-fetch" : "") + 117 ':' + getName()); 118 119 try { 120 if (env != null) { 121 env.close(); 122 } 123 } catch (Throwable e) { 124 System.out.println("tearDown: " + e); 125 } 126 127 try { 128 TestUtils.removeLogFiles("tearDown", envHome, true); 130 TestUtils.removeFiles("tearDown", envHome, FileManager.DEL_SUFFIX); 131 } catch (Throwable e) { 133 System.out.println("tearDown: " + e); 134 } 135 136 db = null; 137 env = null; 138 envHome = null; 139 keyEntry = null; 140 dataEntry = null; 141 } 142 143 146 private void openEnv() 147 throws DatabaseException { 148 149 EnvironmentConfig config = TestUtils.initEnvConfig(); 150 DbInternal.disableParameterValidation(config); 151 config.setTransactional(true); 152 config.setTxnNoSync(true); 153 config.setAllowCreate(true); 154 155 config.setConfigParam 156 (EnvironmentParams.ENV_RUN_CLEANER.getName(), "false"); 157 config.setConfigParam 158 (EnvironmentParams.ENV_RUN_EVICTOR.getName(), "false"); 159 config.setConfigParam 160 (EnvironmentParams.ENV_RUN_CHECKPOINTER.getName(), "false"); 161 config.setConfigParam 162 (EnvironmentParams.ENV_RUN_INCOMPRESSOR.getName(), "false"); 163 164 config.setConfigParam(EnvironmentParams.LOG_FILE_MAX.getName(), 165 Integer.toString(64)); 166 167 config.setConfigParam 168 (EnvironmentParams.LOG_DIRECT_NIO.getName(), "false"); 169 170 171 if (fetchObsoleteSize) { 172 config.setConfigParam 173 (EnvironmentParams.CLEANER_FETCH_OBSOLETE_SIZE.getName(), 174 "true"); 175 } 176 177 env = new Environment(envHome, config); 178 179 180 DbInternal.envGetEnvironmentImpl(env). 181 getFileManager(). 182 setSyncAtFileEnd(false); 183 184 openDb(); 185 } 186 187 190 private void openDb() 191 throws DatabaseException { 192 193 DatabaseConfig dbConfig = new DatabaseConfig(); 194 dbConfig.setTransactional(true); 195 dbConfig.setAllowCreate(true); 196 dbConfig.setSortedDuplicates(dups); 197 db = env.openDatabase(null, DB_NAME, dbConfig); 198 } 199 200 203 private void closeEnv(boolean doCheckpoint) 204 throws DatabaseException { 205 206 207 CleanerTestUtils.verifyUtilization 208 (DbInternal.envGetEnvironmentImpl(env), 209 true, expectAccurateObsoleteLNSize()); 211 212 if (db != null) { 213 db.close(); 214 db = null; 215 } 216 if (env != null) { 217 DbInternal.envGetEnvironmentImpl(env).close(doCheckpoint); 218 env = null; 219 } 220 } 221 222 public void testReuseSlotAfterDelete() 223 throws DatabaseException { 224 225 openEnv(); 226 227 228 Transaction txn = env.beginTransaction(null, null); 229 long file0 = doPut(0, txn); 230 long file1 = doDelete(0, txn); 231 txn.commit(); 232 233 234 txn = env.beginTransaction(null, null); 235 long file2 = doPut(0, txn); 236 237 long file3 = doDelete(0, txn); 238 long file4 = doPut(0, txn); 239 txn.commit(); 240 performRecoveryOperation(); 241 242 expectObsolete(file0, true); 243 expectObsolete(file1, true); 244 expectObsolete(file2, true); 245 expectObsolete(file3, true); 246 expectObsolete(file4, false); 247 248 closeEnv(true); 249 } 250 251 public void testReuseKnownDeletedSlot() 252 throws DatabaseException { 253 254 openEnv(); 255 256 257 Transaction txn = env.beginTransaction(null, null); 258 long file0 = doPut(0, txn); 259 txn.abort(); 260 261 262 txn = env.beginTransaction(null, null); 263 long file1 = doPut(0, txn); 264 txn.commit(); 265 performRecoveryOperation(); 266 267 268 expectObsolete(file0, true); 269 expectObsolete(file1, false); 270 271 closeEnv(true); 272 } 273 274 public void testReuseKnownDeletedSlotAbort() 275 throws DatabaseException { 276 277 openEnv(); 278 279 280 Transaction txn = env.beginTransaction(null, null); 281 long file0 = doPut(0, txn); 282 txn.abort(); 283 284 285 txn = env.beginTransaction(null, null); 286 long file1 = doPut(0, txn); 287 txn.abort(); 288 performRecoveryOperation(); 289 290 291 expectObsolete(file0, true); 292 expectObsolete(file1, true); 293 294 closeEnv(true); 295 } 296 297 public void testReuseKnownDeletedSlotDup() 298 throws DatabaseException { 299 300 dups = true; 301 openEnv(); 302 303 304 Transaction txn = env.beginTransaction(null, null); 305 long file0 = doPut(0, 0, txn); long file2 = doPut(0, 1, txn); long file1 = file2 - 1; txn.commit(); 309 env.checkpoint(forceConfig); 310 311 312 txn = env.beginTransaction(null, null); 313 long file3 = doPut(0, 2, txn); long file4 = file3 + 1; txn.abort(); 316 317 318 txn = env.beginTransaction(null, null); 319 long file5 = doPut(0, 2, txn); long file6 = file5 + 1; txn.commit(); 322 performRecoveryOperation(); 323 324 325 expectObsolete(file0, false); 326 expectObsolete(file1, true); 327 expectObsolete(file2, false); 328 expectObsolete(file3, true); 329 expectObsolete(file4, true); 330 expectObsolete(file5, false); 331 expectObsolete(file6, false); 332 333 closeEnv(true); 334 } 335 336 public void testReuseKnownDeletedSlotDupAbort() 337 throws DatabaseException { 338 339 dups = true; 340 openEnv(); 341 342 343 Transaction txn = env.beginTransaction(null, null); 344 long file0 = doPut(0, 0, txn); long file2 = doPut(0, 1, txn); long file1 = file2 - 1; txn.commit(); 348 env.checkpoint(forceConfig); 349 350 351 txn = env.beginTransaction(null, null); 352 long file3 = doPut(0, 2, txn); long file4 = file3 + 1; txn.abort(); 355 356 357 txn = env.beginTransaction(null, null); 358 long file5 = doPut(0, 2, txn); long file6 = file5 + 1; txn.abort(); 361 performRecoveryOperation(); 362 363 364 expectObsolete(file0, false); 365 expectObsolete(file1, false); 366 expectObsolete(file2, false); 367 expectObsolete(file3, true); 368 expectObsolete(file4, true); 369 expectObsolete(file5, true); 370 expectObsolete(file6, true); 371 372 closeEnv(true); 373 } 374 375 public void testInsert() 376 throws DatabaseException { 377 378 openEnv(); 379 380 381 long file0 = doPut(0, true); 382 performRecoveryOperation(); 383 384 385 FileSummary summary = getSummary(file0); 386 assertEquals(1, summary.totalLNCount); 387 assertEquals(0, summary.obsoleteLNCount); 388 389 closeEnv(true); 390 } 391 392 public void testInsertAbort() 393 throws DatabaseException { 394 395 openEnv(); 396 397 398 long file0 = doPut(0, false); 399 performRecoveryOperation(); 400 401 402 FileSummary summary = getSummary(file0); 403 assertEquals(1, summary.totalLNCount); 404 assertEquals(1, summary.obsoleteLNCount); 405 406 closeEnv(true); 407 } 408 409 public void testInsertDup() 410 throws DatabaseException { 411 412 dups = true; 413 openEnv(); 414 415 416 Transaction txn = env.beginTransaction(null, null); 417 long file0 = doPut(0, 0, txn); 418 long file3 = doPut(0, 1, txn); 419 txn.commit(); 420 performRecoveryOperation(); 421 422 426 long file1 = file0 + 1; long file2 = file1 + 3; assertEquals(file3, file2 + 1); 430 expectObsolete(file0, false); expectObsolete(file1, true); expectObsolete(file2, false); expectObsolete(file3, false); 435 closeEnv(true); 436 } 437 438 public void testInsertDupAbort() 439 throws DatabaseException { 440 441 dups = true; 442 openEnv(); 443 444 445 Transaction txn = env.beginTransaction(null, null); 446 long file0 = doPut(0, 0, txn); 447 long file3 = doPut(0, 1, txn); 448 txn.abort(); 449 performRecoveryOperation(); 450 451 455 long file1 = file0 + 1; long file2 = file1 + 3; assertEquals(file3, file2 + 1); 459 expectObsolete(file0, true); expectObsolete(file1, false); expectObsolete(file2, true); expectObsolete(file3, true); 464 closeEnv(true); 465 } 466 467 public void testUpdate() 468 throws DatabaseException { 469 470 openEnv(); 471 472 473 long file0 = doPut(0, true); 474 env.checkpoint(forceConfig); 475 476 477 long file1 = doPut(0, true); 478 performRecoveryOperation(); 479 480 expectObsolete(file0, true); 481 expectObsolete(file1, false); 482 483 closeEnv(true); 484 } 485 486 public void testUpdateAbort() 487 throws DatabaseException { 488 489 openEnv(); 490 491 492 long file0 = doPut(0, true); 493 env.checkpoint(forceConfig); 494 495 496 long file1 = doPut(0, false); 497 performRecoveryOperation(); 498 499 expectObsolete(file0, false); 500 expectObsolete(file1, true); 501 502 closeEnv(true); 503 } 504 505 public void testUpdateDup() 506 throws DatabaseException { 507 508 dups = true; 509 openEnv(); 510 511 512 Transaction txn = env.beginTransaction(null, null); 513 long file0 = doPut(0, 0, txn); long file2 = doPut(0, 1, txn); long file1 = file2 - 1; txn.commit(); 517 env.checkpoint(forceConfig); 518 519 520 txn = env.beginTransaction(null, null); 521 long file3 = doUpdate(0, 0, txn); txn.commit(); 523 performRecoveryOperation(); 524 525 expectObsolete(file0, true); 526 expectObsolete(file1, false); 527 expectObsolete(file2, false); 528 expectObsolete(file3, false); 529 530 closeEnv(true); 531 } 532 533 public void testUpdateDupAbort() 534 throws DatabaseException { 535 536 dups = true; 537 openEnv(); 538 539 540 Transaction txn = env.beginTransaction(null, null); 541 long file0 = doPut(0, 0, txn); long file2 = doPut(0, 1, txn); long file1 = file2 - 1; txn.commit(); 545 env.checkpoint(forceConfig); 546 547 548 txn = env.beginTransaction(null, null); 549 long file3 = doUpdate(0, 0, txn); txn.abort(); 551 performRecoveryOperation(); 552 553 expectObsolete(file0, false); 554 expectObsolete(file1, false); 555 expectObsolete(file2, false); 556 expectObsolete(file3, true); 557 558 closeEnv(true); 559 } 560 561 public void testDelete() 562 throws DatabaseException { 563 564 openEnv(); 565 566 567 long file0 = doPut(0, true); 568 env.checkpoint(forceConfig); 569 570 571 long file1 = doDelete(0, true); 572 performRecoveryOperation(); 573 574 expectObsolete(file0, true); 575 expectObsolete(file1, true); 576 577 closeEnv(true); 578 } 579 580 public void testDeleteAbort() 581 throws DatabaseException { 582 583 openEnv(); 584 585 586 long file0 = doPut(0, true); 587 env.checkpoint(forceConfig); 588 589 590 long file1 = doDelete(0, false); 591 performRecoveryOperation(); 592 593 expectObsolete(file0, false); 594 expectObsolete(file1, true); 595 596 closeEnv(true); 597 } 598 599 public void testDeleteDup() 600 throws DatabaseException { 601 602 dups = true; 603 openEnv(); 604 605 606 Transaction txn = env.beginTransaction(null, null); 607 long file0 = doPut(0, 0, txn); long file2 = doPut(0, 1, txn); long file1 = file2 - 1; txn.commit(); 611 env.checkpoint(forceConfig); 612 613 614 txn = env.beginTransaction(null, null); 615 long file3 = doDelete(0, 0, txn); long file4 = file3 + 1; txn.commit(); 618 performRecoveryOperation(); 619 620 expectObsolete(file0, true); 621 expectObsolete(file1, true); 622 expectObsolete(file2, false); 623 expectObsolete(file3, true); 624 expectObsolete(file4, false); 625 626 closeEnv(true); 627 } 628 629 public void testDeleteDupAbort() 630 throws DatabaseException { 631 632 dups = true; 633 openEnv(); 634 635 636 Transaction txn = env.beginTransaction(null, null); 637 long file0 = doPut(0, 0, txn); long file2 = doPut(0, 1, txn); long file1 = file2 - 1; txn.commit(); 641 env.checkpoint(forceConfig); 642 643 644 txn = env.beginTransaction(null, null); 645 long file3 = doDelete(0, 0, txn); long file4 = file3 + 1; txn.abort(); 648 performRecoveryOperation(); 649 650 expectObsolete(file0, false); 651 expectObsolete(file1, false); 652 expectObsolete(file2, false); 653 expectObsolete(file3, true); 654 expectObsolete(file4, true); 655 656 closeEnv(true); 657 } 658 659 public void testInsertUpdate() 660 throws DatabaseException { 661 662 openEnv(); 663 664 665 Transaction txn = env.beginTransaction(null, null); 666 long file0 = doPut(0, txn); 667 long file1 = doPut(0, txn); 668 txn.commit(); 669 performRecoveryOperation(); 670 671 expectObsolete(file0, true); 672 expectObsolete(file1, false); 673 674 closeEnv(true); 675 } 676 677 public void testInsertUpdateAbort() 678 throws DatabaseException { 679 680 openEnv(); 681 682 683 Transaction txn = env.beginTransaction(null, null); 684 long file0 = doPut(0, txn); 685 long file1 = doPut(0, txn); 686 txn.abort(); 687 performRecoveryOperation(); 688 689 expectObsolete(file0, true); 690 expectObsolete(file1, true); 691 692 closeEnv(true); 693 } 694 695 public void testInsertUpdateDup() 696 throws DatabaseException { 697 698 dups = true; 699 openEnv(); 700 701 702 Transaction txn = env.beginTransaction(null, null); 703 long file0 = doPut(0, 0, txn); long file2 = doPut(0, 1, txn); long file1 = file2 - 1; txn.commit(); 707 env.checkpoint(forceConfig); 708 709 710 txn = env.beginTransaction(null, null); 711 long file3 = doPut(0, 2, txn); long file4 = file3 + 1; long file5 = doUpdate(0, 2, txn); txn.commit(); 715 performRecoveryOperation(); 716 717 expectObsolete(file0, false); 718 expectObsolete(file1, true); 719 expectObsolete(file2, false); 720 expectObsolete(file3, true); 721 expectObsolete(file4, false); 722 expectObsolete(file5, false); 723 724 closeEnv(true); 725 } 726 727 public void testInsertUpdateDupAbort() 728 throws DatabaseException { 729 730 dups = true; 731 openEnv(); 732 733 734 Transaction txn = env.beginTransaction(null, null); 735 long file0 = doPut(0, 0, txn); long file2 = doPut(0, 1, txn); long file1 = file2 - 1; txn.commit(); 739 env.checkpoint(forceConfig); 740 741 742 txn = env.beginTransaction(null, null); 743 long file3 = doPut(0, 2, txn); long file4 = file3 + 1; long file5 = doUpdate(0, 2, txn); txn.abort(); 747 performRecoveryOperation(); 748 749 expectObsolete(file0, false); 750 expectObsolete(file1, false); 751 expectObsolete(file2, false); 752 expectObsolete(file3, true); 753 expectObsolete(file4, true); 754 expectObsolete(file5, true); 755 756 closeEnv(true); 757 } 758 759 public void testInsertDelete() 760 throws DatabaseException { 761 762 openEnv(); 763 764 765 Transaction txn = env.beginTransaction(null, null); 766 long file0 = doPut(0, txn); 767 long file1 = doDelete(0, txn); 768 txn.commit(); 769 performRecoveryOperation(); 770 771 expectObsolete(file0, true); 772 expectObsolete(file1, true); 773 774 closeEnv(true); 775 } 776 777 public void testInsertDeleteAbort() 778 throws DatabaseException { 779 780 openEnv(); 781 782 783 Transaction txn = env.beginTransaction(null, null); 784 long file0 = doPut(0, txn); 785 long file1 = doDelete(0, txn); 786 txn.abort(); 787 performRecoveryOperation(); 788 789 expectObsolete(file0, true); 790 expectObsolete(file1, true); 791 792 closeEnv(true); 793 } 794 795 public void testInsertDeleteDup() 796 throws DatabaseException { 797 798 dups = true; 799 openEnv(); 800 801 802 Transaction txn = env.beginTransaction(null, null); 803 long file0 = doPut(0, 0, txn); long file2 = doPut(0, 1, txn); long file1 = file2 - 1; txn.commit(); 807 env.checkpoint(forceConfig); 808 809 810 txn = env.beginTransaction(null, null); 811 long file3 = doPut(0, 2, txn); long file4 = file3 + 1; long file5 = doDelete(0, 2, txn); long file6 = file5 + 1; txn.commit(); 816 performRecoveryOperation(); 817 818 expectObsolete(file0, false); 819 expectObsolete(file1, true); 820 expectObsolete(file2, false); 821 expectObsolete(file3, true); 822 expectObsolete(file4, true); 823 expectObsolete(file5, true); 824 expectObsolete(file6, false); 825 826 closeEnv(true); 827 } 828 829 public void testInsertDeleteDupAbort() 830 throws DatabaseException { 831 832 dups = true; 833 openEnv(); 834 835 836 Transaction txn = env.beginTransaction(null, null); 837 long file0 = doPut(0, 0, txn); long file2 = doPut(0, 1, txn); long file1 = file2 - 1; txn.commit(); 841 env.checkpoint(forceConfig); 842 843 844 txn = env.beginTransaction(null, null); 845 long file3 = doPut(0, 2, txn); long file4 = file3 + 1; long file5 = doDelete(0, 2, txn); long file6 = file5 + 1; txn.abort(); 850 performRecoveryOperation(); 851 852 expectObsolete(file0, false); 853 expectObsolete(file1, false); 854 expectObsolete(file2, false); 855 expectObsolete(file3, true); 856 expectObsolete(file4, true); 857 expectObsolete(file5, true); 858 expectObsolete(file6, true); 859 860 closeEnv(true); 861 } 862 863 public void testUpdateUpdate() 864 throws DatabaseException { 865 866 openEnv(); 867 868 869 long file0 = doPut(0, true); 870 env.checkpoint(forceConfig); 871 872 873 Transaction txn = env.beginTransaction(null, null); 874 long file1 = doPut(0, txn); 875 long file2 = doPut(0, txn); 876 txn.commit(); 877 performRecoveryOperation(); 878 879 expectObsolete(file0, true); 880 expectObsolete(file1, true); 881 expectObsolete(file2, false); 882 883 closeEnv(true); 884 } 885 886 public void testUpdateUpdateAbort() 887 throws DatabaseException { 888 889 openEnv(); 890 891 892 long file0 = doPut(0, true); 893 env.checkpoint(forceConfig); 894 895 896 Transaction txn = env.beginTransaction(null, null); 897 long file1 = doPut(0, txn); 898 long file2 = doPut(0, txn); 899 txn.abort(); 900 performRecoveryOperation(); 901 902 expectObsolete(file0, false); 903 expectObsolete(file1, true); 904 expectObsolete(file2, true); 905 906 closeEnv(true); 907 } 908 909 public void testUpdateUpdateDup() 910 throws DatabaseException { 911 912 dups = true; 913 openEnv(); 914 915 916 Transaction txn = env.beginTransaction(null, null); 917 long file0 = doPut(0, 0, txn); long file2 = doPut(0, 1, txn); long file1 = file2 - 1; txn.commit(); 921 env.checkpoint(forceConfig); 922 923 924 txn = env.beginTransaction(null, null); 925 long file3 = doUpdate(0, 1, txn); long file4 = doUpdate(0, 1, txn); txn.commit(); 928 performRecoveryOperation(); 929 930 expectObsolete(file0, false); 931 expectObsolete(file1, false); 932 expectObsolete(file2, true); 933 expectObsolete(file3, true); 934 expectObsolete(file4, false); 935 936 closeEnv(true); 937 } 938 939 public void testUpdateUpdateDupAbort() 940 throws DatabaseException { 941 942 dups = true; 943 openEnv(); 944 945 946 Transaction txn = env.beginTransaction(null, null); 947 long file0 = doPut(0, 0, txn); long file2 = doPut(0, 1, txn); long file1 = file2 - 1; txn.commit(); 951 env.checkpoint(forceConfig); 952 953 954 txn = env.beginTransaction(null, null); 955 long file3 = doUpdate(0, 1, txn); long file4 = doUpdate(0, 1, txn); txn.abort(); 958 performRecoveryOperation(); 959 960 expectObsolete(file0, false); 961 expectObsolete(file1, false); 962 expectObsolete(file2, false); 963 expectObsolete(file3, true); 964 expectObsolete(file4, true); 965 966 closeEnv(true); 967 } 968 969 public void testUpdateDelete() 970 throws DatabaseException { 971 972 openEnv(); 973 974 975 long file0 = doPut(0, true); 976 env.checkpoint(forceConfig); 977 978 979 Transaction txn = env.beginTransaction(null, null); 980 long file1 = doPut(0, txn); 981 long file2 = doDelete(0, txn); 982 txn.commit(); 983 performRecoveryOperation(); 984 985 expectObsolete(file0, true); 986 expectObsolete(file1, true); 987 expectObsolete(file2, true); 988 989 closeEnv(true); 990 } 991 992 public void testUpdateDeleteAbort() 993 throws DatabaseException { 994 995 openEnv(); 996 997 998 long file0 = doPut(0, true); 999 env.checkpoint(forceConfig); 1000 1001 1002 Transaction txn = env.beginTransaction(null, null); 1003 long file1 = doPut(0, txn); 1004 long file2 = doDelete(0, txn); 1005 txn.abort(); 1006 performRecoveryOperation(); 1007 1008 expectObsolete(file0, false); 1009 expectObsolete(file1, true); 1010 expectObsolete(file2, true); 1011 1012 closeEnv(true); 1013 } 1014 1015 public void testUpdateDeleteDup() 1016 throws DatabaseException { 1017 1018 dups = true; 1019 openEnv(); 1020 1021 1022 Transaction txn = env.beginTransaction(null, null); 1023 long file0 = doPut(0, 0, txn); long file2 = doPut(0, 1, txn); long file1 = file2 - 1; txn.commit(); 1027 env.checkpoint(forceConfig); 1028 1029 1030 txn = env.beginTransaction(null, null); 1031 long file3 = doUpdate(0, 1, txn); long file4 = doDelete(0, 1, txn); long file5 = file4 + 1; txn.commit(); 1035 performRecoveryOperation(); 1036 1037 expectObsolete(file0, false); 1038 expectObsolete(file1, true); 1039 expectObsolete(file2, true); 1040 expectObsolete(file3, true); 1041 expectObsolete(file4, true); 1042 expectObsolete(file5, false); 1043 1044 closeEnv(true); 1045 } 1046 1047 public void testUpdateDeleteDupAbort() 1048 throws DatabaseException { 1049 1050 dups = true; 1051 openEnv(); 1052 1053 1054 Transaction txn = env.beginTransaction(null, null); 1055 long file0 = doPut(0, 0, txn); long file2 = doPut(0, 1, txn); long file1 = file2 - 1; txn.commit(); 1059 env.checkpoint(forceConfig); 1060 1061 1062 txn = env.beginTransaction(null, null); 1063 long file3 = doUpdate(0, 1, txn); long file4 = doDelete(0, 1, txn); long file5 = file4 + 1; txn.abort(); 1067 performRecoveryOperation(); 1068 1069 expectObsolete(file0, false); 1070 expectObsolete(file1, false); 1071 expectObsolete(file2, false); 1072 expectObsolete(file3, true); 1073 expectObsolete(file4, true); 1074 expectObsolete(file5, true); 1075 1076 closeEnv(true); 1077 } 1078 1079 public void testTruncate() 1080 throws DatabaseException { 1081 1082 truncateOrRemove(true, true); 1083 } 1084 1085 public void testTruncateAbort() 1086 throws DatabaseException { 1087 1088 truncateOrRemove(true, false); 1089 } 1090 1091 public void testRemove() 1092 throws DatabaseException { 1093 1094 truncateOrRemove(false, true); 1095 } 1096 1097 public void testRemoveAbort() 1098 throws DatabaseException { 1099 1100 truncateOrRemove(false, false); 1101 } 1102 1103 1106 private void truncateOrRemove(boolean truncate, boolean commit) 1107 throws DatabaseException { 1108 1109 openEnv(); 1110 1111 1112 Transaction txn = env.beginTransaction(null, null); 1113 long file0 = doPut(0, txn); 1114 long file1 = doPut(1, txn); 1115 long file2 = doPut(2, txn); 1116 txn.commit(); 1117 env.checkpoint(forceConfig); 1118 1119 1120 txn = env.beginTransaction(null, null); 1121 if (truncate) { 1122 int count = db.truncate(txn, true); 1123 assertEquals(3, count); 1124 } else { 1125 db.close(); 1126 db = null; 1127 env.removeDatabase(txn, DB_NAME); 1128 } 1129 if (commit) { 1130 txn.commit(); 1131 } else { 1132 txn.abort(); 1133 } 1134 performRecoveryOperation(); 1135 1136 expectObsolete(file0, commit); 1137 expectObsolete(file1, commit); 1138 expectObsolete(file2, commit); 1139 1140 closeEnv(true); 1141 } 1142 1143 private void expectObsolete(long file, boolean obsolete) 1144 throws DatabaseException { 1145 1146 FileSummary summary = getSummary(file); 1147 assertEquals("totalLNCount", 1148 1, summary.totalLNCount); 1149 assertEquals("obsoleteLNCount", 1150 obsolete ? 1 : 0, summary.obsoleteLNCount); 1151 1152 if (obsolete) { 1153 if (expectAccurateObsoleteLNSize()) { 1154 assertTrue(summary.obsoleteLNSize > 0); 1155 assertEquals(1, summary.obsoleteLNSizeCounted); 1156 } 1157 1158 if (summary.obsoleteLNSize > 0) { 1159 assertEquals(getLNSize(file), summary.obsoleteLNSize); 1160 } 1161 } else { 1162 assertEquals(0, summary.obsoleteLNSize); 1163 assertEquals(0, summary.obsoleteLNSizeCounted); 1164 } 1165 } 1166 1167 1173 private boolean expectAccurateObsoleteLNSize() { 1174 return fetchObsoleteSize || !OP_RECOVER.equals(operation); 1175 } 1176 1177 private long doPut(int key, boolean commit) 1178 throws DatabaseException { 1179 1180 Transaction txn = env.beginTransaction(null, null); 1181 long file = doPut(key, txn); 1182 if (commit) { 1183 txn.commit(); 1184 } else { 1185 txn.abort(); 1186 } 1187 return file; 1188 } 1189 1190 private long doPut(int key, Transaction txn) 1191 throws DatabaseException { 1192 1193 return doPut(key, key, txn); 1194 } 1195 1196 private long doPut(int key, int data, Transaction txn) 1197 throws DatabaseException { 1198 1199 Cursor cursor = db.openCursor(txn, null); 1200 IntegerBinding.intToEntry(key, keyEntry); 1201 IntegerBinding.intToEntry(data, dataEntry); 1202 cursor.put(keyEntry, dataEntry); 1203 long file = getFile(cursor); 1204 cursor.close(); 1205 return file; 1206 } 1207 1208 private long doUpdate(int key, int data, Transaction txn) 1209 throws DatabaseException { 1210 1211 Cursor cursor = db.openCursor(txn, null); 1212 IntegerBinding.intToEntry(key, keyEntry); 1213 IntegerBinding.intToEntry(data, dataEntry); 1214 assertEquals(OperationStatus.SUCCESS, 1215 cursor.getSearchBoth(keyEntry, dataEntry, null)); 1216 cursor.putCurrent(dataEntry); 1217 long file = getFile(cursor); 1218 cursor.close(); 1219 return file; 1220 } 1221 1222 private long doDelete(int key, boolean commit) 1223 throws DatabaseException { 1224 1225 Transaction txn = env.beginTransaction(null, null); 1226 long file = doDelete(key, txn); 1227 if (commit) { 1228 txn.commit(); 1229 } else { 1230 txn.abort(); 1231 } 1232 return file; 1233 } 1234 1235 private long doDelete(int key, Transaction txn) 1236 throws DatabaseException { 1237 1238 Cursor cursor = db.openCursor(txn, null); 1239 IntegerBinding.intToEntry(key, keyEntry); 1240 assertEquals(OperationStatus.SUCCESS, 1241 cursor.getSearchKey(keyEntry, dataEntry, null)); 1242 cursor.delete(); 1243 long file = getFile(cursor); 1244 cursor.close(); 1245 return file; 1246 } 1247 1248 private long doDelete(int key, int data, Transaction txn) 1249 throws DatabaseException { 1250 1251 Cursor cursor = db.openCursor(txn, null); 1252 IntegerBinding.intToEntry(key, keyEntry); 1253 IntegerBinding.intToEntry(data, dataEntry); 1254 assertEquals(OperationStatus.SUCCESS, 1255 cursor.getSearchBoth(keyEntry, dataEntry, null)); 1256 cursor.delete(); 1257 long file = getFile(cursor); 1258 cursor.close(); 1259 return file; 1260 } 1261 1262 1265 private void performRecoveryOperation() 1266 throws DatabaseException { 1267 1268 if (OP_NONE.equals(operation)) { 1269 1270 env.compress(); 1271 } else if (OP_CHECKPOINT.equals(operation)) { 1272 1273 env.compress(); 1274 env.checkpoint(forceConfig); 1275 } else if (OP_RECOVER.equals(operation)) { 1276 closeEnv(false); 1277 openEnv(); 1278 1279 env.compress(); 1280 } else { 1281 assert false : operation; 1282 } 1283 } 1284 1285 1290 private long getFile(Cursor cursor) 1291 throws DatabaseException { 1292 1293 long file = CleanerTestUtils.getLogFile(this, cursor); 1294 assert file > lastFileSeen; 1295 lastFileSeen = file; 1296 return file; 1297 } 1298 1299 1302 private FileSummary getSummary(long file) 1303 throws DatabaseException { 1304 1305 return (FileSummary) 1306 DbInternal.envGetEnvironmentImpl(env) 1307 .getUtilizationProfile() 1308 .getFileSummaryMap(true) 1309 .get(new Long (file)); 1310 } 1311 1312 1316 private int getLNSize(long file) 1317 throws DatabaseException { 1318 1319 try { 1320 long offset = LogManager.HEADER_BYTES + FileHeader.entrySize(); 1321 long lsn = DbLsn.makeLsn(file, offset); 1322 LogManager lm = 1323 DbInternal.envGetEnvironmentImpl(env).getLogManager(); 1324 LogSource src = lm.getLogSource(lsn); 1325 ByteBuffer buf = 1326 src.getBytes(offset + LogManager.HEADER_SIZE_OFFSET); 1327 int size = LogUtils.readInt(buf); 1328 src.release(); 1329 return size + LogManager.HEADER_BYTES; 1330 } catch (IOException e) { 1331 throw new DatabaseException(e); 1332 } 1333 } 1334} 1335 | Popular Tags |