/// <summary> /// Writes the supplied stream to the binary stream. /// </summary> /// <param name="stream"></param> /// <param name="blockSize"></param> /// <param name="treeNodeType"></param> /// <param name="treeStream"></param> public static void Create(BinaryStreamPointerBase stream, int blockSize, EncodingDefinition treeNodeType, TreeStream <TKey, TValue> treeStream) { if (stream is null) { throw new ArgumentNullException("stream"); } if (treeStream is null) { throw new ArgumentNullException("stream"); } if (treeNodeType is null) { throw new ArgumentNullException("treeNodeType"); } if (!(treeStream.IsAlwaysSequential && treeStream.NeverContainsDuplicates)) { throw new ArgumentException("Stream must gaurentee sequential reads and that it never will contain a duplicate", "treeStream"); } SortedTreeHeader header = new SortedTreeHeader(); header.TreeNodeType = treeNodeType; header.BlockSize = blockSize; header.RootNodeLevel = 0; header.RootNodeIndexAddress = 1; header.LastAllocatedBlock = 1; Func <uint> getNextNewNodeIndex = () => { header.LastAllocatedBlock++; return(header.LastAllocatedBlock); }; SparseIndexWriter <TKey> indexer = new SparseIndexWriter <TKey>(); NodeWriter <TKey, TValue> .Create(treeNodeType, stream, header.BlockSize, header.RootNodeLevel, header.RootNodeIndexAddress, getNextNewNodeIndex, indexer, treeStream); while (indexer.Count > 0) { indexer.SwitchToReading(); header.RootNodeLevel++; header.RootNodeIndexAddress = getNextNewNodeIndex(); SparseIndexWriter <TKey> indexer2 = new SparseIndexWriter <TKey>(); NodeWriter <TKey, SnapUInt32> .Create(EncodingDefinition.FixedSizeCombinedEncoding, stream, header.BlockSize, header.RootNodeLevel, header.RootNodeIndexAddress, getNextNewNodeIndex, indexer2, indexer); indexer.Dispose(); indexer = indexer2; } indexer.Dispose(); header.IsDirty = true; header.SaveHeader(stream); }
/// <summary> /// Closes the current node and prepares a new node with the supplied key. /// </summary> /// <param name="sparseIndex"></param> /// <param name="newNodeIndex">the index for the next node.</param> /// <param name="writePointer">the pointer to the start of the block</param> /// <param name="key">the key to use.</param> /// <param name="header"></param> private static void NewNodeThenInsert(NodeHeader <TKey> header, SparseIndexWriter <TKey> sparseIndex, uint newNodeIndex, byte *writePointer, TKey key) { TKey dividingKey = new TKey(); //m_tempKey; key.CopyTo(dividingKey); uint currentNode = header.NodeIndex; //Finish this header. header.RightSiblingNodeIndex = newNodeIndex; key.CopyTo(header.UpperKey); header.Save(writePointer); //Prepare the next header header.NodeIndex = newNodeIndex; header.RecordCount = 0; header.ValidBytes = (ushort)header.HeaderSize; header.LeftSiblingNodeIndex = currentNode; header.RightSiblingNodeIndex = uint.MaxValue; key.CopyTo(header.LowerKey); header.UpperKey.SetMax(); sparseIndex.Add(currentNode, dividingKey, newNodeIndex); }
public static void Create(EncodingDefinition encodingMethod, BinaryStreamPointerBase stream, int blockSize, byte level, uint startingNodeIndex, Func <uint> getNextNewNodeIndex, SparseIndexWriter <TKey> sparseIndex, TreeStream <TKey, TValue> treeStream) { NodeHeader <TKey> header = new NodeHeader <TKey>(level, blockSize); PairEncodingBase <TKey, TValue> encoding = Library.Encodings.GetEncodingMethod <TKey, TValue>(encodingMethod); SparseIndexWriter <TKey> sparseIndex1 = sparseIndex; Func <uint> getNextNewNodeIndex1 = getNextNewNodeIndex; int maximumStorageSize = encoding.MaxCompressionSize; byte[] buffer1 = new byte[maximumStorageSize]; if ((header.BlockSize - header.HeaderSize) / maximumStorageSize < 4) { throw new Exception("Tree must have at least 4 records per node. Increase the block size or decrease the size of the records."); } //InsideNodeBoundary = m_BoundsFalse; header.NodeIndex = startingNodeIndex; header.RecordCount = 0; header.ValidBytes = (ushort)header.HeaderSize; header.LeftSiblingNodeIndex = uint.MaxValue; header.RightSiblingNodeIndex = uint.MaxValue; header.LowerKey.SetMin(); header.UpperKey.SetMax(); byte *writePointer = stream.GetWritePointer(blockSize * header.NodeIndex, blockSize); fixed(byte *buffer = buffer1) { TKey key1 = new TKey(); TKey key2 = new TKey(); TValue value1 = new TValue(); TValue value2 = new TValue(); key1.Clear(); key2.Clear(); value1.Clear(); value2.Clear(); Read1: //Read part 1. if (treeStream.Read(key1, value1)) { if (header.RemainingBytes < maximumStorageSize) { if (header.RemainingBytes < encoding.Encode(buffer, key2, value2, key1, value1)) { NewNodeThenInsert(header, sparseIndex1, getNextNewNodeIndex1(), writePointer, key1); key2.Clear(); value2.Clear(); writePointer = stream.GetWritePointer(blockSize * header.NodeIndex, blockSize); } } byte *stream1 = writePointer + header.ValidBytes; header.ValidBytes += (ushort)encoding.Encode(stream1, key2, value2, key1, value1); header.RecordCount++; //Read part 2. if (treeStream.Read(key2, value2)) { if (header.RemainingBytes < maximumStorageSize) { if (header.RemainingBytes < encoding.Encode(buffer, key1, value1, key2, value2)) { NewNodeThenInsert(header, sparseIndex1, getNextNewNodeIndex1(), writePointer, key2); key1.Clear(); value1.Clear(); writePointer = stream.GetWritePointer(blockSize * header.NodeIndex, blockSize); } } byte *stream2 = writePointer + header.ValidBytes; header.ValidBytes += (ushort)encoding.Encode(stream2, key1, value1, key2, value2); header.RecordCount++; goto Read1; } } } header.Save(writePointer); }