public string ObjectsReport() { Hashtable usedNodes = new Hashtable(); // Collect used nodes AddUsedNodesRecursive(LastSnapshotId(), usedNodes); StringBuilder sb = new StringBuilder(); foreach (Guid nodeId in usedNodes.Keys) { // We found a node which is not used and should be collected var node = provider.GetNode(nodeId, NodeAccess.Read); string line = nodeId.ToString() + "\t" + node.NodeType.ToString() + "\t"; var typeData = new EdgeData(EdgeType.OfType, null); if (node.Edges.ContainsKey(typeData)) { var typeEdge = node.FindEdge(typeData); if (typeEdge != null) { line += typesService.GetTypeFromIdCached(typeEdge.ToNodeId).Name + "\t"; } } sb.AppendLine(line); } return(sb.ToString()); }
/// <summary> /// Gets next leaf in tree compared to given sample data /// </summary> /// <param name="nodes">Node provider</param> /// <param name="rootNodeId">Root node id</param> /// <param name="sampleData">Sample data in the current leaf</param> /// <returns>Leaf node next in comparison to sample data, or null if no more leaves are found</returns> private static Node <Guid, object, EdgeData> NextLeaf(INodeProvider <Guid, object, EdgeData> nodes, Guid rootNodeId, EdgeData sampleData) { var node = nodes.GetNode(rootNodeId, NodeAccess.Read); Guid id = rootNodeId; Guid nextInternalParentId = Guid.Empty; while (node.Data.Equals(InternalNodeData)) { var leadingEdgeIndex = FindLeadingEdgeIndex(sampleData, node); if (leadingEdgeIndex < node.Edges.Count - 1) { nextInternalParentId = node.Edges[node.Edges.Keys[leadingEdgeIndex + 1]].ToNodeId; } // Advance to next internal node node = nodes.GetNode(node.Edges[node.Edges.Keys[leadingEdgeIndex]].ToNodeId, NodeAccess.Read); } if (nextInternalParentId.Equals(Guid.Empty)) { return(null); } else { return(LeftLeaf(nodes, nodes.GetNode(nextInternalParentId, NodeAccess.Read))); } }
void CachedWriteNodeProvider_OnBeforeKeysEvicted(object sender, KeysEvictedEventArgs <TIdentifier> e) { // Move data to parent provider foreach (var key in e.Keys) { var node = cacheProvider.GetNode(key, NodeAccess.Read); parentProvider.SetNode(key, node); cacheProvider.Remove(key); } }
/// <summary> /// Returns the Id of the type that represents the root of the database (the representation of the Data Model) /// </summary> /// <returns></returns> public Guid GetRootTypeId() { var snapshotRootNode = provider.GetNode(Constants.SnapshotsNodeId, NodeAccess.Read); var snapshotNode = provider.GetNode(snapshotRootNode.Edges.Values[0].ToNodeId, NodeAccess.Read); var objectNode = provider.GetNode(snapshotNode.Edges.Values[0].ToNodeId, NodeAccess.Read); foreach (var edge in objectNode.Edges.Values) { if (edge.Data.Semantic.Equals(EdgeType.OfType)) { return(edge.ToNodeId); } } return(Guid.Empty); }
internal bool ContainsScalar(Guid instanceId, object value) { using (var enumerator = GetEnumerator(instanceId)) { while (enumerator.MoveNext()) { var node = provider.GetNode(enumerator.Current.ToNodeId, NodeAccess.Read); if (node.Data.Equals(value)) { return(true); } } return(false); } }
/// <summary> /// Gets node from collection by an identifier. First attempt to read from cache. /// </summary> /// <param name="nodeId">Node identifier</param> /// <returns>Node object</returns> public Node <TIdentifier, TNodeData, TEdgeData> GetNode(TIdentifier identifier, NodeAccess access) { rwLock.AcquireReaderLock(-1); try { // Read from cache var node = cacheProvider.GetNode(identifier, access); if (node != null) { return(node); } else { // Read from parent node = parentProvider.GetNode(identifier, access); cacheProvider.SetNode(identifier, node); return(node); } } finally { rwLock.ReleaseLock(); } }
/// <summary> /// Looks for leaf tree node which is supposed to have an edge with given hash /// </summary> /// <param name="nodes">Node provider</param> /// <param name="rootNodeId">Root node ID to start the search from</param> /// <param name="edgeHash">Hash to find</param> /// <returns>Leaf node which is supposed to contain the edge</returns> private static FindResult FindLeafNode(INodeProvider <Guid, object, EdgeData> nodes, Guid rootNodeId, EdgeData data) { var node = nodes.GetNode(rootNodeId, NodeAccess.Read); Guid id = rootNodeId; while (node.Data.Equals(InternalNodeData)) { var leadingEdge = FindLeadingEdge(data, node); // Advance to next internal node node = nodes.GetNode(leadingEdge.ToNodeId, NodeAccess.Read); id = leadingEdge.ToNodeId; } return(new FindResult(id, node)); }
private void GetCollectedNodesRecursive(Guid nodeId, AppendableChangeSet <Guid, object, EdgeData> changeSet, IParentMapProvider <Guid, object, EdgeData> mutableParentMap, IParentMapProvider <Guid, object, EdgeData> immutableParentMap, Hashtable collectedNodes, Hashtable visitedNodes) { if (visitedNodes.ContainsKey(nodeId)) { return; } visitedNodes.Add(nodeId, null); if (changeSet.ReusedNodes.ContainsKey(nodeId)) { // Reused nodes and their children are not to be collected return; } if (HasReusedParent(nodeId, changeSet, mutableParentMap, immutableParentMap, collectedNodes, new Hashtable())) { return; } collectedNodes.Add(nodeId, null); var node = dataNodes.GetNode(nodeId, NodeAccess.Read); foreach (var edge in node.Edges.Values) { if (edge.Data.Semantic != EdgeType.OfType && edge.ToNodeId != Constants.NullReferenceNodeId) { GetCollectedNodesRecursive(edge.ToNodeId, changeSet, mutableParentMap, immutableParentMap, collectedNodes, visitedNodes); } } }
/// <summary> /// Runs a recursive pass and prints tree nodes /// </summary> /// <param name="nodes">Node provider which contains tree nodes</param> /// <param name="nodeId">Node to print</param> /// <param name="sb">String builder which contains the string</param> /// <param name="level">Current indentation level</param> private static void PrintTreeRecursive(INodeProvider <Guid, object, EdgeData> nodes, Guid nodeId, StringBuilder sb, int level) { var node = nodes.GetNode(nodeId, NodeAccess.Read); AppendTabs(sb, level); if (node.Data.Equals(InternalNodeData)) { sb.AppendFormat("Internal\n"); foreach (var edge in node.Edges.Values) { AppendTabs(sb, level); sb.AppendFormat("MAX[{0}]\n", edge.Data.Equals(EdgeData.MaxValue) ? "*" : edge.Data.Data.ToString()); PrintTreeRecursive(nodes, edge.ToNodeId, sb, level + 1); } } else { sb.AppendFormat("Leaf\n"); foreach (var edge in node.Edges.Values) { AppendTabs(sb, level); sb.AppendFormat("TO[{0}]\n", edge.ToNodeId.ToString()); } } }
/// <summary> /// Creates clone of existing tree under different ID /// </summary> /// <param name="nodes">Node provider which stores the nodes</param> /// <param name="sourceId">ID of source tree root</param> /// <param name="destinationId">ID of destination tree root</param> public static void Clone(INodeProvider <Guid, object, EdgeData> nodes, Guid sourceId, Guid destinationId) { var node = nodes.GetNode(sourceId, NodeAccess.Read); if (node.Data.Equals(InternalNodeData)) { Node <Guid, object, EdgeData> newNode = new Node <Guid, object, EdgeData>(node.NodeType, node.Data); foreach (var edge in node.Edges.Values) { Guid subId = Guid.NewGuid(); Clone(nodes, edge.ToNodeId, subId); newNode.AddEdge(new Edge <Guid, EdgeData>(subId, edge.Data)); } nodes.SetNode(destinationId, newNode); } else if (node.Data.Equals(LeafNodeData)) { Node <Guid, object, EdgeData> newNode = new Node <Guid, object, EdgeData>(node.NodeType, node.Data, node.Edges); nodes.SetNode(destinationId, newNode); } else { throw new InvalidOperationException(); } }
/// <summary> /// Returns number of edges in the tree /// </summary> /// <param name="nodes">Node provider which hosts the nodes</param> /// <param name="rootNodeId">Tree root node ID</param> /// <param name="data">Edge to find</param> /// <returns></returns> public static int Count(INodeProvider <Guid, object, EdgeData> nodes, Guid rootNodeId, EdgeType data) { var node = nodes.GetNode(rootNodeId, NodeAccess.Read); if (node.Data.Equals(LeafNodeData)) { int sum = 0; foreach (var edge in node.Edges.Values) { if (edge.Data.Semantic.Equals(data)) { sum++; } } return(sum); } else { int sum = 0; foreach (var edge in node.Edges.Values) { sum += Count(nodes, edge.ToNodeId, data); } return(sum); } }
/// <summary> /// Adds new edge to the tree. /// </summary> /// <param name="nodes">Node provider which hosts the nodes</param> /// <param name="rootNodeId">Tree root node ID</param> /// <param name="edge">Edge to add</param> public static void InsertEdge(INodeProvider <Guid, object, EdgeData> nodes, Guid rootNodeId, Edge <Guid, EdgeData> edge, int treeOrder) { if (treeOrder < 6) { throw new ArgumentException(); } var result = FindLeafNode(nodes, rootNodeId, edge.Data); if (result.Node.Edges.Count == treeOrder) { SplitTree(nodes, rootNodeId, true, edge.Data, treeOrder); result = FindLeafNode(nodes, rootNodeId, edge.Data); } if (!result.Node.Data.Equals(LeafNodeData)) { throw new InvalidOperationException("Leaf node expected"); } var node = nodes.GetNode(result.NodeId, NodeAccess.ReadWrite); node.AddEdge(edge); nodes.SetNode(result.NodeId, node); }
/// <summary> /// Creates new instance of BPlusTreeEnumerator type /// </summary> /// <param name="nodes">Node provider which contains tree nodes</param> /// <param name="rootNodeId">Root item ID</param> /// <param name="edgeType">Edge type to use as a filter for enumeration</param> public BPlusTreeEnumerator(INodeProvider <Guid, object, EdgeData> nodes, Guid rootNodeId, EdgeType edgeType) { this.nodes = nodes; this.rootNodeId = rootNodeId; this.edgeType = edgeType; var currentLeaf = BPlusTreeOperations.LeftLeaf(nodes, nodes.GetNode(rootNodeId, NodeAccess.Read)); this.currentLeafEnumerator = currentLeaf.Edges.Values.GetEnumerator(); }
/// <summary> /// Gets leftmost edge in the given subtree /// </summary> /// <param name="nodes"></param> /// <param name="node"></param> /// <returns></returns> private static Edge <Guid, EdgeData> LeftEdge(INodeProvider <Guid, object, EdgeData> nodes, Node <Guid, object, EdgeData> node) { if (node.Data.Equals(LeafNodeData)) { return(node.Edges[node.Edges.Keys[0]]); } else { return(LeftEdge(nodes, nodes.GetNode(node.Edges[node.Edges.Keys[0]].ToNodeId, NodeAccess.Read))); } }
/// <summary> /// Resets the enumerator /// </summary> public void Reset() { if (currentLeafEnumerator != null) { currentLeafEnumerator.Dispose(); } var currentLeaf = BPlusTreeOperations.LeftLeaf(nodes, nodes.GetNode(rootNodeId, NodeAccess.Read)); this.currentLeafEnumerator = currentLeaf.Edges.Values.GetEnumerator(); }
/// <summary> /// Gets node from collection by an identifier /// </summary> /// <param name="nodeId">Node identifier</param> /// <returns>Node object</returns> public Node <Guid, object, EdgeData> GetNode(Guid nodeId, NodeAccess access) { CheckThread(); if (access == NodeAccess.ReadWrite) { EnsureNode(nodeId); return(isolatedProvider.GetNode(nodeId, access)); } else { if (isolatedProvider.Contains(nodeId)) { return(isolatedProvider.GetNode(nodeId, access)); } else { return(parentProvider.GetNode(nodeId, access)); } } }
/// <summary> /// Gets node from collection by an identifier. First attempt to read from cache. /// </summary> /// <param name="nodeId">Node identifier</param> /// <returns>Node object</returns> public Node <TIdentifier, TNodeData, TEdgeData> GetNode(TIdentifier identifier, NodeAccess access) { if (cacheProvider.Contains(identifier)) { return(cacheProvider.GetNode(identifier, access)); } // Read from parent -> move to cache Node <TIdentifier, TNodeData, TEdgeData> node = parentProvider.GetNode(identifier, access); parentProvider.Remove(identifier); cacheProvider.SetNode(identifier, node); return(node); }
private void DeleteTree(Guid nodeId) { var node = nodes.GetNode(nodeId, NodeAccess.Read); if (node.Data.Equals(BPlusTreeOperations.InternalNodeData)) { foreach (var edge in node.Edges) { DeleteTree(edge.Value.ToNodeId); } } nodes.Remove(nodeId); }
private static RemovalResult RemoveEdgeRecursive(INodeProvider <Guid, object, EdgeData> nodes, Guid nodeId, EdgeData data, int treeOrder) { var node = nodes.GetNode(nodeId, NodeAccess.ReadWrite); try { if (node.Data.Equals(LeafNodeData)) { var removeResult = node.Edges.Remove(data); return(new RemovalResult(node.Edges.Count, removeResult, false)); } else { var edgeIndex = FindLeadingEdgeIndex(data, node); var edge = node.Edges[node.Edges.Keys[edgeIndex]]; var res = RemoveEdgeRecursive(nodes, edge.ToNodeId, data, treeOrder); if (!res.WasRemoved) { return(res); } if (res.RemainingCount < treeOrder / 2) { #region Reorganize sub nodes // Take data from a sibling if (edgeIndex < node.Edges.Count - 1) { return(MergeNodes(nodes, node, edgeIndex, edgeIndex + 1, treeOrder)); } else { return(MergeNodes(nodes, node, edgeIndex - 1, edgeIndex, treeOrder)); } #endregion } else { return(res); } } } finally { nodes.SetNode(nodeId, node); } }
internal bool TryGetScalar(Guid instanceId, object key, out object value) { Edge <Guid, EdgeData> edge = null; if (BPlusTreeOperations.TryFindEdge(provider, instanceId, new EdgeData(EdgeType.ListItem, key), out edge)) { value = provider.GetNode(edge.ToNodeId, NodeAccess.Read).Data; return(true); } else { value = null; return(false); } }
/// <summary> /// Gets the rightmost edge in given subtree /// </summary> /// <param name="nodes"></param> /// <param name="node"></param> /// <returns></returns> public static Edge <Guid, EdgeData> RightEdge(INodeProvider <Guid, object, EdgeData> nodes, Node <Guid, object, EdgeData> node) { if (node.Data.Equals(LeafNodeData)) { if (node.Edges.Count > 0) { return(node.Edges[node.Edges.Keys[node.Edges.Count - 1]]); } else { return(null); } } else { return(RightEdge(nodes, nodes.GetNode(node.Edges[node.Edges.Keys[node.Edges.Count - 1]].ToNodeId, NodeAccess.Read))); } }
internal static void LogNodesRecursive(Guid nodeId, INodeProvider <Guid, object, EdgeData> nodes, INodeProvider <Guid, object, EdgeData> changes, int tabLevel, Hashtable visited, TypesService typesService) { if (visited.ContainsKey(nodeId)) { Debug.WriteLine(LogTabs(tabLevel) + nodeId); return; } visited.Add(nodeId, null); if (changes.Contains(nodeId)) { var node = changes.GetNode(nodeId, NodeAccess.Read); switch (node.NodeType) { case NodeType.Object: LogObject(nodeId, node, nodes, changes, tabLevel, visited, typesService); break; case NodeType.Collection: LogCollection(nodeId, node, nodes, changes, tabLevel, visited, typesService); break; case NodeType.Dictionary: LogCollection(nodeId, node, nodes, changes, tabLevel, visited, typesService); break; default: Debug.WriteLine(LogTabs(tabLevel) + node.Previous + "->" + nodeId + "[" + node.NodeType + "]"); foreach (var edge in node.Edges) { Debug.WriteLine(LogTabs(tabLevel) + edge.Key + "="); LogNodesRecursive(edge.Value.ToNodeId, nodes, changes, tabLevel + 1, visited, typesService); } break; } } else { Debug.WriteLine(LogTabs(tabLevel) + nodeId); } }
public ICollection <object> ParentNodes(object instance) { var id = Utils.GetItemId(instance); ICollection <object> result = new Collection <object>(); var node = nodeProvider.GetNode(id, NodeAccess.Read); if (node != null) { foreach (var parentNode in node.ParentNodes) { object proxy = null; if (!immutableProxyMap.TryGetProxy(parentNode, out proxy)) { proxy = proxyCreatorService.NewObject(runtimeProxyFacade, typesService.GetInstanceTypeId(parentNode), parentNode, true); immutableProxyMap.AddProxy(parentNode, proxy); } result.Add(proxy); } } return(result); }
private void AddNodesRecursive(Guid nodeId, INodeProvider <Guid, object, EdgeData> source, INodeProvider <Guid, object, EdgeData> destination, Hashtable visitedNodes) { if (visitedNodes.ContainsKey(nodeId)) { return; } visitedNodes.Add(nodeId, null); var node = source.GetNode(nodeId, NodeAccess.Read); var newNode = new Node <Guid, object, EdgeData>(node.NodeType, node.Data, node.Edges, node.Values); destination.SetNode(nodeId, newNode); foreach (var edge in node.Edges.Values) { if (edge.ToNodeId != Constants.NullReferenceNodeId) { AddNodesRecursive(edge.ToNodeId, source, destination, visitedNodes); } } }
/// <summary> /// Makes room in the tree for new data /// </summary> /// <param name="nodes">Node provider which contains tree nodes</param> /// <param name="nodeId">Current node ID</param> /// <param name="isRoot">Determines if current node is root node</param> /// <param name="data">Data to make room for</param> /// <returns>Result of the operation</returns> private static SplitResult SplitTree(INodeProvider <Guid, object, EdgeData> nodes, Guid nodeId, bool isRoot, EdgeData data, int treeOrder) { var currentNode = nodes.GetNode(nodeId, NodeAccess.ReadWrite); if (isRoot) { if (currentNode.Data.Equals(InternalNodeData)) { #region Is root internal ? var leadingEdge = FindLeadingEdge(data, currentNode); var result = SplitTree(nodes, leadingEdge.ToNodeId, false, data, treeOrder); if (result != null) { currentNode.AddEdge(new Edge <Guid, EdgeData>(result.CreatedNodeId, result.RightKey)); if (currentNode.Edges.Count == (treeOrder + 1)) { // Split root to 2 internal nodes Guid leftNodeId = Guid.NewGuid(); Guid rightNodeId = Guid.NewGuid(); Node <Guid, object, EdgeData> leftNode = new Node <Guid, object, EdgeData>(NodeType.TreeInternal, InternalNodeData); Node <Guid, object, EdgeData> rightNode = new Node <Guid, object, EdgeData>(NodeType.TreeInternal, InternalNodeData); var keys = currentNode.Edges.Keys; for (int i = 0; i < keys.Count; i++) { if (i < keys.Count / 2) { leftNode.AddEdge(currentNode.Edges[keys[i]]); } else { rightNode.AddEdge(currentNode.Edges[keys[i]]); } } //Set last edges SetLastInternalKey(leftNode); SetLastInternalKey(rightNode); currentNode.Edges.Clear(); currentNode.AddEdge(new Edge <Guid, EdgeData>(leftNodeId, LeftEdge(nodes, rightNode).Data)); currentNode.AddEdge(new Edge <Guid, EdgeData>(rightNodeId, EdgeData.MaxValue)); nodes.SetNode(leftNodeId, leftNode); nodes.SetNode(rightNodeId, rightNode); } nodes.SetNode(nodeId, currentNode); } else { return(null); } #endregion } else { #region Root is a leaf if (currentNode.Edges.Count == treeOrder) { // Split root to internal nodes Guid leftNodeId = Guid.NewGuid(); Guid rightNodeId = Guid.NewGuid(); Node <Guid, object, EdgeData> leftNode = new Node <Guid, object, EdgeData>(NodeType.TreeLeaf, LeafNodeData); Node <Guid, object, EdgeData> rightNode = new Node <Guid, object, EdgeData>(NodeType.TreeLeaf, LeafNodeData); var keys = currentNode.Edges.Keys; for (int i = 0; i < keys.Count; i++) { if (i < keys.Count / 2) { leftNode.AddEdge(currentNode.Edges[keys[i]]); } else { rightNode.AddEdge(currentNode.Edges[keys[i]]); } } currentNode.Edges.Clear(); currentNode.AddEdge(new Edge <Guid, EdgeData>(leftNodeId, LeftEdge(nodes, rightNode).Data)); currentNode.AddEdge(new Edge <Guid, EdgeData>(rightNodeId, EdgeData.MaxValue)); currentNode.SetData(InternalNodeData); nodes.SetNode(leftNodeId, leftNode); nodes.SetNode(rightNodeId, rightNode); nodes.SetNode(nodeId, currentNode); } #endregion } return(null); } else { if (currentNode.Data.Equals(InternalNodeData)) { var leadingEdge = FindLeadingEdge(data, currentNode); var result = SplitTree(nodes, leadingEdge.ToNodeId, false, data, treeOrder); if (result != null) { currentNode.AddEdge(new Edge <Guid, EdgeData>(result.CreatedNodeId, result.RightKey)); if (currentNode.Edges.Count == treeOrder) { Guid newInternalId = Guid.NewGuid(); Node <Guid, object, EdgeData> newInternal = new Node <Guid, object, EdgeData>(NodeType.TreeInternal, InternalNodeData); var keys = currentNode.Edges.Keys; for (int i = 0; i < keys.Count / 2; i++) { newInternal.AddEdge(currentNode.Edges[keys[i]]); } int nrToRemove = keys.Count / 2; for (int i = 0; i < nrToRemove; i++) { currentNode.Edges.RemoveAt(0); } // Set last edge of left internal node to MaxInt SetLastInternalKey(newInternal); nodes.SetNode(newInternalId, newInternal); nodes.SetNode(nodeId, currentNode); return(new SplitResult(newInternalId, newInternal, LeftEdge(nodes, currentNode).Data)); } else { nodes.SetNode(nodeId, currentNode); return(null); } } else { return(null); } } else if (currentNode.Data.Equals(LeafNodeData)) { Guid newLeafId = Guid.NewGuid(); Node <Guid, object, EdgeData> newLeaf = new Node <Guid, object, EdgeData>(NodeType.TreeLeaf, LeafNodeData); var keys = currentNode.Edges.Keys; for (int i = 0; i < keys.Count / 2; i++) { newLeaf.AddEdge(currentNode.Edges[keys[i]]); } int nrToRemove = keys.Count / 2; for (int i = 0; i < nrToRemove; i++) { currentNode.Edges.RemoveAt(0); } nodes.SetNode(newLeafId, newLeaf); nodes.SetNode(nodeId, currentNode); return(new SplitResult(newLeafId, newLeaf, LeftEdge(nodes, currentNode).Data)); } else { throw new ArgumentException("Unexpected node data"); } } }
internal static void LogNodesRecursive(Guid nodeId, INodeProvider<Guid, object, EdgeData> nodes, INodeProvider<Guid, object, EdgeData> changes, int tabLevel, Hashtable visited, TypesService typesService) { if (visited.ContainsKey(nodeId)) { Debug.WriteLine(LogTabs(tabLevel) + nodeId); return; } visited.Add(nodeId, null); if (changes.Contains(nodeId)) { var node = changes.GetNode(nodeId, NodeAccess.Read); switch (node.NodeType) { case NodeType.Object: LogObject(nodeId, node, nodes, changes, tabLevel, visited, typesService); break; case NodeType.Collection: LogCollection(nodeId, node, nodes, changes, tabLevel, visited, typesService); break; case NodeType.Dictionary: LogCollection(nodeId, node, nodes, changes, tabLevel, visited, typesService); break; default: Debug.WriteLine(LogTabs(tabLevel) + node.Previous + "->" + nodeId + "[" + node.NodeType + "]"); foreach (var edge in node.Edges) { Debug.WriteLine(LogTabs(tabLevel) + edge.Key + "="); LogNodesRecursive(edge.Value.ToNodeId, nodes, changes, tabLevel + 1, visited, typesService); } break; } } else { Debug.WriteLine(LogTabs(tabLevel) + nodeId); } }
private void AddNodesRecursive(Guid nodeId, INodeProvider<Guid, object, EdgeData> source, INodeProvider<Guid, object, EdgeData> destination, Hashtable visitedNodes) { if (visitedNodes.ContainsKey(nodeId)) { return; } visitedNodes.Add(nodeId, null); var node = source.GetNode(nodeId, NodeAccess.Read); var newNode = new Node<Guid, object, EdgeData>(node.NodeType, node.Data, node.Edges, node.Values); destination.SetNode(nodeId, newNode); foreach (var edge in node.Edges.Values) { if (edge.ToNodeId != Constants.NullReferenceNodeId) { AddNodesRecursive(edge.ToNodeId, source, destination, visitedNodes); } } }
public Guid GetRootObjectId(Guid snapshotId) { var node = archiveProvider.GetNode(Constants.SnapshotsNodeId, NodeAccess.Read); return(node.FindEdge(new EdgeData(EdgeType.Contains, null)).ToNodeId); }
/// <summary> /// Defines new type, it shall add used sub-types, such as member types /// </summary> /// <param name="t">Type to add</param> /// <returns>Type Id</returns> public Guid AddType(Type t) { ValidateType(t); // Try finding the type first Guid typeId = GetTypeId(t); // Type not found? if (typeId == Guid.Empty) { // Assign new ID typeId = Guid.NewGuid(); // Create new node var node = new Node<Guid, object, EdgeData>(NodeType.Type, GetTypeName(t)); // Types "group" node ---> The type var typesNode = provider.GetNode(Constants.TypesNodeId, NodeAccess.ReadWrite); typesNode.AddEdge(new Edge<Guid, EdgeData>(typeId, new EdgeData(EdgeType.Contains, typeId))); provider.SetNode(Constants.TypesNodeId, typesNode); // Add node to collection provider.SetNode(typeId, node); if (t.IsInterface) { // Extract properties var properties = new Collection<PropertyInfo>(); Utils.ExtractProperties(t, properties); // Property member types are also added foreach (PropertyInfo p in properties) { bool isPermanent = p.GetCustomAttributes(typeof(ImmutableAttribute), false).Length == 1; bool isPrimaryKey = p.GetCustomAttributes(typeof(PrimaryKeyAttribute), false).Length == 1; bool saveParentNodes = p.GetCustomAttributes(typeof(StoreParentNodesAttribute), false).Length == 1; // Add the type AddType(p.PropertyType); // Add the member to type Guid memberId = AddTypeMember(p.Name, p.PropertyType, isPrimaryKey); //Add edge to the member node.AddEdge(new Edge<Guid, EdgeData>(memberId, new EdgeData(EdgeType.Property, CalculateEdgeFlags(isPermanent, saveParentNodes), memberId))); } Type collectionType=null; Type dictionaryType= null; // Find all base interfaces and add them too, but not for collections/dictionary if (!Utils.IsCollectionType(t, ref collectionType) && !Utils.IsDictionaryType(t, ref dictionaryType)) { foreach (var baseType in t.GetInterfaces()) { var id = AddType(baseType); node.AddEdge(new Edge<Guid, EdgeData>(id, new EdgeData(EdgeType.OfType, id))); } provider.SetNode(typeId, node); } else { foreach (var baseType in t.GetGenericArguments()) { AddType(baseType); } } } // For types with constant list of values, add the values var values = GetConstantValues(t); if (values.Count > 0) { foreach (var value in values) { Guid valueId = Guid.NewGuid(); var valueNode = new Node<Guid, object, EdgeData>(NodeType.Scalar, value.ToString()); provider.SetNode(valueId, valueNode); node.AddEdge(new Edge<Guid, EdgeData>(valueId, new EdgeData(EdgeType.Contains, value.ToString()))); } } // Add node to collection provider.SetNode(typeId, node); } return typeId; }
/// <summary> /// Returns root object id for given snapshot /// </summary> /// <param name="snapshotId">Snapshot ID</param> /// <returns>Root object ID</returns> public Guid GetRootObjectId(Guid snapshotId) { return(provider.GetNode(snapshotId, NodeAccess.Read).FindEdge(new EdgeData(EdgeType.RootObject, null)).ToNodeId); }
/// <summary> /// Updates parent information based on change set /// </summary> /// <param name="changeSet">Data change description</param> public void UpdateParents(AppendableChangeSet <Guid, object, EdgeData> changeSet, ICollectedNodesProvider <Guid, object, EdgeData> collectedNodesProvider) { lock (dataSync) { if (changeSet.SourceSnapshotId != lastSnapshotId) { // If the last snapshot is not in the memory, clear and return nodes.Clear(); createdNodes = false; return; } using (var enumerator = collectedNodesProvider.GetEdges(changeSet.SourceSnapshotId)) { if (enumerator != null) { while (enumerator.MoveNext()) { if (nodes.Contains(enumerator.Current.ToNodeId)) { DeleteTree(enumerator.Current.ToNodeId); } // Get the old node var node = dataNodeProvider.GetNode(enumerator.Current.ToNodeId, NodeAccess.Read); // For every edge in old node foreach (var edge in node.Edges.Values) { if (EdgeFilter(edge)) { // Find holder in destination snapshot for referenced node if (nodes.Contains(edge.ToNodeId)) { BPlusTreeOperations.RemoveEdge(nodes, edge.ToNodeId, new EdgeData(EdgeType.Contains, enumerator.Current.ToNodeId), ParentsTreeOrder); } } } } } } // Add new node ids to map foreach (Guid nodeId in changeSet.Nodes.EnumerateNodes()) { var holderNode = BPlusTreeOperations.CreateRootNode(NodeType.Collection, nodeId); nodes.SetNode(nodeId, holderNode); } // Add reused nodes if needed foreach (Guid nodeId in changeSet.ReusedNodes.Keys) { if (!nodes.Contains(nodeId)) { var holderNode = BPlusTreeOperations.CreateRootNode(NodeType.Collection, nodeId); nodes.SetNode(nodeId, holderNode); } } // Add new node edges to map foreach (Guid nodeId in changeSet.Nodes.EnumerateNodes()) { var node = changeSet.Nodes.GetNode(nodeId, NodeAccess.Read); // Add this id into all referenced nodes foreach (var edge in node.Edges.Values) { if (EdgeFilter(edge)) { var edgeData = new EdgeData(EdgeType.Contains, nodeId); Edge <Guid, EdgeData> existingEdge = null; if (!BPlusTreeOperations.TryFindEdge(nodes, edge.ToNodeId, edgeData, out existingEdge)) { BPlusTreeOperations.InsertEdge(nodes, edge.ToNodeId, new Edge <Guid, EdgeData>(nodeId, edgeData), ParentsTreeOrder); } } } } // Set last snapshot as the destination ID lastSnapshotId = changeSet.DestinationSnapshotId; } }
private static RemovalResult MergeNodes(INodeProvider <Guid, object, EdgeData> nodes, Node <Guid, object, EdgeData> node, int leftIndex, int rightIndex, int treeOrder) { var leftKey = node.Edges.Keys[leftIndex]; var leftNodeId = node.Edges[leftKey].ToNodeId; var leftNode = nodes.GetNode(leftNodeId, NodeAccess.ReadWrite); var rightKey = node.Edges.Keys[rightIndex]; var rightNodeId = node.Edges[rightKey].ToNodeId; var rightNode = nodes.GetNode(rightNodeId, NodeAccess.ReadWrite); if (!leftNode.Data.Equals(rightNode.Data)) { throw new InvalidOperationException("Both nodes must be of same type"); } if (leftNode.Data.Equals(InternalNodeData)) { var maxEdgeKey = leftNode.Edges.Keys[leftNode.Edges.Count - 1]; var maxEdge = leftNode.Edges[maxEdgeKey]; leftNode.Edges.Remove(maxEdgeKey); leftNode.AddEdge(new Edge <Guid, EdgeData>(maxEdge.ToNodeId, LeftEdge(nodes, rightNode).Data)); } if ((leftNode.Edges.Count + rightNode.Edges.Count) <= treeOrder) { // Take all from left node for (int i = 0; i < leftNode.Edges.Count; i++) { EdgeData removalKey = leftNode.Edges.Keys[i]; rightNode.AddEdge(leftNode.Edges[removalKey]); } nodes.SetNode(rightNodeId, rightNode); nodes.Remove(leftNodeId); node.Edges.Remove(leftKey); if (node.Edges.Count == 1) { // When no more nodes remaining copy from child node.SetData(rightNode.Data); node.Edges.Clear(); foreach (var childEdge in rightNode.Edges.Values) { node.AddEdge(childEdge); } nodes.Remove(rightNodeId); } return(new RemovalResult(node.Edges.Count, true, true)); } else { // Decide how many edges to take from right node int numberToTake = (leftNode.Edges.Count + rightNode.Edges.Count) / 2 - leftNode.Edges.Count; // Copy or merge? if (numberToTake > 0) { // Copy edges from right -> left for (int i = 0; i < numberToTake; i++) { EdgeData removalKey = rightNode.Edges.Keys[0]; leftNode.AddEdge(rightNode.Edges[removalKey]); rightNode.Edges.Remove(removalKey); } node.Edges.Remove(leftKey); node.AddEdge(new Edge <Guid, EdgeData>(leftNodeId, LeftEdge(nodes, rightNode).Data)); nodes.SetNode(leftNodeId, leftNode); nodes.SetNode(rightNodeId, rightNode); // No edges were removed return(new RemovalResult(node.Edges.Count, true, true)); } else if (numberToTake < 0) { // Copy edges from left -> right for (int i = 0; i < Math.Abs(numberToTake); i++) { EdgeData removalKey = leftNode.Edges.Keys[leftNode.Edges.Count - 1]; rightNode.AddEdge(leftNode.Edges[removalKey]); leftNode.Edges.Remove(removalKey); } node.Edges.Remove(leftKey); node.AddEdge(new Edge <Guid, EdgeData>(leftNodeId, LeftEdge(nodes, rightNode).Data)); nodes.SetNode(leftNodeId, leftNode); nodes.SetNode(rightNodeId, rightNode); // No edges were removed return(new RemovalResult(node.Edges.Count, true, true)); } throw new ArgumentException("Nothing to copy"); } }