Пример #1
0
        /// <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));
                    }
                }
            }
        }
Пример #2
0
        public BPlusTree(BPlusTreeOptions <TKey, TValue> ioptions)
        {
            bool fileExists =
                ioptions.StorageType == StorageType.Disk &&
                ioptions.CreateFile != CreatePolicy.Always &&
                File.Exists(ioptions.FileName) &&
                new FileInfo(ioptions.FileName).Length > 0;

            _options      = ioptions.Clone();
            _selfLock     = _options.CallLevelLock;
            _keyComparer  = _options.KeyComparer;
            _itemComparer = new ElementComparer(_keyComparer);

            switch (_options.CachePolicy)
            {
            case CachePolicy.All: _storage = new NodeCacheFull(_options); break;

            case CachePolicy.Recent: _storage = new NodeCacheNormal(_options); break;

            case CachePolicy.None: _storage = new NodeCacheNone(_options); break;

            default: throw new InvalidConfigurationValueException("CachePolicy");
            }

            try
            {
                _storage.Load();
            }
            catch
            {
                _storage.Dispose();
                throw;
            }

            if (_options.LogFile != null && !_options.ReadOnly)
            {
                if (_options.ExistingLogAction == ExistingLogAction.Truncate ||
                    _options.ExistingLogAction == ExistingLogAction.Default && !fileExists)
                {
                    _options.LogFile.TruncateLog();
                }
                else if (_options.LogFile.Size > 0 && (
                             _options.ExistingLogAction == ExistingLogAction.Replay ||
                             _options.ExistingLogAction == ExistingLogAction.ReplayAndCommit ||
                             (_options.ExistingLogAction == ExistingLogAction.Default && fileExists)
                             ))
                {
                    bool commit = (_options.ExistingLogAction == ExistingLogAction.ReplayAndCommit ||
                                   (_options.ExistingLogAction == ExistingLogAction.Default && fileExists));

                    bool merge = false;
                    if (_options.StorageType == StorageType.Disk)
                    {
                        merge = new FileInfo(_options.FileName).Length < _options.LogFile.Size;
                    }

                    if (merge) // log data is larger than we are...
                    {
                        BulkInsertOptions opts = new BulkInsertOptions();
                        opts.CommitOnCompletion = commit;
                        opts.DuplicateHandling  = DuplicateHandling.LastValueWins;
                        opts.InputIsSorted      = true;
                        opts.ReplaceContents    = true;
                        BulkInsert(
                            _options.LogFile.MergeLog(_options.KeyComparer,
                                                      File.Exists(ioptions.FileName) ? EnumerateFile(ioptions) : new KeyValuePair <TKey, TValue> [0]),
                            opts
                            );
                    }
                    else
                    {
                        _options.LogFile.ReplayLog(this);
                        if (commit) //Now commit the recovered changes
                        {
                            Commit();
                        }
                    }
                }
            }

            var nodeStoreWithCount = _storage.Storage as INodeStoreWithCount;

            if (nodeStoreWithCount != null)
            {
                _count    = nodeStoreWithCount.Count;
                _hasCount = _count >= 0;
            }
        }