public void AddChildren(List <Location> childLocations, List <ActivatedFeature> activatedFeatures, List <FeatureDefinition> definitions)
        {
            if (childLocations != null)
            {
                ChildLocations.AddRange(childLocations);
            }

            if (activatedFeatures != null)
            {
                ActivatedFeatures.AddRange(activatedFeatures);
            }

            if (definitions != null)
            {
                Definitions.AddRange(definitions);
            }
        }
        public void AddChild(Location location, IEnumerable <ActivatedFeature> activatedFeatures, IEnumerable <FeatureDefinition> definitions)
        {
            if (location != null)
            {
                ChildLocations.Add(location);
            }

            if (activatedFeatures != null)
            {
                ActivatedFeatures.AddRange(activatedFeatures);
            }

            if (definitions != null)
            {
                Definitions.AddRange(definitions);
            }
        }
Exemple #3
0
 public void AddChildLocation(Location child)
 {
     ChildLocations.Add(child);
 }
        internal BPlusTreeNode <TKey, TValue> SplitChild(BPlusTreeNode <TKey, TValue> originalChild, out int keywordIndex)
        {
            // Split the current node into two nodes:
            //   a. Left node contains all pointers/keywords to the left of the median
            //   b. Right node contains all pointers/keywords to the right of the median
            //   c. Parent node gets median keyword pushed into it
            //
            // Disk-wise: the originalChild is always written back to its original position (since we're splitting it, it's guaranteed to get smaller)
            //            the newChild is placed into either an available abandoned node or tacked on the end of the file.
            //            the parent node is written back to its original position IF IT FITS.  Since we're coyping a keyword
            //               up into the parent node, it may cause it to outgrow its allocated size in the file.  If this occurs,
            //               the call to this.Write() implicitly calls relocate().  relocate() will then either write the parent to
            //               an abandoned node or tack it onto the end of the file.



            // first, determine the offset of the current originalchild in this (the parent)
            keywordIndex = 0;

            try {
                BPlusTree <TKey, TValue> .LogInfo("Begin splitting node=" + this.ToString() + ", child=" + originalChild.ToString());

                if (ChildLocations.Count > 0)
                {
                    // TODO: troubleshoot this -- after several thousand splits, originalChild.Location is no longer found in the ChildLocations array!!!
                    //if (LastChildLocation == originalChild.Location) {
                    //    // rightmost child, on a full node.
                    //} else {
                    while (keywordIndex < ChildLocations.Count && ChildLocations[keywordIndex] != originalChild.Location)
                    {
                        keywordIndex++;
                    }
                    //}
                }

                // assign the median keyword to the parent's Keywords list (inserts just before the current one)
                //if (keywordIndex > this.Keywords.Count) {
                //    // rightmost keyword, add to the end of the list
                //    this.Keywords.Add(originalChild.MedianKeyword);
                //} else {
                // not rightmost keyword, insert it at the proper position
                this.Keywords.Insert(keywordIndex, originalChild.MedianKeyword);
                //}

                if (originalChild.IsLeaf)
                {
                    // since this is a leaf, we will copy up the median keyword to the parent (as opposed to push up for index nodes)

                    // create a leaf node
                    BPlusTreeLeafNode <TKey, TValue> origNode = (BPlusTreeLeafNode <TKey, TValue>)originalChild;
                    BPlusTreeLeafNode <TKey, TValue> newNode  = new BPlusTreeLeafNode <TKey, TValue>(this.Tree, (BPlusTreeIndexNode <TKey, TValue>) this, null);

                    // copy right half of keywords + values from originalChild to newChild
                    newNode.Keywords.AddRange(origNode.Keywords.Skip(this.Tree.Median - 1));
                    newNode.Values.AddRange(origNode.Values.Skip(this.Tree.Median - 1));

                    // remove right half of keywords + values from originalChild
                    origNode.Keywords = origNode.Keywords.Take(this.Tree.Median - 1).ToList();
                    origNode.Values   = origNode.Values.Take(this.Tree.Median - 1).ToList();

                    var nextKeywordIndex = keywordIndex + 1;
                    Tree.Lock(delegate() {
                        // write out nodes so sibling locations can be set properly

                        // note: orig node should never relocate on write since we're making it smaller (moving 1/2 of its keywords to a new node)
                        if (origNode.Write())
                        {
                            BPlusTree <TKey, TValue> .LogInfo("orig leaf node relocated during split child: " + origNode.ToString());
                        }
                        if (newNode.Write())
                        {
                            BPlusTree <TKey, TValue> .LogInfo("new leaf node relocated during split child: " + newNode.ToString());
                        }

                        // adjust sibling locations (we always add the new child to the right of the original one)
                        newNode.RightSiblingLocation = origNode.RightSiblingLocation;
                        //				newNode.LeftSiblingLocation = origNode.Location;

                        origNode.RightSiblingLocation = newNode.Location;

                        ChildLocations.Insert(nextKeywordIndex, newNode.Location);

                        // write them out again so we save sibling locations
                        if (origNode.Write())
                        {
                            BPlusTree <TKey, TValue> .LogInfo("orig leaf node relocated on 2nd write during split child: " + origNode.ToString());
                        }
                        if (newNode.Write())
                        {
                            BPlusTree <TKey, TValue> .LogInfo("new leaf node relocated on 2nd write during split child: " + newNode.ToString());
                        }

                        // and write out the parent since it changed as well
                        if (Write())
                        {
                            BPlusTree <TKey, TValue> .LogInfo("parent of leaf node relocated during split child: " + this.ToString());
                        }
                    });

                    return(newNode);
                }
                else
                {
                    // since this is an index node, we push up the keyword to the parent (as opposed to copy up for leaves)
                    // this means the median keyword will be removed from the original child but not moved to the new child

                    // create an index node
                    BPlusTreeIndexNode <TKey, TValue> origNode = (BPlusTreeIndexNode <TKey, TValue>)originalChild;
                    BPlusTreeIndexNode <TKey, TValue> newNode  = new BPlusTreeIndexNode <TKey, TValue>(this.Tree, (BPlusTreeIndexNode <TKey, TValue>) this, null);

                    // copy right half of keywords + childlocations from originalChild to newChild
                    // (since this is an index node, skip the median keyword
                    newNode.Keywords.AddRange(origNode.Keywords.Skip(this.Tree.Median));
                    newNode.ChildLocations.AddRange(origNode.ChildLocations.Skip(this.Tree.Median));

                    // remove right half of keywords + childlocations from originalChild
                    // (note we stop one shy of the median keyword -- this is because the median keyword needs to be "pushed up"
                    //  on an index node split.  However, we don't drop the corresponding ChildLocation)
                    origNode.Keywords       = origNode.Keywords.Take(this.Tree.Median - 1).ToList();
                    origNode.ChildLocations = origNode.ChildLocations.Take(this.Tree.Median).ToList();

                    var ki = keywordIndex;
                    Tree.Lock(delegate() {
                        if (origNode.Write())
                        {
                            BPlusTree <TKey, TValue> .LogInfo("orig index node relocated during split child: " + origNode.ToString());
                        }
                        if (newNode.Write())
                        {
                            BPlusTree <TKey, TValue> .LogInfo("new index node relocated during split child: " + newNode.ToString());
                        }

                        // original node may have relocated on write...
                        ChildLocations[ki] = origNode.Location;

                        ChildLocations.Insert(ki + 1, newNode.Location);

                        // and write out the parent since it changed as well
                        if (Write())
                        {
                            BPlusTree <TKey, TValue> .LogInfo("parent of index node relocated during split child: " + this.ToString());
                        }
                    });

                    return(newNode);
                }
            } finally {
                BPlusTree <TKey, TValue> .LogInfo("End splitting node=" + this.ToString() + ", child=" + originalChild.ToString());
            }
        }
 public void AddChildLocations(IEnumerable <Location> childLocations)
 {
     ChildLocations.AddRange(childLocations);
 }