public void TestFillRemove() { INodeProvider <Guid, object, EdgeData> nodes = new DirectNodeProviderSafe <Guid, object, EdgeData>(new MemoryStorageUnsafe <Guid, object>(), false); Guid rootId = Guid.NewGuid(); Node <Guid, object, EdgeData> node = BPlusTreeOperations.CreateRootNode(NodeType.Collection, rootId); nodes.SetNode(rootId, node); Collection <Guid> references = new Collection <Guid>(); for (int i = 0; i < 1000; i++) { references.Add(Guid.NewGuid()); } int count = 0; foreach (var reference in references) { Assert.AreEqual(count, BPlusTreeOperations.Count(nodes, rootId, EdgeType.ListItem)); BPlusTreeOperations.InsertEdge(nodes, rootId, new Edge <Guid, EdgeData>(reference, new EdgeData(EdgeType.ListItem, reference)), TreeOrder); count++; } foreach (var reference in references) { Assert.AreEqual(count, BPlusTreeOperations.Count(nodes, rootId, EdgeType.ListItem)); BPlusTreeOperations.RemoveEdge(nodes, rootId, new EdgeData(EdgeType.ListItem, reference), TreeOrder); count--; } }
/// <summary> /// Initialize global root node if not found /// </summary> private void InitializeRoot() { if (!nodes.Contains(Constants.SnapshotsNodeId)) { var node = BPlusTreeOperations.CreateRootNode(NodeType.Collection, Constants.SnapshotsNodeId); nodes.SetNode(Constants.SnapshotsNodeId, node); } }
/// <summary> /// Initializes new dictionary instance /// </summary> /// <param name="typeId">Type ID of dictionary</param> /// <returns>Instance ID</returns> public Guid NewInstance(Guid typeId) { //Determine new id Guid id = Guid.NewGuid(); // Create node as root of B+ tree var node = BPlusTreeOperations.CreateRootNode(NodeType.Dictionary, id); // Add node in provider provider.SetNode(id, node); // Add edge from node to the type of node BPlusTreeOperations.InsertEdge(provider, id, new Edge <Guid, EdgeData>(typeId, new EdgeData(EdgeType.OfType, null)), BPlusTreeOrder); // Add node in provider provider.SetNode(id, node); // Return the instance id return(id); }
/// <summary> /// Stores collectable nodes for a change set /// </summary> /// <param name="changeSet">Change set</param> /// <param name="mutableParentMap">Parent map of mutable data</param> /// <param name="immutableParentMap">Parent map of immutable data</param> public void StoreChangeset(AppendableChangeSet <Guid, object, EdgeData> changeSet, IParentMapProvider <Guid, object, EdgeData> mutableParentMap, IParentMapProvider <Guid, object, EdgeData> immutableParentMap) { Guid snapshotId = changeSet.SourceSnapshotId; var snapshotRoot = BPlusTreeOperations.CreateRootNode(NodeType.Collection, snapshotId); nodes.SetNode(snapshotId, snapshotRoot); Hashtable collectedNodes = new Hashtable(); GetCollectedNodesRecursive(changeSet.SourceSnapshotId, changeSet, mutableParentMap, immutableParentMap, collectedNodes, new Hashtable()); foreach (Guid nodeId in collectedNodes.Keys) { BPlusTreeOperations.InsertEdge(nodes, snapshotId, new Edge <Guid, EdgeData>(nodeId, new EdgeData(EdgeType.ListItem, nodeId)), TreeOrder); } }
/// <summary> /// Stores the change set /// </summary> /// <param name="changeSet">Change set to store</param> public void SetChangeSet(AppendableChangeSet <Guid, object, EdgeData> changeSet) { lock (sync) { var snapshotNode = BPlusTreeOperations.CreateRootNode(NodeType.Dictionary, changeSet.DestinationSnapshotId); nodes.SetNode(changeSet.DestinationSnapshotId, snapshotNode); // Add all changes from changeset to snapshot tree. foreach (var item in changeSet.Mapping) { BPlusTreeOperations.InsertEdge(nodes, changeSet.DestinationSnapshotId, new Edge <Guid, EdgeData>(item.Value, new EdgeData(EdgeType.ListItem, item.Key)), TreeOrder); } // Add snapshot to collection BPlusTreeOperations.InsertEdge(nodes, Constants.SnapshotsNodeId, new Edge <Guid, EdgeData>(changeSet.DestinationSnapshotId, new EdgeData(EdgeType.ListItem, changeSet.DestinationSnapshotId)), TreeOrder); } }
/// <summary> /// Recursive breadth-first pass through node graph which generates parent information /// </summary> /// <param name="snapshotId">Snapshot to generate</param> /// <param name="nodeId">Visited node</param> /// <param name="visitedNodes">List of visited nodes</param> private void AddParentsRecursive(Guid nodeId, Hashtable visitedNodes, INodeProvider <Guid, object, EdgeData> nodes) { if (nodeId.Equals(Constants.NullReferenceNodeId)) { return; } if (visitedNodes.ContainsKey(nodeId)) { return; } else { visitedNodes.Add(nodeId, null); } // Add the node as parent of all child nodes foreach (var edge in dataNodeProvider.GetNode(nodeId, NodeAccess.Read).Edges.Values) { if (EdgeFilter(edge)) { if (!nodes.Contains(edge.ToNodeId)) { var holderNode = BPlusTreeOperations.CreateRootNode(NodeType.Collection, edge.ToNodeId); nodes.SetNode(edge.ToNodeId, holderNode); } 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); } } } foreach (var edge in dataNodeProvider.GetNode(nodeId, NodeAccess.Read).Edges.Values) { AddParentsRecursive(edge.ToNodeId, visitedNodes, nodes); } }
public void TestConsistency() { INodeProvider <Guid, object, EdgeData> nodes = new DirectNodeProviderSafe <Guid, object, EdgeData>(new MemoryStorageUnsafe <Guid, object>(), false); Guid rootId = Guid.NewGuid(); Node <Guid, object, EdgeData> node = BPlusTreeOperations.CreateRootNode(NodeType.Collection, rootId); nodes.SetNode(rootId, node); Collection <Guid> references = new Collection <Guid>(); Collection <Guid> referencesAdded = new Collection <Guid>(); for (int i = 0; i < 1000; i++) { references.Add(Guid.NewGuid()); } foreach (var reference in references) { var data = new EdgeData(EdgeType.ListItem, reference); BPlusTreeOperations.InsertEdge(nodes, rootId, new Edge <Guid, EdgeData>(reference, data), TreeOrder); referencesAdded.Add(reference); foreach (var addedReference in referencesAdded) { var dataAdded = new EdgeData(EdgeType.ListItem, addedReference); Edge <Guid, EdgeData> edge; Assert.IsTrue(BPlusTreeOperations.TryFindEdge(nodes, rootId, dataAdded, out edge)); Assert.AreEqual(addedReference, edge.Data.Data); } } foreach (var reference in references) { var data = new EdgeData(EdgeType.ListItem, reference); Edge <Guid, EdgeData> edge; Assert.IsTrue(BPlusTreeOperations.TryFindEdge(nodes, rootId, data, out edge)); Assert.AreEqual(reference, edge.Data.Data); Assert.AreEqual(reference, edge.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; } }