/// <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></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); }
/// <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> private void createAndEnqueueOperations( ITargetContainerContext targetContainerContext, MemoryIndexTreeNode treeNode, List <ContainerContext> sourceContainers, bool alwaysDefined) { IReadonlyIndexContainer targetContainer = targetContainerContext.getSourceContainer(); // 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 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) { continue; } } // Set parameters and add it to collection operation.TreeNode = childTreeNode; operation.SetTargetIndex(targetIndex); if (!alwaysDefined) { operation.SetUndefined(); } operationQueue.AddLast(operation); } else { // Child is not defined - enqueue delete operation 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); deleteChild(targetContainerContext, childName); } } } // Enqueue merge operation for unknown index if is defined if (treeNode.AnyChild != null) { MergeOperation unknownOperation = new MergeOperation(); foreach (ContainerContext containerContext in sourceContainers) { unknownOperation.Add(new MergeOperationContext( containerContext.IndexContainer.UnknownIndex, containerContext.SnapshotContext)); } unknownOperation.TreeNode = treeNode.AnyChild; unknownOperation.SetTargetIndex(targetContainer.UnknownIndex); unknownOperation.SetUndefined(); operationQueue.AddLast(unknownOperation); } }