예제 #1
0
        public void ChangeObject(Guid nodeId, Node<Guid, object, EdgeData> changedNode, Node<Guid, object, EdgeData> node, MergeRecursiveDelegate mergeRecursive, InsertRecursiveDelegate insertRecursive, RecursiveResolutionParameters parameters)
        {
            // Consolidate the values
            foreach (var item in changedNode.Values)
            {
                node.Values[item.Key] = item.Value;
            }

            // Consolidate the edges
            foreach (var edge in changedNode.Edges)
            {
                Guid newReference = edge.Value.ToNodeId;

                NodeState nodeState = NodeState.None;
                parameters.ChangeSet.NodeStates.TryGetValue(newReference, out nodeState);

                // If changed node is a new node go into the changed node recursion
                if (nodeState == NodeState.Created)
                {
                    // Set the new reference
                    node.SetEdgeToNode(edge.Value.Data, newReference);
                    // Insert the new nodes
                    insertRecursive(newReference, parameters);
                }
                else
                {
                    // Set the new reference
                    node.SetEdgeToNode(edge.Value.Data, newReference);
                    // Follow the new reference and see changes
                    mergeRecursive(newReference, parameters);
                }
            }
        }
예제 #2
0
        private void FindTreeAddedElements(Guid nodeId, RecursiveResolutionParameters parameters, out Dictionary <EdgeData, Edge <Guid, EdgeData> > addedElements, out Dictionary <EdgeData, Edge <Guid, EdgeData> > removedElements)
        {
            addedElements   = new Dictionary <EdgeData, Edge <Guid, EdgeData> >();
            removedElements = new Dictionary <EdgeData, Edge <Guid, EdgeData> >();

            // TODO (nsabo) Optimize searching by new ID value
            Guid originalNodeId = Guid.Empty;

            foreach (var item in parameters.IntermediateChanges)
            {
                if (item.Value.Equals(nodeId))
                {
                    originalNodeId = item.Key;
                    break;
                }
            }

            if (originalNodeId == Guid.Empty)
            {
                originalNodeId = nodeId;
            }

            // Go through changed list and see if some item has not been included in the last version
            using (var enumerator = BPlusTreeOperations.GetEnumerator(parameters.SourceProvider, originalNodeId, EdgeType.ListItem))
            {
                while (enumerator.MoveNext())
                {
                    var edge = enumerator.Current;
                    Edge <Guid, EdgeData> foundEdge = null;

                    // Try finding the element in last version
                    if (!BPlusTreeOperations.TryFindEdge(nodes, originalNodeId, edge.Data, out foundEdge))
                    {
                        addedElements.Add(edge.Data, edge);
                    }
                }
            }

            // Go through last version and see if there are elements which are not found in changed list
            using (var enumerator = BPlusTreeOperations.GetEnumerator(nodes, originalNodeId, EdgeType.ListItem))
            {
                while (enumerator.MoveNext())
                {
                    var edge = enumerator.Current;
                    Edge <Guid, EdgeData> foundEdge = null;

                    // Try finding the element in last version
                    if (!BPlusTreeOperations.TryFindEdge(parameters.SourceProvider, originalNodeId, edge.Data, out foundEdge))
                    {
                        removedElements.Add(edge.Data, edge);
                    }
                }
            }
        }
예제 #3
0
        private void InsertRecursive(Guid nodeId, RecursiveResolutionParameters parameters)
        {
            if (parameters.VisitedNodes.ContainsKey(nodeId))
            {
                return;
            }

            parameters.VisitedNodes.Add(nodeId, null);

            Node <Guid, object, EdgeData> node = null;

            // Get new node from changeset
            if (parameters.ChangeSet.Nodes.Contains(nodeId))
            {
                node = parameters.ChangeSet.Nodes.GetNode(nodeId, NodeAccess.Read);
            }
            else
            {
                node = nodes.GetNode(nodeId, NodeAccess.Read);
            }

            // Process edges
            foreach (var item in node.Edges)
            {
                // Upgrade reference to existing object when changed
                Guid newReferenceId = Guid.Empty;
                if (!Utils.IsPermanentEdge(item.Value) &&                                                // Not permanent edge
                    parameters.IntermediateChanges.TryGetValue(item.Value.ToNodeId, out newReferenceId)) // There is newer version
                {
                    // Update new reference
                    node.Edges[item.Key].ToNodeId = newReferenceId;
                }

                // Follow reference to new object
                NodeState referenceState = NodeState.None;
                if (parameters.ChangeSet.NodeStates.TryGetValue(item.Value.ToNodeId, out referenceState))
                {
                    if (referenceState == NodeState.Created)
                    {
                        InsertRecursive(item.Value.ToNodeId, parameters);
                    }
                }
            }

            parameters.DestinationProvider.SetNode(nodeId, node);
        }
예제 #4
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);
            }
        }
예제 #5
0
        private void InsertRecursive(Guid nodeId, RecursiveResolutionParameters parameters)
        {
            if (parameters.VisitedNodes.ContainsKey(nodeId))
            {
                return;
            }

            parameters.VisitedNodes.Add(nodeId, null);

            Node<Guid, object, EdgeData> node = null;

            // Get new node from changeset
            if (parameters.ChangeSet.Nodes.Contains(nodeId))
            {
                node = parameters.ChangeSet.Nodes.GetNode(nodeId, NodeAccess.Read);
            }
            else
            {
                node = nodes.GetNode(nodeId, NodeAccess.Read);
            }

            // Process edges
            foreach (var item in node.Edges)
            {
                // Upgrade reference to existing object when changed
                Guid newReferenceId = Guid.Empty;
                if (!Utils.IsPermanentEdge(item.Value) && // Not permanent edge
                    parameters.IntermediateChanges.TryGetValue(item.Value.ToNodeId, out newReferenceId)) // There is newer version
                {
                    // Update new reference
                    node.Edges[item.Key].ToNodeId = newReferenceId;
                }

                // Follow reference to new object
                NodeState referenceState = NodeState.None;
                if (parameters.ChangeSet.NodeStates.TryGetValue(item.Value.ToNodeId, out referenceState))
                {
                    if (referenceState == NodeState.Created)
                    {
                        InsertRecursive(item.Value.ToNodeId, parameters);
                    }
                }
            }

            parameters.DestinationProvider.SetNode(nodeId, node);
        }
예제 #6
0
        private void FindTreeAddedElements(Guid nodeId, RecursiveResolutionParameters parameters, out Dictionary<EdgeData, Edge<Guid, EdgeData>> addedElements, out Dictionary<EdgeData, Edge<Guid, EdgeData>> removedElements)
        {
            addedElements = new Dictionary<EdgeData, Edge<Guid, EdgeData>>();
            removedElements = new Dictionary<EdgeData, Edge<Guid, EdgeData>>();

            // TODO (nsabo) Optimize searching by new ID value
            Guid originalNodeId = Guid.Empty;
            foreach (var item in parameters.IntermediateChanges)
            {
                if (item.Value.Equals(nodeId))
                {
                    originalNodeId = item.Key;
                    break;
                }
            }

            if (originalNodeId == Guid.Empty)
            {
                originalNodeId = nodeId;
            }

            // Go through changed list and see if some item has not been included in the last version
            using (var enumerator = BPlusTreeOperations.GetEnumerator(parameters.SourceProvider, originalNodeId, EdgeType.ListItem))
            {
                while (enumerator.MoveNext())
                {
                    var edge = enumerator.Current;
                    Edge<Guid, EdgeData> foundEdge = null;

                    // Try finding the element in last version
                    if (!BPlusTreeOperations.TryFindEdge(nodes, originalNodeId, edge.Data, out foundEdge))
                    {
                        addedElements.Add(edge.Data, edge);
                    }
                }
            }

            // Go through last version and see if there are elements which are not found in changed list
            using (var enumerator = BPlusTreeOperations.GetEnumerator(nodes, originalNodeId, EdgeType.ListItem))
            {
                while (enumerator.MoveNext())
                {
                    var edge = enumerator.Current;
                    Edge<Guid, EdgeData> foundEdge = null;

                    // Try finding the element in last version
                    if (!BPlusTreeOperations.TryFindEdge(parameters.SourceProvider, originalNodeId, edge.Data, out foundEdge))
                    {
                        removedElements.Add(edge.Data, edge);
                    }
                }
            }
        }
예제 #7
0
        public void MergeObjects(Guid nodeId, Node<Guid, object, EdgeData> originalNode, Node<Guid, object, EdgeData> changedNode, Node<Guid, object, EdgeData> node, MergeRecursiveDelegate mergeRecursive, InsertRecursiveDelegate insertRecursive, RecursiveResolutionParameters parameters)
        {
            Guid typeId = typesService.GetInstanceTypeId(originalNode);
            if (!objectAttributeProvider.IsConcurrent(typeId))
            {
                var instanceType = typesService.GetTypeFromId(typesService.GetInstanceTypeId(nodeId));
                throw new ConcurrentModificationException("Concurrent modification not allowed for entity type:" + instanceType.ToString());
            }

            if (objectAttributeProvider.IsStaticConcurrency(typeId))
            {
                MergeObjectsStatic(nodeId, typeId, originalNode, changedNode, node, mergeRecursive, insertRecursive, parameters);
            }
            else
            {
                throw new NotImplementedException("Dynamic concurrency not implemented");
            }
        }
예제 #8
0
        private void MergeObjectsStatic(Guid nodeId, Guid typeId, Node<Guid, object, EdgeData> originalNode, Node<Guid, object, EdgeData> changedNode, Node<Guid, object, EdgeData> node, MergeRecursiveDelegate mergeRecursive, InsertRecursiveDelegate insertRecursive, RecursiveResolutionParameters parameters)
        {
            // Consolidate the values
            foreach (var item in originalNode.Values)
            {
                // Value was changed compared to previous version
                if (!changedNode.Values[item.Key].Equals(item.Value))
                {
                    // Try setting value in the node, if it is still the same
                    if (node.Values[item.Key].Equals(item.Value))
                    {
                        node.Values[item.Key] = changedNode.Values[item.Key];
                    }
                    else
                    {
                        if (objectAttributeProvider.IsMemberOverride(typeId, item.Key))
                        {
                            // Override with changed value
                            node.Values[item.Key] = changedNode.Values[item.Key];
                        }
                        else
                        {
                            throw new ConcurrentModificationException("Concurrent modification of scalar value not allowed in type:" + typesService.GetTypeFromId(typeId).ToString() + " for member " + typesService.GetMemberName(typeId, item.Key));
                        }
                    }
                }
            }

            // Consolidate the edges
            foreach (var edge in originalNode.Edges)
            {
                // Value was changed compared to previous version
                if (!changedNode.Edges[edge.Key].ToNodeId.Equals(edge.Value.ToNodeId))
                {
                    // Was member set to override?
                    bool isOverride = objectAttributeProvider.IsMemberOverride(typeId, (Guid)edge.Key.Data);

                    // Try setting value in the node, if it is still the same or if override is set
                    if (node.Edges[edge.Key].ToNodeId.Equals(edge.Value.ToNodeId) || isOverride)
                    {
                        Guid newReference = changedNode.Edges[edge.Key].ToNodeId;
                        Guid newReferenceUpdated = Guid.Empty;

                        // Is there an intermediate change?
                        if (parameters.IntermediateChanges.TryGetValue(newReference, out newReferenceUpdated))
                        {
                            // Set edge to node from the changed node
                            node.SetEdgeToNode(edge.Value.Data, newReferenceUpdated);
                            // See about the new object
                            mergeRecursive(newReferenceUpdated, parameters);
                        }
                        else
                        {
                            NodeState nodeState = NodeState.None;
                            parameters.ChangeSet.NodeStates.TryGetValue(newReference, out nodeState);

                            // If changed node is a new node go into the changed node recursion
                            if (nodeState == NodeState.Created)
                            {
                                // Set the new reference
                                node.SetEdgeToNode(edge.Value.Data, newReference);
                                // Insert the new nodes
                                insertRecursive(newReference, parameters);
                            }
                            else
                            {
                                // Set the new reference
                                node.SetEdgeToNode(edge.Value.Data, newReference);
                                // Follow the new reference and see changes
                                mergeRecursive(newReference, parameters);
                            }
                        }
                    }
                    else
                    {
                        throw new ConcurrentModificationException("Concurrent modification of referenced item not allowed in type:" + typesService.GetTypeFromId(typeId).ToString() + " for member " + typesService.GetMemberName(typeId, (Guid)edge.Key.Data));
                    }
                }
                else
                {
                    mergeRecursive(node.Edges[edge.Key].ToNodeId, parameters);
                }
            }
        }
예제 #9
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);
            }
        }