Exemplo n.º 1
0
        /// <summary>
        /// The recursive portion of the find key algorithm invoked by the FindKey method of the parent Index.
        /// </summary>
        public bool FindKey(Schema.IRowType keyRowType, NativeRow key, RowTreeSearchPath rowTreeSearchPath, out int entryNumber)
        {
            rowTreeSearchPath.Add(this);
            if (Node.NodeType == NativeRowTreeNodeType.Routing)
            {
                // Perform a binary search among the keys in this node to determine which streamid to follow for the next node
                bool result = NodeSearch(keyRowType, key, out entryNumber);

                // If the key was found, use the given entry number, otherwise, use the one before the given entry
                entryNumber = result ? entryNumber : (entryNumber - 1);
                return
                    (new RowTreeNode
                     (
                         Manager,
                         Tree,
                         RoutingNode.Nodes[entryNumber],
                         LockMode.Shared
                     ).FindKey
                     (
                         keyRowType,
                         key,
                         rowTreeSearchPath,
                         out entryNumber
                     ));
            }
            else
            {
                // Perform a binary search among the keys in this node to determine which entry, if any, is equal to the given key
                return(NodeSearch(keyRowType, key, out entryNumber));
            }
        }
Exemplo n.º 2
0
        // TODO: Asynchronous collapsed node recovery
        /// <summary>Deletes the entry given by AKey.  The streams are disposed through the DisposeKey event, so it is the responsibility of the index user to dispose references within the streams.</summary>
        public override void Delete(IValueManager manager, NativeRow key)
        {
            int entryNumber;

            using (RowTreeSearchPath rowTreeSearchPath = new RowTreeSearchPath())
            {
                bool result = FindKey(manager, KeyRowType, key, rowTreeSearchPath, out entryNumber);
                if (!result)
                {
                    throw new IndexException(IndexException.Codes.KeyNotFound);
                }

                InternalDelete(manager, rowTreeSearchPath, entryNumber);
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// The given streams are copied into the index, so references within the streams
        /// are considered owned by the index after the insert.
        /// </summary>
        public override void Insert(IValueManager manager, NativeRow key, NativeRow data)
        {
            int entryNumber;

            using (RowTreeSearchPath rowTreeSearchPath = new RowTreeSearchPath())
            {
                bool result = FindKey(manager, KeyRowType, key, rowTreeSearchPath, out entryNumber);
                if (result)
                {
                    throw new IndexException(IndexException.Codes.DuplicateKey);
                }

                InternalInsert(manager, rowTreeSearchPath, entryNumber, key, data);
            }
        }
Exemplo n.º 4
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();
            }
        }
Exemplo n.º 5
0
        public void Delete(IValueManager manager, IRow row)
        {
            // Delete the row from all indexes
            Row clusteredKey = GetIndexData(manager, ClusteredIndex.KeyRowType, new IRow[] { row });

            try
            {
                using (RowTreeSearchPath searchPath = new RowTreeSearchPath())
                {
                    int  entryNumber;
                    bool result = ClusteredIndex.FindKey(manager, ClusteredIndex.KeyRowType, (NativeRow)clusteredKey.AsNative, searchPath, out entryNumber);
                    if (!result)
                    {
                        throw new IndexException(IndexException.Codes.KeyNotFound);
                    }

                    Row clusteredData = new Row(manager, ClusteredIndex.DataRowType, searchPath.DataNode.DataNode.Rows[entryNumber]);
                    try
                    {
                        foreach (NativeRowTree bufferIndex in NonClusteredIndexes)
                        {
                            Row key = GetIndexData(manager, bufferIndex.KeyRowType, new IRow[] { clusteredKey, clusteredData });
                            try
                            {
                                bufferIndex.Delete(manager, (NativeRow)key.AsNative);
                            }
                            finally
                            {
                                key.Dispose();
                            }
                        }
                    }
                    finally
                    {
                        clusteredData.Dispose();
                    }
                }

                ClusteredIndex.Delete(manager, (NativeRow)clusteredKey.AsNative);
            }
            finally
            {
                clusteredKey.Dispose();
            }

            _rowCount--;
        }
Exemplo n.º 6
0
        public bool HasRow(IValueManager manager, IRow row)
        {
            IRow key = GetIndexData(manager, ClusteredIndex.KeyRowType, new IRow[] { row });

            try
            {
                using (RowTreeSearchPath searchPath = new RowTreeSearchPath())
                {
                    int entryNumber;
                    return(ClusteredIndex.FindKey(manager, ClusteredIndex.KeyRowType, (NativeRow)key.AsNative, searchPath, out entryNumber));
                }
            }
            finally
            {
                key.Dispose();
            }
        }
Exemplo n.º 7
0
        /// <summary>Updates the entry given by AOldKey to the entry given by ANewKey and ANewData.  If AOldKey == ANewKey, the data for the entry is updated in place, otherwise it is moved to the location given by ANewKey.</summary>
        public override void Update(IValueManager manager, NativeRow oldKey, NativeRow newKey, NativeRow newData)
        {
            int entryNumber;

            using (RowTreeSearchPath rowTreeSearchPath = new RowTreeSearchPath())
            {
                bool result = FindKey(manager, KeyRowType, oldKey, rowTreeSearchPath, out entryNumber);
                if (!result)
                {
                    throw new IndexException(IndexException.Codes.KeyNotFound);
                }

                if (Compare(manager, KeyRowType, oldKey, KeyRowType, newKey) == 0)
                {
                    if (newData != null)
                    {
                        rowTreeSearchPath.DataNode.UpdateData(newData, entryNumber);
                    }
                }
                else
                {
                    if (newData == null)
                    {
                        newData = rowTreeSearchPath.DataNode.DataNode.Rows[entryNumber];
                        rowTreeSearchPath.DataNode.DataNode.Delete(entryNumber);                         // Don't dispose here this is a move
                    }
                    else
                    {
                        InternalDelete(manager, rowTreeSearchPath, entryNumber);                         // Dispose here this is not a move
                    }
                    rowTreeSearchPath.Dispose();
                    result = FindKey(manager, KeyRowType, newKey, rowTreeSearchPath, out entryNumber);
                    if (result)
                    {
                        throw new IndexException(IndexException.Codes.DuplicateKey);
                    }

                    InternalInsert(manager, rowTreeSearchPath, entryNumber, newKey, newData);
                }
            }
        }
Exemplo n.º 8
0
 /// <summary>
 /// Searches for the given key within the index.  ARowTreeSearchPath and AEntryNumber together give the
 /// location of the key in the index.  If the search is successful, the entry exists, otherwise
 /// the EntryNumber indicates where the entry should be placed for an insert.
 /// </summary>
 /// <param name="key">The key to be found.</param>
 /// <param name="rowTreeSearchPath">A <see cref="RowTreeSearchPath"/> which will contain the set of nodes along the search path to the key.</param>
 /// <param name="entryNumber">The EntryNumber where the key either is, or should be, depending on the result of the find.</param>
 /// <returns>A boolean value indicating the success or failure of the find.</returns>
 public bool FindKey(IValueManager manager, Schema.IRowType keyRowType, NativeRow key, RowTreeSearchPath rowTreeSearchPath, out int entryNumber)
 {
     return(new RowTreeNode(manager, this, Root, LockMode.Shared).FindKey(keyRowType, key, rowTreeSearchPath, out entryNumber));
 }
Exemplo n.º 9
0
 private void InternalDelete(IValueManager manager, RowTreeSearchPath rowTreeSearchPath, int entryNumber)
 {
     rowTreeSearchPath.DataNode.DeleteData(entryNumber);
 }
Exemplo n.º 10
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;
                }
            }
        }
Exemplo n.º 11
0
        public void Update(IValueManager manager, IRow oldRow, IRow newRow)
        {
            // AOldRow must have at least the columns of the clustered index key
            Row oldClusteredKey = GetIndexData(manager, ClusteredIndex.KeyRowType, new IRow[] { oldRow });

            try
            {
                bool isClusteredIndexKeyAffected  = GetIsIndexAffected(ClusteredIndex.KeyRowType, newRow);
                bool isClusteredIndexDataAffected = GetIsIndexAffected(ClusteredIndex.DataRowType, newRow);

                Row newClusteredKey  = null;
                Row newClusteredData = null;
                try
                {
                    // Update the row in each index
                    using (RowTreeSearchPath searchPath = new RowTreeSearchPath())
                    {
                        int  entryNumber;
                        bool result = ClusteredIndex.FindKey(manager, ClusteredIndex.KeyRowType, (NativeRow)oldClusteredKey.AsNative, searchPath, out entryNumber);
                        if (!result)
                        {
                            throw new IndexException(IndexException.Codes.KeyNotFound);
                        }

                        Row oldClusteredData = new Row(manager, ClusteredIndex.DataRowType, searchPath.DataNode.DataNode.Rows[entryNumber]);
                        try
                        {
                            bool isIndexAffected;
                            foreach (NativeRowTree tree in NonClusteredIndexes)
                            {
                                isIndexAffected = GetIsIndexAffected(tree.KeyRowType, newRow);

                                if (isClusteredIndexKeyAffected || isIndexAffected)
                                {
                                    Row oldIndexKey = GetIndexData(manager, tree.KeyRowType, new Row[] { oldClusteredKey, oldClusteredData });
                                    try
                                    {
                                        Row newIndexKey  = null;
                                        Row newIndexData = null;
                                        try
                                        {
                                            if (isIndexAffected)
                                            {
                                                newIndexKey = GetIndexData(manager, tree.KeyRowType, new IRow[] { newRow, oldClusteredKey, oldClusteredData });
                                            }

                                            if (isClusteredIndexKeyAffected)
                                            {
                                                newIndexData = GetIndexData(manager, tree.DataRowType, new IRow[] { newRow, oldClusteredKey, oldClusteredData });
                                            }

                                            if (isIndexAffected && isClusteredIndexKeyAffected)
                                            {
                                                tree.Update(manager, (NativeRow)oldIndexKey.AsNative, (NativeRow)newIndexKey.AsNative, (NativeRow)newIndexData.AsNative);
                                                newIndexKey.ValuesOwned  = false;
                                                newIndexData.ValuesOwned = false;
                                            }
                                            else if (isIndexAffected)
                                            {
                                                tree.Update(manager, (NativeRow)oldIndexKey.AsNative, (NativeRow)newIndexKey.AsNative);
                                                newIndexKey.ValuesOwned = false;
                                            }
                                            else if (isClusteredIndexKeyAffected)
                                            {
                                                tree.Update(manager, (NativeRow)oldIndexKey.AsNative, (NativeRow)oldIndexKey.AsNative, (NativeRow)newIndexData.AsNative);
                                                newIndexData.ValuesOwned = false;
                                            }
                                        }
                                        finally
                                        {
                                            if (newIndexKey != null)
                                            {
                                                newIndexKey.Dispose();
                                            }

                                            if (newIndexData != null)
                                            {
                                                newIndexData.Dispose();
                                            }
                                        }
                                    }
                                    finally
                                    {
                                        oldIndexKey.Dispose();
                                    }
                                }
                            }

                            if (isClusteredIndexKeyAffected)
                            {
                                newClusteredKey = GetIndexData(manager, ClusteredIndex.KeyRowType, new IRow[] { newRow, oldClusteredKey, oldClusteredData });
                            }

                            if (isClusteredIndexDataAffected)
                            {
                                newClusteredData = GetIndexData(manager, ClusteredIndex.DataRowType, new IRow[] { newRow, oldClusteredData });
                            }
                        }
                        finally
                        {
                            oldClusteredData.Dispose();
                        }
                    }

                    if (isClusteredIndexKeyAffected && isClusteredIndexDataAffected)
                    {
                        ClusteredIndex.Update(manager, (NativeRow)oldClusteredKey.AsNative, (NativeRow)newClusteredKey.AsNative, (NativeRow)newClusteredData.AsNative);
                        newClusteredKey.ValuesOwned  = false;
                        newClusteredData.ValuesOwned = false;
                    }
                    else if (isClusteredIndexKeyAffected)
                    {
                        ClusteredIndex.Update(manager, (NativeRow)oldClusteredKey.AsNative, (NativeRow)newClusteredKey.AsNative);
                        newClusteredKey.ValuesOwned = false;
                    }
                    else if (isClusteredIndexDataAffected)
                    {
                        ClusteredIndex.Update(manager, (NativeRow)oldClusteredKey.AsNative, (NativeRow)oldClusteredKey.AsNative, (NativeRow)newClusteredData.AsNative);
                        newClusteredData.ValuesOwned = false;
                    }
                }
                finally
                {
                    if (newClusteredKey != null)
                    {
                        newClusteredKey.Dispose();
                    }

                    if (newClusteredData != null)
                    {
                        newClusteredData.Dispose();
                    }
                }
            }
            finally
            {
                oldClusteredKey.Dispose();
            }
        }
Exemplo n.º 12
0
        public void GetRow(IRow row)
        {
                        #if SAFETABLES
            CheckActive();
                        #endif
            CheckNotCrack();

            if ((_accessPath.IsClustered) || IsSubset(row, _accessPath))
            {
                Row localRow = new Row(_manager, _accessPath.KeyRowType, _indexNode.Node.Keys[_entryNumber]);
                try
                {
                    localRow.CopyTo(row);
                }
                finally
                {
                    localRow.Dispose();
                }

                localRow = new Row(_manager, _accessPath.DataRowType, _indexNode.DataNode.Rows[_entryNumber]);
                try
                {
                    localRow.CopyTo(row);
                }
                finally
                {
                    localRow.Dispose();
                }
            }
            else
            {
                using (RowTreeSearchPath searchPath = new RowTreeSearchPath())
                {
                    int  entryNumber;
                    bool result = _table.ClusteredIndex.FindKey(_manager, _table.ClusteredIndex.KeyRowType, _indexNode.DataNode.Rows[_entryNumber], searchPath, out entryNumber);
                    if (result)
                    {
                        Row localRow = new Row(_manager, _table.ClusteredIndex.KeyRowType, searchPath.DataNode.Node.Keys[entryNumber]);
                        try
                        {
                            localRow.CopyTo(row);
                        }
                        finally
                        {
                            localRow.Dispose();
                        }

                        localRow = new Row(_manager, _table.ClusteredIndex.DataRowType, searchPath.DataNode.DataNode.Rows[entryNumber]);
                        try
                        {
                            localRow.CopyTo(row);
                        }
                        finally
                        {
                            localRow.Dispose();
                        }
                    }
                    else
                    {
                        throw new ScanException(ScanException.Codes.ClusteredRowNotFound);
                    }
                }
            }
        }