Exemple #1
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
 }
Exemple #2
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.m_childKeys[0];
                return;
            }
            // merge non-leaves
            deleteRight = false;
            var allkeys = new string[left.m_size*2+1];
            var allseeks = new long[left.m_size*2+2];
            var allMaterialized = new BplusNode[left.m_size*2+2];
            if (left.m_childBufferNumbers[0]==BplusTreeLong.Nullbuffernumber ||
                right.m_childBufferNumbers[0]==BplusTreeLong.Nullbuffernumber)
            {
                throw new BplusTreeException("cannot merge empty non-leaf with non-leaf");
            }
            var index = 0;
            allseeks[0] = left.m_childBufferNumbers[0];
            allMaterialized[0] = left.m_materializedChildNodes[0];
            for (var i=0; i<left.m_size; i++)
            {
                if (left.m_childKeys[i]==null)
                {
                    break;
                }
                allkeys[index] = left.m_childKeys[i];
                allseeks[index+1] = left.m_childBufferNumbers[i+1];
                allMaterialized[index+1] = left.m_materializedChildNodes[i+1];
                index++;
            }
            allkeys[index] = keyBetween;
            index++;
            allseeks[index] = right.m_childBufferNumbers[0];
            allMaterialized[index] = right.m_materializedChildNodes[0];
            var rightcount = 0;
            for (var i=0; i<right.m_size; i++)
            {
                if (right.m_childKeys[i]==null)
                {
                    break;
                }
                allkeys[index] = right.m_childKeys[i];
                allseeks[index+1] = right.m_childBufferNumbers[i+1];
                allMaterialized[index+1] = right.m_materializedChildNodes[i+1];
                index++;
                rightcount++;
            }
            if (index<=left.m_size)
            {
                // it will all fit in one node
                //System.Diagnostics.Debug.WriteLine("deciding to forget "+right.myBufferNumber+" into "+left.myBufferNumber);
                deleteRight = true;
                for (var i=0; i<index; i++)
                {
                    left.m_childKeys[i] = allkeys[i];
                    left.m_childBufferNumbers[i] = allseeks[i];
                    left.m_materializedChildNodes[i] = allMaterialized[i];
                }
                left.m_childBufferNumbers[index] = allseeks[index];
                left.m_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();
            var leftcontent = index/2;
            var rightcontent = index-leftcontent-1;
            rightLeastKey = allkeys[leftcontent];
            var outputindex = 0;
            for (var i=0; i<leftcontent; i++)
            {
                left.m_childKeys[i] = allkeys[outputindex];
                left.m_childBufferNumbers[i] = allseeks[outputindex];
                left.m_materializedChildNodes[i] = allMaterialized[outputindex];
                outputindex++;
            }
            rightLeastKey = allkeys[outputindex];
            left.m_childBufferNumbers[outputindex] = allseeks[outputindex];
            left.m_materializedChildNodes[outputindex] = allMaterialized[outputindex];
            outputindex++;
            rightcount = 0;
            for (var i=0; i<rightcontent; i++)
            {
                right.m_childKeys[i] = allkeys[outputindex];
                right.m_childBufferNumbers[i] = allseeks[outputindex];
                right.m_materializedChildNodes[i] = allMaterialized[outputindex];
                outputindex++;
                rightcount++;
            }
            right.m_childBufferNumbers[rightcount] = allseeks[outputindex];
            right.m_materializedChildNodes[rightcount] = allMaterialized[outputindex];
            left.ReParentAllChildren();
            right.ReParentAllChildren();
        }