private void DoDisposeNode(NodeId id) { // If the node is a special node, then we don't dispose it if (id.IsSpecial) { return; } // Is 'id' a leaf node? IMutableArea nodeArea = nodeStore.GetMutableArea(ToInt64StoreAddress(id)); // Are we a leaf? nodeArea.Position = 0; int nodeType = nodeArea.ReadInt2(); if (nodeType == StoreLeafType) { // Yes, get its reference_count, lock (referenceCountLock) { nodeArea.Position = 4; int refCount = nodeArea.ReadInt4(); // If the reference_count is >1 then decrement it and return if (refCount > 1) { nodeArea.Position = 4; nodeArea.WriteInt4(refCount - 1); return; } } } else if (nodeType != StoreBranchType) { // Has to be a branch type, otherwise failure throw new IOException("Unknown node type."); } // 'id' is a none leaf branch or its reference count is 1, so delete the // area. // NOTE, we delete from the cache first before we delete the area // because the deleted area may be reclaimed immediately and deleting // from the cache after may be too late. // Delete from the cache because the given ref may be recycled for a new // node at some point. lock (branchCache) { branchCache.Remove(id); } // Delete the area nodeStore.DeleteArea(ToInt64StoreAddress(id)); }
public bool LinkLeaf(Key key, NodeId id) { // If the node is a special node, then we don't need to reference count it. if (id.IsSpecial) { return(true); } try { nodeStore.LockForWrite(); // Get the area as a MutableArea object IMutableArea leafArea = nodeStore.GetMutableArea(ToInt64StoreAddress(id)); // We synchronize over a reference count lock // (Pending: should we lock by area instead? I'm not sure it will be // worth the complexity of a more fine grained locking mechanism for the // performance improvements - maybe we should implement a locking // mechanism inside MutableArea). lock (referenceCountLock) { // Assert this is a leaf leafArea.Position = 0; short nodeType = leafArea.ReadInt2(); if (nodeType != StoreLeafType) { throw new IOException("Can only link to a leaf node."); } leafArea.Position = 4; int refCount = leafArea.ReadInt4(); // If reference counter is near overflowing, return false. if (refCount > Int32.MaxValue - 8) { return(false); } leafArea.Position = 4; leafArea.WriteInt4(refCount + 1); } return(true); } finally { nodeStore.UnlockForWrite(); } }