private void mergeWithEmptyAssignedArray(AssociativeArray sourceArray, AssociativeArray targetArray) { // Get descriptors IArrayDescriptor sourceDescriptor = Worker.Structure.GetDescriptor(sourceArray); IArrayDescriptorBuilder targetDescriptorBuilder = Worker.Structure.GetDescriptor(targetArray).Builder(Worker.Structure); // Create child index and merge with empty node foreach (var item in sourceDescriptor.Indexes) { string name = item.Key; MemoryIndex index = item.Value; MemoryIndex createdIndex = TargetIndex.CreateIndex(name); targetDescriptorBuilder.AddIndex(name, createdIndex); Worker.AddOperation(new UnknownIndexMayAssign(Worker, index, createdIndex, MemoryEntryCollectorNode.GetEmptyNode(Worker.Snapshot))); } // Merge unknown index with empty node (unknown index was created in array initialization - scip new array) UnknownIndexMayAssign toUnknownAssignOperation = new UnknownIndexMayAssign(Worker, sourceDescriptor.UnknownIndex, targetDescriptorBuilder.UnknownIndex, MemoryEntryCollectorNode.GetEmptyNode(Worker.Snapshot)); toUnknownAssignOperation.CreateNewIndex = false; Worker.AddOperation(toUnknownAssignOperation); // Build and set modified target descriptor Worker.Structure.SetDescriptor(targetArray, targetDescriptorBuilder.Build(Worker.Structure)); }
/// <summary> /// Processes the index - traverse thru array or sets path to undefined. When memory location contains /// no array and undefined value new array is created. /// </summary> /// <param name="segment">The segment.</param> /// <param name="parentIndex">Index of the parent.</param> /// <param name="visitor">The visitor to process scalar values.</param> /// <param name="isMust">if set to <c>true</c> [is must].</param> private void processIndex(PathSegment segment, MemoryIndex parentIndex, IndexLocationVisitor visitor, bool isMust) { AssociativeArray arrayValue = null; bool processOtherValues = false; MemoryEntry entry; if (snapshot.Data.Readonly.TryGetMemoryEntry(parentIndex, out entry)) { if (snapshot.Structure.Readonly.TryGetArray(parentIndex, out arrayValue)) { processOtherValues = entry.Count > 1; } else if (entry.Count > 0) { processOtherValues = true; } else { entry = snapshot.EmptyEntry; processOtherValues = true; } } else { entry = snapshot.EmptyEntry; processOtherValues = true; snapshot.Structure.Readonly.TryGetArray(parentIndex, out arrayValue); } if (!snapshot.Structure.Locked && processOtherValues) { visitor.ProcessValues(parentIndex, entry.PossibleValues, isMust); ReadIndexVisitor valueVisitor = visitor.LastValueVisitor; bool removeUndefined = isMust; if (valueVisitor.ContainsDefinedValue || valueVisitor.ContainsAnyValue) { isMust = false; } if (valueVisitor.ContainsUndefinedValue) { if (arrayValue == null) { arrayValue = snapshot.CreateArray(parentIndex, isMust, removeUndefined); } else if (removeUndefined) { snapshot.RemoveUndefinedFromMemoryEntry(parentIndex); } } } if (arrayValue != null) { IArrayDescriptor descriptor = snapshot.Structure.Readonly.GetDescriptor(arrayValue); creatorVisitor.ArrayValue = arrayValue; processSegment(segment, descriptor, isMust); } }
/// <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); }
/// <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; } }
/// <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 source array. /// </summary> /// <param name="node">The node.</param> /// <param name="arrayValue">The array value.</param> /// <param name="values">The values.</param> private void processSourceArray(MemoryCollectorNode node, AssociativeArray arrayValue, ICollection <Value> values) { if (arrayValue != null) { IArrayDescriptor sourceArray = Structure.GetDescriptor(arrayValue); if (node.AnyChildNode == null) { node.CreateMemoryIndexAnyChild(sourceArray.UnknownIndex); } foreach (var item in sourceArray.Indexes) { string name = item.Key; MemoryIndex index = item.Value; if (!node.NamedChildNodes.ContainsKey(name)) { LocationCollectorNode newChild = node.CreateMemoryIndexChildFromAny(name, sourceArray.UnknownIndex); newChild.IsMust = node.IsMust; } } createArray(node, values); } else { testAndCreateImplicitArray(node, values); } }
private void mergeWithAssignedArray(AssociativeArray sourceArray, AssociativeArray targetArray) { // Get descriptors IArrayDescriptor sourceDescriptor = Worker.Structure.GetDescriptor(sourceArray); IArrayDescriptorBuilder targetDescriptorBuilder = Worker.Structure.GetDescriptor(targetArray).Builder(Worker.Structure); // Iterate source indexes which are not present in node foreach (var item in sourceDescriptor.Indexes) { string name = item.Key; MemoryIndex index = item.Value; if (!Node.NamedChildren.ContainsKey(name)) { // Index is present in source but not in node MemoryIndex createdIndex = TargetIndex.CreateIndex(name); targetDescriptorBuilder.AddIndex(name, createdIndex); Worker.AddOperation(new UnknownIndexMayAssign(Worker, index, createdIndex, MemoryEntryCollectorNode.GetEmptyNode(Worker.Snapshot))); } } // Iterate all child nodes foreach (var item in Node.NamedChildren) { string name = item.Key; MemoryEntryCollectorNode node = item.Value; if (sourceDescriptor.ContainsIndex(name)) { // Index is present in source and node MemoryIndex createdIndex = TargetIndex.CreateIndex(name); targetDescriptorBuilder.AddIndex(name, createdIndex); Worker.AddOperation(new UnknownIndexMayAssign(Worker, sourceDescriptor.GetIndex(name), createdIndex, node)); } else { // Index is present in node but not in source MemoryIndex createdIndex = TargetIndex.CreateIndex(name); targetDescriptorBuilder.AddIndex(name, createdIndex); Worker.AddOperation(new UnknownIndexMayAssign(Worker, sourceDescriptor.UnknownIndex, createdIndex, node)); } } // Merge unknown index with unknown node (unknown index was created in array initialization - scip new array) UnknownIndexMayAssign toUnknownAssignOperation = new UnknownIndexMayAssign(Worker, sourceDescriptor.UnknownIndex, targetDescriptorBuilder.UnknownIndex, Node.AnyChild); toUnknownAssignOperation.CreateNewIndex = false; Worker.AddOperation(toUnknownAssignOperation); // Build and set modified target descriptor Worker.Structure.SetDescriptor(targetArray, targetDescriptorBuilder.Build(Worker.Structure)); }
private void mergeWithAssignedArray(AssociativeArray arrayValue) { // Get descriptors IArrayDescriptor descriptor = Worker.Structure.GetDescriptor(arrayValue); IArrayDescriptorBuilder builder = Worker.Structure.GetDescriptor(arrayValue).Builder(Worker.Structure); // Iterate source indexes which are not present in node List <string> namesToRemove = new List <string>(); foreach (var item in descriptor.Indexes) { string name = item.Key; MemoryIndex index = item.Value; if (!Node.NamedChildren.ContainsKey(name)) { // Index is present in source but not in node Worker.AddOperation(new MemoryIndexDeleteAssignOperation(Worker, index)); namesToRemove.Add(name); } } // Safely removes nodes which are no longer used (prevents changes in lazy builder) foreach (string name in namesToRemove) { builder.RemoveIndex(name); } // Iterate all child nodes foreach (var item in Node.NamedChildren) { string name = item.Key; MemoryEntryCollectorNode node = item.Value; if (descriptor.ContainsIndex(name)) { // Index is present in source and node Worker.AddOperation(new MemoryIndexMustAssignOperation(Worker, descriptor.GetIndex(name), node)); } else { // Index is present in node but not in source MemoryIndex createdIndex = TargetIndex.CreateIndex(name); builder.AddIndex(name, createdIndex); Worker.AddOperation(new UndefinedMustAssignOperation(Worker, createdIndex, node)); } } // Merge unknown index with unknown node (unknown index was created in array initialization - scip new array) Worker.AddOperation(new MemoryIndexMustAssignOperation(Worker, descriptor.UnknownIndex, Node.AnyChild)); // Build and set modified target descriptor Worker.Structure.SetDescriptor(arrayValue, builder.Build(Worker.Structure)); }
private void mergeWithEmptyAssignedArray(AssociativeArray arrayValue) { IArrayDescriptor descriptor = Worker.Structure.GetDescriptor(arrayValue); foreach (var item in descriptor.Indexes) { string name = item.Key; MemoryIndex index = item.Value; Worker.AddOperation(new MemoryIndexMayAssignOperation(Worker, index, MemoryEntryCollectorNode.GetEmptyNode(Worker.Snapshot))); } Worker.AddOperation(new MemoryIndexMayAssignOperation(Worker, descriptor.UnknownIndex, MemoryEntryCollectorNode.GetEmptyNode(Worker.Snapshot))); }
/// <summary> /// Prepares operation for every descendant index and merge the array into one which will be /// stored in the target memory entry. /// </summary> /// <param name="operation">The operation.</param> /// <returns>Array where the input arrays is merged into.</returns> private Value mergeArrays(MergeOperation operation) { var structure = writeableStrucure; IArrayDescriptorBuilder builder = Factories.StructuralContainersFactories.ArrayDescriptorFactory.CreateArrayDescriptor(writeableStrucure, null, operation.TargetIndex).Builder(structure); builder.SetUnknownIndex(operation.TargetIndex.CreateUnknownIndex()); ContainerOperations collectVariables = new ContainerOperations(this, builder, operation.TargetIndex, builder.UnknownIndex); // Collecting possible indexes of merged array AssociativeArray targetArray = null; foreach (var operationData in operation.Indexes) { MemoryIndex index = operationData.Item1; Snapshot snapshot = operationData.Item2; AssociativeArray arrayValue; if (snapshot.Structure.Readonly.TryGetArray(index, out arrayValue)) { // Target array value will be the firs one if (targetArray == null) { if (index.Equals(operation.TargetIndex)) { targetArray = arrayValue; } } IArrayDescriptor descriptor = snapshot.Structure.Readonly.GetDescriptor(arrayValue); collectVariables.CollectIndexes(snapshot, index, descriptor); } else { collectVariables.SetUndefined(); } } if (targetArray == null) { targetArray = targetSnapshot.CreateArray(); } builder.SetArrayValue(targetArray); collectVariables.MergeContainers(); structure.SetArray(operation.TargetIndex, targetArray); structure.SetDescriptor(targetArray, builder.Build(structure)); return(targetArray); }
private void deleteArray(AssociativeArray arrayValue) { IArrayDescriptor oldDescriptor = Worker.Structure.GetDescriptor(arrayValue); foreach (var item in oldDescriptor.Indexes) { string name = item.Key; MemoryIndex index = item.Value; Worker.AddOperation(new MemoryIndexDeleteAssignOperation(Worker, index)); } Worker.AddOperation(new MemoryIndexDeleteAssignOperation(Worker, oldDescriptor.UnknownIndex)); Worker.Structure.RemoveArray(TargetIndex, arrayValue); }
/// <summary> /// Creates the array. /// </summary> /// <param name="node">The node.</param> /// <param name="values">The values.</param> /// <returns>New created array</returns> public AssociativeArray createArray(MemoryCollectorNode node, ICollection <Value> values) { AssociativeArray createdArrayValue = Snapshot.CreateArray(node.TargetIndex); values.Add(createdArrayValue); if (node.AnyChildNode != null) { IArrayDescriptor descriptor = Structure.GetDescriptor(createdArrayValue); node.AnyChildNode.TargetIndex = descriptor.UnknownIndex; } return(createdArrayValue); }
/// <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; }
/// <summary> /// Collects the index of the index from memory. /// </summary> /// <param name="collector">The collector.</param> /// <param name="indexSegment">The index segment.</param> /// <param name="index">The index.</param> protected void CollectIndexFromMemoryIndex(TreeIndexCollector collector, IndexPathSegment indexSegment, MemoryIndex index) { MemoryEntry entry = collector.GetMemoryEntry(index); this.ContainsUndefinedValue = entry.ContainsUndefinedValue; bool processOtherValues = false; AssociativeArray arrayValue; if (collector.Structure.TryGetArray(index, out arrayValue)) { if (entry.ContainsUndefinedValue) { processOtherValues = entry.Count > 2; } else { processOtherValues = entry.Count > 1; } IArrayDescriptor descriptor = collector.Structure.GetDescriptor(arrayValue); collector.CollectSegmentFromStructure(indexSegment, this, descriptor, !processOtherValues); } else if (entry.ContainsUndefinedValue) { processOtherValues = entry.Count > 1; this.HasNewImplicitArray = true; collector.CollectSegmentWithoutStructure(indexSegment, this, !processOtherValues); } else { processOtherValues = true; } if (processOtherValues) { collector.CollectIndexSegmentFromValues(indexSegment, this, entry.PossibleValues, true); } }
/// <summary> /// Processes the array value - create new copy of this level of memory tree. /// </summary> /// <param name="targetIndex">Index of the target.</param> /// <param name="value">The value.</param> /// <returns>Array value which should be inserted into target location.</returns> internal AssociativeArray ProcessArrayValue(MemoryIndex targetIndex, AssociativeArray value) { AssociativeArray arrayValue = snapshot.CreateArray(targetIndex, isMust); IArrayDescriptor sourceDescriptor = snapshot.Structure.Readonly.GetDescriptor(value); IArrayDescriptor targetDescriptor = snapshot.Structure.Readonly.GetDescriptor(arrayValue); CopyAliasState oldState = AliasState; AliasState = CopyAliasState.OnlyAliases; Copy(sourceDescriptor.UnknownIndex, targetDescriptor.UnknownIndex); AliasState = CopyAliasState.LinkWithIndex; foreach (var index in sourceDescriptor.Indexes) { MemoryIndex newIndex = snapshot.CreateIndex(index.Key, arrayValue, false, false); Copy(index.Value, newIndex); } AliasState = oldState; return(arrayValue); }
/// <summary> /// Tests the and create undefined children. /// </summary> /// <param name="node">The node.</param> private void testAndCreateUndefinedChildren(MemoryCollectorNode node) { if (node.HasUndefinedChildren) { AssociativeArray arrayValue = Structure.GetArray(node.TargetIndex); IArrayDescriptor oldDescriptor = Structure.GetDescriptor(arrayValue); IArrayDescriptorBuilder builder = oldDescriptor.Builder(Structure); foreach (var newChild in node.UndefinedChildren) { string childName = newChild.Item1; MemoryCollectorNode childNode = newChild.Item2; MemoryIndex index = node.TargetIndex.CreateIndex(childName); childNode.TargetIndex = index; builder.AddIndex(childName, index); } IArrayDescriptor newDescriptor = builder.Build(Structure); Structure.SetDescriptor(arrayValue, newDescriptor); } }
/// <summary> /// Initializes a new instance of the <see cref="ArrayTargetContainerContext"/> class. /// </summary> /// <param name="strucure">The strucure.</param> /// <param name="arrayDescriptor">The array descriptor.</param> public ArrayTargetContainerContext(IWriteableSnapshotStructure strucure, IArrayDescriptor arrayDescriptor) { this.arrayDescriptor = arrayDescriptor; this.strucure = strucure; }
/// <inheritdoc /> public override void SetDescriptor(AssociativeArray arrayvalue, IArrayDescriptor descriptor) { arrayDescriptors[arrayvalue] = descriptor; }
/// <inheritdoc /> public override bool TryGetDescriptor(AssociativeArray arrayValue, out IArrayDescriptor descriptor) { return(arrayDescriptors.TryGetValue(arrayValue, out descriptor)); }
/// <inheritdoc /> public abstract bool TryGetDescriptor(AssociativeArray arrayValue, out IArrayDescriptor descriptor);
/// <inheritdoc /> public abstract void SetDescriptor(AssociativeArray arrayvalue, IArrayDescriptor descriptor);
private AssociativeArray mergeArrays( MemoryIndex targetIndex, HashSet <AssociativeArray> arrays, bool includeUndefined) { AssociativeArray arrayValue; if (!targetSnapshot.Structure.Readonly.TryGetArray(targetIndex, out arrayValue)) { arrayValue = targetSnapshot.CreateArray(targetIndex); } IArrayDescriptor newDescriptor = targetSnapshot.Structure.Readonly.GetDescriptor(arrayValue); MergeOperation unknownMerge = new MergeOperation(newDescriptor.UnknownIndex); unknownMerge.SetUndefined(); addOperation(unknownMerge); HashSet <string> indexNames = new HashSet <string>(); foreach (AssociativeArray array in arrays) { foreach (Tuple <Snapshot, IArrayDescriptor> item in getIArrayDescriptor(array)) { Snapshot snapshot = item.Item1; IArrayDescriptor descriptor = item.Item2; unknownMerge.Add(descriptor.UnknownIndex, snapshot); foreach (var index in descriptor.Indexes) { indexNames.Add(index.Key); } } } foreach (string indexName in indexNames) { MergeOperation operation = new MergeOperation(); if (includeUndefined) { operation.SetUndefined(); } foreach (var array in arrays) { foreach (Tuple <Snapshot, IArrayDescriptor> item in getIArrayDescriptor(array)) { Snapshot snapshot = item.Item1; IArrayDescriptor descriptor = item.Item2; MemoryIndex sourceIndex; if (descriptor.TryGetIndex(indexName, out sourceIndex)) { operation.Add(sourceIndex, snapshot); } else { operation.Add(descriptor.UnknownIndex, snapshot); } } } MemoryIndex arrayIndex; if (!newDescriptor.TryGetIndex(indexName, out arrayIndex)) { arrayIndex = targetSnapshot.CreateIndex(indexName, arrayValue, true, false); } operation.SetTargetIndex(arrayIndex); addOperation(operation); } return(arrayValue); }
/// <inheritdoc /> public override void SetDescriptor(AssociativeArray arrayvalue, IArrayDescriptor descriptor) { arrayDescriptors[arrayvalue] = descriptor; changeTracker.ModifiedIndex(descriptor.ParentIndex); }
public void CollectChildren(MemoryEntryCollector collector) { if (Arrays != null && Arrays.Count > 0) { // Create new collection for named children NamedChildren = new Dictionary <string, MemoryEntryCollectorNode>(); // Any child node AnyChild = new MemoryEntryCollectorNode(); AnyChild.SourceIndexes = new List <SourceIndex>(); AnyChild.IsMust = false; collector.AddNode(AnyChild); // Collect child names and adds any child sources HashSet <string> names = new HashSet <string>(); List <Tuple <Snapshot, IArrayDescriptor> > sourceDescriptors = new List <Tuple <Snapshot, IArrayDescriptor> >(); foreach (AssociativeArray arrayValue in Arrays) { var descriptors = getIArrayDescriptors(collector, arrayValue); foreach (var tuple in descriptors) { sourceDescriptors.Add(tuple); Snapshot sourceSnapshot = tuple.Item1; IArrayDescriptor descriptor = tuple.Item2; AnyChild.SourceIndexes.Add(new SourceIndex(descriptor.UnknownIndex, sourceSnapshot)); foreach (var item in descriptor.Indexes) { names.Add(item.Key); } } } // Test whether new array as MAY or MUST bool mustHaveChildren = this.IsMust && mustHaveArray; mustHaveChildren &= (ScalarValues == null || ScalarValues.Count == 0); mustHaveChildren &= (Objects == null || Objects.Count == 0); // Iterates collected names and stors them into the structure foreach (string name in names) { MemoryEntryCollectorNode childNode = new MemoryEntryCollectorNode(); childNode.SourceIndexes = new List <SourceIndex>(); childNode.IsMust = mustHaveChildren; collector.AddNode(childNode); NamedChildren.Add(name, childNode); // Collect sources for named child foreach (var tuple in sourceDescriptors) { Snapshot sourceSnapshot = tuple.Item1; IArrayDescriptor descriptor = tuple.Item2; MemoryIndex index; if (descriptor.TryGetIndex(name, out index)) { childNode.SourceIndexes.Add(new SourceIndex(index, sourceSnapshot)); } else { childNode.IsMust = false; childNode.SourceIndexes.Add(new SourceIndex(descriptor.UnknownIndex, sourceSnapshot)); } } } } }
/// <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); } } } }