Beispiel #1
0
        /// <summary>
        /// Collects the source array.
        /// </summary>
        /// <param name="targetIndex">Index of the target.</param>
        /// <param name="operation">The operation.</param>
        /// <param name="operationContext">The operation context.</param>
        /// <param name="sourceArray">The source array.</param>
        public void collectSourceArray(MemoryIndex targetIndex, MergeOperation operation, MergeOperationContext operationContext, AssociativeArray sourceArray)
        {
            // Source array
            if (sourceArray != null)
            {
                // Becomes target array when not set
                if (targetArray == null && operationContext.Index.Equals(targetIndex))
                {
                    targetArray = sourceArray;
                }
                hasArray = true;

                // Save source array to merge descriptors
                IArrayDescriptor descriptor = operationContext.SnapshotContext.SourceStructure.GetDescriptor(sourceArray);
                sourceArrays.Add(new ContainerContext(operationContext.SnapshotContext, descriptor, operationContext.OperationType));

                // Equeue all array indexes when whole subtree should be merged
                if (operationContext.OperationType == MergeOperationType.WholeSubtree)
                {
                    foreach (var index in descriptor.Indexes)
                    {
                        operation.TreeNode.GetOrCreateChild(index.Key);
                    }
                    operation.TreeNode.GetOrCreateAny();
                }
            }
            else
            {
                // Source do not contain array - at least one source is empty
                arrayAlwaysDefined = false;
            }
        }
Beispiel #2
0
 public OperationAccessor(MergeOperation operation, Snapshot targetSnapshot, IWriteableSnapshotData writeableTargetData, IReadOnlySnapshotStructure targetStructure)
 {
     this.operation           = operation;
     this.targetSnapshot      = targetSnapshot;
     this.writeableTargetData = writeableTargetData;
     this.targetStructure     = targetStructure;
 }
Beispiel #3
0
        /// <summary>
        /// Enqueues the merge operation.
        /// </summary>
        /// <param name="childName">Name of the child.</param>
        /// <param name="operation">The operation.</param>
        /// <param name="targetContainerContext">The target container context.</param>
        /// <param name="childTreeNode">The child tree node.</param>
        /// <param name="alwaysDefined">if set to <c>true</c> [always defined].</param>
        private void enqueueMergeOperation(string childName, MergeOperation operation, ITargetContainerContext targetContainerContext, MemoryIndexTreeNode childTreeNode, bool alwaysDefined)
        {
            IReadonlyIndexContainer targetContainer = targetContainerContext.getSourceContainer();
            MemoryIndex             targetIndex;

            // Use index from target collection or crete and add it to the target collection
            if (!targetContainer.TryGetIndex(childName, out targetIndex))
            {
                targetIndex = createNewTargetIndex(targetContainerContext, childName);

                if (targetIndex == null)
                {
                    return;
                }
            }

            // Set parameters and add it to collection
            operation.TreeNode = childTreeNode;
            operation.SetTargetIndex(targetIndex);

            if (!alwaysDefined)
            {
                operation.SetUndefined();
            }

            operationQueue.AddLast(operation);
        }
Beispiel #4
0
        /// <summary>
        /// Deletes the array.
        /// </summary>
        /// <param name="targetIndex">Index of the target.</param>
        /// <param name="targetArray">The target array.</param>
        public void DeleteArray(MemoryIndex targetIndex, AssociativeArray targetArray)
        {
            IArrayDescriptor targetArrayDescriptor = targetStructure.GetDescriptor(targetArray);

            foreach (var index in targetArrayDescriptor.Indexes)
            {
                // Enqueue delete operation for every child index
                MemoryIndex    childIndex     = index.Value;
                MergeOperation childOperation = new MergeOperation();
                childOperation.SetTargetIndex(childIndex);
                childOperation.SetDeleteOperation();
                operationQueue.AddLast(childOperation);
            }

            // Enqueue delete operation for unknown index
            MergeOperation unknownOperation = new MergeOperation();

            unknownOperation.SetTargetIndex(targetArrayDescriptor.UnknownIndex);
            unknownOperation.SetUndefined();
            unknownOperation.SetDeleteOperation();
            operationQueue.AddLast(unknownOperation);

            // Deletes array from structure
            writeableTargetStructure.RemoveArray(targetIndex, targetArray);
        }
Beispiel #5
0
        /// <summary>
        /// Creates the and enqueue operations.
        /// </summary>
        /// <param name="targetContainerContext">The target container context.</param>
        /// <param name="treeNode">The tree node.</param>
        /// <param name="sourceContainers">The source containers.</param>
        /// <param name="alwaysDefined">if set to <c>true</c> [always defined].</param>
        public void CreateAndEnqueueOperations(ITargetContainerContext targetContainerContext, MemoryIndexTreeNode treeNode,
                                               List <ContainerContext> sourceContainers, bool alwaysDefined)
        {
            // Creates and enques merge operations for all child nodes of given node
            foreach (var childNode in treeNode.ChildNodes)
            {
                string childName = childNode.Key;
                MemoryIndexTreeNode childTreeNode = childNode.Value;

                MergeOperation operation      = new MergeOperation();
                bool           isChildDefined = collectIndexes(childName, sourceContainers, operation);

                if (isChildDefined)
                {
                    // Child is defined at least in one collection - enqueue merge operation
                    enqueueMergeOperation(childName, operation, targetContainerContext, childTreeNode, alwaysDefined);
                }
                else
                {
                    // Child is not defined - enqueue delete operation
                    enqueueDeleteOperation(childName, operation, targetContainerContext, childTreeNode);
                }
            }

            // Enqueue merge operation for unknown index if is defined
            if (treeNode.AnyChild != null)
            {
                enqueueMergeUnknownOperation(targetContainerContext, treeNode.AnyChild, sourceContainers);
            }
        }
Beispiel #6
0
            public OperationAccessor(MergeOperation operation, Snapshot targetSnapshot, IWriteableSnapshotStructure writeableTargetStructure, TrackingCallMergeStructureWorker mergeWorker)
            {
                this.operation                = operation;
                this.targetSnapshot           = targetSnapshot;
                this.writeableTargetStructure = writeableTargetStructure;
                this.mergeWorker              = mergeWorker;

                this.references = new ReferenceCollector(writeableTargetStructure);
            }
Beispiel #7
0
        /// <summary>
        /// Enqueues the delete operation.
        /// </summary>
        /// <param name="childName">Name of the child.</param>
        /// <param name="operation">The operation.</param>
        /// <param name="targetContainerContext">The target container context.</param>
        /// <param name="childTreeNode">The child tree node.</param>
        private void enqueueDeleteOperation(string childName, MergeOperation operation, ITargetContainerContext targetContainerContext, MemoryIndexTreeNode childTreeNode)
        {
            IReadonlyIndexContainer targetContainer = targetContainerContext.getSourceContainer();
            MemoryIndex             targetIndex;

            if (targetContainer.TryGetIndex(childName, out targetIndex))
            {
                // Enque delete operation only if target index exists in paret snapshot
                operation.TreeNode = childTreeNode;
                operation.SetTargetIndex(targetIndex);
                operation.SetDeleteOperation();
                operationQueue.AddLast(operation);

                // Delete child from parent container
                targetContainerContext.getWriteableSourceContainer().RemoveIndex(childName);
            }
        }
Beispiel #8
0
        /// <summary>
        /// Enqueues the merge unknown operation.
        /// </summary>
        /// <param name="targetContainerContext">The target container context.</param>
        /// <param name="anyNode">Any node.</param>
        /// <param name="sourceContainers">The source containers.</param>
        private void enqueueMergeUnknownOperation(ITargetContainerContext targetContainerContext, MemoryIndexTreeNode anyNode, List <ContainerContext> sourceContainers)
        {
            MergeOperation unknownOperation = new MergeOperation();

            foreach (ContainerContext containerContext in sourceContainers)
            {
                unknownOperation.Add(new MergeOperationContext(
                                         containerContext.IndexContainer.UnknownIndex, containerContext.SnapshotContext));
            }

            IReadonlyIndexContainer targetContainer = targetContainerContext.getSourceContainer();

            unknownOperation.TreeNode = anyNode;
            unknownOperation.SetTargetIndex(targetContainer.UnknownIndex);
            unknownOperation.SetUndefined();

            operationQueue.AddLast(unknownOperation);
        }
Beispiel #9
0
        /// <summary>
        /// Processes the merge operations.
        /// </summary>
        private void processMergeOperations()
        {
            // Process operations while queue is not empty
            while (operationQueue.Count > 0)
            {
                // Dequeue next operation
                MergeOperation operation = operationQueue.First.Value;
                operationQueue.RemoveFirst();

                if (operation.IsDeleteOperation)
                {
                    processDeleteOperation(operation);
                }
                else
                {
                    processMergeOperation(operation);
                }
            }
        }
Beispiel #10
0
        /// <summary>
        /// Processes the merge operation.
        /// </summary>
        /// <param name="operation">The operation.</param>
        private void processMergeOperation(MergeOperation operation)
        {
            MemoryIndex targetIndex            = operation.TargetIndex;
            var         targetIndexDatasources = targetSnapshot.MergeInfo.GetOrCreateDatasourcesContaier(targetIndex);

            // Iterate sources
            foreach (MergeOperationContext operationContext in operation.Indexes)
            {
                // Retreive source context and definition
                MemoryIndex      sourceIndex      = operationContext.Index;
                SnapshotContext  context          = operationContext.SnapshotContext;
                IIndexDefinition sourceDefinition = context.SourceStructure.GetIndexDefinition(sourceIndex);

                // Collect array and aliases data
                arrayWorker.collectSourceArray(targetIndex, operation, operationContext, sourceDefinition.Array);
                aliasWorker.collectSourceAliases(sourceDefinition.Aliases);
                objectWorker.collectSourceObjects(sourceDefinition.Objects);

                // Store datasource for data and info merging
                targetIndexDatasources.SetDatasource(context.SourceSnapshot, sourceIndex);
            }

            IIndexDefinition targetDefinition;

            if (targetStructure.TryGetIndexDefinition(targetIndex, out targetDefinition))
            {
                // Index is set in target snapshot
                if (targetDefinition.Array != null)
                {
                    arrayWorker.SetTargetArray(targetDefinition.Array);
                }
            }
            else
            {
                // Index is not set in target snapshot - create it
                writeableTargetStructure.NewIndex(targetIndex);
            }

            aliasWorker.MergeAliasesAndClear(targetIndex, operation);
            arrayWorker.MergeArraysAndClear(targetSnapshot, targetIndex, operation);
            objectWorker.MergeObjectsAndClear(targetIndex);
        }
Beispiel #11
0
        /// <summary>
        /// Merges the aliases to target and clear inner container.
        /// </summary>
        /// <param name="targetIndex">Index of the target.</param>
        /// <param name="operation">The operation.</param>
        /// <exception cref="System.Exception">Alias merge - memory index was not included into collection of aliases</exception>
        public void MergeAliasesAndClear(MemoryIndex targetIndex, MergeOperation operation)
        {
            if (hasAliases && references.HasAliases)
            {
                references.SetAliases(targetIndex, worker, aliasesAlwaysDefined && !operation.IsUndefined);

                MemoryAliasInfo aliasInfo;
                if (worker.MemoryAliases.TryGetValue(targetIndex, out aliasInfo))
                {
                    aliasInfo.IsTargetOfMerge = true;
                }
                else
                {
                    throw new Exception("Alias merge - memory index was not included into collection of aliases");
                }

                references.Clear();
                hasAliases = false;
            }
            aliasesAlwaysDefined = true;
        }
Beispiel #12
0
        /// <summary>
        /// Processes the delete operation.
        /// </summary>
        /// <param name="operation">The operation.</param>
        private void processDeleteOperation(MergeOperation operation)
        {
            MemoryIndex      targetIndex = operation.TargetIndex;
            IIndexDefinition targetDefinition;

            // Index is set in target snapshot
            if (targetStructure.TryGetIndexDefinition(targetIndex, out targetDefinition))
            {
                // Delete array and enqueue deletein operations if exists
                if (targetDefinition.Array != null)
                {
                    DeleteArray(targetIndex, targetDefinition.Array);
                }

                // Delete aliases if any
                if (targetDefinition.Aliases != null && targetDefinition.Aliases.HasAliases)
                {
                    deleteAliases(targetIndex, targetDefinition.Aliases);
                }

                // Removes index from target structure
                writeableTargetStructure.RemoveIndex(targetIndex);
            }
        }
Beispiel #13
0
 /// <summary>
 /// Creates the new operation accessor.
 /// </summary>
 /// <param name="operation">The operation.</param>
 /// <returns>Operation accesor</returns>
 protected override TrackingMergeWorkerOperationAccessor createNewOperationAccessor(MergeOperation operation)
 {
     return(new OperationAccessor(operation, targetSnapshot, writeableTargetData, targetStructure));
 }
Beispiel #14
0
        /// <summary>
        /// Merges the arrays into the target index and clear inner collection.
        /// </summary>
        /// <param name="targetSnapshot">The target snapshot.</param>
        /// <param name="targetIndex">Index of the target.</param>
        /// <param name="operation">The operation.</param>
        public void MergeArraysAndClear(Snapshot targetSnapshot, MemoryIndex targetIndex, MergeOperation operation)
        {
            if (hasArray)
            {
                if (targetArray == null)
                {
                    targetArray = targetSnapshot.CreateArray();
                }

                IArrayDescriptor targetArrayDescriptor;
                if (!writeableTargetStructure.TryGetDescriptor(targetArray, out targetArrayDescriptor))
                {
                    // Target does not contain array - create and add new in target snapshot
                    targetArrayDescriptor = worker.Factories.StructuralContainersFactories.ArrayDescriptorFactory.CreateArrayDescriptor(writeableTargetStructure, targetArray, targetIndex);
                    writeableTargetStructure.SetDescriptor(targetArray, targetArrayDescriptor);
                    writeableTargetStructure.NewIndex(targetArrayDescriptor.UnknownIndex);
                    writeableTargetStructure.SetArray(targetIndex, targetArray);
                }

                // Create context and merge descriptors
                var arrayContext = new ArrayTargetContainerContext(writeableTargetStructure, targetArrayDescriptor);
                worker.CreateAndEnqueueOperations(arrayContext, operation.TreeNode, sourceArrays, arrayAlwaysDefined && !operation.IsUndefined);

                // Update current descriptor when changed
                IArrayDescriptor currentDescriptor = arrayContext.getCurrentDescriptor();
                if (currentDescriptor != targetArrayDescriptor)
                {
                    writeableTargetStructure.SetDescriptor(targetArray, currentDescriptor);
                }

                sourceArrays.Clear();
                hasArray    = false;
                targetArray = null;
            }
            else if (targetArray != null)
            {
                worker.DeleteArray(targetIndex, targetArray);

                targetArray = null;
            }
            arrayAlwaysDefined = true;
        }
Beispiel #15
0
        /// <summary>
        /// Collects the indexes.
        /// </summary>
        /// <param name="childName">Name of the child.</param>
        /// <param name="sourceContainers">The source containers.</param>
        /// <param name="operation">The operation.</param>
        /// <returns>True if there is some defined child; otherwise false</returns>
        private bool collectIndexes(string childName, List <ContainerContext> sourceContainers, MergeOperation operation)
        {
            bool childDefined = false;

            // Collect source indexes from source collection
            foreach (ContainerContext containerContext in sourceContainers)
            {
                MemoryIndex sourceIndex;
                if (containerContext.IndexContainer.TryGetIndex(childName, out sourceIndex))
                {
                    // Collection contains field - use it
                    operation.Add(new MergeOperationContext(sourceIndex, containerContext.SnapshotContext));
                    childDefined = true;
                }
                else
                {
                    // Collection do not contain - use unknown index as source
                    // When unknown index is the source - all subtree has to be merged into
                    operation.Add(
                        new MergeOperationContext(
                            containerContext.IndexContainer.UnknownIndex,
                            containerContext.SnapshotContext,
                            MergeOperationType.WholeSubtree)
                        );
                    operation.SetUndefined();
                }
            }

            return(childDefined);
        }