1 8 9 package com.sleepycat.je.tree; 10 11 import java.nio.ByteBuffer ; 12 13 import com.sleepycat.je.DatabaseEntry; 14 import com.sleepycat.je.DatabaseException; 15 import com.sleepycat.je.cleaner.UtilizationTracker; 16 import com.sleepycat.je.dbi.DatabaseId; 17 import com.sleepycat.je.dbi.DatabaseImpl; 18 import com.sleepycat.je.dbi.EnvironmentImpl; 19 import com.sleepycat.je.dbi.INList; 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.LogReadable; 25 import com.sleepycat.je.log.LogUtils; 26 import com.sleepycat.je.log.LoggableObject; 27 import com.sleepycat.je.log.entry.DeletedDupLNLogEntry; 28 import com.sleepycat.je.log.entry.LNLogEntry; 29 import com.sleepycat.je.txn.Locker; 30 import com.sleepycat.je.txn.Txn; 31 import com.sleepycat.je.txn.WriteLockInfo; 32 import com.sleepycat.je.utilint.DbLsn; 33 34 37 public class LN extends Node implements LoggableObject, LogReadable { 38 private static final String BEGIN_TAG = "<ln>"; 39 private static final String END_TAG = "</ln>"; 40 41 private byte[] data; 42 43 50 private static final byte DIRTY_BIT = 0x1; 51 private static final byte CLEAR_DIRTY_BIT = ~0x1; 52 private static final byte TXN_BIT = 0x2; 53 private static final byte CLEAR_TXN_BIT = ~0x2; 54 private byte state; 56 59 public LN() { 60 super(false); 61 this.data = null; 62 } 63 64 67 public LN(byte[] data) { 68 super(true); 69 if (data == null) { 70 this.data = null; 71 } else { 72 init(data, 0, data.length); 73 } 74 setDirty(); 75 } 76 77 80 public LN(DatabaseEntry dbt) { 81 super(true); 82 byte[] data = dbt.getData(); 83 if (data == null) { 84 this.data = null; 85 } else if (dbt.getPartial()) { 86 init(data, 87 dbt.getOffset(), 88 dbt.getPartialOffset() + dbt.getSize(), 89 dbt.getPartialOffset(), 90 dbt.getSize()); 91 } else { 92 init(data, dbt.getOffset(), dbt.getSize()); 93 } 94 setDirty(); 95 } 96 97 private void init(byte[] data, int off, int len, int doff, int dlen) { 98 if (len == 0) { 99 this.data = LogUtils.ZERO_LENGTH_BYTE_ARRAY; 100 } else { 101 this.data = new byte[len]; 102 System.arraycopy(data, off, this.data, doff, dlen); 103 } 104 } 105 106 private void init(byte[] data, int off, int len) { 107 init(data, off, len, 0, len); 108 } 109 110 public byte[] getData() { 111 return data; 112 } 113 114 public byte[] copyData() { 115 int len = data.length; 116 byte[] ret = new byte[len]; 117 System.arraycopy(data, 0, ret, 0, len); 118 return ret; 119 } 120 121 public boolean isDeleted() { 122 return (data == null); 123 } 124 125 void makeDeleted() { 126 data = null; 127 } 128 129 boolean isDirty() { 130 return ((state & DIRTY_BIT) != 0); 131 } 132 133 void setDirty() { 134 state |= DIRTY_BIT; 135 } 136 137 private void clearDirty() { 138 state &= CLEAR_DIRTY_BIT; 139 } 140 141 private boolean wasLastLoggedTransactionally() { 142 return ((state & TXN_BIT) != 0); 143 } 144 145 public void setLastLoggedTransactionally() { 146 state |= TXN_BIT; 147 } 148 149 public void clearLastLoggedTransactionally() { 150 state &= CLEAR_TXN_BIT; 151 } 152 153 160 boolean isValidForDelete() { 161 return false; 162 } 163 164 167 protected boolean isSoughtNode(long nid, boolean updateGeneration) { 168 return false; 169 } 170 171 174 protected boolean canBeAncestor(boolean targetContainsDuplicates) { 175 return false; 176 } 177 178 181 public long delete(DatabaseImpl database, 182 byte[] lnKey, 183 byte[] dupKey, 184 long oldLsn, 185 Locker locker) 186 throws DatabaseException { 187 188 int oldSize = getTotalLastLoggedSize(lnKey); 189 makeDeleted(); 190 setDirty(); 191 192 193 EnvironmentImpl env = database.getDbEnvironment(); 194 long newLsn = DbLsn.NULL_LSN; 195 if (dupKey != null) { 196 197 203 if (database.isDeferredWrite() && 204 oldLsn == DbLsn.NULL_LSN) { 205 clearDirty(); 206 } else { 207 208 newLsn = log(env, database.getId(), lnKey, dupKey, oldLsn, 209 oldSize, locker, 210 false, false); } 213 } else { 214 215 218 newLsn = optionalLog(env, database, lnKey, oldLsn, oldSize, locker); 219 } 220 return newLsn; 221 } 222 223 226 public long modify(byte[] newData, 227 DatabaseImpl database, 228 byte[] lnKey, 229 long oldLsn, 230 Locker locker) 231 throws DatabaseException { 232 233 int oldSize = getTotalLastLoggedSize(lnKey); 234 data = newData; 235 setDirty(); 236 237 238 EnvironmentImpl env = database.getDbEnvironment(); 239 long newLsn = 240 optionalLog(env, database, lnKey, oldLsn, oldSize, locker); 241 return newLsn; 242 } 243 244 248 void rebuildINList(INList inList) { 249 } 251 252 255 void accountForSubtreeRemoval(INList inList, 256 UtilizationTracker tracker) { 257 258 } 259 260 264 public long getMemorySizeIncludedByParent() { 265 int size = MemoryBudget.LN_OVERHEAD; 266 if (data != null) { 267 size += MemoryBudget.byteArraySize(data.length); 268 } 269 return size; 270 } 271 272 275 276 public String beginTag() { 277 return BEGIN_TAG; 278 } 279 280 public String endTag() { 281 return END_TAG; 282 } 283 284 public String dumpString(int nSpaces, boolean dumpTags) { 285 StringBuffer self = new StringBuffer (); 286 if (dumpTags) { 287 self.append(TreeUtils.indent(nSpaces)); 288 self.append(beginTag()); 289 self.append('\n'); 290 } 291 292 self.append(super.dumpString(nSpaces + 2, true)); 293 self.append('\n'); 294 if (data != null) { 295 self.append(TreeUtils.indent(nSpaces+2)); 296 self.append("<data>"); 297 self.append(TreeUtils.dumpByteArray(data)); 298 self.append("</data>"); 299 self.append('\n'); 300 } 301 if (dumpTags) { 302 self.append(TreeUtils.indent(nSpaces)); 303 self.append(endTag()); 304 } 305 return self.toString(); 306 } 307 308 311 312 322 public long log(EnvironmentImpl env, 323 DatabaseId dbId, 324 byte[] key, 325 long oldLsn, 326 int oldSize, 327 Locker locker, 328 boolean backgroundIO) 329 throws DatabaseException { 330 331 return log(env, dbId, key, 332 null, oldLsn, oldSize, locker, backgroundIO, 334 false); } 336 337 347 public long optionalLog(EnvironmentImpl env, 348 DatabaseImpl databaseImpl, 349 byte[] key, 350 long oldLsn, 351 int oldSize, 352 Locker locker) 353 throws DatabaseException { 354 355 if (databaseImpl.isDeferredWrite()) { 356 return DbLsn.NULL_LSN; 357 } else { 358 return log 359 (env, databaseImpl.getId(), key, 360 null, oldLsn, oldSize, locker, 362 false, false); } 365 } 366 367 375 public long optionalLogProvisional(EnvironmentImpl env, 376 DatabaseImpl databaseImpl, 377 byte[] key, 378 long oldLsn, 379 int oldSize) 380 throws DatabaseException { 381 382 if (databaseImpl.isDeferredWrite()) { 383 return DbLsn.NULL_LSN; 384 } else { 385 return log 386 (env, databaseImpl.getId(), key, 387 null, oldLsn, oldSize, 389 null, false, true); } 393 } 394 395 406 long log(EnvironmentImpl env, 407 DatabaseId dbId, 408 byte[] key, 409 byte[] delDupKey, 410 long oldLsn, 411 int oldSize, 412 Locker locker, 413 boolean backgroundIO, 414 boolean isProvisional) 415 throws DatabaseException { 416 417 boolean isDelDup = (delDupKey != null); 418 LogEntryType entryType; 419 long logAbortLsn; 420 boolean logAbortKnownDeleted; 421 Txn logTxn; 422 if (locker != null && locker.isTransactional()) { 423 entryType = isDelDup ? LogEntryType.LOG_DEL_DUPLN_TRANSACTIONAL 424 : getTransactionalLogType(); 425 WriteLockInfo info = locker.getWriteLockInfo(getNodeId()); 426 logAbortLsn = info.getAbortLsn(); 427 logAbortKnownDeleted = info.getAbortKnownDeleted(); 428 logTxn = locker.getTxnLocker(); 429 assert logTxn != null; 430 if (oldLsn == logAbortLsn) { 431 info.setAbortLogSize(oldSize); 432 } 433 } else { 434 entryType = isDelDup ? LogEntryType.LOG_DEL_DUPLN 435 : getLogType(); 436 logAbortLsn = DbLsn.NULL_LSN; 437 logAbortKnownDeleted = false; 438 logTxn = null; 439 } 440 441 442 if (oldLsn == logAbortLsn) { 443 oldLsn = DbLsn.NULL_LSN; 444 } 445 446 LNLogEntry logEntry; 447 if (isDelDup) { 448 449 459 logEntry = 460 new DeletedDupLNLogEntry(entryType, 461 this, 462 dbId, 463 delDupKey, 464 key, 465 logAbortLsn, 466 logAbortKnownDeleted, 467 logTxn); 468 } else { 469 470 logEntry = new LNLogEntry(entryType, 471 this, 472 dbId, 473 key, 474 logAbortLsn, 475 logAbortKnownDeleted, 476 logTxn); 477 } 478 479 LogManager logManager = env.getLogManager(); 480 long lsn = logManager.log(logEntry, isProvisional, 481 backgroundIO, oldLsn, oldSize); 482 clearDirty(); 483 return lsn; 484 } 485 486 489 protected LogEntryType getTransactionalLogType() { 490 return LogEntryType.LOG_LN_TRANSACTIONAL; 491 } 492 493 496 public boolean countAsObsoleteWhenLogged() { 497 return false; 498 } 499 500 503 public LogEntryType getLogType() { 504 return LogEntryType.LOG_LN; 505 } 506 507 513 public int getTotalLastLoggedSize(byte[] lnKey) { 514 515 520 assert !isDeleted(); 521 522 return LNLogEntry.getStaticLogSize 523 (getLastLoggedSize(), lnKey, 524 wasLastLoggedTransactionally()) + 525 LogManager.HEADER_BYTES; 526 } 527 528 536 public int getLastLoggedSize() { 537 return getLogSize(); 538 } 539 540 543 public int getLogSize() { 544 int size = super.getLogSize(); 545 546 size += LogUtils.getBooleanLogSize(); if (!isDeleted()) { 549 size += LogUtils.getByteArrayLogSize(data); 550 } 551 552 return size; 553 } 554 555 558 public void writeToLog(ByteBuffer logBuffer) { 559 560 super.writeToLog(logBuffer); 561 562 563 boolean dataExists = !isDeleted(); 564 LogUtils.writeBoolean(logBuffer, dataExists); 565 if (dataExists) { 566 LogUtils.writeByteArray(logBuffer, data); 567 } 568 } 569 570 573 public void readFromLog(ByteBuffer itemBuffer, byte entryTypeVersion) 574 throws LogException { 575 576 super.readFromLog(itemBuffer, entryTypeVersion); 577 578 boolean dataExists = LogUtils.readBoolean(itemBuffer); 579 if (dataExists) { 580 data = LogUtils.readByteArray(itemBuffer); 581 } 582 } 583 584 587 public void dumpLog(StringBuffer sb, boolean verbose) { 588 sb.append(beginTag()); 589 super.dumpLog(sb, verbose); 590 591 if (data != null) { 592 sb.append("<data>"); 593 sb.append(TreeUtils.dumpByteArray(data)); 594 sb.append("</data>"); 595 } 596 597 dumpLogAdditional(sb, verbose); 598 599 sb.append(endTag()); 600 } 601 602 606 public boolean logEntryIsTransactional() { 607 return false; 608 } 609 610 614 public long getTransactionId() { 615 return 0; 616 } 617 618 621 protected void dumpLogAdditional(StringBuffer sb, boolean verbose) { 622 } 623 } 624 | Popular Tags |