public Row RequestRow(IServerProcess AProcess, Schema.IRowType ARowType, NativeRow ARow) { Row LRow = GetRow(); LRow.Open(AProcess, ARowType, ARow); return(LRow); }
/// <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)); } }
internal IValueManager _manager; // Only used during the Add and Remove calls public bool CompareEqual(IValueManager manager, NativeRow indexKey, NativeRow compareKey) { // If AIndexKeyRowType is null, the index key must have the structure of an index key, // Otherwise, the IndexKey row could be a subset of the actual index key. // In that case, AIndexKeyRowType is the RowType for the IndexKey row. // It is the caller's responsibility to ensure that the passed IndexKey RowType // is a subset of the actual IndexKey with order intact. //Row LIndexKey = new Row(AManager, AIndexKeyRowType, AIndexKey); // If ACompareContext is null, the compare key must have the structure of an index key, // Otherwise the CompareKey could be a subset of the actual index key. // In that case, ACompareContext is the RowType for the CompareKey row. // It is the caller's responsibility to ensure that the passed CompareKey RowType // is a subset of the IndexKey with order intact. //Row LCompareKey = new Row(AManager, ACompareKeyRowType, ACompareKey); for (int index = 0; index < _keyRowType.Columns.Count; index++) { if (index >= compareKey.Values.Count()) { return(false); } if ((indexKey.Values[index] != null) && (compareKey.Values[index] != null)) { if (_keyRowType.Columns[index].DataType is Schema.ScalarType) { if (!manager.EvaluateEqualitySort(GetEqualitySort(Key.Columns[index].Name), indexKey.Values[index], compareKey.Values[index])) { return(false); } } else { using (var indexValue = DataValue.FromNative(manager, indexKey.DataTypes[index], indexKey.Values[index])) { using (var compareValue = DataValue.FromNative(manager, compareKey.DataTypes[index], compareKey.Values[index])) { if (!manager.EvaluateEqualitySort(GetEqualitySort(Key.Columns[index].Name), indexValue, compareValue)) { return(false); } } } } } else if (indexKey.Values[index] != null) { return(false); } else if (compareKey.Values[index] != null) { return(false); } } return(true); }
public Row(IValueManager manager, Schema.IRowType dataType) : base(manager, dataType) { _row = new NativeRow(DataType.Columns.Count); #if USEDATATYPESINNATIVEROW for (int index = 0; index < DataType.Columns.Count; index++) { _row.DataTypes[index] = DataType.Columns[index].DataType; } #endif ValuesOwned = true; }
private void InternalAdd(IValueManager manager, NativeRow key, NativeRow data) { _manager = manager; try { _rows.Add(key, data); } finally { _manager = null; } }
private void InternalRemove(IValueManager manager, NativeRow key) { _manager = manager; try { _rows.Remove(key); } finally { _manager = null; } }
public void Insert(NativeRow key, NativeRow row, int entryNumber) { // Slide all entries above the insert index Array.Copy(_keys, entryNumber, _keys, entryNumber + 1, _entryCount - entryNumber); Array.Copy(_rows, entryNumber, _rows, entryNumber + 1, _entryCount - entryNumber); // Set the new entry data _keys[entryNumber] = key; _rows[entryNumber] = row; // Increment entry count _entryCount++; }
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 NativeRow InternalGet(IValueManager manager, NativeRow key) { _manager = manager; try { NativeRow result; _rows.TryGetValue(key, out result); return(result); } finally { _manager = null; } }
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(); } }
// 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); } }
/// <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); } }
public override void Update(IValueManager manager, NativeRow oldKey, NativeRow newKey, NativeRow newData) { var oldData = InternalGet(manager, oldKey); if (newData != null) { DisposeData(manager, oldData); } else { newData = oldData; } DisposeKey(manager, oldKey); InternalRemove(manager, oldKey); InternalAdd(manager, newKey, newData); }
public override object CopyNativeAs(Schema.IDataType dataType) { if (_row == null) { return(null); } if (Object.ReferenceEquals(DataType, dataType)) { NativeRow newRow = new NativeRow(DataType.Columns.Count); if (_row != null) { for (int index = 0; index < DataType.Columns.Count; index++) { #if USEDATATYPESINNATIVEROW newRow.DataTypes[index] = _row.DataTypes[index]; newRow.Values[index] = CopyNative(Manager, _row.DataTypes[index], _row.Values[index]); #else newRow.Values[index] = CopyNative(Manager, DataType.Columns[index].DataType, FRow.Values[index]); #endif } } return(newRow); } else { NativeRow newRow = new NativeRow(DataType.Columns.Count); Schema.IRowType newRowType = (Schema.IRowType)dataType; if (_row != null) { for (int index = 0; index < DataType.Columns.Count; index++) { int newIndex = newRowType.Columns.IndexOfName(DataType.Columns[index].Name); #if USEDATATYPESINNATIVEROW newRow.DataTypes[newIndex] = _row.DataTypes[index]; newRow.Values[newIndex] = CopyNative(Manager, _row.DataTypes[index], _row.Values[index]); #else newRow.Values[newIndex] = CopyNative(Manager, DataType.Columns[index].DataType, FRow.Values[index]); #endif } } return(newRow); } }
public static void DisposeValue(IValueManager manager, object tempValue) { IDataValue localTempValue = tempValue as IDataValue; if (localTempValue != null) { localTempValue.Dispose(); return; } if (tempValue is StreamID) { manager.StreamManager.Deallocate((StreamID)tempValue); return; } NativeRow nativeRow = tempValue as NativeRow; if (nativeRow != null) { for (int index = 0; index < nativeRow.Values.Length; index++) { DisposeValue(manager, nativeRow.Values[index]); } return; } NativeList nativeList = tempValue as NativeList; if (nativeList != null) { for (int index = 0; index < nativeList.Values.Count; index++) { DisposeValue(manager, nativeList.Values[index]); } } NativeTable nativeTable = tempValue as NativeTable; if (nativeTable != null) { DisposeNative(manager, nativeTable.TableType, nativeTable); } }
/// <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); } } }
/// <summary> /// Performs a binary search among the entries in this node for the given key. Will always return an /// entry index in AEntryNumber, which is the index of the entry that was found if the method returns true, /// otherwise it is the index where the key should be inserted if the method returns false. /// </summary> public bool NodeSearch(Schema.IRowType keyRowType, NativeRow key, out int entryNumber) { int lo = (Node.NodeType == NativeRowTreeNodeType.Routing ? 1 : 0); int hi = Node.EntryCount - 1; int index = 0; int result = -1; while (lo <= hi) { index = (lo + hi) / 2; result = Tree.Compare(Manager, Tree.KeyRowType, Node.Keys[index], keyRowType, key); if (result == 0) { break; } else if (result > 0) { hi = index - 1; } else // if (LResult < 0) unnecessary { lo = index + 1; } } if (result == 0) { entryNumber = index; } else { entryNumber = lo; } return(result == 0); }
public override void Insert(IValueManager manager, NativeRow key, NativeRow data) { InternalAdd(manager, key, data); }
public NativeRowTreeRoutingNode(NativeRowTree nativeRowTree) : base(nativeRowTree) { _nodeType = NativeRowTreeNodeType.Routing; _keys = new NativeRow[_nativeRowTree.Fanout]; _nodes = new NativeRowTreeNode[_nativeRowTree.Fanout]; }
public int Compare(IValueManager manager, Schema.IRowType indexKeyRowType, NativeRow indexKey, Schema.IRowType compareKeyRowType, NativeRow compareKey) { // If AIndexKeyRowType is null, the index key must have the structure of an index key, // Otherwise, the IndexKey row could be a subset of the actual index key. // In that case, AIndexKeyRowType is the RowType for the IndexKey row. // It is the caller's responsibility to ensure that the passed IndexKey RowType // is a subset of the actual IndexKey with order intact. //Row LIndexKey = new Row(AManager, AIndexKeyRowType, AIndexKey); // If ACompareContext is null, the compare key must have the structure of an index key, // Otherwise the CompareKey could be a subset of the actual index key. // In that case, ACompareContext is the RowType for the CompareKey row. // It is the caller's responsibility to ensure that the passed CompareKey RowType // is a subset of the IndexKey with order intact. //Row LCompareKey = new Row(AManager, ACompareKeyRowType, ACompareKey); int result = 0; for (int index = 0; index < indexKeyRowType.Columns.Count; index++) { if (index >= compareKeyRowType.Columns.Count) { break; } if ((indexKey.Values[index] != null) && (compareKey.Values[index] != null)) { if (indexKeyRowType.Columns[index].DataType is Schema.ScalarType) { result = manager.EvaluateSort(Key.Columns[index], indexKey.Values[index], compareKey.Values[index]); } else { using (var indexValue = DataValue.FromNative(manager, indexKey.DataTypes[index], indexKey.Values[index])) { using (var compareValue = DataValue.FromNative(manager, compareKey.DataTypes[index], compareKey.Values[index])) { result = manager.EvaluateSort(Key.Columns[index], indexValue, compareValue); } } } } else if (indexKey.Values[index] != null) { result = Key.Columns[index].Ascending ? 1 : -1; } else if (compareKey.Values[index] != null) { result = Key.Columns[index].Ascending ? -1 : 1; } else { result = 0; } if (result != 0) { break; } } //LIndexKey.Dispose(); //LCompareKey.Dispose(); return(result); }
/// <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)); }
/// <summary>Updates the entry given by AOldKey to the stream given by ANewKey. The data for the entry is moved to the new location.</summary> public void Update(IValueManager manager, NativeRow oldKey, NativeRow newKey) { Update(manager, oldKey, newKey, null); }
public override void Delete(IValueManager manager, NativeRow key) { DisposeData(manager, InternalGet(manager, key)); DisposeKey(manager, key); InternalRemove(manager, key); }
public NativeRowTreeDataNode(NativeRowTree nativeRowTree) : base(nativeRowTree) { _nodeType = NativeRowTreeNodeType.Data; _keys = new NativeRow[_nativeRowTree.Capacity]; _rows = new NativeRow[_nativeRowTree.Capacity]; }
public bool ContainsKey(IValueManager manager, NativeRow key) { return(InternalGet(manager, key) != null); }
public void InsertRouting(NativeRow key, NativeRowTreeNode node, int entryNumber) { RoutingNode.Insert(key, node, entryNumber); Tree.RowsMoved(Node, entryNumber, Node.EntryCount - 2, Node, 1); }
/// <summary>Inserts the given Key and Data streams into this node at the given index.</summary> public void InsertData(NativeRow key, NativeRow data, int entryNumber) { DataNode.Insert(key, data, entryNumber); Tree.RowsMoved(Node, entryNumber, Node.EntryCount - 2, Node, 1); }
public RowInternedScalar(IValueManager manager, Schema.IScalarType dataType, NativeRow nativeRow, int index) : base(manager, dataType) { _nativeRow = nativeRow; _index = index; }
public void UpdateData(NativeRow data, int entryNumber) { Tree.DisposeData(Manager, DataNode.Rows[entryNumber]); DataNode.Rows[entryNumber] = data; }
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; } } }