Ejemplo n.º 1
0
 public static BplusNode BinaryRoot(BplusNode LeftNode, string key, BplusNode RightNode, BplusTreeLong owner)
 {
     BplusNode newRoot = new BplusNode(owner, null, -1, false);
     //newRoot.Clear(); // redundant
     newRoot.ChildKeys[0] = key;
     LeftNode.Reparent(newRoot, 0);
     RightNode.Reparent(newRoot, 1);
     // new root is stored elsewhere
     return newRoot;
 }
Ejemplo n.º 2
0
		public BplusTreeLong(System.IO.Stream fromfile, int NodeSize, int KeyLength, long StartSeek, int CultureId)
		{
			this.cultureContext = new System.Globalization.CultureInfo(CultureId);
			this.cmp = this.cultureContext.CompareInfo;
			this.fromfile = fromfile;
			this.NodeSize = NodeSize;
			this.seekStart = StartSeek;
			// add in key prefix overhead
			this.KeyLength = KeyLength + BufferFile.SHORTSTORAGE;
			this.rootSeek = NULLBUFFERNUMBER;
			this.root = null;
			this.freeHeadSeek = NULLBUFFERNUMBER;
			this.SanityCheck();
		}
Ejemplo n.º 3
0
 /// <summary>
 /// Create a new BplusNode and install in parent if parent is not null.
 /// </summary>
 /// <param name="owner">tree containing the node</param>
 /// <param name="parent">parent node (if provided)</param>
 /// <param name="indexInParent">location in parent if provided</param>
 public BplusNode(BplusTreeLong owner, BplusNode parent, int indexInParent, bool isLeaf)
 {
     this.isLeaf = isLeaf;
     this.owner = owner;
     this.parent = parent;
     this.Size = owner.NodeSize;
     //this.isValid = true;
     this.Dirty = true;
     //			this.ChildBufferNumbers = new long[this.Size+1];
     //			this.ChildKeys = new string[this.Size];
     //			this.MaterializedChildNodes = new BplusNode[this.Size+1];
     this.Clear();
     if (parent!=null && indexInParent>=0)
     {
         if (indexInParent>this.Size)
         {
             throw new BplusTreeException("parent index too large");
         }
         // key info, etc, set elsewhere
         this.parent.MaterializedChildNodes[indexInParent] = this;
         this.myBufferNumber = this.parent.ChildBufferNumbers[indexInParent];
         this.indexInParent = indexInParent;
     }
 }
Ejemplo n.º 4
0
 /// <summary>
 /// Find the first key below atIndex, or if no such node traverse to the next key to the right.
 /// If no such key exists, return nulls.
 /// </summary>
 /// <param name="atIndex">where to look in this node</param>
 /// <param name="foundInLeaf">leaf where found</param>
 /// <param name="keyFound">key value found</param>
 void TraverseToFollowingKey(int atIndex, out BplusNode foundInLeaf, out string keyFound)
 {
     foundInLeaf = null;
     keyFound = null;
     bool lookInParent;
     if (IsLeaf)
     {
         lookInParent = (atIndex>=m_size) || (m_childKeys[atIndex]==null);
     }
     else
     {
         lookInParent = (atIndex>m_size) ||
             (atIndex>0 && m_childKeys[atIndex-1]==null);
     }
     if (lookInParent)
     {
         // if it's anywhere it's in the next child of parent
         if (m_parent!=null && m_indexInParent>=0)
         {
             m_parent.TraverseToFollowingKey(m_indexInParent+1, out foundInLeaf, out keyFound);
             return;
         }
         else
         {
             return; // no such following key
         }
     }
     if (IsLeaf)
     {
         // leaf, we found it.
         foundInLeaf = this;
         keyFound = m_childKeys[atIndex];
     }
     else
     {
         // nonleaf, look in child (if there is one)
         if (atIndex==0 || m_childKeys[atIndex-1]!=null)
         {
             var thechild = MaterializeNodeAtIndex(atIndex);
             thechild.TraverseToFollowingKey(0, out foundInLeaf, out keyFound);
         }
     }
 }
Ejemplo n.º 5
0
 public void RemoveKey(string key)
 {
     if (this.root==null)
     {
         throw new BplusTreeKeyMissing("tree is empty: cannot delete");
     }
     bool MergeMe;
     BplusNode theroot = this.root;
     theroot.Delete(key, out MergeMe);
     // if the root is not a leaf and contains only one child (no key), reroot
     if (MergeMe && !this.root.isLeaf && this.root.SizeInUse()==0)
     {
         this.root = this.root.FirstChild();
         this.rootSeek = this.root.makeRoot();
         theroot.Free();
     }
 }
Ejemplo n.º 6
0
 public void ForgetTerminalNode(BplusNode nonterminalNode)
 {
     if (!this.TerminalNodeToId.ContainsKey(nonterminalNode))
     {
         // silently ignore (?)
         return;
     }
     int id = (int) this.TerminalNodeToId[nonterminalNode];
     if (id == this.LowerTerminalNodeCount)
     {
         this.LowerTerminalNodeCount++;
     }
     this.IdToTerminalNode.Remove(id);
     this.TerminalNodeToId.Remove(nonterminalNode);
 }
Ejemplo n.º 7
0
 public long this[string key]
 {
     get
     {
         return MyGetKey(key, true);
     }
     set
     {
         if (!BplusNode.KeyOK(key, this))
         {
             throw new BplusTreeBadKeyValue("null or too large key cannot be inserted into tree: "+key);
         }
         bool rootinit = false;
         if (this.root==null)
         {
             // allocate root
             this.root = new BplusNode(this, null, -1, true);
             rootinit = true;
             //this.rootSeek = root.DumpToFreshBuffer();
         }
         // insert into root...
         string splitString;
         BplusNode splitNode;
         root.Insert(key, value, out splitString, out splitNode);
         if (splitNode!=null)
         {
             // split of root: make a new root.
             rootinit = true;
             BplusNode oldRoot = this.root;
             this.root = BplusNode.BinaryRoot(oldRoot, splitString, splitNode, this);
         }
         if (rootinit)
         {
             this.rootSeek = root.DumpToFreshBuffer();
         }
         // check size in memory
         this.ShrinkFootprint();
     }
 }
Ejemplo n.º 8
0
 void Reparent(BplusNode newParent, int ParentIndex)
 {
     // keys and existing parent structure must be updated elsewhere.
     this.parent = newParent;
     this.indexInParent = ParentIndex;
     newParent.ChildBufferNumbers[ParentIndex] = this.myBufferNumber;
     newParent.MaterializedChildNodes[ParentIndex] = this;
     // parent is no longer terminal
     this.owner.ForgetTerminalNode(parent);
 }
Ejemplo n.º 9
0
 /// <summary>
 /// insert key/position entry in self 
 /// </summary>
 /// <param name="key">Key to associate with the leaf</param>
 /// <param name="position">position associated with key in external structur</param>
 /// <param name="splitString">if not null then the smallest key in the new split leaf</param>
 /// <param name="splitNode">if not null then the node was split and this is the leaf to the right.</param>
 /// <returns>null unless the smallest key under this node has changed, in which case it returns the smallest key.</returns>
 public string Insert(string key, long position, out string splitString, out BplusNode splitNode)
 {
     if (IsLeaf)
     {
         return InsertLeaf(key, position, out splitString, out splitNode);
     }
     splitString = null;
     splitNode = null;
     var insertposition = FindAtOrNextPosition(key, false);
     var insertBufferNumber = m_childBufferNumbers[insertposition];
     if (insertBufferNumber==BplusTreeLong.Nullbuffernumber)
     {
         throw new BplusTreeException("key not followed by buffer number in non-leaf");
     }
     // insert in subtree
     var insertChild = MaterializeNodeAtIndex(insertposition);
     BplusNode childSplit;
     string childSplitString;
     var childInsert = insertChild.Insert(key, position, out childSplitString, out childSplit);
     // if there was a split the node must expand
     if (childSplit!=null)
     {
         // insert the child
         Soil(); // redundant -- a child will have a change so this node will need to be copied
         var newChildPosition = insertposition+1;
         var dosplit = false;
         // if there is no free space we must do a split
         if (m_childBufferNumbers[m_size]!=BplusTreeLong.Nullbuffernumber)
         {
             dosplit = true;
             PrepareForSplit();
         }
         // bubble over the current values to make space for new child
         for (var i=m_childKeys.Length-2; i>=newChildPosition-1; i--)
         {
             var i1 = i+1;
             var i2 = i1+1;
             m_childKeys[i1] = m_childKeys[i];
             m_childBufferNumbers[i2] = m_childBufferNumbers[i1];
             var childNode = m_materializedChildNodes[i2] = m_materializedChildNodes[i1];
         }
         // record the new child
         m_childKeys[newChildPosition-1] = childSplitString;
         //this.MaterializedChildNodes[newChildPosition] = childSplit;
         //this.ChildBufferNumbers[newChildPosition] = childSplit.myBufferNumber;
         childSplit.Reparent(this, newChildPosition);
         // split, if needed
         if (dosplit)
         {
             var splitpoint = m_materializedChildNodes.Length/2-1;
             splitString = m_childKeys[splitpoint];
             splitNode = new BplusNode(m_owner, m_parent, -1, IsLeaf);
             // make copy of expanded node structure
             var materialized = m_materializedChildNodes;
             var buffernumbers = m_childBufferNumbers;
             var keys = m_childKeys;
             // repair the expanded node
             m_childKeys = new string[m_size];
             m_materializedChildNodes = new BplusNode[m_size+1];
             m_childBufferNumbers = new long[m_size+1];
             Clear();
             Array.Copy(materialized, 0, m_materializedChildNodes, 0, splitpoint+1);
             Array.Copy(buffernumbers, 0, m_childBufferNumbers, 0, splitpoint+1);
             Array.Copy(keys, 0, m_childKeys, 0, splitpoint);
             // initialize the new node
             splitNode.Clear(); // redundant.
             var remainingKeys = m_size-splitpoint;
             Array.Copy(materialized, splitpoint+1, splitNode.m_materializedChildNodes, 0, remainingKeys+1);
             Array.Copy(buffernumbers, splitpoint+1, splitNode.m_childBufferNumbers, 0, remainingKeys+1);
             Array.Copy(keys, splitpoint+1, splitNode.m_childKeys, 0, remainingKeys);
             // fix pointers in materialized children of splitnode
             splitNode.ReParentAllChildren();
             // store the new node
             splitNode.DumpToFreshBuffer();
             splitNode.CheckIfTerminal();
             splitNode.Soil();
             CheckIfTerminal();
         }
         // fix pointers in children
         ReParentAllChildren();
     }
     if (insertposition==0)
     {
         // the smallest key may have changed
         return childInsert;
     }
     return null;  // no change in smallest key
 }
Ejemplo n.º 10
0
 public void RemoveKey(string key)
 {
     if (m_root==null)
     {
         throw new BplusTreeKeyMissing("tree is empty: cannot delete");
     }
     bool mergeMe;
     var theroot = m_root;
     theroot.Delete(key, out mergeMe);
     // if the root is not a leaf and contains only one child (no key), reroot
     if (mergeMe && !m_root.IsLeaf && m_root.SizeInUse()==0)
     {
         m_root = m_root.FirstChild();
         m_rootSeek = m_root.MakeRoot();
         theroot.Free();
     }
 }
Ejemplo n.º 11
0
 public void RecordTerminalNode(BplusNode terminalNode)
 {
     if (terminalNode==m_root)
     {
         return; // never record the root node
     }
     if (m_terminalNodeToId.ContainsKey(terminalNode) )
     {
         return; // don't record it again
     }
     var id = m_terminalNodeCount;
     m_terminalNodeCount++;
     m_terminalNodeToId[terminalNode] = id;
     m_idToTerminalNode[id] = terminalNode;
 }
Ejemplo n.º 12
0
 public void ForgetTerminalNode(BplusNode nonterminalNode)
 {
     if (!m_terminalNodeToId.ContainsKey(nonterminalNode))
     {
         // silently ignore (?)
         return;
     }
     var id = (int) m_terminalNodeToId[nonterminalNode];
     if (id == m_lowerTerminalNodeCount)
     {
         m_lowerTerminalNodeCount++;
     }
     m_idToTerminalNode.Remove(id);
     m_terminalNodeToId.Remove(nonterminalNode);
 }
Ejemplo n.º 13
0
 /// <summary>
 /// Forget all changes since last commit
 /// </summary>
 public void Abort()
 {
     // deallocate allocated blocks
     var toFree = new ArrayList();
     foreach (DictionaryEntry d in FreeBuffersOnAbort)
     {
         toFree.Add(d.Key);
     }
     toFree.Sort();
     toFree.Reverse();
     foreach (var thing in toFree)
     {
         var buffernumber = (long) thing;
         DeallocateBuffer(buffernumber);
     }
     var freehead = m_freeHeadSeek;
     // reread the header (except for freelist head)
     ReadHeader();
     // restore the root
     if (m_rootSeek==Nullbuffernumber)
     {
         m_root = null; // nothing was committed
     }
     else
     {
         m_root.LoadFromBuffer(m_rootSeek);
     }
     ResetBookkeeping();
     m_freeHeadSeek = freehead;
     SetHeader(); // store new freelist head
     Fromfile.Flush();
 }
Ejemplo n.º 14
0
 public long this[string key]
 {
     get
     {
         long valueFound;
         var test = ContainsKey(key, out valueFound);
         if (!test)
         {
             throw new BplusTreeKeyMissing("no such key found: "+key);
         }
         return valueFound;
     }
     set
     {
         if (!BplusNode.KeyOK(key, this))
         {
             throw new BplusTreeBadKeyValue("null or too large key cannot be inserted into tree: "+key);
         }
         var rootinit = false;
         if (m_root==null)
         {
             // allocate root
             m_root = new BplusNode(this, null, -1, true);
             rootinit = true;
             //this.rootSeek = root.DumpToFreshBuffer();
         }
         // insert into root...
         string splitString;
         BplusNode splitNode;
         m_root.Insert(key, value, out splitString, out splitNode);
         if (splitNode!=null)
         {
             // split of root: make a new root.
             rootinit = true;
             var oldRoot = m_root;
             m_root = BplusNode.BinaryRoot(oldRoot, splitString, splitNode, this);
         }
         if (rootinit)
         {
             m_rootSeek = m_root.DumpToFreshBuffer();
         }
         // check size in memory
         ShrinkFootprint();
     }
 }
Ejemplo n.º 15
0
 public BplusTreeLong(Stream fromfile, int nodeSize, int keyLength, long startSeek, int cultureId)
 {
     CultureContext = new CultureInfo(cultureId);
     m_cmp = CultureContext.CompareInfo;
     Fromfile = fromfile;
     NodeSize = nodeSize;
     SeekStart = startSeek;
     // add in key prefix overhead
     KeyLength = keyLength + BufferFile.Shortstorage;
     m_rootSeek = Nullbuffernumber;
     m_root = null;
     m_freeHeadSeek = Nullbuffernumber;
     SanityCheck();
 }
Ejemplo n.º 16
0
 BplusNode MaterializeNodeAtIndex(int myposition)
 {
     if (this.isLeaf)
     {
         throw new BplusTreeException("cannot materialize child for leaf");
     }
     long childBufferNumber = this.ChildBufferNumbers[myposition];
     if (childBufferNumber==BplusTreeLong.NULLBUFFERNUMBER)
     {
         throw new BplusTreeException("can't search null subtree at position "+myposition+" in "+this.myBufferNumber);
     }
     // is it already materialized?
     BplusNode result = this.MaterializedChildNodes[myposition];
     if (result!=null)
     {
         return result;
     }
     // otherwise read it in...
     result = new BplusNode(this.owner, this, myposition, true); // dummy isLeaf value
     result.LoadFromBuffer(childBufferNumber);
     this.MaterializedChildNodes[myposition] = result;
     // no longer terminal
     this.owner.ForgetTerminalNode(this);
     return result;
 }
Ejemplo n.º 17
0
 /// <summary>
 /// Grow to this.size+1 in preparation for insertion and split
 /// </summary>
 void PrepareForSplit()
 {
     int supersize = this.Size+1;
     long[] positions = new long[supersize+1];
     string[] keys = new string[supersize];
     BplusNode[] materialized = new BplusNode[supersize+1];
     Array.Copy(this.ChildBufferNumbers, 0, positions, 0, this.Size+1);
     positions[this.Size+1] = BplusTreeLong.NULLBUFFERNUMBER;
     Array.Copy(this.ChildKeys, 0, keys, 0, this.Size);
     keys[this.Size] = null;
     Array.Copy(this.MaterializedChildNodes, 0, materialized, 0, this.Size+1);
     materialized[this.Size+1] = null;
     this.ChildBufferNumbers = positions;
     this.ChildKeys = keys;
     this.MaterializedChildNodes = materialized;
 }
Ejemplo n.º 18
0
 /// <summary>
 /// insert key/position entry in self (as leaf)
 /// </summary>
 /// <param name="key">Key to associate with the leaf</param>
 /// <param name="position">position associated with key in external structure</param>
 /// <param name="splitString">if not null then the smallest key in the new split leaf</param>
 /// <param name="splitNode">if not null then the node was split and this is the leaf to the right.</param>
 /// <returns>smallest key value in keys, or null if no change</returns>
 public string InsertLeaf(string key, long position, out string splitString, out BplusNode splitNode)
 {
     splitString = null;
     splitNode = null;
     var dosplit = false;
     if (!IsLeaf)
     {
         throw new BplusTreeException("bad call to InsertLeaf: this is not a leaf");
     }
     Soil();
     var insertposition = FindAtOrNextPosition(key, false);
     if (insertposition>=m_size)
     {
         //throw new BplusTreeException("key too big and leaf is full");
         dosplit = true;
         PrepareForSplit();
     }
     else
     {
         // if it's already there then change the value at the current location (duplicate entries not supported).
         if (m_childKeys[insertposition]==null || m_owner.Compare(m_childKeys[insertposition], key)==0) // this.ChildKeys[insertposition].Equals(key)
         {
             m_childBufferNumbers[insertposition] = position;
             m_childKeys[insertposition] = key;
             if (insertposition==0)
             {
                 return key;
             }
             else
             {
                 return null;
             }
         }
     }
     // check for a null position
     var nullindex = insertposition;
     while (nullindex<m_childKeys.Length && m_childKeys[nullindex]!=null)
     {
         nullindex++;
     }
     if (nullindex>=m_childKeys.Length)
     {
         if (dosplit)
         {
             throw new BplusTreeException("can't split twice!!");
         }
         //throw new BplusTreeException("no space in leaf");
         dosplit = true;
         PrepareForSplit();
     }
     // bubble in the new info XXXX THIS SHOULD BUBBLE BACKWARDS
     var nextkey = m_childKeys[insertposition];
     var nextposition = m_childBufferNumbers[insertposition];
     m_childKeys[insertposition] = key;
     m_childBufferNumbers[insertposition] = position;
     while (nextkey!=null)
     {
         key = nextkey;
         position = nextposition;
         insertposition++;
         nextkey = m_childKeys[insertposition];
         nextposition = m_childBufferNumbers[insertposition];
         m_childKeys[insertposition] = key;
         m_childBufferNumbers[insertposition] = position;
     }
     // split if needed
     if (dosplit)
     {
         var splitpoint = m_childKeys.Length/2;
         var splitlength = m_childKeys.Length - splitpoint;
         splitNode = new BplusNode(m_owner, m_parent, -1, IsLeaf);
         // copy the split info into the splitNode
         Array.Copy(m_childBufferNumbers, splitpoint, splitNode.m_childBufferNumbers, 0, splitlength);
         Array.Copy(m_childKeys, splitpoint, splitNode.m_childKeys, 0, splitlength);
         Array.Copy(m_materializedChildNodes, splitpoint, splitNode.m_materializedChildNodes, 0, splitlength);
         splitString = splitNode.m_childKeys[0];
         // archive the new node
         splitNode.DumpToFreshBuffer();
         // store the node data temporarily
         var buffernumbers = m_childBufferNumbers;
         var keys = m_childKeys;
         var nodes = m_materializedChildNodes;
         // repair current node, copy in the other part of the split
         m_childBufferNumbers = new long[m_size+1];
         m_childKeys = new string[m_size];
         m_materializedChildNodes = new BplusNode[m_size+1];
         Array.Copy(buffernumbers, 0, m_childBufferNumbers, 0, splitpoint);
         Array.Copy(keys, 0, m_childKeys, 0, splitpoint);
         Array.Copy(nodes, 0, m_materializedChildNodes, 0, splitpoint);
         for (var i=splitpoint; i<m_childKeys.Length; i++)
         {
             m_childKeys[i] = null;
             m_childBufferNumbers[i] = BplusTreeLong.Nullbuffernumber;
             m_materializedChildNodes[i] = null;
         }
         // store the new node
         //splitNode.DumpToFreshBuffer();
         m_owner.RecordTerminalNode(splitNode);
         splitNode.Soil();
     }
     //return this.ChildKeys[0];
     if (insertposition==0)
     {
         return key; // smallest key changed.
     }
     else
     {
         return null; // no change in smallest key
     }
 }
Ejemplo n.º 19
0
 /// <summary>
 /// Find the first key below atIndex, or if no such node traverse to the next key to the right.
 /// If no such key exists, return nulls.
 /// </summary>
 /// <param name="atIndex">where to look in this node</param>
 /// <param name="FoundInLeaf">leaf where found</param>
 /// <param name="KeyFound">key value found</param>
 void TraverseToFollowingKey(int atIndex, out BplusNode FoundInLeaf, out string KeyFound)
 {
     FoundInLeaf = null;
     KeyFound = null;
     bool LookInParent = false;
     if (this.isLeaf)
     {
         LookInParent = (atIndex>=this.Size) || (this.ChildKeys[atIndex]==null);
     }
     else
     {
         LookInParent = (atIndex>this.Size) ||
             (atIndex>0 && this.ChildKeys[atIndex-1]==null);
     }
     if (LookInParent)
     {
         // if it's anywhere it's in the next child of parent
         if (this.parent!=null && this.indexInParent>=0)
         {
             this.parent.TraverseToFollowingKey(this.indexInParent+1, out FoundInLeaf, out KeyFound);
             return;
         }
         else
         {
             return; // no such following key
         }
     }
     if (this.isLeaf)
     {
         // leaf, we found it.
         FoundInLeaf = this;
         KeyFound = this.ChildKeys[atIndex];
         return;
     }
     else
     {
         // nonleaf, look in child (if there is one)
         if (atIndex==0 || this.ChildKeys[atIndex-1]!=null)
         {
             BplusNode thechild = this.MaterializeNodeAtIndex(atIndex);
             thechild.TraverseToFollowingKey(0, out FoundInLeaf, out KeyFound);
         }
     }
 }
Ejemplo n.º 20
0
 public long makeRoot()
 {
     this.parent = null;
     this.indexInParent = -1;
     if (this.myBufferNumber==BplusTreeLong.NULLBUFFERNUMBER)
     {
         throw new BplusTreeException("no root seek allocated to new root");
     }
     return this.myBufferNumber;
 }
Ejemplo n.º 21
0
 /// <summary>
 /// Forget all changes since last commit
 /// </summary>
 public void Abort()
 {
     // deallocate allocated blocks
     ArrayList toFree = new ArrayList();
     foreach (DictionaryEntry d in this.FreeBuffersOnAbort)
     {
         toFree.Add(d.Key);
     }
     toFree.Sort();
     toFree.Reverse();
     foreach (object thing in toFree)
     {
         long buffernumber = (long) thing;
         this.deallocateBuffer(buffernumber);
     }
     long freehead = this.freeHeadSeek;
     // reread the header (except for freelist head)
     this.readHeader();
     // restore the root
     if (this.rootSeek==NULLBUFFERNUMBER)
     {
         this.root = null; // nothing was committed
     }
     else
     {
         this.root.LoadFromBuffer(this.rootSeek);
     }
     this.ResetBookkeeping();
     this.freeHeadSeek = freehead;
     this.setHeader(); // store new freelist head
     this.fromfile.Flush();
 }
Ejemplo n.º 22
0
        public static void Merge(BplusNode left, string KeyBetween, BplusNode right, out string rightLeastKey, 
			out bool DeleteRight)
        {
            //System.Diagnostics.Debug.WriteLine("\r\n<br> merging "+right.myBufferNumber+" ("+KeyBetween+") "+left.myBufferNumber);
            //System.Diagnostics.Debug.WriteLine(left.owner.toHtml());
            rightLeastKey = null; // only if DeleteRight
            if (left.isLeaf || right.isLeaf)
            {
                if (!(left.isLeaf&&right.isLeaf))
                {
                    throw new BplusTreeException("can't merge leaf with non-leaf");
                }
                MergeLeaves(left, right, out DeleteRight);
                rightLeastKey = right.ChildKeys[0];
                return;
            }
            // merge non-leaves
            DeleteRight = false;
            string[] allkeys = new string[left.Size*2+1];
            long[] allseeks = new long[left.Size*2+2];
            BplusNode[] allMaterialized = new BplusNode[left.Size*2+2];
            if (left.ChildBufferNumbers[0]==BplusTreeLong.NULLBUFFERNUMBER ||
                right.ChildBufferNumbers[0]==BplusTreeLong.NULLBUFFERNUMBER)
            {
                throw new BplusTreeException("cannot merge empty non-leaf with non-leaf");
            }
            int index = 0;
            allseeks[0] = left.ChildBufferNumbers[0];
            allMaterialized[0] = left.MaterializedChildNodes[0];
            for (int i=0; i<left.Size; i++)
            {
                if (left.ChildKeys[i]==null)
                {
                    break;
                }
                allkeys[index] = left.ChildKeys[i];
                allseeks[index+1] = left.ChildBufferNumbers[i+1];
                allMaterialized[index+1] = left.MaterializedChildNodes[i+1];
                index++;
            }
            allkeys[index] = KeyBetween;
            index++;
            allseeks[index] = right.ChildBufferNumbers[0];
            allMaterialized[index] = right.MaterializedChildNodes[0];
            int rightcount = 0;
            for (int i=0; i<right.Size; i++)
            {
                if (right.ChildKeys[i]==null)
                {
                    break;
                }
                allkeys[index] = right.ChildKeys[i];
                allseeks[index+1] = right.ChildBufferNumbers[i+1];
                allMaterialized[index+1] = right.MaterializedChildNodes[i+1];
                index++;
                rightcount++;
            }
            if (index<=left.Size)
            {
                // it will all fit in one node
                //System.Diagnostics.Debug.WriteLine("deciding to forget "+right.myBufferNumber+" into "+left.myBufferNumber);
                DeleteRight = true;
                for (int i=0; i<index; i++)
                {
                    left.ChildKeys[i] = allkeys[i];
                    left.ChildBufferNumbers[i] = allseeks[i];
                    left.MaterializedChildNodes[i] = allMaterialized[i];
                }
                left.ChildBufferNumbers[index] = allseeks[index];
                left.MaterializedChildNodes[index] = allMaterialized[index];
                left.reParentAllChildren();
                left.Soil();
                right.Free();
                return;
            }
            // otherwise split the content between the nodes
            left.Clear();
            right.Clear();
            left.Soil();
            right.Soil();
            int leftcontent = index/2;
            int rightcontent = index-leftcontent-1;
            rightLeastKey = allkeys[leftcontent];
            int outputindex = 0;
            for (int i=0; i<leftcontent; i++)
            {
                left.ChildKeys[i] = allkeys[outputindex];
                left.ChildBufferNumbers[i] = allseeks[outputindex];
                left.MaterializedChildNodes[i] = allMaterialized[outputindex];
                outputindex++;
            }
            rightLeastKey = allkeys[outputindex];
            left.ChildBufferNumbers[outputindex] = allseeks[outputindex];
            left.MaterializedChildNodes[outputindex] = allMaterialized[outputindex];
            outputindex++;
            rightcount = 0;
            for (int i=0; i<rightcontent; i++)
            {
                right.ChildKeys[i] = allkeys[outputindex];
                right.ChildBufferNumbers[i] = allseeks[outputindex];
                right.MaterializedChildNodes[i] = allMaterialized[outputindex];
                outputindex++;
                rightcount++;
            }
            right.ChildBufferNumbers[rightcount] = allseeks[outputindex];
            right.MaterializedChildNodes[rightcount] = allMaterialized[outputindex];
            left.reParentAllChildren();
            right.reParentAllChildren();
        }
Ejemplo n.º 23
0
 public void RecordTerminalNode(BplusNode terminalNode)
 {
     if (terminalNode==this.root)
     {
         return; // never record the root node
     }
     if (this.TerminalNodeToId.ContainsKey(terminalNode) )
     {
         return; // don't record it again
     }
     int id = this.TerminalNodeCount;
     this.TerminalNodeCount++;
     this.TerminalNodeToId[terminalNode] = id;
     this.IdToTerminalNode[id] = terminalNode;
 }
Ejemplo n.º 24
0
 public void SerializationCheck()
 {
     BplusNode A = new BplusNode(this.owner, null, -1, false);
     for (int i=0; i<this.Size; i++)
     {
         long j = i*((long)0xf0f0f0f0f0f0f01);
         A.ChildBufferNumbers[i] = j;
         A.ChildKeys[i] = "k"+i;
     }
     A.ChildBufferNumbers[this.Size] = 7;
     A.TestRebuffer();
     A.isLeaf = true;
     for (int i=0; i<this.Size; i++)
     {
         long j = -i*((long)0x3e3e3e3e3e3e666);
         A.ChildBufferNumbers[i] = j;
         A.ChildKeys[i] = "key"+i;
     }
     A.ChildBufferNumbers[this.Size] = -9097;
     A.TestRebuffer();
 }
Ejemplo n.º 25
0
 public static void MergeLeaves(BplusNode left, BplusNode right, out bool DeleteRight)
 {
     DeleteRight = false;
     string[] allkeys = new string[left.Size*2];
     long[] allseeks = new long[left.Size*2];
     int index = 0;
     for (int i=0; i<left.Size; i++)
     {
         if (left.ChildKeys[i]==null)
         {
             break;
         }
         allkeys[index] = left.ChildKeys[i];
         allseeks[index] = left.ChildBufferNumbers[i];
         index++;
     }
     for (int i=0; i<right.Size; i++)
     {
         if (right.ChildKeys[i]==null)
         {
             break;
         }
         allkeys[index] = right.ChildKeys[i];
         allseeks[index] = right.ChildBufferNumbers[i];
         index++;
     }
     if (index<=left.Size)
     {
         left.Clear();
         DeleteRight = true;
         for (int i=0; i<index; i++)
         {
             left.ChildKeys[i] = allkeys[i];
             left.ChildBufferNumbers[i] = allseeks[i];
         }
         right.Free();
         left.Soil();
         return;
     }
     left.Clear();
     right.Clear();
     left.Soil();
     right.Soil();
     int rightcontent = index/2;
     int leftcontent = index - rightcontent;
     int newindex = 0;
     for (int i=0; i<leftcontent; i++)
     {
         left.ChildKeys[i] = allkeys[newindex];
         left.ChildBufferNumbers[i] = allseeks[newindex];
         newindex++;
     }
     for (int i=0; i<rightcontent; i++)
     {
         right.ChildKeys[i] = allkeys[newindex];
         right.ChildBufferNumbers[i] = allseeks[newindex];
         newindex++;
     }
 }
Ejemplo n.º 26
0
 void Destroy()
 {
     // make sure the structure is useless, it should no longer be used.
     this.owner = null;
     this.parent = null;
     this.Size = -100;
     this.ChildBufferNumbers = null;
     this.ChildKeys = null;
     this.MaterializedChildNodes = null;
     this.myBufferNumber = BplusTreeLong.NULLBUFFERNUMBER;
     this.indexInParent = -100;
     this.Dirty = false;
 }
Ejemplo n.º 27
0
 /// <summary>
 /// insert key/position entry in self 
 /// </summary>
 /// <param name="key">Key to associate with the leaf</param>
 /// <param name="position">position associated with key in external structur</param>
 /// <param name="splitString">if not null then the smallest key in the new split leaf</param>
 /// <param name="splitNode">if not null then the node was split and this is the leaf to the right.</param>
 /// <returns>null unless the smallest key under this node has changed, in which case it returns the smallest key.</returns>
 public string Insert(string key, long position, out string splitString, out BplusNode splitNode)
 {
     if (this.isLeaf)
     {
         return this.InsertLeaf(key, position, out splitString, out splitNode);
     }
     splitString = null;
     splitNode = null;
     int insertposition = this.FindAtOrNextPosition(key, false, true);
     long insertBufferNumber = this.ChildBufferNumbers[insertposition];
     if (insertBufferNumber==BplusTreeLong.NULLBUFFERNUMBER)
     {
         throw new BplusTreeException("key not followed by buffer number in non-leaf");
     }
     // insert in subtree
     BplusNode InsertChild = this.MaterializeNodeAtIndex(insertposition);
     BplusNode childSplit;
     string childSplitString;
     string childInsert = InsertChild.Insert(key, position, out childSplitString, out childSplit);
     // if there was a split the node must expand
     if (childSplit!=null)
     {
         // insert the child
         this.Soil(); // redundant -- a child will have a change so this node will need to be copied
         int newChildPosition = insertposition+1;
         bool dosplit = false;
         // if there is no free space we must do a split
         if (this.ChildBufferNumbers[this.Size]!=BplusTreeLong.NULLBUFFERNUMBER)
         {
             dosplit = true;
             this.PrepareForSplit();
         }
         // bubble over the current values to make space for new child
         for (int i=this.ChildKeys.Length-2; i>=newChildPosition-1; i--)
         {
             int i1 = i+1;
             int i2 = i1+1;
             this.ChildKeys[i1] = this.ChildKeys[i];
             this.ChildBufferNumbers[i2] = this.ChildBufferNumbers[i1];
             BplusNode childNode = this.MaterializedChildNodes[i2] = this.MaterializedChildNodes[i1];
         }
         // record the new child
         this.ChildKeys[newChildPosition-1] = childSplitString;
         //this.MaterializedChildNodes[newChildPosition] = childSplit;
         //this.ChildBufferNumbers[newChildPosition] = childSplit.myBufferNumber;
         childSplit.Reparent(this, newChildPosition);
         // split, if needed
         if (dosplit)
         {
             int splitpoint = this.MaterializedChildNodes.Length/2-1;
             splitString = this.ChildKeys[splitpoint];
             splitNode = new BplusNode(this.owner, this.parent, -1, this.isLeaf);
             // make copy of expanded node structure
             BplusNode[] materialized = this.MaterializedChildNodes;
             long[] buffernumbers = this.ChildBufferNumbers;
             string[] keys = this.ChildKeys;
             // repair the expanded node
             this.ChildKeys = new string[this.Size];
             this.MaterializedChildNodes = new BplusNode[this.Size+1];
             this.ChildBufferNumbers = new long[this.Size+1];
             this.Clear();
             Array.Copy(materialized, 0, this.MaterializedChildNodes, 0, splitpoint+1);
             Array.Copy(buffernumbers, 0, this.ChildBufferNumbers, 0, splitpoint+1);
             Array.Copy(keys, 0, this.ChildKeys, 0, splitpoint);
             // initialize the new node
             splitNode.Clear(); // redundant.
             int remainingKeys = this.Size-splitpoint;
             Array.Copy(materialized, splitpoint+1, splitNode.MaterializedChildNodes, 0, remainingKeys+1);
             Array.Copy(buffernumbers, splitpoint+1, splitNode.ChildBufferNumbers, 0, remainingKeys+1);
             Array.Copy(keys, splitpoint+1, splitNode.ChildKeys, 0, remainingKeys);
             // fix pointers in materialized children of splitnode
             splitNode.reParentAllChildren();
             // store the new node
             splitNode.DumpToFreshBuffer();
             splitNode.CheckIfTerminal();
             splitNode.Soil();
             this.CheckIfTerminal();
         }
         // fix pointers in children
         this.reParentAllChildren();
     }
     if (insertposition==0)
     {
         // the smallest key may have changed
         return childInsert;
     }
     return null;  // no change in smallest key
 }
Ejemplo n.º 28
0
 /// <summary>
 /// Find near-index of comparekey in leaf under this node. 
 /// </summary>
 /// <param name="CompareKey">the key to look for</param>
 /// <param name="inLeaf">the leaf where found</param>
 /// <param name="LookPastOnly">If true then only look for a greater value, not an exact match.</param>
 /// <returns>index of match in leaf</returns>
 int FindAtOrNextPositionInLeaf(string CompareKey, out BplusNode inLeaf, bool LookPastOnly, bool caseSensitive)
 {
     int myposition = this.FindAtOrNextPosition(CompareKey, LookPastOnly, caseSensitive);
     if (this.isLeaf)
     {
         inLeaf = this;
         return myposition;
     }
     long childBufferNumber = this.ChildBufferNumbers[myposition];
     if (childBufferNumber==BplusTreeLong.NULLBUFFERNUMBER)
     {
         throw new BplusTreeException("can't search null subtree");
     }
     BplusNode child = this.MaterializeNodeAtIndex(myposition);
     return child.FindAtOrNextPositionInLeaf(CompareKey, out inLeaf, LookPastOnly, caseSensitive);
 }
Ejemplo n.º 29
0
 /// <summary>
 /// insert key/position entry in self (as leaf)
 /// </summary>
 /// <param name="key">Key to associate with the leaf</param>
 /// <param name="position">position associated with key in external structure</param>
 /// <param name="splitString">if not null then the smallest key in the new split leaf</param>
 /// <param name="splitNode">if not null then the node was split and this is the leaf to the right.</param>
 /// <returns>smallest key value in keys, or null if no change</returns>
 public string InsertLeaf(string key, long position, out string splitString, out BplusNode splitNode)
 {
     splitString = null;
     splitNode = null;
     bool dosplit = false;
     if (!this.isLeaf)
     {
         throw new BplusTreeException("bad call to InsertLeaf: this is not a leaf");
     }
     this.Soil();
     int insertposition = this.FindAtOrNextPosition(key, false, true);
     if (insertposition>=this.Size)
     {
         //throw new BplusTreeException("key too big and leaf is full");
         dosplit = true;
         this.PrepareForSplit();
     }
     else
     {
         // if it's already there then change the value at the current location (duplicate entries not supported).
         if (this.ChildKeys[insertposition]==null || this.owner.Compare(this.ChildKeys[insertposition], key, true)==0) // this.ChildKeys[insertposition].Equals(key)
         {
             this.ChildBufferNumbers[insertposition] = position;
             this.ChildKeys[insertposition] = key;
             if (insertposition==0)
             {
                 return key;
             }
             else
             {
                 return null;
             }
         }
     }
     // check for a null position
     int nullindex = insertposition;
     while (nullindex<this.ChildKeys.Length && this.ChildKeys[nullindex]!=null)
     {
         nullindex++;
     }
     if (nullindex>=this.ChildKeys.Length)
     {
         if (dosplit)
         {
             throw new BplusTreeException("can't split twice!!");
         }
         //throw new BplusTreeException("no space in leaf");
         dosplit = true;
         this.PrepareForSplit();
     }
     // bubble in the new info XXXX THIS SHOULD BUBBLE BACKWARDS
     string nextkey = this.ChildKeys[insertposition];
     long nextposition = this.ChildBufferNumbers[insertposition];
     this.ChildKeys[insertposition] = key;
     this.ChildBufferNumbers[insertposition] = position;
     while (nextkey!=null)
     {
         key = nextkey;
         position = nextposition;
         insertposition++;
         nextkey = this.ChildKeys[insertposition];
         nextposition = this.ChildBufferNumbers[insertposition];
         this.ChildKeys[insertposition] = key;
         this.ChildBufferNumbers[insertposition] = position;
     }
     // split if needed
     if (dosplit)
     {
         int splitpoint = this.ChildKeys.Length/2;
         int splitlength = this.ChildKeys.Length - splitpoint;
         splitNode = new BplusNode(this.owner, this.parent, -1, this.isLeaf);
         // copy the split info into the splitNode
         Array.Copy(this.ChildBufferNumbers, splitpoint, splitNode.ChildBufferNumbers, 0, splitlength);
         Array.Copy(this.ChildKeys, splitpoint, splitNode.ChildKeys, 0, splitlength);
         Array.Copy(this.MaterializedChildNodes, splitpoint, splitNode.MaterializedChildNodes, 0, splitlength);
         splitString = splitNode.ChildKeys[0];
         // archive the new node
         splitNode.DumpToFreshBuffer();
         // store the node data temporarily
         long[] buffernumbers = this.ChildBufferNumbers;
         string[] keys = this.ChildKeys;
         BplusNode[] nodes = this.MaterializedChildNodes;
         // repair current node, copy in the other part of the split
         this.ChildBufferNumbers = new long[this.Size+1];
         this.ChildKeys = new string[this.Size];
         this.MaterializedChildNodes = new BplusNode[this.Size+1];
         Array.Copy(buffernumbers, 0, this.ChildBufferNumbers, 0, splitpoint);
         Array.Copy(keys, 0, this.ChildKeys, 0, splitpoint);
         Array.Copy(nodes, 0, this.MaterializedChildNodes, 0, splitpoint);
         for (int i=splitpoint; i<this.ChildKeys.Length; i++)
         {
             this.ChildKeys[i] = null;
             this.ChildBufferNumbers[i] = BplusTreeLong.NULLBUFFERNUMBER;
             this.MaterializedChildNodes[i] = null;
         }
         // store the new node
         //splitNode.DumpToFreshBuffer();
         this.owner.RecordTerminalNode(splitNode);
         splitNode.Soil();
     }
     //return this.ChildKeys[0];
     if (insertposition==0)
     {
         return key; // smallest key changed.
     }
     else
     {
         return null; // no change in smallest key
     }
 }
Ejemplo n.º 30
0
 void Reparent(BplusNode newParent, int parentIndex)
 {
     // keys and existing parent structure must be updated elsewhere.
     m_parent = newParent;
     m_indexInParent = parentIndex;
     newParent.m_childBufferNumbers[parentIndex] = MyBufferNumber;
     newParent.m_materializedChildNodes[parentIndex] = this;
     // parent is no longer terminal
     m_owner.ForgetTerminalNode(m_parent);
 }