/// <summary> /// Creates a new sparse index. Be sure to initialize this class by calling <see cref="Initialize"/> before using this. /// </summary> public SparseIndex() { m_initializer = Library.CreateTreeNode <TKey, SnapUInt32>(EncodingDefinition.FixedSizeCombinedEncoding, 0); m_tmpKey = new TKey(); m_keySize = m_tmpKey.Size; m_tmpValue = new SnapUInt32(); }
/// <summary> /// Removes the specified leaf node from the sparse index /// </summary> /// <param name="key">The leaf node to remove</param> /// <param name="level"></param> public void Remove(TKey key, byte level) { if (level <= RootNodeLevel) { SortedTreeNodeBase <TKey, SnapUInt32> node = GetNode(level); if (!node.TryRemove(key)) { throw new KeyNotFoundException(); } if (level == RootNodeLevel) { if (node.RightSiblingNodeIndex == uint.MaxValue && node.LeftSiblingNodeIndex == uint.MaxValue && node.RecordCount == 1) { RootNodeLevel--; node.TryGetFirstRecord(m_tmpKey, m_tmpValue); RootNodeIndexAddress = m_tmpValue.Value; node.Clear(); } } } else { throw new Exception("Cannot update value of root"); } }
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); }
/// <summary> /// Gets the data for the following key. /// </summary> /// <param name="key">The key to look up. Only uses the key portion of the TKeyValue</param> /// <param name="level"></param> public uint Get(TKey key, byte level) { if (RootNodeLevel == 0) { return(RootNodeIndexAddress); } SortedTreeNodeBase <TKey, SnapUInt32> node = FindNode(key, level + 1); node.GetOrGetNext(key, m_tmpValue); return(m_tmpValue.Value); }
/// <summary> /// Gets the node index of the last leaf node in the tree. /// </summary> /// <param name="level">the level of the node requesting the lookup</param> /// <returns></returns> public uint GetLastIndex(byte level) { if (RootNodeLevel == level) { return(RootNodeIndexAddress); } uint nodeIndexAddress = RootNodeIndexAddress; byte nodeLevel = RootNodeLevel; while (nodeLevel > level) { SortedTreeNodeBase <TKey, SnapUInt32> currentNode = GetNode(nodeLevel); currentNode.SetNodeIndex(nodeIndexAddress); if (!currentNode.TryGetLastRecord(m_tmpValue)) { throw new Exception("Node is empty"); } nodeIndexAddress = m_tmpValue.Value; nodeLevel--; } return(nodeIndexAddress); }
/// <summary> /// Creates a new root node by combining the current root node with the provided node data. /// </summary> /// <param name="leafKey"></param> /// <param name="leafNodeIndex"></param> private void CreateNewRootNode(TKey leafKey, uint leafNodeIndex) { if (RootNodeLevel + 1 > 250) { throw new Exception("Tree is full. Tree cannot exceede 250 levels in depth."); } int nodeLevel = RootNodeLevel + 1; if (nodeLevel > m_nodes.Length) { SetCapacity(nodeLevel); } //Get the ID for the new root node. uint oldRootNode = RootNodeIndexAddress; RootNodeIndexAddress = m_getNextNewNodeIndex(); RootNodeLevel += 1; //Create the empty node SortedTreeNodeBase <TKey, SnapUInt32> rootNode = GetNode(RootNodeLevel); rootNode.CreateEmptyNode(RootNodeIndexAddress); //Insert the first entry in the root node. m_tmpKey.SetMin(); m_tmpValue.Value = oldRootNode; rootNode.TryInsert(m_tmpKey, m_tmpValue); //Insert the second entry in the root node. m_tmpValue.Value = leafNodeIndex; rootNode.TryInsert(leafKey, m_tmpValue); OnRootHasChanged(); //foreach (var node in m_nodes) // node.Clear(); }
public void TestRandom() { SortedTreeNodeBase <SnapUInt32, SnapUInt32> tree = Library.CreateTreeNode <SnapUInt32, SnapUInt32>(EncodingDefinition.FixedSizeCombinedEncoding, 0); LeafNodeTest.TestNode(tree, new RandomTest(), 2000); }
public void TestReverseSequently() { SortedTreeNodeBase <SnapUInt32, SnapUInt32> tree = Library.CreateTreeNode <SnapUInt32, SnapUInt32>(EncodingDefinition.FixedSizeCombinedEncoding, 0); LeafNodeTest.TestNode(tree, new ReverseSequentialTest(), 5000); }
public void BenchmarkBigRandom() { SortedTreeNodeBase <SnapUInt32, SnapUInt32> tree = Library.CreateTreeNode <SnapUInt32, SnapUInt32>(EncodingDefinition.FixedSizeCombinedEncoding, 0); LeafNodeTest.TestSpeed(tree, new RandomTest(), 5000, 4096); }
public void BenchmarkSequently() { SortedTreeNodeBase <SnapUInt32, SnapUInt32> tree = Library.CreateTreeNode <SnapUInt32, SnapUInt32>(EncodingDefinition.FixedSizeCombinedEncoding, 0); LeafNodeTest.TestSpeed(tree, new SequentialTest(), 500, 512); }
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; } }