/// <summary> /// 从指定的流初始化树 /// </summary> /// <param name="fromFile">指定的流</param> /// <param name="seekStart">流起始查询点</param> /// <returns>树</returns> public static BPlusTreeLong SetupFromExistingStream(Stream fromFile, long seekStart) { if (fromFile == null) { throw new ArgumentNullException("fromFile"); } BPlusTreeLong tree = new BPlusTreeLong(fromFile, seekStart, 100, 7, (byte)1); // dummy values for nodesize, keysize tree.ReadHeader(); tree.BlockFile = BlockFile.SetupFromExistingStream(fromFile, seekStart + HeaderSize, StoredConstants.BlockFileHeaderPrefix); if (tree.BlockFile.BlockSize != tree.BlockSize) { throw new BPlusTreeException("inner and outer block sizes should match"); } if (tree.RootNodeBlockNumber != StoredConstants.NullBlockNumber) { tree.RootNode = BPlusTreeNode.MakeRoot(tree, true); tree.RootNode.LoadFromBlock(tree.RootNodeBlockNumber); } return(tree); }
/// <summary> /// 创建B+树 /// </summary> /// <param name="treeFileStream">指定树文件的文件流</param> /// <param name="blockFileStream">指定块文件的文件流</param> /// <param name="keyLength">树允许的键的长度</param> /// <param name="nodeCapacity">树允许的各子节点的最大容量</param> /// <param name="blockSize">块大小</param> /// <returns>B+树</returns> public static BPlusTreeBytes Create(Stream treeFileStream, Stream blockFileStream, int keyLength, int nodeCapacity, int blockSize) { BPlusTreeLong tree = BPlusTreeLong.InitializeInStream(treeFileStream, (long)0, keyLength, nodeCapacity); LinkedFile archive = LinkedFile.InitializeInStream(blockFileStream, (long)0, blockSize); return(new BPlusTreeBytes(tree, archive)); }
/// <summary> /// 从文件打开B+树 /// </summary> /// <param name="treeFileStream">指定树文件的文件流</param> /// <param name="blockFileStream">指定块文件的文件流</param> /// <returns>B+树</returns> public static BPlusTreeBytes Open(Stream treeFileStream, Stream blockFileStream) { BPlusTreeLong tree = BPlusTreeLong.SetupFromExistingStream(treeFileStream, (long)0); LinkedFile archive = LinkedFile.SetupFromExistingStream(blockFileStream, (long)0); return(new BPlusTreeBytes(tree, archive)); }
/// <summary> /// 检测给定的键是否符合树要求键的长度 /// </summary> /// <param name="key">给定的键</param> /// <param name="tree">给定的树</param> /// <returns>是否符合树要求键的长度</returns> public static bool ValidateKey(string key, BPlusTreeLong tree) { if (tree == null) { throw new ArgumentNullException("tree"); } if (string.IsNullOrEmpty(key)) { return(false); } int maxKeyLength = tree.KeyLength; int maxKeyPayload = maxKeyLength - StoredConstants.ShortLength; char[] keyChars = key.ToCharArray(); int charCount = Encoding.UTF8.GetEncoder().GetByteCount(keyChars, 0, keyChars.Length, true); if (charCount > maxKeyPayload) { return(false); } return(true); }
/// <summary> /// 从指定的流初始化树 /// </summary> /// <param name="fromFile">指定的流</param> /// <param name="seekStart">流起始查询点</param> /// <param name="keyLength">键长度</param> /// <param name="nodeCapacity">节点容量</param> /// <returns>树</returns> public static BPlusTreeLong InitializeInStream(Stream fromFile, long seekStart, int keyLength, int nodeCapacity) { if (fromFile == null) { throw new ArgumentNullException("fromFile"); } if (fromFile.Length > seekStart) { throw new BPlusTreeException("can't initialize tree inside written area of stream"); } BPlusTreeLong tree = new BPlusTreeLong(fromFile, seekStart, keyLength, nodeCapacity, (byte)1); tree.WriteHeader(); tree.BlockFile = BlockFile.InitializeInStream(fromFile, seekStart + HeaderSize, StoredConstants.BlockFileHeaderPrefix, tree.BlockSize); return(tree); }
public static void Check(BPlusTreeLong bpt) { Console.WriteLine(bpt.ToText()); bpt.CheckFreeBlock(); ArrayList allkeys = new ArrayList(); foreach (DictionaryEntry d in AllInsertHashtable) { allkeys.Add(d.Key); } allkeys.Sort(); allkeys.Reverse(); foreach (object thing in allkeys) { string thekey = (string)thing; long thevalue = (long)AllInsertHashtable[thing]; if (thevalue != bpt[thekey]) { throw new ApplicationException("no match on retrieval " + thekey + " --> " + bpt[thekey] + " not " + thevalue); } } allkeys.Reverse(); string currentkey = bpt.FirstKey(); foreach (object thing in allkeys) { string testkey = (string)thing; if (currentkey == null) { throw new ApplicationException("end of keys found when expecting " + testkey); } if (!testkey.Equals(currentkey)) { throw new ApplicationException("when walking found " + currentkey + " when expecting " + testkey); } currentkey = bpt.NextKey(testkey); } }
/// <summary> /// B+树,固定长度字符串为键,映射至Byte数组。 /// </summary> /// <param name="tree">B+树</param> /// <param name="archive">链式块文件</param> internal BPlusTreeBytes(BPlusTreeLong tree, LinkedFile archive) { this.tree = tree; this.archive = archive; }
/// <summary> /// B+树节点 /// </summary> /// <param name="tree">包含该节点的树</param> /// <param name="parent">节点的父节点</param> /// <param name="indexInParent">在父节点中的索引</param> /// <param name="isLeaf">是否为叶子节点</param> public BPlusTreeNode(BPlusTreeLong tree, BPlusTreeNode parent, int indexInParent, bool isLeaf) { if(tree == null) throw new ArgumentNullException("tree"); this.Tree = tree; this.Parent = parent; this.IsLeaf = isLeaf; this.IndexInParent = -1; this.BlockNumber = StoredConstants.NullBlockNumber; this.Capacity = tree.NodeCapacity; this.Dirty = true; this.Clear(); // 存在父节点 if (parent != null && indexInParent >= 0) { // B+树 父节点中键值数与子节点数量相等 if (indexInParent > this.Capacity) { throw new BPlusTreeException("parent index too large"); } // 建立与父节点关系 this.Parent.ChildNodes[indexInParent] = this; this.BlockNumber = this.Parent.ChildValues[indexInParent]; this.IndexInParent = indexInParent; } }
/// <summary> /// 从指定的流初始化树 /// </summary> /// <param name="fromFile">指定的流</param> /// <param name="seekStart">流起始查询点</param> /// <param name="keyLength">键长度</param> /// <param name="nodeCapacity">节点容量</param> /// <returns>树</returns> public static BPlusTreeLong InitializeInStream(Stream fromFile, long seekStart, int keyLength, int nodeCapacity) { if (fromFile == null) throw new ArgumentNullException("fromFile"); if (fromFile.Length > seekStart) { throw new BPlusTreeException("can't initialize tree inside written area of stream"); } BPlusTreeLong tree = new BPlusTreeLong(fromFile, seekStart, keyLength, nodeCapacity, (byte)1); tree.WriteHeader(); tree.BlockFile = BlockFile.InitializeInStream(fromFile, seekStart + HeaderSize, StoredConstants.BlockFileHeaderPrefix, tree.BlockSize); return tree; }
/// <summary> /// 为指定树构造一个根节点 /// </summary> /// <param name="tree">指定树</param> /// <param name="isLeaf">是否为叶子节点</param> /// <returns>根节点</returns> public static BPlusTreeNode MakeRoot(BPlusTreeLong tree, bool isLeaf) { return new BPlusTreeNode(tree, null, -1, isLeaf); }
/// <summary> /// 重新组织分割树,新的根节点将有两个子节点 /// </summary> /// <param name="oldRoot">原根节点</param> /// <param name="splitFirstKey">新根节点的第一个Key</param> /// <param name="splitNode">新分割出的节点</param> /// <param name="tree">指定的树</param> /// <returns>新根节点</returns> public static BPlusTreeNode BinaryRoot(BPlusTreeNode oldRoot, string splitFirstKey, BPlusTreeNode splitNode, BPlusTreeLong tree) { if (oldRoot == null) throw new ArgumentNullException("oldRoot"); if (splitNode == null) throw new ArgumentNullException("splitNode"); // 已不是叶子节点 BPlusTreeNode newRoot = MakeRoot(tree, false); // 新的跟记录分割节点的第一个Key newRoot.ChildKeys[0] = splitFirstKey; // 新旧节点分别为新的根节点的索引 0 1 位置 oldRoot.ResetParent(newRoot, 0); splitNode.ResetParent(newRoot, 1); // new root is stored elsewhere return newRoot; }
public static void Delete(BPlusTreeLong bpt, string key) { bpt.RemoveKey(key); AllInsertHashtable.Remove(key); Check(bpt); }
public static void Commit(BPlusTreeLong bpt) { bpt.Commit(); LastCommittedInsertHashtable = (Hashtable)AllInsertHashtable.Clone(); Check(bpt); }
/// <summary> /// 从指定的流初始化树 /// </summary> /// <param name="fromFile">指定的流</param> /// <param name="seekStart">流起始查询点</param> /// <returns>树</returns> public static BPlusTreeLong SetupFromExistingStream(Stream fromFile, long seekStart) { if (fromFile == null) throw new ArgumentNullException("fromFile"); BPlusTreeLong tree = new BPlusTreeLong(fromFile, seekStart, 100, 7, (byte)1); // dummy values for nodesize, keysize tree.ReadHeader(); tree.BlockFile = BlockFile.SetupFromExistingStream(fromFile, seekStart + HeaderSize, StoredConstants.BlockFileHeaderPrefix); if (tree.BlockFile.BlockSize != tree.BlockSize) { throw new BPlusTreeException("inner and outer block sizes should match"); } if (tree.RootNodeBlockNumber != StoredConstants.NullBlockNumber) { tree.RootNode = BPlusTreeNode.MakeRoot(tree, true); tree.RootNode.LoadFromBlock(tree.RootNodeBlockNumber); } return tree; }
public static void Insert(BPlusTreeLong bpt, string key, long map) { bpt.Set(key, map); AllInsertHashtable[key] = map; Check(bpt); }
/// <summary> /// 检测给定的键是否符合树要求键的长度 /// </summary> /// <param name="key">给定的键</param> /// <param name="tree">给定的树</param> /// <returns>是否符合树要求键的长度</returns> public static bool ValidateKey(string key, BPlusTreeLong tree) { if (tree == null) throw new ArgumentNullException("tree"); if (string.IsNullOrEmpty(key)) { return false; } int maxKeyLength = tree.KeyLength; int maxKeyPayload = maxKeyLength - StoredConstants.ShortLength; char[] keyChars = key.ToCharArray(); int charCount = Encoding.UTF8.GetEncoder().GetByteCount(keyChars, 0, keyChars.Length, true); if (charCount > maxKeyPayload) { return false; } return true; }