1 8 9 package com.sleepycat.je.cleaner; 10 11 import java.io.IOException ; 12 import java.util.HashMap ; 13 import java.util.HashSet ; 14 import java.util.Iterator ; 15 import java.util.Map ; 16 import java.util.Set ; 17 import java.util.SortedMap ; 18 import java.util.TreeMap ; 19 import java.util.logging.Level ; 20 21 import com.sleepycat.je.DatabaseException; 22 import com.sleepycat.je.dbi.DatabaseId; 23 import com.sleepycat.je.dbi.DatabaseImpl; 24 import com.sleepycat.je.dbi.DbTree; 25 import com.sleepycat.je.dbi.EnvironmentImpl; 26 import com.sleepycat.je.dbi.MemoryBudget; 27 import com.sleepycat.je.log.CleanerFileReader; 28 import com.sleepycat.je.tree.BIN; 29 import com.sleepycat.je.tree.ChildReference; 30 import com.sleepycat.je.tree.DIN; 31 import com.sleepycat.je.tree.IN; 32 import com.sleepycat.je.tree.LN; 33 import com.sleepycat.je.tree.SearchResult; 34 import com.sleepycat.je.tree.Tree; 35 import com.sleepycat.je.tree.TreeLocation; 36 import com.sleepycat.je.tree.WithRootLatched; 37 import com.sleepycat.je.txn.BasicLocker; 38 import com.sleepycat.je.txn.LockGrantType; 39 import com.sleepycat.je.txn.LockResult; 40 import com.sleepycat.je.txn.LockType; 41 import com.sleepycat.je.utilint.DaemonThread; 42 import com.sleepycat.je.utilint.DbLsn; 43 import com.sleepycat.je.utilint.Tracer; 44 45 53 class FileProcessor extends DaemonThread { 54 55 61 private static final int PROCESS_PENDING_EVERY_N_LNS = 100; 62 63 72 private static final boolean PROHIBIT_DELTAS_WHEN_FETCHING = false; 73 74 private static final boolean DEBUG_TRACING = false; 75 76 private EnvironmentImpl env; 77 private Cleaner cleaner; 78 private FileSelector fileSelector; 79 private UtilizationProfile profile; 80 81 82 private int fileLogVersion; 83 84 85 private int nINsObsoleteThisRun = 0; 86 private int nINsCleanedThisRun = 0; 87 private int nINsDeadThisRun = 0; 88 private int nINsMigratedThisRun = 0; 89 private int nLNsObsoleteThisRun = 0; 90 private int nLNsCleanedThisRun = 0; 91 private int nLNsDeadThisRun = 0; 92 private int nLNsLockedThisRun = 0; 93 private int nLNsMigratedThisRun = 0; 94 private int nLNsMarkedThisRun = 0; 95 private int nLNQueueHitsThisRun = 0; 96 private int nEntriesReadThisRun; 97 private long nRepeatIteratorReadsThisRun; 98 99 FileProcessor(String name, 100 EnvironmentImpl env, 101 Cleaner cleaner, 102 UtilizationProfile profile, 103 FileSelector fileSelector) { 104 super(0, name, env); 105 this.env = env; 106 this.cleaner = cleaner; 107 this.fileSelector = fileSelector; 108 this.profile = profile; 109 } 110 111 public void clearEnv() { 112 env = null; 113 cleaner = null; 114 fileSelector = null; 115 profile = null; 116 } 117 118 123 void addSentinalWorkObject() { 124 try { 125 workQueueLatch.acquire(); 126 workQueue.add(new Object ()); 127 workQueueLatch.release(); 128 } catch (DatabaseException e) { 129 throw new IllegalStateException (e); 130 } 131 } 132 133 136 protected int nDeadlockRetries() 137 throws DatabaseException { 138 139 return cleaner.nDeadlockRetries; 140 } 141 142 146 public void addToQueue(Object o) 147 throws DatabaseException { 148 149 throw new DatabaseException 150 ("Cleaner.addToQueue should never be called."); 151 } 152 153 157 public void onWakeup() 158 throws DatabaseException { 159 160 doClean(true, true, false); 164 165 workQueueLatch.acquire(); 166 workQueue.clear(); 167 workQueueLatch.release(); 168 } 169 170 185 public synchronized int doClean(boolean invokedFromDaemon, 186 boolean cleanMultipleFiles, 187 boolean forceCleaning) 188 throws DatabaseException { 189 190 if (env.isClosed()) { 191 return 0; 192 } 193 194 195 int nOriginalLogFiles = profile.getNumberOfFiles(); 196 int nFilesCleaned = 0; 197 while (true) { 198 199 200 if (nFilesCleaned >= nOriginalLogFiles) { 201 break; 202 } 203 204 205 if ((invokedFromDaemon && isPaused()) || env.isClosing()) { 206 break; 207 } 208 209 213 cleaner.processPending(); 214 cleaner.deleteSafeToDeleteFiles(); 215 216 220 boolean needLowUtilizationSet = 221 cleaner.clusterResident || cleaner.clusterAll; 222 223 Long fileNum = fileSelector.selectFileForCleaning 224 (profile, forceCleaning, needLowUtilizationSet, 225 cleaner.maxBatchFiles); 226 227 cleaner.updateReadOnlyFileCollections(); 228 229 233 if (fileNum == null) { 234 break; 235 } 236 237 240 resetPerRunCounters(); 241 boolean finished = false; 242 long fileNumValue = fileNum.longValue(); 243 int runId = ++cleaner.nCleanerRuns; 244 try { 245 246 String traceMsg = 247 "CleanerRun " + runId + 248 " on file 0x" + Long.toHexString(fileNumValue) + 249 " begins backlog=" + cleaner.nBacklogFiles; 250 Tracer.trace(Level.INFO, env, traceMsg); 251 if (DEBUG_TRACING) { 252 System.out.println("\n" + traceMsg); 253 } 254 255 256 Set deferredWriteDbs = new HashSet (); 257 if (processFile(fileNum, deferredWriteDbs)) { 258 259 fileSelector.addCleanedFile(fileNum, deferredWriteDbs); 260 nFilesCleaned += 1; 261 accumulatePerRunCounters(); 262 finished = true; 263 } 264 } catch (IOException IOE) { 265 Tracer.trace(env, "Cleaner", "doClean", "", IOE); 266 throw new DatabaseException(IOE); 267 } finally { 268 if (!finished) { 269 fileSelector.putBackFileForCleaning(fileNum); 270 } 271 String traceMsg = 272 "CleanerRun " + runId + 273 " on file 0x" + Long.toHexString(fileNumValue) + 274 " invokedFromDaemon=" + invokedFromDaemon + 275 " finished=" + finished + 276 " nEntriesRead=" + nEntriesReadThisRun + 277 " nINsObsolete=" + nINsObsoleteThisRun + 278 " nINsCleaned=" + nINsCleanedThisRun + 279 " nINsDead=" + nINsDeadThisRun + 280 " nINsMigrated=" + nINsMigratedThisRun + 281 " nLNsObsolete=" + nLNsObsoleteThisRun + 282 " nLNsCleaned=" + nLNsCleanedThisRun + 283 " nLNsDead=" + nLNsDeadThisRun + 284 " nLNsMigrated=" + nLNsMigratedThisRun + 285 " nLNsMarked=" + nLNsMarkedThisRun + 286 " nLNQueueHits=" + nLNQueueHitsThisRun + 287 " nLNsLocked=" + nLNsLockedThisRun; 288 Tracer.trace(Level.SEVERE, env, traceMsg); 289 if (DEBUG_TRACING) { 290 System.out.println("\n" + traceMsg); 291 } 292 } 293 294 295 if (!cleanMultipleFiles) { 296 break; 297 } 298 } 299 300 return nFilesCleaned; 301 } 302 303 327 private boolean processFile(Long fileNum, Set deferredWriteDbs) 328 throws DatabaseException, IOException { 329 330 331 PackedOffsets obsoleteOffsets = new PackedOffsets(); 332 TrackedFileSummary tfs = 333 profile.getObsoleteDetail(fileNum, 334 obsoleteOffsets, 335 true ); 336 PackedOffsets.Iterator obsoleteIter = obsoleteOffsets.iterator(); 337 long nextObsolete = -1; 338 339 340 final int readBufferSize = cleaner.readBufferSize; 341 int lookAheadCacheSize = cleaner.lookAheadCacheSize; 342 343 348 int adjustMem = (2 * readBufferSize) + 349 obsoleteOffsets.getLogSize() + 350 lookAheadCacheSize; 351 MemoryBudget budget = env.getMemoryBudget(); 352 budget.updateMiscMemoryUsage(adjustMem); 353 354 355 if (Cleaner.DO_CRITICAL_EVICTION) { 356 env.getEvictor().doCriticalEviction(true); } 358 359 364 LookAheadCache lookAheadCache = new LookAheadCache(lookAheadCacheSize); 365 366 371 Set checkPendingDbSet = new HashSet (); 372 373 374 Map dbCache = new HashMap (); 375 376 try { 377 378 CleanerFileReader reader = new CleanerFileReader 379 (env, readBufferSize, DbLsn.NULL_LSN, fileNum); 380 381 reader.setAlwaysValidateChecksum(true); 382 383 DbTree dbMapTree = env.getDbMapTree(); 384 TreeLocation location = new TreeLocation(); 385 386 int nProcessedLNs = 0; 387 while (reader.readNextEntry()) { 388 cleaner.nEntriesRead += 1; 389 long logLsn = reader.getLastLsn(); 390 long fileOffset = DbLsn.getFileOffset(logLsn); 391 boolean isLN = reader.isLN(); 392 boolean isIN = reader.isIN(); 393 boolean isRoot = reader.isRoot(); 394 boolean isFileHeader = reader.isFileHeader(); 395 boolean isObsolete = false; 396 397 if (reader.isFileHeader()) { 398 fileLogVersion = reader.getFileHeader().getLogVersion(); 399 } 400 401 402 if (env.isClosing()) { 403 return false; 404 } 405 406 407 int nReads = reader.getAndResetNReads(); 408 if (nReads > 0) { 409 env.updateBackgroundReads(nReads); 410 } 411 412 413 env.sleepAfterBackgroundIO(); 414 415 416 while (nextObsolete < fileOffset && obsoleteIter.hasNext()) { 417 nextObsolete = obsoleteIter.next(); 418 } 419 if (nextObsolete == fileOffset) { 420 isObsolete = true; 421 } 422 423 424 if (!isObsolete && 425 !isLN && 426 !isIN && 427 !isRoot) { 428 429 isObsolete = true; 430 } 431 432 441 if (!isObsolete && 442 isLN && 443 reader.getLN().isDeleted() && 444 fileLogVersion > 2) { 445 446 isObsolete = true; 447 } 448 449 450 if (!isObsolete && 451 tfs != null && 452 tfs.containsObsoleteOffset(fileOffset)) { 453 isObsolete = true; 454 } 455 456 457 if (isObsolete) { 458 459 if (isLN) { 460 nLNsObsoleteThisRun++; 461 } else if (isIN) { 462 nINsObsoleteThisRun++; 463 } 464 465 DatabaseId dbId = reader.getDatabaseId(); 466 if (dbId != null) { 467 checkPendingDbSet.add(dbId); 468 } 469 continue; 470 } 471 472 473 if (Cleaner.DO_CRITICAL_EVICTION) { 474 env.getEvictor().doCriticalEviction(true); } 476 477 478 if (isLN) { 479 480 LN targetLN = reader.getLN(); 481 DatabaseId dbId = reader.getDatabaseId(); 482 byte[] key = reader.getKey(); 483 byte[] dupKey = reader.getDupTreeKey(); 484 485 lookAheadCache.add 486 (new Long (DbLsn.getFileOffset(logLsn)), 487 new LNInfo(targetLN, dbId, key, dupKey)); 488 489 if (lookAheadCache.isFull()) { 490 processLN(fileNum, location, lookAheadCache, 491 dbCache, deferredWriteDbs); 492 } 493 494 498 nProcessedLNs += 1; 499 if (nProcessedLNs % PROCESS_PENDING_EVERY_N_LNS == 0) { 500 cleaner.processPending(); 501 } 502 503 } else if (isIN) { 504 505 IN targetIN = reader.getIN(); 506 DatabaseId dbId = reader.getDatabaseId(); 507 DatabaseImpl db = dbMapTree.getDb 508 (dbId, cleaner.lockTimeout, dbCache); 509 targetIN.setDatabase(db); 510 511 processIN(targetIN, db, logLsn, deferredWriteDbs); 512 513 } else if (isRoot) { 514 515 env.rewriteMapTreeRoot(logLsn); 516 } else { 517 assert false; 518 } 519 } 520 521 522 while (!lookAheadCache.isEmpty()) { 523 if (Cleaner.DO_CRITICAL_EVICTION) { 524 env.getEvictor().doCriticalEviction(true); } 526 processLN(fileNum, location, lookAheadCache, dbCache, 527 deferredWriteDbs); 528 529 env.sleepAfterBackgroundIO(); 530 } 531 532 533 for (Iterator i = checkPendingDbSet.iterator(); i.hasNext();) { 534 DatabaseId dbId = (DatabaseId) i.next(); 535 DatabaseImpl db = dbMapTree.getDb 536 (dbId, cleaner.lockTimeout, dbCache); 537 cleaner.addPendingDB(db); 538 } 539 540 541 nEntriesReadThisRun = reader.getNumRead(); 542 nRepeatIteratorReadsThisRun = reader.getNRepeatIteratorReads(); 543 544 } finally { 545 546 budget.updateMiscMemoryUsage(0 - adjustMem); 547 548 549 if (tfs != null) { 550 tfs.setAllowFlush(true); 551 } 552 } 553 554 return true; 555 } 556 557 562 private void processLN(Long fileNum, 563 TreeLocation location, 564 LookAheadCache lookAheadCache, 565 Map dbCache, 566 Set deferredWriteDbs) 567 throws DatabaseException { 568 569 nLNsCleanedThisRun++; 570 571 572 Long offset = lookAheadCache.nextOffset(); 573 LNInfo info = lookAheadCache.remove(offset); 574 575 LN ln = info.getLN(); 576 byte[] key = info.getKey(); 577 byte[] dupKey = info.getDupKey(); 578 579 long logLsn = DbLsn.makeLsn 580 (fileNum.longValue(), offset.longValue()); 581 582 DatabaseImpl db = env.getDbMapTree().getDb 583 (info.getDbId(), cleaner.lockTimeout, dbCache); 584 585 586 boolean processedHere = true; boolean obsolete = false; boolean completed = false; 590 BIN bin = null; 591 DIN parentDIN = null; try { 593 594 599 if (db == null || db.isDeleted()) { 600 cleaner.addPendingDB(db); 601 nLNsDeadThisRun++; 602 obsolete = true; 603 completed = true; 604 return; 605 } 606 607 Tree tree = db.getTree(); 608 assert tree != null; 609 610 613 boolean parentFound = tree.getParentBINForChildLN 614 (location, key, dupKey, ln, 615 false, true, false, Cleaner.UPDATE_GENERATION); 619 bin = location.bin; 620 int index = location.index; 621 622 if (!parentFound) { 623 nLNsDeadThisRun++; 624 obsolete = true; 625 completed = true; 626 return; 627 } 628 629 633 if (bin.isEntryKnownDeleted(index)) { 634 nLNsDeadThisRun++; 635 obsolete = true; 636 completed = true; 637 return; 638 } 639 640 644 boolean isDupCountLN = ln.containsDuplicates(); 645 long treeLsn; 646 if (isDupCountLN) { 647 parentDIN = (DIN) bin.fetchTarget(index); 648 parentDIN.latch(Cleaner.UPDATE_GENERATION); 649 ChildReference dclRef = parentDIN.getDupCountLNRef(); 650 treeLsn = dclRef.getLsn(); 651 } else { 652 treeLsn = bin.getLsn(index); 653 } 654 655 656 processedHere = false; 657 processFoundLN(info, logLsn, treeLsn, bin, index, parentDIN); 658 completed = true; 659 660 664 if (!isDupCountLN) { 665 for (int i = 0; i < bin.getNEntries(); i += 1) { 666 long binLsn = bin.getLsn(i); 667 if (i != index && 668 !bin.isEntryKnownDeleted(i) && 669 !bin.isEntryPendingDeleted(i) && 670 DbLsn.getFileNumber(binLsn) == fileNum.longValue()) { 671 672 Long myOffset = new Long (DbLsn.getFileOffset(binLsn)); 673 LNInfo myInfo = lookAheadCache.remove(myOffset); 674 675 if (myInfo != null) { 676 nLNQueueHitsThisRun++; 677 nLNsCleanedThisRun++; 678 processFoundLN 679 (myInfo, binLsn, binLsn, bin, i, null); 680 } 681 } 682 } 683 } 684 return; 685 686 } finally { 687 noteDbsRequiringSync(db, deferredWriteDbs); 688 689 if (parentDIN != null) { 690 parentDIN.releaseLatchIfOwner(); 691 } 692 693 if (bin != null) { 694 bin.releaseLatchIfOwner(); 695 } 696 697 if (processedHere) { 698 cleaner.trace 699 (cleaner.detailedTraceLevel, Cleaner.CLEAN_LN, ln, logLsn, 700 completed, obsolete, false ); 701 } 702 } 703 } 704 705 724 private void processFoundLN(LNInfo info, 725 long logLsn, 726 long treeLsn, 727 BIN bin, 728 int index, 729 DIN parentDIN) 730 throws DatabaseException { 731 732 LN ln = info.getLN(); 733 byte[] key = info.getKey(); 734 byte[] dupKey = info.getDupKey(); 735 736 DatabaseImpl db = bin.getDatabase(); 737 boolean isDupCountLN = parentDIN != null; 738 739 740 boolean obsolete = false; boolean migrated = false; boolean lockDenied = false; boolean completed = false; 745 long nodeId = ln.getNodeId(); 746 BasicLocker locker = null; 747 try { 748 Tree tree = db.getTree(); 749 assert tree != null; 750 751 779 if (ln.isDeleted() && 780 (treeLsn == logLsn) && 781 fileLogVersion <= 2) { 782 783 790 obsolete = true; 791 nLNsDeadThisRun++; 792 bin.setPendingDeleted(index); 793 } else if (treeLsn == DbLsn.NULL_LSN) { 794 795 799 obsolete = true; 800 } else if (treeLsn != logLsn) { 801 802 810 locker = new BasicLocker(env); 811 LockResult lockRet = locker.nonBlockingLock 812 (nodeId, LockType.READ, db); 813 if (lockRet.getLockGrant() == LockGrantType.DENIED) { 814 815 819 nLNsLockedThisRun++; 820 lockDenied = true; 821 } else { 822 823 nLNsDeadThisRun++; 824 obsolete = true; 825 } 826 } 827 828 if (!obsolete && !lockDenied) { 829 830 840 if (isDupCountLN) { 841 ChildReference dclRef = parentDIN.getDupCountLNRef(); 842 dclRef.setMigrate(true); 843 parentDIN.setDirty(true); 844 845 if (treeLsn == logLsn && dclRef.getTarget() == null) { 846 ln.postFetchInit(db, logLsn); 847 parentDIN.updateDupCountLN(ln); 848 } 849 } else { 850 bin.setMigrate(index, true); 851 bin.setDirty(true); 852 853 if (treeLsn == logLsn && bin.getTarget(index) == null) { 854 ln.postFetchInit(db, logLsn); 855 bin.updateEntry(index, ln); 856 } 857 858 862 if (PROHIBIT_DELTAS_WHEN_FETCHING && 863 bin.getGeneration() == 0) { 864 bin.setProhibitNextDelta(); 865 } 866 867 873 bin.setGeneration(); 874 } 875 876 nLNsMarkedThisRun++; 877 migrated = true; 878 } 879 completed = true; 880 } finally { 881 if (locker != null) { 882 locker.operationEnd(); 883 } 884 885 891 if (completed && lockDenied) { 892 fileSelector.addPendingLN(ln, db.getId(), key, dupKey); 893 } 894 895 cleaner.trace 896 (cleaner.detailedTraceLevel, Cleaner.CLEAN_LN, ln, logLsn, 897 completed, obsolete, migrated); 898 } 899 } 900 901 905 private void processIN(IN inClone, 906 DatabaseImpl db, 907 long logLsn, 908 Set deferredWriteDbs) 909 throws DatabaseException { 910 911 boolean obsolete = false; 912 boolean dirtied = false; 913 boolean completed = false; 914 915 try { 916 nINsCleanedThisRun++; 917 918 923 if (db == null || db.isDeleted()) { 924 cleaner.addPendingDB(db); 925 nINsDeadThisRun++; 926 obsolete = true; 927 completed = true; 928 return; 929 } 930 931 Tree tree = db.getTree(); 932 assert tree != null; 933 934 IN inInTree = findINInTree(tree, db, inClone, logLsn); 935 936 if (inInTree == null) { 937 938 nINsDeadThisRun++; 939 obsolete = true; 940 } else { 941 942 947 nINsMigratedThisRun++; 948 inInTree.setDirty(true); 949 inInTree.setProhibitNextDelta(); 950 inInTree.releaseLatch(); 951 dirtied = true; 952 } 953 954 completed = true; 955 } finally { 956 noteDbsRequiringSync(db, deferredWriteDbs); 957 958 cleaner.trace 959 (cleaner.detailedTraceLevel, Cleaner.CLEAN_IN, inClone, logLsn, 960 completed, obsolete, dirtied); 961 } 962 } 963 964 972 private IN findINInTree(Tree tree, 973 DatabaseImpl db, 974 IN inClone, 975 long logLsn) 976 throws DatabaseException { 977 978 979 if (inClone.isDbRoot()) { 980 IN rootIN = isRoot(tree, db, inClone, logLsn); 981 if (rootIN == null) { 982 983 988 return null; 989 } else { 990 return rootIN; 991 } 992 } 993 994 995 inClone.latch(Cleaner.UPDATE_GENERATION); 996 SearchResult result = null; 997 try { 998 999 result = tree.getParentINForChildIN 1000 (inClone, 1001 true, Cleaner.UPDATE_GENERATION, 1003 inClone.getLevel(), 1004 null); 1006 if (!result.exactParentFound) { 1007 return null; 1008 } 1009 1010 long treeLsn = result.parent.getLsn(result.index); 1011 1012 1018 if (treeLsn == DbLsn.NULL_LSN) { 1019 throw new DatabaseException 1020 ("Deferred Write IN should not have a NULL_LSN " + 1021 " logLsn=" + DbLsn.getNoFormatString(logLsn)); 1022 } 1023 1024 int compareVal = DbLsn.compareTo(treeLsn, logLsn); 1025 1026 if (compareVal > 0) { 1027 1028 return null; 1029 } else { 1030 1031 1035 IN in; 1036 if (compareVal == 0) { 1037 1038 in = (IN) result.parent.getTarget(result.index); 1039 if (in == null) { 1040 in = inClone; 1041 in.postFetchInit(db, logLsn); 1042 result.parent.updateEntry(result.index, in); 1043 } 1044 } else { 1045 in = (IN) result.parent.fetchTarget(result.index); 1046 } 1047 in.latch(Cleaner.UPDATE_GENERATION); 1048 return in; 1049 } 1050 } finally { 1051 if ((result != null) && (result.exactParentFound)) { 1052 result.parent.releaseLatch(); 1053 } 1054 } 1055 } 1056 1057 1077 private void noteDbsRequiringSync(DatabaseImpl db, 1078 Set deferredWriteDbs) { 1079 if ((db != null) && (!db.isDeleted()) && db.isDeferredWrite()) { 1080 deferredWriteDbs.add(db.getId()); 1081 } 1082 } 1083 1084 1088 private static class RootDoWork implements WithRootLatched { 1089 private DatabaseImpl db; 1090 private IN inClone; 1091 private long logLsn; 1092 1093 RootDoWork(DatabaseImpl db, IN inClone, long logLsn) { 1094 this.db = db; 1095 this.inClone = inClone; 1096 this.logLsn = logLsn; 1097 } 1098 1099 public IN doWork(ChildReference root) 1100 throws DatabaseException { 1101 1102 if (root == null || 1103 (root.getLsn() == DbLsn.NULL_LSN) || (root.fetchTarget(db, null).getNodeId() != 1105 inClone.getNodeId())) { 1106 return null; 1107 } 1108 1109 1113 if (DbLsn.compareTo(root.getLsn(), logLsn) <= 0) { 1114 IN rootIN = (IN) root.fetchTarget(db, null); 1115 rootIN.latch(Cleaner.UPDATE_GENERATION); 1116 return rootIN; 1117 } else { 1118 return null; 1119 } 1120 } 1121 } 1122 1123 1129 private IN isRoot(Tree tree, DatabaseImpl db, IN inClone, long lsn) 1130 throws DatabaseException { 1131 1132 RootDoWork rdw = new RootDoWork(db, inClone, lsn); 1133 return tree.withRootLatchedShared(rdw); 1134 } 1135 1136 1139 private void resetPerRunCounters() { 1140 nINsObsoleteThisRun = 0; 1141 nINsCleanedThisRun = 0; 1142 nINsDeadThisRun = 0; 1143 nINsMigratedThisRun = 0; 1144 nLNsObsoleteThisRun = 0; 1145 nLNsCleanedThisRun = 0; 1146 nLNsDeadThisRun = 0; 1147 nLNsMigratedThisRun = 0; 1148 nLNsMarkedThisRun = 0; 1149 nLNQueueHitsThisRun = 0; 1150 nLNsLockedThisRun = 0; 1151 nEntriesReadThisRun = 0; 1152 nRepeatIteratorReadsThisRun = 0; 1153 } 1154 1155 1158 private void accumulatePerRunCounters() { 1159 cleaner.nINsObsolete += nINsObsoleteThisRun; 1160 cleaner.nINsCleaned += nINsCleanedThisRun; 1161 cleaner.nINsDead += nINsDeadThisRun; 1162 cleaner.nINsMigrated += nINsMigratedThisRun; 1163 cleaner.nLNsObsolete += nLNsObsoleteThisRun; 1164 cleaner.nLNsCleaned += nLNsCleanedThisRun; 1165 cleaner.nLNsDead += nLNsDeadThisRun; 1166 cleaner.nLNsMigrated += nLNsMigratedThisRun; 1167 cleaner.nLNsMarked += nLNsMarkedThisRun; 1168 cleaner.nLNQueueHits += nLNQueueHitsThisRun; 1169 cleaner.nLNsLocked += nLNsLockedThisRun; 1170 cleaner.nRepeatIteratorReads += nRepeatIteratorReadsThisRun; 1171 } 1172 1173 1177 public String toString() { 1178 StringBuffer sb = new StringBuffer (); 1179 sb.append("<Cleaner name=\"").append(name).append("\"/>"); 1180 return sb.toString(); 1181 } 1182 1183 1188 private static class LookAheadCache { 1189 1190 private SortedMap map; 1191 private int maxMem; 1192 private int usedMem; 1193 1194 LookAheadCache(int lookAheadCacheSize) { 1195 map = new TreeMap (); 1196 maxMem = lookAheadCacheSize; 1197 usedMem = MemoryBudget.TREEMAP_OVERHEAD; 1198 } 1199 1200 boolean isEmpty() { 1201 return map.isEmpty(); 1202 } 1203 1204 boolean isFull() { 1205 return usedMem >= maxMem; 1206 } 1207 1208 Long nextOffset() { 1209 return (Long ) map.firstKey(); 1210 } 1211 1212 void add(Long lsnOffset, LNInfo info) { 1213 map.put(lsnOffset, info); 1214 usedMem += info.getMemorySize(); 1215 usedMem += MemoryBudget.TREEMAP_ENTRY_OVERHEAD; 1216 } 1217 1218 LNInfo remove(Long offset) { 1219 LNInfo info = (LNInfo) map.remove(offset); 1220 if (info != null) { 1221 usedMem -= info.getMemorySize(); 1222 usedMem -= MemoryBudget.TREEMAP_ENTRY_OVERHEAD; 1223 } 1224 return info; 1225 } 1226 } 1227} 1228 | Popular Tags |