예제 #1
0
        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--;
            }
        }
예제 #2
0
 /// <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);
         }
     }
 }
예제 #3
0
        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);
            }
        }
예제 #4
0
        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);
            }
        }
예제 #5
0
        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);
            }
        }
예제 #6
0
 internal bool Remove(Guid instanceId, object key)
 {
     return(BPlusTreeOperations.RemoveEdge(provider, instanceId, new EdgeData(EdgeType.ListItem, key), BPlusTreeOrder));
 }
예제 #7
0
        /// <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;
            }
        }
예제 #8
0
        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);
            }
        }