1 8 9 package com.sleepycat.je.tree; 10 11 import java.nio.ByteBuffer ; 12 13 import com.sleepycat.je.DatabaseException; 14 import com.sleepycat.je.dbi.DatabaseImpl; 15 import com.sleepycat.je.dbi.EnvironmentImpl; 16 import com.sleepycat.je.log.LogFileNotFoundException; 17 import com.sleepycat.je.log.LogReadable; 18 import com.sleepycat.je.log.LogUtils; 19 import com.sleepycat.je.log.LogWritable; 20 import com.sleepycat.je.utilint.DbLsn; 21 22 26 public class ChildReference implements LogWritable, LogReadable { 27 28 static final int ROOT_LOG_SIZE = 29 LogUtils.getByteArrayLogSize(new byte[0]) + LogUtils.getLongLogSize() + 1; 33 private Node target; 34 private long lsn; 35 private byte[] key; 36 37 53 private byte state; 54 private static final byte KNOWN_DELETED_BIT = 0x1; 55 private static final byte DIRTY_BIT = 0x2; 56 private static final byte CLEAR_DIRTY_BIT = ~0x2; 57 private static final byte MIGRATE_BIT = 0x4; 58 private static final byte CLEAR_MIGRATE_BIT = ~0x4; 59 private static final byte PENDING_DELETED_BIT = 0x8; 60 61 64 ChildReference() { 65 init(null, Key.EMPTY_KEY, DbLsn.NULL_LSN, 0); 66 } 67 68 71 public ChildReference(Node target, byte[] key, long lsn) { 72 init(target, key, lsn, DIRTY_BIT); 73 } 74 75 78 public ChildReference(Node target, 79 byte[] key, 80 long lsn, 81 byte existingState) { 82 init(target, key, lsn, existingState | DIRTY_BIT); 83 } 84 85 private void init(Node target, 86 byte[] key, 87 long lsn, 88 int state) { 89 this.target = target; 90 this.key = key; 91 this.lsn = lsn; 92 this.state = (byte) state; 93 } 94 95 98 public byte[] getKey() { 99 return key; 100 } 101 102 105 public void setKey(byte[] key) { 106 this.key = key; 107 setDirty(); 108 } 109 110 127 public Node fetchTarget(DatabaseImpl database, IN in) 128 throws DatabaseException { 129 130 if (target == null) { 131 132 if (lsn == DbLsn.NULL_LSN) { 133 if (!isKnownDeleted()) { 134 throw new DatabaseException(IN.makeFetchErrorMsg 135 ("NULL_LSN without KnownDeleted", in, lsn, state)); 136 } 137 138 } else { 139 try { 140 EnvironmentImpl env = database.getDbEnvironment(); 141 Node node = (Node) env.getLogManager().get(lsn); 142 node.postFetchInit(database, lsn); 143 target = node; 144 if (in != null) { 145 in.updateMemorySize(null, target); 146 } 147 } catch (LogFileNotFoundException LNFE) { 148 if (!isKnownDeleted() && !isPendingDeleted()) { 149 throw new DatabaseException 150 (IN.makeFetchErrorMsg 151 (LNFE.toString(), in, lsn, state), 152 LNFE); 153 } 154 155 } catch (Exception e) { 156 throw new DatabaseException 157 (IN.makeFetchErrorMsg(e.toString(), in, lsn, state), 158 e); 159 } 160 } 161 } 162 163 return target; 164 } 165 166 169 byte getState() { 170 return state; 171 } 172 173 176 public Node getTarget() { 177 return target; 178 } 179 180 184 public void setTarget(Node target) { 185 this.target = target; 186 } 187 188 193 public void clearTarget() { 194 this.target = null; 195 } 196 197 202 public long getLsn() { 203 return lsn; 204 } 205 206 211 public void setLsn(long lsn) { 212 this.lsn = lsn; 213 setDirty(); 214 } 215 216 219 void updateLsnAfterOptionalLog(DatabaseImpl dbImpl, long lsn) { 220 if ((lsn == DbLsn.NULL_LSN) && 221 dbImpl.isDeferredWrite()) { 222 226 setDirty(); 227 } else { 228 setLsn(lsn); 229 } 230 } 231 232 private void setDirty() { 233 state |= DIRTY_BIT; 234 } 235 236 240 private boolean isPendingDeleted() { 241 return ((state & PENDING_DELETED_BIT) != 0); 242 } 243 244 247 public boolean isKnownDeleted() { 248 return ((state & KNOWN_DELETED_BIT) != 0); 249 } 250 251 254 private boolean isDirty() { 255 return ((state & DIRTY_BIT) != 0); 256 } 257 258 261 public boolean getMigrate() { 262 return (state & MIGRATE_BIT) != 0; 263 } 264 265 268 public void setMigrate(boolean migrate) { 269 if (migrate) { 270 state |= MIGRATE_BIT; 271 } else { 272 state &= CLEAR_MIGRATE_BIT; 273 } 274 } 275 276 279 280 283 public int getLogSize() { 284 return 285 LogUtils.getByteArrayLogSize(key) + LogUtils.getLongLogSize() + 1; } 289 290 293 public void writeToLog(ByteBuffer logBuffer) { 294 LogUtils.writeByteArray(logBuffer, key); LogUtils.writeLong(logBuffer, lsn); 296 logBuffer.put(state); state &= CLEAR_DIRTY_BIT; 298 } 299 300 303 public void readFromLog(ByteBuffer itemBuffer, byte entryTypeVersion) { 304 key = LogUtils.readByteArray(itemBuffer); lsn = LogUtils.readLong(itemBuffer); state = itemBuffer.get(); state &= CLEAR_DIRTY_BIT; 308 } 309 310 313 public void dumpLog(StringBuffer sb, boolean verbose) { 314 sb.append("<ref knownDeleted=\"").append(isKnownDeleted()); 315 sb.append("\" pendingDeleted=\"").append(isPendingDeleted()); 316 sb.append("\">"); 317 sb.append(Key.dumpString(key, 0)); 318 sb.append(DbLsn.toString(lsn)); 319 sb.append("</ref>"); 320 } 321 322 325 public boolean logEntryIsTransactional() { 326 return false; 327 } 328 329 332 public long getTransactionId() { 333 return 0; 334 } 335 336 339 String dumpString(int nspaces, boolean dumpTags) { 340 StringBuffer sb = new StringBuffer (); 341 if (lsn == DbLsn.NULL_LSN) { 342 sb.append(TreeUtils.indent(nspaces)); 343 sb.append("<lsn/>"); 344 } else { 345 sb.append(DbLsn.dumpString(lsn, nspaces)); 346 } 347 sb.append('\n'); 348 if (key == null) { 349 sb.append(TreeUtils.indent(nspaces)); 350 sb.append("<key/>"); 351 } else { 352 sb.append(Key.dumpString(key, nspaces)); 353 } 354 sb.append('\n'); 355 if (target == null) { 356 sb.append(TreeUtils.indent(nspaces)); 357 sb.append("<target/>"); 358 } else { 359 sb.append(target.dumpString(nspaces, true)); 360 } 361 sb.append('\n'); 362 sb.append(TreeUtils.indent(nspaces)); 363 sb.append("<knownDeleted val=\""); 364 sb.append(isKnownDeleted()).append("\"/>"); 365 sb.append("<pendingDeleted val=\""); 366 sb.append(isPendingDeleted()).append("\"/>"); 367 sb.append("<dirty val=\"").append(isDirty()).append("\"/>"); 368 return sb.toString(); 369 } 370 371 public String toString() { 372 return dumpString(0, false); 373 } 374 } 375 | Popular Tags |