/// <summary> /// Processes the delete operation. /// </summary> /// <param name="operation">The operation.</param> /// <param name="operationAccessor">The operation accessor.</param> private void processDeleteOperation(MergeOperation operation, TrackingMergeWorkerOperationAccessor operationAccessor) { MemoryIndex targetIndex = operation.TargetIndex; IIndexDefinition targetDefinition; if (targetStructure.TryGetIndexDefinition(targetIndex, out targetDefinition)) { // Index is set in target snapshot if (targetDefinition.Array != null) { // Target contains array - continue deleting AssociativeArray targetArray = targetDefinition.Array; 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); } operationAccessor.provideCustomDeleteOperation(targetIndex, targetDefinition); } }
/// <summary> /// Processes the merge operations. /// </summary> protected void processMergeOperations() { // Process operations while queue is not empty while (operationQueue.Count > 0) { // Dequeue next operation MergeOperation operation = operationQueue.First.Value; operationQueue.RemoveFirst(); TrackingMergeWorkerOperationAccessor operationAccessor = createNewOperationAccessor(operation); if (operation.IsDeleteOperation) { processDeleteOperation(operation, operationAccessor); } else { processMergeOperation(operation, operationAccessor); } } }
/// <summary> /// Processes the merge operation. /// </summary> /// <param name="operation">The operation.</param> /// <param name="operationAccessor">The operation accessor.</param> /// <exception cref="System.Exception"> /// Error merging structure in readonly mode - undefined index + targetIndex /// or /// Error merging structure in readonly mode - target descriptor for + targetIndex /// </exception> private void processMergeOperation(MergeOperation operation, TrackingMergeWorkerOperationAccessor operationAccessor) { MemoryIndex targetIndex = operation.TargetIndex; AssociativeArray targetArray = null; List <ContainerContext> sourceArrays = new List <ContainerContext>(); bool arrayAlwaysDefined = !operation.IsUndefined; bool cotainsArray = false; // 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); // Provide custom operation for merge algorithm operationAccessor.addSource(operationContext, sourceDefinition); // Source array if (sourceDefinition.Array != null) { // Becomes target array when not set if (targetArray == null && sourceIndex.Equals(targetIndex)) { targetArray = sourceDefinition.Array; } cotainsArray = true; // Save source array to merge descriptors IArrayDescriptor descriptor = context.SourceStructure.GetDescriptor(sourceDefinition.Array); sourceArrays.Add(new ContainerContext(context, 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; } } IIndexDefinition targetDefinition; IArrayDescriptor targetArrayDescriptor = null; if (targetStructure.TryGetIndexDefinition(targetIndex, out targetDefinition)) { // Index is set in target snapshot if (targetDefinition.Array != null) { // Target contains array - continue merging targetArray = targetDefinition.Array; targetArrayDescriptor = targetStructure.GetDescriptor(targetArray); } } else { // Index is not set in target snapshot - create it if (isStructureWriteable) { writeableTargetStructure.NewIndex(targetIndex); } else { throw new Exception("Error merging structure in readonly mode - undefined index " + targetIndex); } } // Provide custom operation for merge algorithm operationAccessor.provideCustomOperation(targetIndex); // Process next array if (cotainsArray) { if (targetArray == null) { targetArray = targetSnapshot.CreateArray(); } if (targetArrayDescriptor == null) { // Target does not contain array - create and add new in target snapshot if (isStructureWriteable) { targetArrayDescriptor = Factories.StructuralContainersFactories.ArrayDescriptorFactory.CreateArrayDescriptor(writeableTargetStructure, targetArray, targetIndex); writeableTargetStructure.SetDescriptor(targetArray, targetArrayDescriptor); writeableTargetStructure.NewIndex(targetArrayDescriptor.UnknownIndex); writeableTargetStructure.SetArray(targetIndex, targetArray); } else { throw new Exception("Error merging structure in readonly mode - target descriptor for " + targetIndex); } } // Create context and merge descriptors var arrayContext = new ArrayTargetContainerContext(writeableTargetStructure, targetArrayDescriptor); createAndEnqueueOperations(arrayContext, operation.TreeNode, sourceArrays, arrayAlwaysDefined); if (isStructureWriteable) { // Ubdate current descriptor when changed IArrayDescriptor currentDescriptor = arrayContext.getCurrentDescriptor(); if (currentDescriptor != targetArrayDescriptor) { writeableTargetStructure.SetDescriptor(targetArray, currentDescriptor); } } } }