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> /// Removes information for a snapshot /// </summary> /// <param name="snapshotId">Snapshot ID to remove</param> public void RemoveChangeSet(Guid snapshotId) { lock (sync) { // Remove from snapshots list if (BPlusTreeOperations.RemoveEdge(nodes, Constants.SnapshotsNodeId, new EdgeData(EdgeType.ListItem, snapshotId), TreeOrder)) { DeleteTree(snapshotId); } } }
internal bool RemoveReference(Guid instanceId, Guid referenceId) { using (var enumerator = GetEnumerator(instanceId)) { while (enumerator.MoveNext()) { if (enumerator.Current.ToNodeId.Equals(referenceId)) { return(BPlusTreeOperations.RemoveEdge(provider, instanceId, enumerator.Current.Data, BPlusTreeOrder)); } } return(false); } }
internal bool RemoveScalar(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(BPlusTreeOperations.RemoveEdge(provider, instanceId, enumerator.Current.Data, BPlusTreeOrder)); } } return(false); } }
internal void Clear(Guid instanceId) { var removalKeys = new Collection <EdgeData>(); using (var enumerator = GetEnumerator(instanceId)) { while (enumerator.MoveNext()) { removalKeys.Add(enumerator.Current.Data); } } foreach (var key in removalKeys) { BPlusTreeOperations.RemoveEdge(provider, instanceId, key, BPlusTreeOrder); } }
internal bool Remove(Guid instanceId, object key) { return(BPlusTreeOperations.RemoveEdge(provider, instanceId, new EdgeData(EdgeType.ListItem, key), BPlusTreeOrder)); }
/// <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 void MergeRecursive(Guid nodeId, RecursiveResolutionParameters parameters) { if (parameters.VisitedNodes.ContainsKey(nodeId)) { return; } parameters.VisitedNodes.Add(nodeId, null); // Are we within the last snapshot affected sub tree if (parameters.SubTree.ContainsKey(nodeId)) { // Create node which we will change var node = parameters.DestinationProvider.GetNode(nodeId, NodeAccess.ReadWrite); // Perform the change depending on node type switch (node.NodeType) { case NodeType.Snapshot: foreach (var edge in node.Edges.Values) { MergeRecursive(edge.ToNodeId, parameters); } break; case NodeType.Scalar: throw new NotImplementedException("TODO"); case NodeType.Object: { // Is there a change in the changeset with conflicting change? // TODO (nsabo) Optimize searching by new ID value Guid changeNodeId = (Guid)parameters.SubTree[nodeId]; if (changeNodeId != Guid.Empty) { var changedNode = parameters.ChangeSet.Nodes.GetNode(changeNodeId, NodeAccess.Read); var originalNode = nodes.GetNode(changeNodeId, NodeAccess.Read); nodeMergeExecutor.MergeObjects(nodeId, originalNode, changedNode, node, new MergeRecursiveDelegate(MergeRecursive), new InsertRecursiveDelegate(InsertRecursive), parameters); } else { var changedNode = parameters.ChangeSet.Nodes.GetNode(nodeId, NodeAccess.Read); if (changedNode != null) { nodeMergeExecutor.ChangeObject(nodeId, changedNode, node, new MergeRecursiveDelegate(MergeRecursive), new InsertRecursiveDelegate(InsertRecursive), parameters); } else { // Follow edges foreach (var item in node.Edges.Values) { MergeRecursive(item.ToNodeId, parameters); } } } break; } case NodeType.Collection: case NodeType.Dictionary: { var treeOrder = node.NodeType == NodeType.Collection ? CollectionInstancesService.BPlusTreeOrder : DictionaryInstancesService.BPlusTreeOrder; // Search the changeset for new added elements Dictionary <EdgeData, Edge <Guid, EdgeData> > addedEdges = null; Dictionary <EdgeData, Edge <Guid, EdgeData> > removedEdges = null; FindTreeAddedElements(nodeId, parameters, out addedEdges, out removedEdges); foreach (var addedEdge in addedEdges.Values) { // Add node in the isolated provider InsertRecursive(addedEdge.ToNodeId, parameters); // Create edge from the current collection BPlusTreeOperations.InsertEdge(parameters.DestinationProvider, nodeId, addedEdge, treeOrder); } foreach (var removedEdge in removedEdges.Values) { BPlusTreeOperations.RemoveEdge(parameters.DestinationProvider, nodeId, removedEdge.Data, treeOrder); } // Enumerate through existing elements and look for their changes using (var enumerator = BPlusTreeOperations.GetEnumerator(nodes, nodeId, EdgeType.ListItem)) { while (enumerator.MoveNext()) { if (!addedEdges.ContainsKey(enumerator.Current.Data) && !removedEdges.ContainsKey(enumerator.Current.Data)) { MergeRecursive(enumerator.Current.ToNodeId, parameters); } } } break; } default: throw new ArgumentException("Unexpected node type in tree :" + node.NodeType); } parameters.DestinationProvider.SetNode(nodeId, node); } }