/// <summary> /// Directly enumerates the contents of BPlusTree from disk in read-only mode. /// </summary> /// <param name="options"> The options normally used to create the <see cref="BPlusTree{TKey, TValue}"/> instance </param> /// <returns> Yields the Key/Value pairs found in the file </returns> public static IEnumerable <KeyValuePair <TKey, TValue> > EnumerateFile(BPlusTreeOptions <TKey, TValue> options) { options = options.Clone(); options.CreateFile = CreatePolicy.Never; options.ReadOnly = true; using (INodeStorage store = options.CreateStorage()) { bool isnew; Node root; IStorageHandle hroot = store.OpenRoot(out isnew); if (isnew) { yield break; } NodeSerializer nodeReader = new NodeSerializer(options, new NodeHandleSerializer(store)); if (isnew || !store.TryGetNode(hroot, out root, nodeReader)) { throw new InvalidDataException(); } Stack <KeyValuePair <Node, int> > todo = new Stack <KeyValuePair <Node, int> >(); todo.Push(new KeyValuePair <Node, int>(root, 0)); while (todo.Count > 0) { KeyValuePair <Node, int> cur = todo.Pop(); if (cur.Value == cur.Key.Count) { continue; } todo.Push(new KeyValuePair <Node, int>(cur.Key, cur.Value + 1)); Node child; if (!store.TryGetNode(cur.Key[cur.Value].ChildNode.StoreHandle, out child, nodeReader)) { throw new InvalidDataException(); } if (child.IsLeaf) { for (int ix = 0; ix < child.Count; ix++) { var set = child[ix].ToKeyValuePair(); var enumerator = set.Value.GetEnumerator(); while (enumerator.MoveNext()) { yield return(new KeyValuePair <TKey, TValue>(set.Key, enumerator.Current.Key)); } } } else { todo.Push(new KeyValuePair <Node, int>(child, 0)); } } } }
public NodeCacheBase(BPlusTreeOptions <TKey, TValue> options) { Options = options; LockFactory = Options.LockingFactory; Storage = Options.CreateStorage(); if (Options.UseStorageCache) { Storage = new StorageCache(Storage, Options.CacheKeepAliveMaximumHistory); } NodeSerializer = new NodeSerializer(Options, new NodeHandleSerializer(Storage)); _version = new NodeVersion(); }