public void RowsMoved(NativeRowTreeNode oldNode, int oldEntryNumberMin, int oldEntryNumberMax, NativeRowTreeNode newNode, int entryNumberDelta) { if (OnRowsMoved != null) { OnRowsMoved(this, oldNode, oldEntryNumberMin, oldEntryNumberMax, newNode, entryNumberDelta); } }
public void RowDeleted(NativeRowTreeNode node, int entryNumber) { if (OnRowDeleted != null) { OnRowDeleted(this, node, entryNumber); } }
private void RowTreeRowDeleted(NativeRowTree rowTree, NativeRowTreeNode node, int entryNumber) { if ((_indexNode.Node == node) && (_entryNumber == entryNumber)) { UpdateScanPointer(); } }
public override void Drop(IValueManager manager) { // Deallocate all nodes in the tree DeallocateNode(manager, Root); Root = null; Tail = null; Head = null; Height = 0; }
public RowTreeNode(IValueManager manager, NativeRowTree tree, NativeRowTreeNode node, LockMode lockMode) { Manager = manager; Tree = tree; Node = node; DataNode = Node as NativeRowTreeDataNode; RoutingNode = Node as NativeRowTreeRoutingNode; #if LOCKROWTREE Manager.Lock(Node.LockID, ALockMode); #endif }
public void Insert(NativeRow key, NativeRowTreeNode node, int entryNumber) { // Slide all entries above the insert index Array.Copy(_keys, entryNumber, _keys, entryNumber + 1, _entryCount - entryNumber); Array.Copy(_nodes, entryNumber, _nodes, entryNumber + 1, _entryCount - entryNumber); // Set the new entry data _keys[entryNumber] = key; _nodes[entryNumber] = node; // Increment entry count _entryCount++; }
private void RowTreeRowsMoved(NativeRowTree rowTree, NativeRowTreeNode oldNode, int oldEntryNumberMin, int oldEntryNumberMax, NativeRowTreeNode newNode, int entryNumberDelta) { if ((_indexNode.Node == oldNode) && (_entryNumber >= oldEntryNumberMin) && (_entryNumber <= oldEntryNumberMax)) { if (oldNode != newNode) { SetIndexNode(new RowTreeNode(_manager, _indexNode.Tree, newNode, LockMode.Shared)); } _entryNumber += entryNumberDelta; UpdateScanPointer(); } }
protected void DeallocateNode(IValueManager manager, NativeRowTreeNode node) { using (RowTreeNode localNode = new RowTreeNode(manager, this, node, LockMode.Exclusive)) { NativeRowTreeDataNode dataNode = node as NativeRowTreeDataNode; NativeRowTreeRoutingNode routingNode = node as NativeRowTreeRoutingNode; for (int entryIndex = 0; entryIndex < node.EntryCount; entryIndex++) { if (node.NodeType == NativeRowTreeNodeType.Routing) { if (entryIndex > 0) { DisposeKey(manager, node.Keys[entryIndex]); } DeallocateNode(manager, routingNode.Nodes[entryIndex]); } else { DisposeKey(manager, dataNode.Keys[entryIndex]); DisposeData(manager, dataNode.Rows[entryIndex]); } } if (node.NextNode == null) { Tail = node.PriorNode; } else { using (RowTreeNode nextNode = new RowTreeNode(manager, this, node.NextNode, LockMode.Exclusive)) { nextNode.Node.PriorNode = node.PriorNode; } } if (node.PriorNode == null) { Head = node.NextNode; } else { using (RowTreeNode priorNode = new RowTreeNode(manager, this, node.PriorNode, LockMode.Exclusive)) { priorNode.Node.NextNode = node.NextNode; } } } }
private int Split(NativeRowTreeNode sourceNode, NativeRowTreeNode targetNode) { int entryCount = sourceNode.EntryCount; int entryPivot = entryCount / 2; if (sourceNode.NodeType == NativeRowTreeNodeType.Data) { NativeRowTreeDataNode sourceDataNode = (NativeRowTreeDataNode)sourceNode; NativeRowTreeDataNode targetDataNode = (NativeRowTreeDataNode)targetNode; // Insert the upper half of the entries from ASourceNode into ATargetNode for (int entryIndex = entryPivot; entryIndex < entryCount; entryIndex++) { targetDataNode.Insert(sourceDataNode.Keys[entryIndex], sourceDataNode.Rows[entryIndex], entryIndex - entryPivot); } // Remove the upper half of the entries from ASourceNode for (int entryIndex = entryCount - 1; entryIndex >= entryPivot; entryIndex--) { sourceDataNode.Delete(entryIndex); // Don't dispose the values here, this is a move } } else { NativeRowTreeRoutingNode sourceRoutingNode = (NativeRowTreeRoutingNode)sourceNode; NativeRowTreeRoutingNode targetRoutingNode = (NativeRowTreeRoutingNode)targetNode; // Insert the upper half of the entries from ASourceNode into ATargetNode for (int entryIndex = entryPivot; entryIndex < entryCount; entryIndex++) { targetRoutingNode.Insert(sourceRoutingNode.Keys[entryIndex], sourceRoutingNode.Nodes[entryIndex], entryIndex - entryPivot); } // Remove the upper half of the entries from ASourceNode for (int entryIndex = entryCount - 1; entryIndex >= entryPivot; entryIndex--) { sourceRoutingNode.Delete(entryIndex); } } // Notify index clients of the data change RowsMoved(sourceNode, entryPivot, entryCount - 1, targetNode, -entryPivot); return(entryPivot); }
public NativeRowTreeRoutingNode(NativeRowTree nativeRowTree) : base(nativeRowTree) { _nodeType = NativeRowTreeNodeType.Routing; _keys = new NativeRow[_nativeRowTree.Fanout]; _nodes = new NativeRowTreeNode[_nativeRowTree.Fanout]; }
private void InternalInsert(IValueManager manager, RowTreeSearchPath rowTreeSearchPath, int entryNumber, NativeRow key, NativeRow data) { // Walk back up the search path, inserting data and splitting pages as necessary RowTreeNode newRowTreeNode; NativeRowTreeNode splitNode = null; for (int index = rowTreeSearchPath.Count - 1; index >= 0; index--) { if (rowTreeSearchPath[index].Node.EntryCount >= Capacity) { // Allocate a new node using (newRowTreeNode = AllocateNode(manager, rowTreeSearchPath[index].Node.NodeType)) { // Thread it into the list of leaves, if necessary if (newRowTreeNode.Node.NodeType == NativeRowTreeNodeType.Data) { newRowTreeNode.Node.PriorNode = rowTreeSearchPath[index].Node; newRowTreeNode.Node.NextNode = rowTreeSearchPath[index].Node.NextNode; rowTreeSearchPath[index].Node.NextNode = newRowTreeNode.Node; if (newRowTreeNode.Node.NextNode == null) { Tail = newRowTreeNode.Node; } else { using (RowTreeNode nextRowTreeNode = new RowTreeNode(manager, this, newRowTreeNode.Node.NextNode, LockMode.Exclusive)) { nextRowTreeNode.Node.PriorNode = newRowTreeNode.Node; } } } int entryPivot = Split(rowTreeSearchPath[index].Node, newRowTreeNode.Node); // Insert the new entry into the appropriate node if (entryNumber >= entryPivot) { if (newRowTreeNode.Node.NodeType == NativeRowTreeNodeType.Data) { newRowTreeNode.InsertData(key, data, entryNumber - entryPivot); } else { newRowTreeNode.InsertRouting(key, splitNode, entryNumber - entryPivot); } } else if (newRowTreeNode.Node.NodeType == NativeRowTreeNodeType.Data) { rowTreeSearchPath[index].InsertData(key, data, entryNumber); } else { rowTreeSearchPath[index].InsertRouting(key, splitNode, entryNumber); } // Reset the AKey for the next round // The key for the entry one level up is the first key for the newly allocated node key = CopyKey(manager, newRowTreeNode.Node.Keys[0]); // Set LSplitNode to the newly allocated node splitNode = newRowTreeNode.Node; } if (index == 0) { // Allocate a new root node and grow the height of the tree by 1 using (newRowTreeNode = AllocateNode(manager, NativeRowTreeNodeType.Routing)) { newRowTreeNode.InsertRouting(null, rowTreeSearchPath[index].Node, 0); // 1st key of a routing node is not used newRowTreeNode.InsertRouting(key, splitNode, 1); Root = newRowTreeNode.Node; Height++; } } else { // reset AEntryNumber for the next round bool result = rowTreeSearchPath[index - 1].NodeSearch(KeyRowType, key, out entryNumber); // At this point we should be guaranteed to have a routing key which does not exist in the parent node if (result) { throw new IndexException(IndexException.Codes.DuplicateRoutingKey); } } } else { if (rowTreeSearchPath[index].Node.NodeType == NativeRowTreeNodeType.Data) { rowTreeSearchPath[index].InsertData(key, data, entryNumber); } else { rowTreeSearchPath[index].InsertRouting(key, splitNode, entryNumber); } break; } } }
public void UpdateRouting(NativeRowTreeNode node, int entryNumber) { RoutingNode.Nodes[entryNumber] = node; }
public void InsertRouting(NativeRow key, NativeRowTreeNode node, int entryNumber) { RoutingNode.Insert(key, node, entryNumber); Tree.RowsMoved(Node, entryNumber, Node.EntryCount - 2, Node, 1); }