/// <summary> /// Removes key-value pair by key. /// </summary> /// <param name="key">The key</param> public void Remove(TKey key) { var leafNode = GetSuitableLeafNodeForKeyIfRangeExists(key); if (leafNode == null) { return; } int index; var entry = FindSuitableEntry(leafNode.Entries, key, out index); if (entry.HasValue) { // free referenced value _valueStorage.Free(leafNode.Entries[index].Value); // delete reference from node leafNode.Entries.RemoveAt(index); if (IsSufficientlyFilled(leafNode)) { _nodeStorage.Update(leafNode); return; } var nodesToUpdate = new Dictionary <long, IBPlusTreeNode <TKey> >(); CombineIfNeeded(leafNode, nodesToUpdate); foreach (var nodeToUpdate in nodesToUpdate) { _nodeStorage.Update(nodeToUpdate.Value); } } }
/// <summary> /// Removes key-value pair by key. /// </summary> /// <param name="key">The key</param> public void Remove(TKey key) { var binaryKey = _keySerializer.Serialize(key); int keyOffset; int nodePrefixOffset; bool isFullMatch; IRadixTreeNode node = FindMostSuitableNode(binaryKey, out keyOffset, out nodePrefixOffset, out isFullMatch); if (isFullMatch) { _valueStorage.Free(node.ValueReference); node.ValueReference = null; if (node.Entries.Any()) { if (node.Prefix != null && node.Entries.Count == 1) { var child = _nodeStorage.Fetch(node.Entries[0].Value); var newPrefixLength = node.Prefix.Length + child.Prefix.Length; if (newPrefixLength <= MaxPrefixLength) { var newPrefix = new byte[newPrefixLength]; Buffer.BlockCopy(node.Prefix, 0, newPrefix, 0, node.Prefix.Length); Buffer.BlockCopy(child.Prefix, 0, newPrefix, node.Prefix.Length, child.Prefix.Length); child.Prefix = newPrefix; child.ParentNodeReference = node.ParentNodeReference; _nodeStorage.Remove(node.Reference); bool reallocated; child = UpdateOrReallocateNode(child, out reallocated); var parent = _nodeStorage.Fetch(child.ParentNodeReference); int index; FindSuitableEntry(parent.Entries, child.Prefix[0], out index); parent.Entries[index] = new KeyValuePair <byte, DbItemReference>(child.Prefix[0], child.Reference); UpdateOrFail(parent); } else { UpdateOrFail(node); } } else { UpdateOrFail(node); } } else { while (!DbItemReference.IsNull(node.ParentNodeReference)) { var parentNode = _nodeStorage.Fetch(node.ParentNodeReference); int index; FindSuitableEntry(parentNode.Entries, node.Prefix[0], out index); parentNode.Entries.RemoveAt(index); _nodeStorage.Remove(node.Reference); if (parentNode.Entries.Any() || parentNode.ValueReference != null || DbItemReference.IsNull(parentNode.ParentNodeReference)) { UpdateOrFail(parentNode); break; } node = parentNode; } } } }