예제 #1
0
 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;
 }
예제 #2
0
        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();
            }
        }
예제 #3
0
        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;
                    }
                }
            }
        }
예제 #4
0
        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;
            }
        }
예제 #5
0
        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;
                }
            }
        }