1 8 9 package com.sleepycat.je.tree; 10 11 import java.nio.ByteBuffer ; 12 import java.util.Comparator ; 13 14 import com.sleepycat.je.DatabaseException; 15 import com.sleepycat.je.cleaner.Cleaner; 16 import com.sleepycat.je.dbi.DatabaseId; 17 import com.sleepycat.je.dbi.DatabaseImpl; 18 import com.sleepycat.je.dbi.DbConfigManager; 19 import com.sleepycat.je.dbi.EnvironmentImpl; 20 import com.sleepycat.je.dbi.MemoryBudget; 21 import com.sleepycat.je.log.LogEntryType; 22 import com.sleepycat.je.log.LogException; 23 import com.sleepycat.je.log.LogManager; 24 import com.sleepycat.je.log.LogUtils; 25 import com.sleepycat.je.txn.LockResult; 26 import com.sleepycat.je.txn.Locker; 27 import com.sleepycat.je.utilint.DbLsn; 28 29 32 public final class DIN extends IN { 33 34 private static final String BEGIN_TAG = "<din>"; 35 private static final String END_TAG = "</din>"; 36 37 40 private byte[] dupKey; 41 42 45 private ChildReference dupCountLNRef; 46 47 50 public DIN() { 51 super(); 52 53 dupCountLNRef = new ChildReference(); 54 init(null, Key.EMPTY_KEY, 0, 0); 55 } 56 57 60 public DIN(DatabaseImpl db, 61 byte[] identifierKey, 62 int capacity, 63 byte[] dupKey, 64 ChildReference dupCountLNRef, 65 int level) { 66 super(db, identifierKey, capacity, level); 67 68 this.dupKey = dupKey; 69 this.dupCountLNRef = dupCountLNRef; 70 initMemorySize(); } 72 73 74 protected int generateLevel(DatabaseId dbId, int newLevel) { 75 return newLevel; 76 } 77 78 82 protected IN createNewInstance(byte[] identifierKey, 83 int maxEntries, 84 int level) { 85 return new DIN(getDatabase(), 86 identifierKey, 87 maxEntries, 88 dupKey, 89 dupCountLNRef, 90 level); 91 } 92 93 98 boolean isAlwaysLatchedExclusively() { 99 return true; 100 } 101 102 105 public byte[] getDupKey() { 106 return dupKey; 107 } 108 109 113 public byte[] getChildKey(IN child) 114 throws DatabaseException { 115 116 return child.getIdentifierKey(); 117 } 118 119 122 public byte[] selectKey(byte[] mainTreeKey, byte[] dupTreeKey) { 123 return dupTreeKey; 124 } 125 126 129 public byte[] getDupTreeKey() { 130 return getIdentifierKey(); 131 } 132 133 136 public byte[] getMainTreeKey() { 137 return dupKey; 138 } 139 140 public ChildReference getDupCountLNRef() { 141 return dupCountLNRef; 142 } 143 144 public DupCountLN getDupCountLN() 145 throws DatabaseException { 146 147 return (DupCountLN) dupCountLNRef.fetchTarget(getDatabase(), this); 148 } 149 150 153 154 157 void setDupCountLN(ChildReference dupCountLNRef) { 158 updateMemorySize(this.dupCountLNRef, dupCountLNRef); 159 this.dupCountLNRef = dupCountLNRef; 160 } 161 162 165 public void updateDupCountLN(Node target) { 166 long oldSize = getEntryInMemorySize(dupCountLNRef.getKey(), 167 dupCountLNRef.getTarget()); 168 dupCountLNRef.setTarget(target); 169 long newSize = getEntryInMemorySize(dupCountLNRef.getKey(), 170 dupCountLNRef.getTarget()); 171 updateMemorySize(oldSize, newSize); 172 } 173 174 177 public void updateDupCountLNRefAndNullTarget(long newLsn) { 178 setDirty(true); 179 long oldSize = getEntryInMemorySize(dupCountLNRef.getKey(), 180 dupCountLNRef.getTarget()); 181 dupCountLNRef.setTarget(null); 182 if (notOverwritingDeferredWriteEntry(newLsn)) { 183 dupCountLNRef.setLsn(newLsn); 184 } 185 long newSize = getEntryInMemorySize(dupCountLNRef.getKey(), 186 dupCountLNRef.getTarget()); 187 updateMemorySize(oldSize, newSize); 188 } 189 190 193 public void updateDupCountLNRef(long newLsn) { 194 setDirty(true); 195 if (notOverwritingDeferredWriteEntry(newLsn)) { 196 dupCountLNRef.setLsn(newLsn); 197 } 198 } 199 200 204 public boolean containsDuplicates() { 205 return true; 206 } 207 208 209 public boolean isDbRoot() { 210 return false; 211 } 212 213 217 public final Comparator getKeyComparator() { 218 return getDatabase().getDuplicateComparator(); 219 } 220 221 228 public void incrementDuplicateCount(LockResult lockResult, 229 byte[] key, 230 Locker locker, 231 boolean increment) 232 throws DatabaseException { 233 234 235 long oldLsn = dupCountLNRef.getLsn(); 236 lockResult.setAbortLsn(oldLsn, dupCountLNRef.isKnownDeleted()); 237 DupCountLN dupCountLN = getDupCountLN(); 238 int oldSize = dupCountLN.getTotalLastLoggedSize(key); 239 if (increment) { 240 dupCountLN.incDupCount(); 241 } else { 242 dupCountLN.decDupCount(); 243 assert dupCountLN.getDupCount() >= 0; 244 } 245 DatabaseImpl db = getDatabase(); 246 long newCountLSN = dupCountLN.optionalLog 247 (db.getDbEnvironment(), db, key, oldLsn, oldSize, locker); 248 updateDupCountLNRef(newCountLSN); 249 250 } 251 252 257 protected long computeMemorySize() { 258 long size = super.computeMemorySize(); 259 if (dupCountLNRef != null) { 260 size += getEntryInMemorySize(dupCountLNRef.getKey(), 261 dupCountLNRef.getTarget()); 262 } 263 268 return size; 269 } 270 271 272 public static long computeOverhead(DbConfigManager configManager) 273 throws DatabaseException { 274 275 279 return MemoryBudget.DIN_FIXED_OVERHEAD + 280 IN.computeArraysOverhead(configManager); 281 } 282 283 protected long getMemoryOverhead(MemoryBudget mb) { 284 return mb.getDINOverhead(); 285 } 286 287 294 boolean matchLNByNodeId(TreeLocation location, long nodeId) 295 throws DatabaseException { 296 297 latch(); 298 try { 299 for (int i = 0; i < getNEntries(); i++) { 300 Node n = fetchTarget(i); 301 if (n != null) { 302 boolean ret = n.matchLNByNodeId(location, nodeId); 303 if (ret) { 304 return true; 305 } 306 } 307 } 308 309 return false; 310 } finally { 311 releaseLatch(); 312 } 313 } 314 315 318 void accumulateStats(TreeWalkerStatsAccumulator acc) { 319 acc.processDIN(this, new Long (getNodeId()), getLevel()); 320 } 321 322 325 326 329 public LogEntryType getLogType() { 330 return LogEntryType.LOG_DIN; 331 } 332 333 337 protected long logInternal(LogManager logManager, 338 boolean allowDeltas, 339 boolean isProvisional, 340 boolean proactiveMigration, 341 boolean backgroundIO, 342 IN parent) 343 throws DatabaseException { 344 345 346 if (dupCountLNRef != null) { 347 EnvironmentImpl envImpl = getDatabase().getDbEnvironment(); 348 DupCountLN dupCntLN = (DupCountLN) dupCountLNRef.getTarget(); 349 350 if ((dupCntLN != null) && (dupCntLN.isDirty())) { 351 352 356 long newLsn = dupCntLN.log(envImpl, 357 getDatabaseId(), 358 dupKey, 359 DbLsn.NULL_LSN, 0, null, false); dupCountLNRef.setLsn(newLsn); 364 } else { 365 366 369 Cleaner cleaner = 370 getDatabase().getDbEnvironment().getCleaner(); 371 cleaner.lazyMigrateDupCountLN 372 (this, dupCountLNRef, proactiveMigration); 373 } 374 } 375 376 return super.logInternal 377 (logManager, allowDeltas, isProvisional, proactiveMigration, 378 backgroundIO, parent); 379 } 380 381 384 public int getLogSize() { 385 int size = super.getLogSize(); size += LogUtils.getByteArrayLogSize(dupKey); size += LogUtils.getBooleanLogSize(); if (dupCountLNRef != null) { 389 size += dupCountLNRef.getLogSize(); 390 } 391 return size; 392 } 393 394 397 public void writeToLog(ByteBuffer logBuffer) { 398 399 super.writeToLog(logBuffer); 401 402 LogUtils.writeByteArray(logBuffer, dupKey); 404 405 406 boolean dupCountLNRefExists = (dupCountLNRef != null); 407 LogUtils.writeBoolean(logBuffer, dupCountLNRefExists); 408 if (dupCountLNRefExists) { 409 dupCountLNRef.writeToLog(logBuffer); 410 } 411 } 412 413 416 public void readFromLog(ByteBuffer itemBuffer, byte entryTypeVersion) 417 throws LogException { 418 419 super.readFromLog(itemBuffer, entryTypeVersion); 421 422 dupKey = LogUtils.readByteArray(itemBuffer); 424 425 426 boolean dupCountLNRefExists = LogUtils.readBoolean(itemBuffer); 427 if (dupCountLNRefExists) { 428 dupCountLNRef.readFromLog(itemBuffer, entryTypeVersion); 429 } else { 430 dupCountLNRef = null; 431 } 432 } 433 434 437 protected void dumpLogAdditional(StringBuffer sb) { 438 super.dumpLogAdditional(sb); 439 sb.append(Key.dumpString(dupKey, 0)); 440 if (dupCountLNRef != null) { 441 dupCountLNRef.dumpLog(sb, true); 442 } 443 } 444 445 448 449 public String beginTag() { 450 return BEGIN_TAG; 451 } 452 453 public String endTag() { 454 return END_TAG; 455 } 456 457 461 public String dumpString(int nSpaces, boolean dumpTags) { 462 StringBuffer sb = new StringBuffer (); 463 if (dumpTags) { 464 sb.append(TreeUtils.indent(nSpaces)); 465 sb.append(beginTag()); 466 sb.append('\n'); 467 } 468 469 sb.append(TreeUtils.indent(nSpaces+2)); 470 sb.append("<dupkey>"); 471 sb.append(dupKey == null ? "" : 472 Key.dumpString(dupKey, 0)); 473 sb.append("</dupkey>"); 474 sb.append('\n'); 475 if (dupCountLNRef == null) { 476 sb.append(TreeUtils.indent(nSpaces+2)); 477 sb.append("<dupCountLN/>"); 478 } else { 479 sb.append(dupCountLNRef.dumpString(nSpaces + 4, true)); 480 } 481 sb.append('\n'); 482 sb.append(super.dumpString(nSpaces, false)); 483 484 if (dumpTags) { 485 sb.append(TreeUtils.indent(nSpaces)); 486 sb.append(endTag()); 487 } 488 return sb.toString(); 489 } 490 491 public String toString() { 492 return dumpString(0, true); 493 } 494 495 public String shortClassName() { 496 return "DIN"; 497 } 498 } 499 | Popular Tags |