예제 #1
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);
                    }
                }
            }
        }
예제 #2
0
 /// <summary>
 /// Provides change set edges for given snapshot
 /// </summary>
 /// <param name="snapshotId">Snapshot ID</param>
 /// <returns>Change set edge enumerator</returns>
 public IEnumerator <Edge <Guid, EdgeData> > GetChangeSetEdges(Guid snapshotId)
 {
     lock (sync)
     {
         Edge <Guid, EdgeData> edge = null;
         if (BPlusTreeOperations.TryFindEdge(nodes, Constants.SnapshotsNodeId, new EdgeData(EdgeType.ListItem, snapshotId), out edge))
         {
             return(BPlusTreeOperations.GetEnumerator(nodes, snapshotId, EdgeType.ListItem));
         }
         else
         {
             // Returtn empty enumerator
             return(new Collection <Edge <Guid, EdgeData> >().GetEnumerator());
         }
     }
 }
예제 #3
0
        /// <summary>
        /// Returns list of parents for given node witin a snapshot
        /// </summary>
        /// <param name="snapshotId">Snapshot within parents are requested</param>
        /// <param name="nodeId">Node which parents are returned</param>
        /// <returns>List of parent node identifiers for each node in dictionary format, or null if there are no parent edges</returns>
        public IEnumerator <Edge <Guid, EdgeData> > ParentEdges(Guid snapshotId, Guid nodeId)
        {
            lock (dataSync)
            {
                // Generate parents if they dont exist
                if (!createdNodes)
                {
                    createdNodes = true;
                    AddParentsRecursive(snapshotId, new Hashtable(), nodes);
                    lastSnapshotId = snapshotId;
                }

                // Do we have the last snapshot in the memory
                if (snapshotId != lastSnapshotId)
                {
                    // Try going for fallback provider
                    if (fallbackParentMapProvider != null)
                    {
                        return(fallbackParentMapProvider.ParentEdges(snapshotId, nodeId));
                    }
                    else
                    {
                        // If not, generate asked snapshot
                        nodes.Clear();
                        AddParentsRecursive(snapshotId, new Hashtable(), nodes);
                        lastSnapshotId = snapshotId;
                    }
                }

                // Find edge leading to holder node for given ID
                if (nodes.Contains(nodeId))
                {
                    return(BPlusTreeOperations.GetEnumerator(nodes, nodeId, EdgeType.Contains));
                }
                else
                {
                    return(null);
                }
            }
        }
예제 #4
0
        private static void LogCollection(Guid nodeId, Node <Guid, object, EdgeData> node, INodeProvider <Guid, object, EdgeData> nodes, INodeProvider <Guid, object, EdgeData> changes, int tabLevel, Hashtable visited, TypesService typesService)
        {
            Edge <Guid, EdgeData> typeEdge = null;

            BPlusTreeOperations.TryFindEdge(nodes, nodeId, new EdgeData(EdgeType.OfType, null), out typeEdge);

            var typeId   = typeEdge.ToNodeId;
            var typeName = typesService.GetTypeFromId(typeId).Name;

            Debug.WriteLine(LogTabs(tabLevel) + nodeId + "(" + typeName + ")");
            Debug.WriteLine(LogTabs(tabLevel) + "Previous=" + node.Previous);


            using (var enumeration = BPlusTreeOperations.GetEnumerator(nodes, nodeId, EdgeType.ListItem))
            {
                while (enumeration.MoveNext())
                {
                    Debug.WriteLine(LogTabs(tabLevel) + enumeration.Current.Data + "=");
                    LogNodesRecursive(enumeration.Current.ToNodeId, nodes, changes, tabLevel + 1, visited, typesService);
                }
            }
        }
예제 #5
0
 /// <summary>
 /// Returns edges to collectable nodes for a snapshot
 /// </summary>
 /// <param name="snapshotId">Snapshot identifier</param>
 /// <returns>Enumerator of edges towards collectable nodes</returns>
 public IEnumerator <Edge <Guid, EdgeData> > GetEdges(Guid snapshotId)
 {
     return(BPlusTreeOperations.GetEnumerator(nodes, snapshotId, EdgeType.ListItem));
 }
예제 #6
0
 internal IEnumerator <Edge <Guid, EdgeData> > GetEnumerator(Guid instanceId)
 {
     return(BPlusTreeOperations.GetEnumerator(provider, instanceId, EdgeType.ListItem));
 }
예제 #7
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);
            }
        }