コード例 #1
0
        private void GetCollectedNodesRecursive(Guid nodeId, AppendableChangeSet <Guid, object, EdgeData> changeSet, IParentMapProvider <Guid, object, EdgeData> mutableParentMap, IParentMapProvider <Guid, object, EdgeData> immutableParentMap, Hashtable collectedNodes, Hashtable visitedNodes)
        {
            if (visitedNodes.ContainsKey(nodeId))
            {
                return;
            }

            visitedNodes.Add(nodeId, null);

            if (changeSet.ReusedNodes.ContainsKey(nodeId))
            {
                // Reused nodes and their children are not to be collected
                return;
            }

            if (HasReusedParent(nodeId, changeSet, mutableParentMap, immutableParentMap, collectedNodes, new Hashtable()))
            {
                return;
            }

            collectedNodes.Add(nodeId, null);

            var node = dataNodes.GetNode(nodeId, NodeAccess.Read);

            foreach (var edge in node.Edges.Values)
            {
                if (edge.Data.Semantic != EdgeType.OfType && edge.ToNodeId != Constants.NullReferenceNodeId)
                {
                    GetCollectedNodesRecursive(edge.ToNodeId, changeSet, mutableParentMap, immutableParentMap, collectedNodes, visitedNodes);
                }
            }
        }
コード例 #2
0
        private bool HasReusedParent(Guid nodeId, AppendableChangeSet <Guid, object, EdgeData> changeSet, IParentMapProvider <Guid, object, EdgeData> mutableParentMap, IParentMapProvider <Guid, object, EdgeData> immutableParentMap, Hashtable collectedNodes, Hashtable visitedNodes)
        {
            if (visitedNodes.ContainsKey(nodeId))
            {
                return((bool)visitedNodes[nodeId]);
            }

            visitedNodes.Add(nodeId, false);

            if (changeSet.ReusedNodes.ContainsKey(nodeId))
            {
                return(true);
            }

            if (collectedNodes.ContainsKey(nodeId))
            {
                return(false);
            }

            using (var mutableParentEnumerator = mutableParentMap.ParentEdges(changeSet.SourceSnapshotId, nodeId))
            {
                if (mutableParentEnumerator != null)
                {
                    while (mutableParentEnumerator.MoveNext())
                    {
                        if (HasReusedParent(mutableParentEnumerator.Current.ToNodeId, changeSet, mutableParentMap, immutableParentMap, collectedNodes, visitedNodes))
                        {
                            return(true);
                        }
                    }
                }
            }

            using (var immutableParentEnumerator = immutableParentMap.ParentEdges(changeSet.SourceSnapshotId, nodeId))
            {
                if (immutableParentEnumerator != null)
                {
                    while (immutableParentEnumerator.MoveNext())
                    {
                        if (HasReusedParent(immutableParentEnumerator.Current.ToNodeId, changeSet, mutableParentMap, immutableParentMap, collectedNodes, visitedNodes))
                        {
                            return(true);
                        }
                    }
                }
            }

            return(false);
        }
コード例 #3
0
        /// <summary>
        /// Direct commit of data is appended on the existing nodes
        /// </summary>
        /// <param name="changeSet">Changes</param>
        private void CommitDirect(AppendableChangeSet <Guid, object, EdgeData> changeSet)
        {
            // Add all nodes to the provider
            foreach (Guid nodeId in changeSet.Nodes.EnumerateNodes())
            {
                var node = changeSet.Nodes.GetNode(nodeId, NodeAccess.Read);
                nodes.SetNode(nodeId, node);
            }

            // Store the change set in the change set provider
            changeSetProvider.SetChangeSet(changeSet);

            // Calculate collected nodes in the source changeset
            collectedNodesProvider.StoreChangeset(changeSet, mutableParentProvider, immutableParentProvider);

            // Update parent information in the parent map provider
            mutableParentProvider.UpdateParents(changeSet, collectedNodesProvider);

            // Update parent information in the immutable parent map provider
            immutableParentProvider.UpdateParents(changeSet, collectedNodesProvider);

            // Add new snapshot making it visible
            snapshotsService.AddSnapshot(changeSet.DestinationSnapshotId);

#if DEBUG
            Debug.WriteLine("Created snapshot " + changeSet.DestinationSnapshotId);

            Utils.LogNodesRecursive(changeSet.DestinationSnapshotId, nodes, changeSet.Nodes, 0, new Hashtable(), typesService);

            Debug.WriteLine("---------------------------------------------");

            Debug.WriteLine("Collected nodes are:");

            var enumerator = collectedNodesProvider.GetEdges(changeSet.SourceSnapshotId);

            if (enumerator != null)
            {
                using (enumerator)
                {
                    while (enumerator.MoveNext())
                    {
                        Debug.WriteLine(enumerator.Current.ToNodeId);
                    }
                }
            }

            Debug.WriteLine("---------------------------------------------");
#endif
        }
コード例 #4
0
        /// <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);
            }
        }
コード例 #5
0
        /// <summary>
        /// Accepts incoming isolated commit
        /// </summary>
        /// <param name="isolatedChangeSet">Isolated changeset</param>
        /// <returns>Appended changes</returns>
        public CommitResult <Guid> AcceptCommit(IsolatedChangeSet <Guid, object, EdgeData> isolatedChangeSet)
        {
            lock (commitSync)
            {
                var latestSnapshot = snapshotsService.GetLatestSnapshotId();
                if (latestSnapshot.Equals(isolatedChangeSet.SourceSnapshotId))
                {
                    AppendableChangeSet <Guid, object, EdgeData> appendableChangeSet = CreateAppendableChangeSet(isolatedChangeSet.SourceSnapshotId, Guid.NewGuid(), isolatedChangeSet);
                    // Commit is directly on the last snapshot
                    CommitDirect(appendableChangeSet);
                    return(new CommitResult <Guid>(appendableChangeSet.DestinationSnapshotId, appendableChangeSet.Mapping));
                }
                else
                {
                    // There are snapshots in between
#if DEBUG
                    Debug.WriteLine("Source snapshot = " + isolatedChangeSet.SourceSnapshotId);
#endif
                    // Calculate changes between last snapshot and source snapshot
                    var intermediateChanges = ChangesBetween(isolatedChangeSet.SourceSnapshotId, latestSnapshot);

                    // Isolate portion of the last snapshot which is relevant for the change set
                    var subTree = IsolateSubTree(latestSnapshot, isolatedChangeSet, intermediateChanges);

                    // Create a brand new changeset which is compatible with last snapshot
                    // Do this by recursive walk through the last snapshot and perform the "compatible" operations done in the incomming changeset

                    var mergedChangeSet = CreateMergedChangeSet(latestSnapshot, subTree, isolatedChangeSet, intermediateChanges);

                    // When complete perform the CommitDirect of the new changeset
                    CommitDirect(mergedChangeSet);

                    // Start with created change mapping
                    var mapping = mergedChangeSet.Mapping;

                    // Merge intermediate changes items to it
                    foreach (var item in intermediateChanges)
                    {
                        AddChangeItem(mapping, item.Key, item.Value);
                    }

                    return(new CommitResult <Guid>(mergedChangeSet.DestinationSnapshotId, mapping));
                }
            }
        }
コード例 #6
0
        /// <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);
            }
        }
コード例 #7
0
ファイル: CommitDataService.cs プロジェクト: nemanjazz/iog
        /// <summary>
        /// Direct commit of data is appended on the existing nodes
        /// </summary>
        /// <param name="changeSet">Changes</param>
        private void CommitDirect(AppendableChangeSet<Guid, object, EdgeData> changeSet)
        {
            // Add all nodes to the provider
            foreach (Guid nodeId in changeSet.Nodes.EnumerateNodes())
            {
                var node = changeSet.Nodes.GetNode(nodeId, NodeAccess.Read);
                nodes.SetNode(nodeId, node);
            }

            // Store the change set in the change set provider
            changeSetProvider.SetChangeSet(changeSet);

            // Calculate collected nodes in the source changeset
            collectedNodesProvider.StoreChangeset(changeSet, mutableParentProvider, immutableParentProvider);

            // Update parent information in the parent map provider
            mutableParentProvider.UpdateParents(changeSet, collectedNodesProvider);

            // Update parent information in the immutable parent map provider
            immutableParentProvider.UpdateParents(changeSet, collectedNodesProvider);

            // Add new snapshot making it visible
            snapshotsService.AddSnapshot(changeSet.DestinationSnapshotId);

            #if DEBUG
            Debug.WriteLine("Created snapshot " + changeSet.DestinationSnapshotId);

            Utils.LogNodesRecursive(changeSet.DestinationSnapshotId, nodes, changeSet.Nodes, 0, new Hashtable(), typesService);

            Debug.WriteLine("---------------------------------------------");

            Debug.WriteLine("Collected nodes are:");

            var enumerator = collectedNodesProvider.GetEdges(changeSet.SourceSnapshotId);

            if (enumerator != null)
            {
                using (enumerator)
                {
                    while (enumerator.MoveNext())
                    {
                        Debug.WriteLine(enumerator.Current.ToNodeId);
                    }
                }
            }

            Debug.WriteLine("---------------------------------------------");
            #endif
        }
コード例 #8
0
ファイル: ParentMapProvider.cs プロジェクト: nemanjazz/iog
        /// <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;
            }
        }