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); } }
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); }