1 8 9 package com.sleepycat.je.dbi; 10 11 import java.util.Arrays ; 12 import java.util.HashSet ; 13 import java.util.Iterator ; 14 import java.util.List ; 15 import java.util.Set ; 16 17 import com.sleepycat.je.DatabaseEntry; 18 import com.sleepycat.je.DatabaseException; 19 import com.sleepycat.je.cleaner.OffsetList; 20 import com.sleepycat.je.log.LogEntryType; 21 import com.sleepycat.je.log.entry.LNLogEntry; 22 import com.sleepycat.je.log.entry.LogEntry; 23 import com.sleepycat.je.tree.ChildReference; 24 import com.sleepycat.je.tree.BIN; 25 import com.sleepycat.je.tree.DBIN; 26 import com.sleepycat.je.tree.DIN; 27 import com.sleepycat.je.tree.DupCountLN; 28 import com.sleepycat.je.tree.IN; 29 import com.sleepycat.je.tree.LN; 30 import com.sleepycat.je.tree.Node; 31 import com.sleepycat.je.utilint.DbLsn; 32 33 55 public class SortedLSNTreeWalker { 56 57 60 public interface TreeNodeProcessor { 61 void processLSN(long childLSN, 62 LogEntryType childType, 63 Node theNode, 64 byte[] lnKey) 65 throws DatabaseException; 66 67 68 void processDupCount(long count); 69 } 70 71 75 public interface ExceptionPredicate { 76 77 boolean ignoreException(Exception e); 78 } 79 80 protected DatabaseImpl dbImpl; 81 private EnvironmentImpl envImpl; 82 83 87 private long rootLsn; 88 89 90 private boolean dups; 91 92 96 private boolean removeINsFromINList; 97 98 101 private boolean setDbState; 102 103 107 private long[] currentLSNs; 108 private int currentLSNIdx = 0; 109 110 118 private OffsetList accumulatedLSNFileNumbers; 119 private OffsetList accumulatedLSNFileOffsets; 120 121 private TreeNodeProcessor callback; 122 123 127 protected boolean accumulateLNs = false; 128 129 133 private boolean processDupTree = true; 134 135 139 private boolean passNullLSNNodes = false; 140 141 146 private List savedExceptions; 147 148 private ExceptionPredicate excPredicate; 149 150 151 private DatabaseEntry lnKeyEntry = new DatabaseEntry(); 152 153 157 public SortedLSNTreeWalker(DatabaseImpl dbImpl, 158 boolean removeINsFromINList, 159 boolean setDbState, 160 long rootLsn, 161 TreeNodeProcessor callback, 162 List savedExceptions, 163 ExceptionPredicate excPredicate) 164 throws DatabaseException { 165 166 167 this.dbImpl = dbImpl; 168 this.envImpl = dbImpl.getDbEnvironment(); 169 if (envImpl == null) { 170 throw new DatabaseException 171 ("environmentImpl is null for target db " + 172 dbImpl.getDebugName()); 173 } 174 this.dups = dbImpl.getSortedDuplicates(); 175 176 this.removeINsFromINList = removeINsFromINList; 177 this.setDbState = setDbState; 178 this.rootLsn = rootLsn; 179 this.callback = callback; 180 this.savedExceptions = savedExceptions; 181 this.excPredicate = excPredicate; 182 currentLSNs = new long[0]; 183 currentLSNIdx = 0; 184 } 185 186 void setProcessDupTree(boolean processDupTree) { 187 this.processDupTree = processDupTree; 188 } 189 190 void setPassNullLSNNodes(boolean passNullLSNNodes) { 191 this.passNullLSNNodes = passNullLSNNodes; 192 } 193 194 197 private boolean extractINsForDb(INList inList) 198 throws DatabaseException { 199 200 boolean foundSome = false; 201 202 203 Set foundSet = new HashSet (); 204 long memoryChange = 0; 205 MemoryBudget mb = envImpl.getMemoryBudget(); 206 inList.latchMajor(); 207 try { 208 209 inList.latchMinorAndDumpAddedINs(); 210 211 Iterator iter = inList.iterator(); 212 while (iter.hasNext()) { 213 IN thisIN = (IN) iter.next(); 214 if (thisIN.getDatabase() == dbImpl) { 215 foundSome = true; 216 if (removeINsFromINList) { 217 iter.remove(); 218 memoryChange += (thisIN.getAccumulatedDelta() - 219 thisIN.getInMemorySize()); 220 thisIN.setInListResident(false); 221 } 222 foundSet.add(thisIN); 223 } 224 } 225 } catch (DatabaseException e) { 226 227 mb.updateTreeMemoryUsage(memoryChange); 228 throw e; 229 } finally { 230 inList.releaseMajorLatch(); 231 } 232 233 237 if (foundSome) { 238 Iterator iter = foundSet.iterator(); 239 while (iter.hasNext()) { 240 IN thisIN = (IN) iter.next(); 241 accumulateLSNs(thisIN); 242 } 243 } 244 245 250 foundSet = null; 251 mb.updateTreeMemoryUsage(memoryChange); 252 253 return foundSome; 254 } 255 256 260 public void walk() 261 throws DatabaseException { 262 263 walkInternal(); 264 } 265 266 protected void walkInternal() 267 throws DatabaseException { 268 269 INList inList = envImpl.getInMemoryINs(); 270 IN root = null; 271 if (!extractINsForDb(inList)) { 272 if (rootLsn == DbLsn.NULL_LSN) { 273 return; 274 } 275 276 root = getRootIN(rootLsn); 277 accumulateLSNs(root); 278 releaseRootIN(root); 279 } 280 281 if (setDbState) { 282 dbImpl.finishedINListHarvest(); 283 } 284 285 while (true) { 286 maybeGetMoreINs(); 287 if (currentLSNs != null && 288 currentLSNIdx < currentLSNs.length) { 289 fetchAndProcessLSN(currentLSNs[currentLSNIdx++]); 290 } else { 291 break; 292 } 293 } 294 } 295 296 private void maybeGetMoreINs() { 297 298 if ((currentLSNs != null && 299 currentLSNIdx >= currentLSNs.length)) { 300 301 if (accumulatedLSNFileNumbers == null || 302 accumulatedLSNFileNumbers.size() == 0) { 303 304 305 currentLSNs = null; 306 currentLSNIdx = Integer.MAX_VALUE; 307 return; 308 } 309 310 long[] tempFileNumbers = accumulatedLSNFileNumbers.toArray(); 311 long[] tempFileOffsets = accumulatedLSNFileOffsets.toArray(); 312 int nLSNs = tempFileNumbers.length; 313 currentLSNIdx = 0; 314 currentLSNs = new long[nLSNs]; 315 for (int i = 0; i < nLSNs; i++) { 316 currentLSNs[i] = 317 DbLsn.makeLsn(tempFileNumbers[i], tempFileOffsets[i]); 318 } 319 320 Arrays.sort(currentLSNs); 321 accumulatedLSNFileNumbers = null; 322 accumulatedLSNFileOffsets = null; 323 } 324 } 325 326 private void accumulateLSNs(IN in) 327 throws DatabaseException { 328 329 boolean accumulate = true; 330 331 336 boolean childIsLN = (!dups && (in instanceof BIN)) || 337 (in instanceof DBIN); 338 if (childIsLN) { 339 if (!accumulateLNs) { 340 341 344 accumulate = false; 345 } 346 } 347 348 boolean isDINRoot = (in instanceof DIN) && in.isRoot(); 349 350 354 if (processDupTree || !in.containsDuplicates()) { 355 for (int i = 0; i < in.getNEntries(); i++) { 356 357 if (in.isEntryPendingDeleted(i) || 358 in.isEntryKnownDeleted(i)) { 359 continue; 360 } 361 362 long lsn = in.getLsn(i); 363 Node node = in.getTarget(i); 364 if (accumulate && (node == null)) { 365 if (accumulatedLSNFileNumbers == null) { 366 accumulatedLSNFileNumbers = new OffsetList(); 367 accumulatedLSNFileOffsets = new OffsetList(); 368 } 369 370 accumulatedLSNFileNumbers.add(DbLsn.getFileNumber(lsn), 371 false); 372 accumulatedLSNFileOffsets.add(DbLsn.getFileOffset(lsn), 373 false); 374 375 379 addToLsnINMap(new Long (lsn), in, i); 380 381 } else if (lsn != DbLsn.NULL_LSN || 382 passNullLSNNodes){ 383 384 388 byte[] lnKey = (node == null || node instanceof LN) ? 389 in.getKey(i) : null; 390 callback.processLSN(lsn, 391 (node == null) ? LogEntryType.LOG_LN : 392 node.getLogType(), 393 node, 394 lnKey); 395 } 396 } 397 } 398 399 400 if (isDINRoot) { 401 DIN din = (DIN) in; 402 ChildReference dupCountLNRef = din.getDupCountLNRef(); 403 long lsn = dupCountLNRef.getLsn(); 404 if (lsn == DbLsn.NULL_LSN) { 405 DupCountLN dcl = (DupCountLN) din.getDupCountLN(); 406 callback.processDupCount(dcl.getDupCount()); 407 } else { 408 Node node = fetchLSN(lsn, lnKeyEntry); 409 callback.processLSN 410 (lsn, LogEntryType.LOG_DUPCOUNTLN, node, 411 dupCountLNRef.getKey()); 412 } 413 } 414 } 415 416 420 private void fetchAndProcessLSN(long lsn) 421 throws DatabaseException { 422 423 try { 424 lnKeyEntry.setData(null); 425 Node node = fetchLSN(lsn, lnKeyEntry); 426 if (node != null) { 427 callback.processLSN 428 (lsn, node.getLogType(), node, lnKeyEntry.getData()); 429 430 if (node instanceof IN) { 431 accumulateLSNs((IN) node); 432 } 433 } 434 } catch (DatabaseException e) { 435 if (excPredicate == null || 436 !excPredicate.ignoreException(e)) { 437 if (savedExceptions != null) { 438 439 443 savedExceptions.add(e); 444 } else { 445 throw e; 446 } 447 } 448 } 449 } 450 451 455 protected IN getRootIN(long rootLsn) 456 throws DatabaseException { 457 458 return (IN) envImpl.getLogManager().get(rootLsn); 459 } 460 461 protected void releaseRootIN(IN ignore) 462 throws DatabaseException { 463 464 468 } 469 470 protected void addToLsnINMap(Long lsn, IN in, int index) { 471 } 472 473 protected Node fetchLSN(long lsn, DatabaseEntry lnKeyEntry) 474 throws DatabaseException { 475 476 LogEntry entry = envImpl.getLogManager().getLogEntry(lsn); 477 if (entry instanceof LNLogEntry) { 478 lnKeyEntry.setData(((LNLogEntry) entry).getKey()); 479 } 480 return (Node) entry.getMainItem(); 481 } 482 483 public List getSavedExceptions() { 484 return savedExceptions; 485 } 486 } 487 | Popular Tags |