private void SetIndexNode(RowTreeNode indexNode) { // This implements crabbing, because the new node is locked before the old node lock is released if (_indexNode != null) { _indexNode.Dispose(); } _indexNode = indexNode; }
private bool FindIndexKey(Schema.IRowType keyRowType, NativeRow key, out RowTreeNode indexNode, out int entryNumber) { RowTreeSearchPath searchPath = new RowTreeSearchPath(); try { bool result = _accessPath.FindKey(_manager, keyRowType, key, searchPath, out entryNumber); indexNode = searchPath.DisownAt(searchPath.Count - 1); return(result); } finally { searchPath.Dispose(); } }
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; } } } }
public void Last() { #if SAFETABLES CheckActive(); #endif _eOF = true; _bOF = false; bool result = false; if (_lastKey != null) { RowTreeNode indexNode; result = FindIndexKey(_lastKey.DataType, (NativeRow)_lastKey.AsNative, out indexNode, out _entryNumber); SetIndexNode(indexNode); } else { if (_direction == ScanDirection.Forward) { SetIndexNode(new RowTreeNode(_manager, _accessPath, _accessPath.Tail, LockMode.Shared)); _entryNumber = _indexNode.Node.EntryCount - 1; } else { SetIndexNode(new RowTreeNode(_manager, _accessPath, _accessPath.Head, LockMode.Shared)); _entryNumber = 0; } } if (!result) { // Determine FBOF RowTreeNode saveIndexNode = new RowTreeNode(_manager, _indexNode.Tree, _indexNode.Node, LockMode.Shared); int saveEntryNumber = _entryNumber; Prior(); _eOF = true; if (_indexNode != null) { _indexNode.Dispose(); } _indexNode = saveIndexNode; _entryNumber = saveEntryNumber; } }
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; } } }