/// <summary> /// Creates an empty right sibling node and inserts the provided key in this node. /// Note: This should only be called if there is no right sibling and the key should go in /// that node. /// </summary> private void NewNodeThenInsert(TKey key, TValue value) { TKey dividingKey = new TKey(); //m_tempKey; key.CopyTo(dividingKey); uint newNodeIndex = m_getNextNewNodeIndex(); if (!IsRightSiblingIndexNull) { throw new Exception("Incorrectly implemented"); } RightSiblingNodeIndex = newNodeIndex; CreateNewNode(newNodeIndex, 0, (ushort)HeaderSize, NodeIndex, uint.MaxValue, key, UpperKey); UpperKey = key; SetNodeIndex(newNodeIndex); InsertUnlessFull(0, key, value); SparseIndex.Add(dividingKey, newNodeIndex, (byte)(Level + 1)); }
private void UpdateBoundsAndRemoveEmptyNode(Node <TKey> leftNode, Node <TKey> rightNode) { if (leftNode.RecordCount == 0) //Remove the left node { //Change the existing pointer to the left node to point to the right node. SparseIndex.UpdateValue(leftNode.LowerKey, new SnapUInt32(rightNode.NodeIndex), (byte)(Level + 1)); //Now remove the unused key position SparseIndex.Remove(rightNode.LowerKey, (byte)(Level + 1)); rightNode.LowerKey = leftNode.LowerKey; rightNode.LeftSiblingNodeIndex = leftNode.LeftSiblingNodeIndex; if (leftNode.LeftSiblingNodeIndex != uint.MaxValue) { leftNode.SeekToLeftSibling(); leftNode.RightSiblingNodeIndex = rightNode.NodeIndex; } } else if (rightNode.RecordCount == 0) //Remove the right node. { SparseIndex.Remove(rightNode.LowerKey, (byte)(Level + 1)); leftNode.UpperKey = rightNode.UpperKey; leftNode.RightSiblingNodeIndex = rightNode.RightSiblingNodeIndex; if (rightNode.RightSiblingNodeIndex != uint.MaxValue) { rightNode.SeekToRightSibling(); rightNode.LeftSiblingNodeIndex = leftNode.NodeIndex; } } else { throw new Exception("Should never get here"); } }
//private TKey[] m_keys; //private TValue[] m_values; //public TKey[] Keys //{ // get // { // BuildKeyList(); // return m_keys; // } //} //public TValue[] Values //{ // get // { // BuildKeyList(); // return m_values; // } //} //public void WriteNodeData(StringBuilder sb) //{ // BuildKeyList(); // sb.AppendLine(string.Format("Node Index: {0} Record Count: {1} Node Level: {2} " + // "Right Sibling: {3} Left Sibling: {4} Lower Key: {5} Upper Key: {6}", NodeIndex, RecordCount, // Level, RightSiblingNodeIndex, LeftSiblingNodeIndex, LowerKey, UpperKey)); // foreach (TKey key in m_keys) // { // sb.Append(key.ToString()); // sb.Append("\t"); // } // sb.AppendLine(); // foreach (TValue value in m_values) // { // sb.Append(value.ToString()); // sb.Append("\t"); // } // sb.AppendLine(); //} //private void BuildKeyList() //{ // if (m_keys is null || m_keys.Length != RecordCount) // { // m_keys = new TKey[RecordCount]; // m_values = new TValue[RecordCount]; // for (int x = 0; x < RecordCount; x++) // { // m_keys[x] = new TKey(); // m_values[x] = new TValue(); // } // } // for (int x = 0; x < RecordCount; x++) // { // Read(x, m_keys[x], m_values[x]); // } //} #region [ Methods ] /// <summary> /// Seeks to the first node at this level of the tree /// </summary> public void SeekToFirstNode() { //Only need to do a seek if I'm not already on the first node. if (NodeIndex == uint.MaxValue || LeftSiblingNodeIndex != uint.MaxValue) { SetNodeIndex(SparseIndex.GetFirstIndex(Level)); } }
private void Initialize() { Indexer = new SparseIndex <TKey>(); LeafStorage = Library.CreateTreeNode <TKey, TValue>(m_header.TreeNodeType, 0); Indexer.RootHasChanged += IndexerOnRootHasChanged; Indexer.Initialize(Stream, m_header.BlockSize, GetNextNewNodeIndex, m_header.RootNodeLevel, m_header.RootNodeIndexAddress); LeafStorage.Initialize(Stream, m_header.BlockSize, GetNextNewNodeIndex, Indexer); }
private void UpdateBoundsOfNode(Node <TKey> leftNode, Node <TKey> rightNode) { TKey oldLowerKey = new TKey(); TKey newLowerKey = new TKey(); rightNode.LowerKey.CopyTo(oldLowerKey); newLowerKey.Read(rightNode.GetReadPointerAfterHeader()); //ToDo: Make Generic rightNode.LowerKey = newLowerKey; leftNode.UpperKey = newLowerKey; SparseIndex.UpdateKey(oldLowerKey, newLowerKey, (byte)(Level + 1)); }
/// <summary> /// Initializes the required parameters for this tree to function. Must be called once. /// </summary> /// <param name="stream">the stream to use.</param> /// <param name="blockSize">the size of each block</param> /// <param name="getNextNewNodeIndex"></param> /// <param name="sparseIndex"></param> public void Initialize(BinaryStreamPointerBase stream, int blockSize, Func <uint> getNextNewNodeIndex, SparseIndex <TKey> sparseIndex) { if (m_initialized) { throw new Exception("Duplicate calls to initialize"); } m_initialized = true; InitializeNode(stream, blockSize); m_tempNode1 = new Node <TKey>(stream, blockSize, Level); m_tempNode2 = new Node <TKey>(stream, blockSize, Level); SparseIndex = sparseIndex; m_minRecordNodeBytes = BlockSize >> 2; m_getNextNewNodeIndex = getNextNewNodeIndex; InitializeType(); }
/// <summary> /// Splits the current node and then inserts the provided key/value into the correct node. /// </summary> private void SplitNodeThenInsert(TKey key, TValue value) { uint currentNode = NodeIndex; uint newNodeIndex = m_getNextNewNodeIndex(); TKey dividingKey = new TKey(); //m_tempKey; Split(newNodeIndex, dividingKey); SetNodeIndex(currentNode); if (IsKeyInsideBounds(key)) { InsertUnlessFull(~GetIndexOf(key), key, value); UpperKey.CopyTo(dividingKey); } else { SeekToRightSibling(); InsertUnlessFull(~GetIndexOf(key), key, value); LowerKey.CopyTo(dividingKey); } SparseIndex.Add(dividingKey, newNodeIndex, (byte)(Level + 1)); }
public static void TestNode <TKey, TValue>(SortedTreeNodeBase <TKey, TValue> node, TreeNodeRandomizerBase <TKey, TValue> randomizer, int count) where TKey : SnapTypeBase <TKey>, new() where TValue : SnapTypeBase <TValue>, new() { int Max = count; uint rootKey = 0; byte rootLevel = 0; uint nextKeyIndex = 2; bool hasChanged = false; Func <uint> getNextKey = () => { nextKeyIndex++; return(nextKeyIndex - 1); }; StringBuilder sb = new StringBuilder(); using (BinaryStream bs = new BinaryStream()) { const int pageSize = 512; SparseIndex <TKey> sparse = new SparseIndex <TKey>(); sparse.Initialize(bs, pageSize, getNextKey, 0, 1); node.Initialize(bs, pageSize, getNextKey, sparse); node.CreateEmptyNode(1); TKey key = new TKey(); TKey key2 = new TKey(); TValue value = new TValue(); TValue value2 = new TValue(); randomizer.Reset(Max); for (int x = 0; x < Max; x++) { randomizer.Next(); //Add the next point randomizer.GetRandom(x, key, value); //node.WriteNodeData(sb); if (!node.TryInsert(key, value)) { throw new Exception(); } //node.WriteNodeData(sb); //File.WriteAllText("c:\\temp\\temp.log", sb.ToString()); //Check if all points exist for (int y = 0; y <= x; y++) { randomizer.GetRandom(y, key, value); if (!node.TryGet(key, value2)) { throw new Exception(); } if (!value.IsEqualTo(value2)) { throw new Exception(); } } //Check if scanner works. SortedTreeScannerBase <TKey, TValue> scanner = node.CreateTreeScanner(); scanner.SeekToStart(); for (int y = 0; y <= x; y++) { randomizer.GetInSequence(y, key, value); if (!scanner.Read(key2, value2)) { throw new Exception(); } if (!key.IsEqualTo(key2)) { throw new Exception(); } if (!value.IsEqualTo(value2)) { throw new Exception(); } } if (scanner.Read(key2, value2)) { throw new Exception(); } } node = node; } }
internal static void TestSpeed <TKey, TValue>(SortedTreeNodeBase <TKey, TValue> nodeInitializer, TreeNodeRandomizerBase <TKey, TValue> randomizer, int count, int pageSize) where TKey : SnapTypeBase <TKey>, new() where TValue : SnapTypeBase <TValue>, new() { int Max = count; uint nextKeyIndex = 2; Func <uint> getNextKey = () => { nextKeyIndex++; return(nextKeyIndex - 1); }; using (BinaryStream bs = new BinaryStream()) { randomizer.Reset(Max); for (int x = 0; x < Max; x++) { randomizer.Next(); } TKey key = new TKey(); TValue value = new TValue(); SortedTreeNodeBase <TKey, TValue> node = null; System.Console.WriteLine(StepTimer.Time(count, (sw) => { nextKeyIndex = 2; node = nodeInitializer.Clone(0); SparseIndex <TKey> sparse = new SparseIndex <TKey>(); sparse.Initialize(bs, pageSize, getNextKey, 0, 1); node.Initialize(bs, pageSize, getNextKey, sparse); node.CreateEmptyNode(1); sw.Start(); for (int x = 0; x < Max; x++) { //Add the next point randomizer.GetRandom(x, key, value); if (!node.TryInsert(key, value)) { throw new Exception(); } } sw.Stop(); })); System.Console.WriteLine(StepTimer.Time(count, () => { for (int x = 0; x < Max; x++) { //Add the next point randomizer.GetRandom(x, key, value); if (!node.TryGet(key, value)) { throw new Exception(); } } })); System.Console.WriteLine(StepTimer.Time(count, () => { SortedTreeScannerBase <TKey, TValue> scanner = node.CreateTreeScanner(); scanner.SeekToStart(); while (scanner.Read(key, value)) { ; } })); node = node; } }
//ToDO: Checked protected bool TryRemove2(TKey key) { NavigateToNode(key); int index = GetIndexOf(key); if (index < 0) { return(false); } if (!RemoveUnlessOverflow(index)) { //ToDo:SplitAndThenRemove throw new NotImplementedException(); } if (ValidBytes > m_minRecordNodeBytes) //if the node has not underflowed, we can exit early. { return(true); } if (IsRightSiblingIndexNull && IsLeftSiblingIndexNull) //If there are no nodes to combine with, we can quit early. { return(true); } if (RecordCount > 0 && (IsRightSiblingIndexNull || IsLeftSiblingIndexNull)) //There can be fewer than the minimum it is the first or last node on the level. { return(true); } bool canCombineWithLeft; bool canCombineWithRight; SparseIndex.CanCombineWithSiblings(LowerKey, (byte)(Level + 1), out canCombineWithLeft, out canCombineWithRight); if (RecordCount == 0) //Only will occur if the right or left node is empty (but not both) { if (canCombineWithLeft && IsRightSiblingIndexNull) { CombineNodes(LeftSiblingNodeIndex, NodeIndex); } else if (canCombineWithRight && IsLeftSiblingIndexNull) { CombineNodes(NodeIndex, RightSiblingNodeIndex); } else { throw new Exception("Should never reach this condition"); } return(true); } int deltaBytesWhenCombining = MaxOverheadWithCombineNodes - HeaderSize; if (IsRightSiblingIndexNull) //We can only combine with the left node. { if (!canCombineWithLeft) { throw new Exception("Should never reach this condition"); } if (ValidBytes + GetValidBytes(LeftSiblingNodeIndex) + deltaBytesWhenCombining < BlockSize) { CombineNodes(LeftSiblingNodeIndex, NodeIndex); } else { RebalanceNodes(LeftSiblingNodeIndex, NodeIndex); } } else if (IsLeftSiblingIndexNull) //We can only combine with the right node. { if (!canCombineWithRight) { throw new Exception("Should never reach this condition"); } if (ValidBytes + GetValidBytes(RightSiblingNodeIndex) + deltaBytesWhenCombining < BlockSize) { CombineNodes(NodeIndex, RightSiblingNodeIndex); } else { RebalanceNodes(NodeIndex, RightSiblingNodeIndex); } } else //I can combine with the right or the left node { if (canCombineWithLeft && ValidBytes + GetValidBytes(LeftSiblingNodeIndex) + deltaBytesWhenCombining < BlockSize) { CombineNodes(LeftSiblingNodeIndex, NodeIndex); } else if (canCombineWithRight && ValidBytes + GetValidBytes(RightSiblingNodeIndex) + deltaBytesWhenCombining < BlockSize) { CombineNodes(NodeIndex, RightSiblingNodeIndex); } else if (canCombineWithLeft) { RebalanceNodes(LeftSiblingNodeIndex, NodeIndex); } else if (canCombineWithRight) { RebalanceNodes(NodeIndex, RightSiblingNodeIndex); } else { throw new Exception("Should never reach this condition"); } } return(true); }