package com.sleepycat.je.tree; public class IN { private boolean inListResident; private int accumulatedDelta=0; /** * Initialize the per-node memory count by computing its memory usage. */ protected void initMemorySize(){ inMemorySize=computeMemorySize(); } public boolean verifyMemorySize(){ long calcMemorySize=computeMemorySize(); if (calcMemorySize != inMemorySize) { String msg="-Warning: Out of sync. " + "Should be " + calcMemorySize + " / actual: "+ inMemorySize+ " node: "+ getNodeId(); this.hook615(msg); System.out.println(msg); return false; } else { return true; } } /** * Return the number of bytes used by this IN. Latching is up to the * caller. */ public long getInMemorySize(){ return inMemorySize; } private long getEntryInMemorySize( int idx){ return getEntryInMemorySize(entryKeyVals[idx],entryTargets[idx]); } protected long getEntryInMemorySize( byte[] key, Node target){ long ret=0; if (key != null) { ret+=MemoryBudget.byteArraySize(key.length); } if (target != null) { ret+=target.getMemorySizeIncludedByParent(); } return ret; } /** * Count up the memory usage attributable to this node alone. LNs children * are counted by their BIN/DIN parents, but INs are not counted by their * parents because they are resident on the IN list. */ protected long computeMemorySize(){ MemoryBudget mb=databaseImpl.getDbEnvironment().getMemoryBudget(); long calcMemorySize=getMemoryOverhead(mb); calcMemorySize+=computeLsnOverhead(); for (int i=0; i < nEntries; i++) { calcMemorySize+=getEntryInMemorySize(i); } if (provisionalObsolete != null) { calcMemorySize+=provisionalObsolete.size() * MemoryBudget.LONG_LIST_PER_ITEM_OVERHEAD; } return calcMemorySize; } public static long computeOverhead( DbConfigManager configManager) throws DatabaseException { return MemoryBudget.IN_FIXED_OVERHEAD + IN.computeArraysOverhead(configManager); } private int computeLsnOverhead(){ if (entryLsnLongArray == null) { return MemoryBudget.byteArraySize(entryLsnByteArray.length); } else { return MemoryBudget.BYTE_ARRAY_OVERHEAD + entryLsnLongArray.length * MemoryBudget.LONG_OVERHEAD; } } protected static long computeArraysOverhead( DbConfigManager configManager) throws DatabaseException { int capacity=configManager.getInt(EnvironmentParams.NODE_MAX); return MemoryBudget.byteArraySize(capacity) + (capacity * (2 * MemoryBudget.ARRAY_ITEM_OVERHEAD)); } protected long getMemoryOverhead( MemoryBudget mb){ return mb.getINOverhead(); } protected void updateMemorySize( ChildReference oldRef, ChildReference newRef){ long delta=0; if (newRef != null) { delta=getEntryInMemorySize(newRef.getKey(),newRef.getTarget()); } if (oldRef != null) { delta-=getEntryInMemorySize(oldRef.getKey(),oldRef.getTarget()); } changeMemorySize(delta); } protected void updateMemorySize( long oldSize, long newSize){ long delta=newSize - oldSize; changeMemorySize(delta); } void updateMemorySize( Node oldNode, Node newNode){ long delta=0; if (newNode != null) { delta=newNode.getMemorySizeIncludedByParent(); } if (oldNode != null) { delta-=oldNode.getMemorySizeIncludedByParent(); } changeMemorySize(delta); } private void changeMemorySize( long delta){ inMemorySize+=delta; if (inListResident) { MemoryBudget mb=databaseImpl.getDbEnvironment().getMemoryBudget(); accumulatedDelta+=delta; if (accumulatedDelta > ACCUMULATED_LIMIT || accumulatedDelta < -ACCUMULATED_LIMIT) { mb.updateTreeMemoryUsage(accumulatedDelta); accumulatedDelta=0; } } } public int getAccumulatedDelta(){ return accumulatedDelta; } public void setInListResident( boolean resident){ inListResident=resident; } protected void hook615( String msg){ } /** * Create a new IN. */ IN( DatabaseImpl db, byte[] identifierKey, int capacity, int level){ initMemorySize(); } /** * Initialize IN object. */ protected void init( DatabaseImpl db, byte[] identifierKey, int initialCapacity, int level){ original(db,identifierKey,initialCapacity,level); inListResident=false; } protected void hook637() throws DatabaseException { initMemorySize(); original(); } /** * Initialize a node read in during recovery. */ public void postRecoveryInit( DatabaseImpl db, long sourceLsn){ original(db,sourceLsn); initMemorySize(); } protected void hook638( Node node) throws DatabaseException, LogFileNotFoundException, Exception { updateMemorySize(null,node); original(node); } /** * Update the idx'th entry of this node. This flavor is used when the * target LN is being modified, by an operation like a delete or update. We * don't have to check whether the LSN has been nulled or not, because we * know an LSN existed before. Also, the modification of the target is done * in the caller, so instead of passing in the old and new nodes, we pass * in the old and new node sizes. */ public void updateEntry( int idx, long lsn, long oldLNSize, long newLNSize){ updateMemorySize(oldLNSize,newLNSize); original(idx,lsn,oldLNSize,newLNSize); } /** * Add self and children to this in-memory IN list. Called by recovery, can * run with no latching. */ void rebuildINList( INList inList) throws DatabaseException { initMemorySize(); original(inList); } @MethodObject static class IN_splitInternal { protected void hook650() throws DatabaseException { newSize=_this.computeMemorySize(); _this.updateMemorySize(oldMemorySize,newSize); original(); } } @MethodObject static class IN_deleteEntry { protected void hook648() throws DatabaseException { _this.updateMemorySize(oldLSNArraySize,_this.computeLsnOverhead()); original(); } protected void hook649() throws DatabaseException { _this.updateMemorySize(_this.getEntryInMemorySize(index),0); oldLSNArraySize=_this.computeLsnOverhead(); original(); } } @MethodObject static class IN_trackProvisionalObsolete { void execute(){ original(); if (memDelta != 0) { _this.changeMemorySize(memDelta); } } protected void hook651(){ child.changeMemorySize(0 - childMemDelta); memDelta+=childMemDelta; original(); } protected void hook652(){ childMemDelta=child.provisionalObsolete.size() * MemoryBudget.LONG_LIST_PER_ITEM_OVERHEAD; original(); } protected void hook653(){ memDelta+=MemoryBudget.LONG_LIST_PER_ITEM_OVERHEAD; original(); } protected void hook654(){ memDelta+=MemoryBudget.LONG_LIST_PER_ITEM_OVERHEAD; original(); } } @MethodObject static class IN_insertEntry1 { protected void hook645() throws DatabaseException { _this.updateMemorySize(0,_this.getEntryInMemorySize(index)); original(); } protected void hook646() throws DatabaseException { _this.changeMemorySize(_this.computeLsnOverhead() - oldSize); original(); } protected void hook647() throws DatabaseException { oldSize=_this.computeLsnOverhead(); original(); } } @MethodObject static class IN_updateEntryCompareKey { void execute(){ oldSize=_this.getEntryInMemorySize(idx); original(); } protected void hook644(){ newSize=_this.getEntryInMemorySize(idx); _this.updateMemorySize(oldSize,newSize); original(); } } @MethodObject static class IN_updateEntry { void execute(){ oldSize=_this.getEntryInMemorySize(idx); original(); newSize=_this.getEntryInMemorySize(idx); _this.updateMemorySize(oldSize,newSize); } } @MethodObject static class IN_setLsn { void execute(){ oldSize=_this.computeLsnOverhead(); original(); } protected void hook639(){ _this.changeMemorySize(_this.computeLsnOverhead() - oldSize); original(); } } @MethodObject static class IN_updateEntry2 { void execute(){ oldSize=_this.getEntryInMemorySize(idx); original(); } protected void hook642(){ newSize=_this.getEntryInMemorySize(idx); _this.updateMemorySize(oldSize,newSize); original(); } } @MethodObject static class IN_flushProvisionalObsolete { protected void hook655() throws DatabaseException { _this.changeMemorySize(0 - memDelta); original(); } protected void hook656() throws DatabaseException { memDelta=_this.provisionalObsolete.size() * MemoryBudget.LONG_LIST_PER_ITEM_OVERHEAD; original(); } } @MethodObject static class IN_updateEntry3 { void execute(){ oldSize=_this.getEntryInMemorySize(idx); original(); } protected void hook643(){ newSize=_this.getEntryInMemorySize(idx); _this.updateMemorySize(oldSize,newSize); original(); } } @MethodObject static class IN_setEntry { void execute(){ oldSize=_this.getEntryInMemorySize(idx); original(); } protected void hook640(){ newSize=_this.getEntryInMemorySize(idx); _this.updateMemorySize(oldSize,newSize); original(); } protected void hook641(){ oldSize=0; original(); } } }