IEnumerable <BTreePageItems <T> > GetNodeItemPages <T>(BTreePageBase <T> rootPage) where T : IComparable <T> { var stack = new Stack <BTreePageBase <T> >(); stack.Push(rootPage); while (stack.Count > 0) { var item = stack.Pop(); if (item.Type == BTreePageType.Collection) { yield return(item as BTreePageItems <T>); } else { var node = item as BTreePageNode <T>; if (node.Right != null) { stack.Push(node.Right); } if (node.Left != null) { stack.Push(node.Left); } } } }
void StoreTreePage <T>(BTreePageBase <T> rootPage, io.BinaryWriter writer) where T : IComparable <T> { if (rootPage.IsLeaf) { //store id of left Int32 valueInt32 = Consts.BTreePageNodeItemsFlag; writer.Write(valueInt32); //offset ///////////////// TO BE USED AS AN ID ////////////////////////// var leaf = rootPage as BTreePageItems <T>; writer.Write(leaf.Offset); } else { //store page node var buffer = rootPage.ToBuffer(); writer.Write(buffer, 0, buffer.Length); //try to navigate left or right var node = rootPage as BTreePageNode <T>; int empty = 0; if (node.Left == null) { //signal, no left node writer.Write(empty); throw new ArgumentException($"Tree Node key:[{node.Root.Key}] has no left child"); } else { StoreTreePage <T>(node.Left, writer); } if (node.Right == null) { //signal, no right node writer.Write(empty); throw new ArgumentException($"Tree Node key:[{node.Root.Key}] has no right child"); } else { StoreTreePage <T>(node.Right, writer); } } }
void SaveBinaryIndex <T>(BTreePageBase <T> rootPage, DbColumn index) where T : IComparable <T> { if (rootPage == null) { return; } var pageCount = rootPage.ChildrenCount; Console.WriteLine($" saving ({pageCount}) page(s)"); //update column tree page count index.NodePages = pageCount; index.Table.Database.Modified = true; string indexfilepath = io.Path.Combine(Database.BinaryPath, $"{index.Indexer}"); //page with items .bin //this where the main info is var indexBinFilePath = indexfilepath + ".bin"; using (var writer = new io.BinaryWriter(io.File.Create(indexBinFilePath))) { var collectionPage = GetNodeItemPages <T>(rootPage).ToList(); //update column item page count index.ItemPages = collectionPage.Count; //MAIN HEADER Int32 pageCollectionCount = collectionPage.Count; //write amount of pages writer.Write(pageCollectionCount); //write index key type Int32 keyType = (int)index.TypeEnum; writer.Write(keyType); //pages //sizeof: pageCollectionCount, keyType var offset = DbGenerator.ItemsPageStart; // 8; foreach (var page in collectionPage) { page.Offset = offset; //save page var buffer = page.ToBuffer(); // offset += buffer.Length; // writer.Write(buffer, 0, buffer.Length); } } //tree page indexer .index //this is a light in-memory tree structure for fast search using (var writer = new io.BinaryWriter(io.File.Create(indexfilepath))) { Int32 valueInt32 = 0; //write Index main Header PageIndexTreeHeader header = new PageIndexTreeHeader(); // header.Value0 = 0; //page count header.PageCount = pageCount; //index.Index header.ColumnIndex = index.Index; //index.Unique //index.Key valueInt32 = (index.Unique ? Consts.IndexHeaderIsUnique : 0) | (index.Key ? Consts.IndexHeaderIsKey : 0) | (rootPage.IsLeaf ? Consts.IndexHeaderIsLeaf : 0); //index.Type //valueInt32 = valueInt32 << 8; valueInt32 |= (byte)index.TypeEnum; header.Flags = valueInt32; //write Header byte[] buffer = header.ToByteArray(); writer.Write(buffer, 0, buffer.Length); //test var bin = Convert.ToString(header.Flags, 2); //write page tree if (!rootPage.IsLeaf) { StoreTreePage <T>(rootPage, writer); } } }