1 8 9 package com.sleepycat.je.cleaner; 10 11 import java.io.File ; 12 import java.io.IOException ; 13 14 import junit.framework.TestCase; 15 16 import com.sleepycat.bind.tuple.IntegerBinding; 17 import com.sleepycat.je.CheckpointConfig; 18 import com.sleepycat.je.Cursor; 19 import com.sleepycat.je.Database; 20 import com.sleepycat.je.DatabaseConfig; 21 import com.sleepycat.je.DatabaseEntry; 22 import com.sleepycat.je.DatabaseException; 23 import com.sleepycat.je.DbInternal; 24 import com.sleepycat.je.Environment; 25 import com.sleepycat.je.EnvironmentConfig; 26 import com.sleepycat.je.Transaction; 27 import com.sleepycat.je.config.EnvironmentParams; 28 import com.sleepycat.je.dbi.EnvironmentImpl; 29 import com.sleepycat.je.log.FileManager; 30 import com.sleepycat.je.log.LogEntryType; 31 import com.sleepycat.je.log.SearchFileReader; 32 import com.sleepycat.je.tree.IN; 33 import com.sleepycat.je.util.TestUtils; 34 import com.sleepycat.je.utilint.CmdUtil; 35 import com.sleepycat.je.utilint.DbLsn; 36 37 public class INUtilizationTest extends TestCase { 38 39 private static final String DB_NAME = "foo"; 40 41 private static final CheckpointConfig forceConfig = new CheckpointConfig(); 42 static { 43 forceConfig.setForce(true); 44 } 45 46 private File envHome; 47 private Environment env; 48 private EnvironmentImpl envImpl; 49 private Database db; 50 private Transaction txn; 51 private Cursor cursor; 52 private boolean dups = false; 53 private DatabaseEntry keyEntry = new DatabaseEntry(); 54 private DatabaseEntry dataEntry = new DatabaseEntry(); 55 56 public INUtilizationTest() { 57 envHome = new File (System.getProperty(TestUtils.DEST_DIR)); 58 } 59 60 public void setUp() 61 throws IOException , DatabaseException { 62 63 TestUtils.removeLogFiles("Setup", envHome, false); 64 TestUtils.removeFiles("Setup", envHome, FileManager.DEL_SUFFIX); 65 } 66 67 public void tearDown() 68 throws IOException , DatabaseException { 69 70 try { 71 if (env != null) { 72 env.close(); 73 } 74 } catch (Throwable e) { 75 System.out.println("tearDown: " + e); 76 } 77 78 try { 79 TestUtils.removeLogFiles("tearDown", envHome, true); 81 TestUtils.removeFiles("tearDown", envHome, FileManager.DEL_SUFFIX); 82 } catch (Throwable e) { 84 System.out.println("tearDown: " + e); 85 } 86 87 envHome = null; 88 env = null; 89 envImpl = null; 90 db = null; 91 txn = null; 92 cursor = null; 93 keyEntry = null; 94 dataEntry = null; 95 } 96 97 100 private void openEnv() 101 throws DatabaseException { 102 103 EnvironmentConfig config = TestUtils.initEnvConfig(); 104 DbInternal.disableParameterValidation(config); 105 config.setTransactional(true); 106 config.setTxnNoSync(true); 107 config.setAllowCreate(true); 108 109 config.setConfigParam 110 (EnvironmentParams.ENV_RUN_CLEANER.getName(), "false"); 111 config.setConfigParam 112 (EnvironmentParams.ENV_RUN_EVICTOR.getName(), "false"); 113 config.setConfigParam 114 (EnvironmentParams.ENV_RUN_CHECKPOINTER.getName(), "false"); 115 config.setConfigParam 116 (EnvironmentParams.ENV_RUN_INCOMPRESSOR.getName(), "false"); 117 118 config.setConfigParam(EnvironmentParams.LOG_FILE_MAX.getName(), 119 Integer.toString(64)); 120 env = new Environment(envHome, config); 121 envImpl = DbInternal.envGetEnvironmentImpl(env); 122 123 124 envImpl.getFileManager().setSyncAtFileEnd(false); 125 126 openDb(); 127 } 128 129 132 private void openDb() 133 throws DatabaseException { 134 135 DatabaseConfig dbConfig = new DatabaseConfig(); 136 dbConfig.setTransactional(true); 137 dbConfig.setAllowCreate(true); 138 dbConfig.setSortedDuplicates(dups); 139 db = env.openDatabase(null, DB_NAME, dbConfig); 140 } 141 142 private void closeEnv(boolean doCheckpoint) 143 throws DatabaseException { 144 145 closeEnv(doCheckpoint, 146 true, true); } 149 150 private void closeEnv(boolean doCheckpoint, 151 boolean expectAccurateObsoleteLNCount) 152 throws DatabaseException { 153 154 closeEnv(doCheckpoint, 155 expectAccurateObsoleteLNCount, 156 expectAccurateObsoleteLNCount); 157 } 158 159 165 private void closeEnv(boolean doCheckpoint, 166 boolean expectAccurateObsoleteLNCount, 167 boolean expectAccurateObsoleteLNSize) 168 throws DatabaseException { 169 170 176 CleanerTestUtils.verifyUtilization 177 (envImpl, expectAccurateObsoleteLNCount, 178 expectAccurateObsoleteLNSize); 179 180 if (db != null) { 181 db.close(); 182 db = null; 183 } 184 if (envImpl != null) { 185 envImpl.close(doCheckpoint); 186 envImpl = null; 187 env = null; 188 } 189 } 190 191 195 private void openAndWriteDatabase() 196 throws DatabaseException { 197 198 openEnv(); 199 txn = env.beginTransaction(null, null); 200 cursor = db.openCursor(txn, null); 201 202 203 IntegerBinding.intToEntry(0, keyEntry); 204 IntegerBinding.intToEntry(0, dataEntry); 205 cursor.put(keyEntry, dataEntry); 206 207 208 if (dups) { 209 IntegerBinding.intToEntry(1, dataEntry); 210 cursor.put(keyEntry, dataEntry); 211 cursor.getFirst(keyEntry, dataEntry, null); 212 } 213 214 215 env.sync(); 216 217 218 long binFile = getBINFile(cursor); 219 long inFile = getINFile(cursor); 220 expectObsolete(binFile, false); 221 expectObsolete(inFile, false); 222 } 223 224 227 public void testBasic() 228 throws DatabaseException { 229 230 openAndWriteDatabase(); 231 long binFile = getBINFile(cursor); 232 long inFile = getINFile(cursor); 233 234 235 cursor.put(keyEntry, dataEntry); 236 237 238 env.checkpoint(forceConfig); 239 240 if (!dups) { 241 242 expectObsolete(binFile, true); 243 expectObsolete(inFile, false); 244 assertTrue(binFile != getBINFile(cursor)); 245 assertEquals(inFile, getINFile(cursor)); 246 247 248 env.checkpoint(forceConfig); 249 } 250 251 252 expectObsolete(binFile, true); 253 expectObsolete(inFile, true); 254 assertTrue(binFile != getBINFile(cursor)); 255 assertTrue(inFile != getINFile(cursor)); 256 257 258 long binFile2 = getBINFile(cursor); 259 long inFile2 = getINFile(cursor); 260 expectObsolete(binFile2, false); 261 expectObsolete(inFile2, false); 262 263 cursor.close(); 264 txn.commit(); 265 closeEnv(true); 266 } 267 268 271 public void testBasicDup() 272 throws DatabaseException { 273 274 dups = true; 275 testBasic(); 276 } 277 278 282 public void testRecovery() 283 throws DatabaseException { 284 285 openAndWriteDatabase(); 286 long binFile = getBINFile(cursor); 287 long inFile = getINFile(cursor); 288 289 290 cursor.close(); 291 txn.commit(); 292 closeEnv(true); 293 openEnv(); 294 txn = env.beginTransaction(null, null); 295 cursor = db.openCursor(txn, null); 296 297 298 cursor.getSearchKey(keyEntry, dataEntry, null); 299 300 301 assertEquals(binFile, getBINFile(cursor)); 302 assertEquals(inFile, getINFile(cursor)); 303 expectObsolete(binFile, false); 304 expectObsolete(inFile, false); 305 306 310 TestUtils.logBINAndIN(env, cursor); 311 312 313 expectObsolete(binFile, true); 314 expectObsolete(inFile, true); 315 assertTrue(binFile != getBINFile(cursor)); 316 assertTrue(inFile != getINFile(cursor)); 317 318 319 long binFile2 = getBINFile(cursor); 320 long inFile2 = getINFile(cursor); 321 expectObsolete(binFile2, false); 322 expectObsolete(inFile2, false); 323 324 325 cursor.close(); 326 txn.commit(); 327 closeEnv(false); 328 openEnv(); 329 txn = env.beginTransaction(null, null); 330 cursor = db.openCursor(txn, null); 331 332 333 cursor.getSearchKey(keyEntry, dataEntry, null); 334 335 336 expectObsolete(binFile, true); 337 expectObsolete(inFile, true); 338 assertTrue(binFile != getBINFile(cursor)); 339 assertTrue(inFile != getINFile(cursor)); 340 341 347 assertTrue(binFile2 == getBINFile(cursor)); 348 assertTrue(inFile2 == getINFile(cursor)); 349 expectObsolete(binFile2, false); 350 expectObsolete(inFile2, false); 351 352 353 cursor.put(keyEntry, dataEntry); 354 355 356 assertTrue(binFile2 == getBINFile(cursor)); 357 assertTrue(inFile2 == getINFile(cursor)); 358 expectObsolete(binFile2, false); 359 expectObsolete(inFile2, false); 360 361 362 cursor.close(); 363 txn.commit(); 364 closeEnv(true); 365 openEnv(); 366 txn = env.beginTransaction(null, null); 367 cursor = db.openCursor(txn, null); 368 369 370 cursor.getSearchKey(keyEntry, dataEntry, null); 371 372 373 assertTrue(binFile2 != getBINFile(cursor)); 374 assertTrue(inFile2 != getINFile(cursor)); 375 expectObsolete(binFile2, true); 376 expectObsolete(inFile2, true); 377 378 cursor.close(); 379 txn.commit(); 380 closeEnv(true); 381 } 382 383 386 public void testRecoveryDup() 387 throws DatabaseException { 388 389 dups = true; 390 testRecovery(); 391 } 392 393 397 public void testPartialCheckpoint() 398 throws DatabaseException, IOException { 399 400 openAndWriteDatabase(); 401 long binFile = getBINFile(cursor); 402 long inFile = getINFile(cursor); 403 404 405 cursor.close(); 406 txn.commit(); 407 performPartialCheckpoint(true); openEnv(); 409 txn = env.beginTransaction(null, null); 410 cursor = db.openCursor(txn, null); 411 412 413 cursor.getSearchKey(keyEntry, dataEntry, null); 414 415 416 assertEquals(binFile, getBINFile(cursor)); 417 assertEquals(inFile, getINFile(cursor)); 418 expectObsolete(binFile, false); 419 expectObsolete(inFile, false); 420 421 422 cursor.put(keyEntry, dataEntry); 423 424 425 assertTrue(binFile == getBINFile(cursor)); 426 assertTrue(inFile == getINFile(cursor)); 427 expectObsolete(binFile, false); 428 expectObsolete(inFile, false); 429 430 431 cursor.close(); 432 txn.commit(); 433 performPartialCheckpoint(true, false); openEnv(); 436 txn = env.beginTransaction(null, null); 437 cursor = db.openCursor(txn, null); 438 439 440 cursor.getSearchKey(keyEntry, dataEntry, null); 441 442 443 assertTrue(binFile != getBINFile(cursor)); 444 assertTrue(inFile != getINFile(cursor)); 445 expectObsolete(binFile, true); 446 expectObsolete(inFile, true); 447 448 456 long binFile2 = getBINFile(cursor); 457 long inFile2 = getINFile(cursor); 458 expectObsolete(binFile2, true); 459 expectObsolete(inFile2, dups); 460 461 466 467 468 cursor.put(keyEntry, dataEntry); 469 470 471 cursor.close(); 472 txn.commit(); 473 performPartialCheckpoint(false, false); openEnv(); 476 txn = env.beginTransaction(null, null); 477 cursor = db.openCursor(txn, null); 478 479 480 cursor.getSearchKey(keyEntry, dataEntry, null); 481 482 483 assertTrue(binFile2 != getBINFile(cursor)); 484 assertTrue(inFile2 != getINFile(cursor)); 485 expectObsolete(binFile2, 2); 486 expectObsolete(inFile2, dups ? 2 : 1); 487 488 489 binFile2 = getBINFile(cursor); 490 inFile2 = getINFile(cursor); 491 expectObsolete(binFile2, false); 492 expectObsolete(inFile2, false); 493 494 cursor.close(); 495 txn.commit(); 496 closeEnv(true, false); } 499 500 503 public void testPartialCheckpointDup() 504 throws DatabaseException, IOException { 505 506 dups = true; 507 testPartialCheckpoint(); 508 } 509 510 514 public void testDelete() 515 throws DatabaseException, IOException { 516 517 openAndWriteDatabase(); 518 long binFile = getBINFile(cursor); 519 long inFile = getINFile(cursor); 520 521 522 cursor.close(); 523 txn.commit(); 524 closeEnv(true); 525 openEnv(); 526 txn = env.beginTransaction(null, null); 527 cursor = db.openCursor(txn, null); 528 529 530 cursor.getSearchKey(keyEntry, dataEntry, null); 531 532 533 assertEquals(binFile, getBINFile(cursor)); 534 assertEquals(inFile, getINFile(cursor)); 535 expectObsolete(binFile, false); 536 expectObsolete(inFile, false); 537 538 if (dups) { 539 540 cursor.delete(); 541 cursor.getNext(keyEntry, dataEntry, null); 542 cursor.delete(); 543 } else { 544 545 550 int keyVal = 0; 551 while (binFile == getBINFile(cursor)) { 552 keyVal += 1; 553 IntegerBinding.intToEntry(keyVal, keyEntry); 554 cursor.put(keyEntry, dataEntry); 555 } 556 binFile = getBINFile(cursor); 557 inFile = getINFile(cursor); 558 559 560 while (binFile == getBINFile(cursor)) { 561 cursor.delete(); 562 cursor.getLast(keyEntry, dataEntry, null); 563 } 564 } 565 566 567 expectObsolete(binFile, false); 568 expectObsolete(inFile, false); 569 570 571 cursor.close(); 572 txn.commit(); 573 env.compress(); 574 575 578 expectObsolete(binFile, true); 579 expectObsolete(inFile, true); 580 581 582 performPartialCheckpoint(true); openEnv(); 584 585 589 expectObsolete(binFile, true); 590 expectObsolete(inFile, true); 591 592 closeEnv(true, false); } 595 596 599 public void testDeleteDup() 600 throws DatabaseException, IOException { 601 602 dups = true; 603 testDelete(); 604 } 605 606 611 public void testTruncate() 612 throws DatabaseException, IOException { 613 614 openAndWriteDatabase(); 615 long binFile = getBINFile(cursor); 616 long inFile = getINFile(cursor); 617 618 619 cursor.close(); 620 txn.commit(); 621 closeEnv(true, true, false); openEnv(); 625 626 627 txn = env.beginTransaction(null, null); 628 db.truncate(txn, false); 629 txn.commit(); 630 631 632 expectObsolete(binFile, true); 633 expectObsolete(inFile, true); 634 635 636 performPartialCheckpoint(true, true, false); openEnv(); 640 641 642 expectObsolete(binFile, true); 643 expectObsolete(inFile, true); 644 645 closeEnv(true, false); } 648 649 653 public void testRemove() 654 throws DatabaseException, IOException { 655 656 openAndWriteDatabase(); 657 long binFile = getBINFile(cursor); 658 long inFile = getINFile(cursor); 659 660 661 cursor.close(); 662 txn.commit(); 663 closeEnv(true, true, false); openEnv(); 667 668 669 db.close(); 670 db = null; 671 txn = env.beginTransaction(null, null); 672 env.removeDatabase(txn, DB_NAME); 673 txn.commit(); 674 675 676 expectObsolete(binFile, true); 677 expectObsolete(inFile, true); 678 679 680 performPartialCheckpoint(true, true, false); openEnv(); 684 685 686 expectObsolete(binFile, true); 687 expectObsolete(inFile, true); 688 689 closeEnv(true, false); } 692 693 private void expectObsolete(long file, boolean obsolete) 694 throws DatabaseException { 695 696 FileSummary summary = getSummary(file); 697 assertEquals("totalINCount", 698 1, summary.totalINCount); 699 assertEquals("obsoleteINCount", 700 obsolete ? 1 : 0, summary.obsoleteINCount); 701 } 702 703 private void expectObsolete(long file, int obsoleteCount) 704 throws DatabaseException { 705 706 FileSummary summary = getSummary(file); 707 assertEquals("totalINCount", 708 1, summary.totalINCount); 709 assertEquals("obsoleteINCount", 710 obsoleteCount, summary.obsoleteINCount); 711 } 712 713 private long getINFile(Cursor cursor) 714 throws DatabaseException { 715 716 IN in = TestUtils.getIN(TestUtils.getBIN(cursor)); 717 long lsn = in.getLastFullVersion(); 718 assertTrue(lsn != DbLsn.NULL_LSN); 719 return DbLsn.getFileNumber(lsn); 720 } 721 722 private long getBINFile(Cursor cursor) 723 throws DatabaseException { 724 725 long lsn = TestUtils.getBIN(cursor).getLastFullVersion(); 726 assertTrue(lsn != DbLsn.NULL_LSN); 727 return DbLsn.getFileNumber(lsn); 728 } 729 730 733 private FileSummary getSummary(long file) 734 throws DatabaseException { 735 736 return (FileSummary) envImpl.getUtilizationProfile() 737 .getFileSummaryMap(true) 738 .get(new Long (file)); 739 } 740 741 private void performPartialCheckpoint(boolean truncateFileSummariesAlso) 742 throws DatabaseException, IOException { 743 744 performPartialCheckpoint(truncateFileSummariesAlso, 745 true, true); } 748 749 private void performPartialCheckpoint(boolean truncateFileSummariesAlso, 750 boolean 751 expectAccurateObsoleteLNCount) 752 throws DatabaseException, IOException { 753 754 performPartialCheckpoint(truncateFileSummariesAlso, 755 expectAccurateObsoleteLNCount, 756 expectAccurateObsoleteLNCount); 757 } 758 759 765 private void performPartialCheckpoint 766 (boolean truncateFileSummariesAlso, 767 boolean expectAccurateObsoleteLNCount, 768 boolean expectAccurateObsoleteLNSize) 769 throws DatabaseException, IOException { 770 771 772 env.checkpoint(forceConfig); 773 long eofLsn = envImpl.getFileManager().getNextLsn(); 774 long lastLsn = envImpl.getFileManager().getLastUsedLsn(); 775 long truncateLsn; 776 777 778 SearchFileReader searcher = 779 new SearchFileReader(envImpl, 1000, false, lastLsn, eofLsn, 780 LogEntryType.LOG_CKPT_END); 781 assertTrue(searcher.readNextEntry()); 782 long ckptEnd = searcher.getLastLsn(); 783 784 if (truncateFileSummariesAlso) { 785 786 787 searcher = 788 new SearchFileReader(envImpl, 1000, false, ckptEnd, eofLsn, 789 LogEntryType.LOG_CKPT_START); 790 assertTrue(searcher.readNextEntry()); 791 long ckptStart = searcher.getLastLsn(); 792 793 794 searcher = 795 new SearchFileReader(envImpl, 1000, true, ckptStart, eofLsn, 796 LogEntryType.LOG_FILESUMMARYLN); 797 assertTrue(searcher.readNextEntry()); 798 truncateLsn = searcher.getLastLsn(); 799 } else { 800 truncateLsn = ckptEnd; 801 } 802 803 807 closeEnv(false, expectAccurateObsoleteLNCount, 809 expectAccurateObsoleteLNSize); 810 811 812 EnvironmentImpl cmdEnv = 813 CmdUtil.makeUtilityEnvironment(envHome, false); 814 cmdEnv.getFileManager().truncateLog(DbLsn.getFileNumber(truncateLsn), 815 DbLsn.getFileOffset(truncateLsn)); 816 cmdEnv.close(false); 817 818 819 String [] fileNames = envHome.list(); 820 for (int i = 0; i < fileNames.length; i += 1) { 821 String name = fileNames[i]; 822 if (name.endsWith(".jdb")) { 823 String numStr = name.substring(0, name.length() - 4); 824 long fileNum = Long.parseLong(numStr, 16); 825 if (fileNum > DbLsn.getFileNumber(truncateLsn)) { 826 assertTrue(new File (envHome, name).delete()); 827 } 828 } 829 } 830 } 831 } 832 | Popular Tags |