/// <summary> /// Creates the new data from common ancestor. /// </summary> /// <param name="commonAncestor">The common ancestor.</param> private void createNewDataFromCommonAncestor(IReadonlyChangeTracker <IReadOnlySnapshotData> commonAncestor) { Data = Factories.SnapshotDataFactory.CreateNewInstanceWithData(commonAncestor.Container); writeableTargetData = Data.Writeable; writeableTargetData.ReinitializeTracker(commonAncestor.Container); }
/// <summary> /// Collects the single function changes. /// </summary> /// <param name="callSnapshot">The call snapshot.</param> /// <param name="tracker">The tracker.</param> protected void collectSingleFunctionChanges( Snapshot callSnapshot, IReadonlyChangeTracker <IReadOnlySnapshotData> tracker) { int functionCallLevel = tracker.CallLevel; bool done = false; while (!done && tracker != null && tracker.CallLevel == functionCallLevel) { if (tracker.ConnectionType != TrackerConnectionType.SUBPROGRAM_MERGE) { done = tracker.ConnectionType == TrackerConnectionType.CALL_EXTEND; CollectionMemoryUtils.AddAll(indexChanges, tracker.IndexChanges); tracker = tracker.PreviousTracker; } else { IReadonlyChangeTracker <IReadOnlySnapshotData> callTracker; if (tracker.TryGetCallTracker(callSnapshot, out callTracker)) { tracker = callTracker; } else { tracker = tracker.PreviousTracker; } } } }
/// <summary> /// Initializes a new instance of the <see cref="ChangeTracker{C}"/> class. /// </summary> /// <param name="trackerId">The tracker identifier.</param> /// <param name="container">The container.</param> /// <param name="previousTracker">The previous tracker.</param> public ChangeTracker(int trackerId, C container, IReadonlyChangeTracker <C> previousTracker) { ConnectionType = TrackerConnectionType.EXTEND; CallLevel = previousTracker != null ? previousTracker.CallLevel : Snapshot.GLOBAL_CALL_LEVEL; TrackerId = trackerId; Container = container; PreviousTracker = previousTracker; indexChanges = new HashSet <MemoryIndex>(); }
/// <summary> /// Merges the data. /// </summary> public void MergeData() { IReadonlyChangeTracker <IReadOnlySnapshotData> commonAncestor = collectDataChangesAndFindAncestor(); createNewDataFromCommonAncestor(commonAncestor); foreach (MemoryIndex memoryIndex in indexChanges) { mergeMemoryIndexData(memoryIndex); } }
/// <summary> /// Collects the information changes and find ancestor. /// </summary> /// <returns>Ancestor</returns> private IReadonlyChangeTracker <IReadOnlySnapshotData> collectInfoChangesAndFindAncestor() { CollectionMemoryUtils.AddAll(indexChanges, targetSnapshot.MergeInfo.GetIndexes()); IReadonlyChangeTracker <IReadOnlySnapshotData> ancestor = sourceSnapshots[0].Infos.Readonly.ReadonlyChangeTracker; for (int x = 1; x < sourceSnapshots.Count; x++) { Snapshot sourceSnapshot = sourceSnapshots[x]; ancestor = getFirstCommonAncestor(sourceSnapshot.Infos.Readonly.ReadonlyChangeTracker, ancestor); } return(ancestor); }
/// <summary> /// Creates the new structure from common ancestor. /// </summary> /// <param name="commonAncestor">The common ancestor.</param> private void createNewStructureFromCommonAncestor(IReadonlyChangeTracker <IReadOnlySnapshotStructure> commonAncestor) { Structure = Factories.SnapshotStructureFactory.CreateNewInstanceWithData(commonAncestor.Container); writeableTargetStructure = Structure.Writeable; targetStructure = writeableTargetStructure; writeableTargetStructure.ReinitializeTracker(commonAncestor.Container); // Initializes merge workers with newly created structure arrayWorker = new MergeArrayStructureWorker(writeableTargetStructure, this); aliasWorker = new MergeAliasStructureWorker(writeableTargetStructure, this); objectWorker = new MergeObjectsStructureWorker(writeableTargetStructure, this); }
/// <inheritdoc /> public void AddCallTracker(Snapshot callSnapshot, IReadonlyChangeTracker <C> callTracker) { if (callRouting == null) { callRouting = new Dictionary <Snapshot, IReadonlyChangeTracker <C> >(); } if (!callRouting.ContainsKey(callSnapshot)) { callRouting.Add(callSnapshot, callTracker); } else { callRouting[callSnapshot] = null; } }
/// <inheritdoc /> public bool TryGetCallTracker(Snapshot callSnapshot, out IReadonlyChangeTracker <C> callTracker) { if (callRouting != null) { if (callRouting.TryGetValue(callSnapshot, out callTracker)) { return(callTracker != null); } else { return(false); } } else { callTracker = null; return(false); } }
/// <summary> /// Collects the structure changes and find ancestor. /// </summary> /// <returns></returns> private IReadonlyChangeTracker <IReadOnlySnapshotStructure> collectStructureChangesAndFindAncestor() { SnapshotContext ancestorContext = snapshotContexts[0]; IReadonlyChangeTracker <IReadOnlySnapshotStructure> ancestor = ancestorContext.SourceStructure.ReadonlyChangeTracker; List <MemoryIndexTree> changes = new List <MemoryIndexTree>(); changes.Add(snapshotContexts[0].ChangedIndexesTree); for (int x = 1; x < snapshotContexts.Count; x++) { SnapshotContext context = snapshotContexts[x]; MemoryIndexTree currentChanges = context.ChangedIndexesTree; changes.Add(currentChanges); ancestor = getFirstCommonAncestor(context.SourceStructure.ReadonlyChangeTracker, ancestor, currentChanges, changes); } return(ancestor); }
/// <summary> /// Merges the structure. /// </summary> public void MergeStructure() { createSnapshotContexts(); IReadonlyChangeTracker <IReadOnlySnapshotStructure> commonAncestor = collectStructureChangesAndFindAncestor(); createNewStructureFromCommonAncestor(commonAncestor); createStackLevels(); mergeDeclarations(); mergeObjectDefinitions(); mergeMemoryStacksRoots(); processMergeOperations(); updateAliases(); ensureTrackingChanges(); }
/// <summary> /// Gets the first common ancestor. /// </summary> /// <param name="trackerA">The tracker a.</param> /// <param name="trackerB">The tracker b.</param> /// <returns>Common ancestor</returns> protected IReadonlyChangeTracker <IReadOnlySnapshotData> getFirstCommonAncestor( IReadonlyChangeTracker <IReadOnlySnapshotData> trackerA, IReadonlyChangeTracker <IReadOnlySnapshotData> trackerB ) { while (trackerA != trackerB) { if (trackerA == null || trackerB != null && trackerA.TrackerId < trackerB.TrackerId) { var swap = trackerA; trackerA = trackerB; trackerB = swap; } CollectionMemoryUtils.AddAll(indexChanges, trackerA.IndexChanges); trackerA = trackerA.PreviousTracker; } return(trackerA); }
/// <summary> /// Collects the single function changes. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="callSnapshot">The call snapshot.</param> /// <param name="tracker">The tracker.</param> /// <param name="currentChanges">The current changes.</param> /// <param name="changes">The changes.</param> protected void collectSingleFunctionChanges <T>( Snapshot callSnapshot, IReadonlyChangeTracker <T> tracker, MemoryIndexTree currentChanges, List <MemoryIndexTree> changes) where T : class { int functionCallLevel = tracker.CallLevel; bool done = false; while (!done && tracker != null && tracker.CallLevel == functionCallLevel) { if (tracker.ConnectionType != TrackerConnectionType.SUBPROGRAM_MERGE) { done = tracker.ConnectionType == TrackerConnectionType.CALL_EXTEND; CollectionMemoryUtils.AddAll(currentChanges, tracker.IndexChanges); CollectionMemoryUtils.AddAll(this.changeTree, tracker.IndexChanges); CollectionMemoryUtils.AddAllIfNotNull(functionChages, tracker.FunctionChanges); CollectionMemoryUtils.AddAllIfNotNull(classChanges, tracker.ClassChanges); tracker = tracker.PreviousTracker; } else { IReadonlyChangeTracker <T> callTracker; if (tracker.TryGetCallTracker(callSnapshot, out callTracker)) { tracker = callTracker; } else { tracker = tracker.PreviousTracker; } } } }
/// <summary> /// Gets the first common ancestor. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="trackerA">The tracker a.</param> /// <param name="trackerB">The tracker b.</param> /// <param name="currentChanges">The current changes.</param> /// <param name="changes">The changes.</param> /// <returns>Located ancestor</returns> protected IReadonlyChangeTracker <T> getFirstCommonAncestor <T>( IReadonlyChangeTracker <T> trackerA, IReadonlyChangeTracker <T> trackerB, MemoryIndexTree currentChanges, List <MemoryIndexTree> changes ) where T : class { bool swapped = false; while (trackerA != trackerB) { if (trackerA == null || trackerB != null && trackerA.TrackerId < trackerB.TrackerId) { var swap = trackerA; trackerA = trackerB; trackerB = swap; swapped = true; } CollectionMemoryUtils.AddAll(currentChanges, trackerA.IndexChanges); CollectionMemoryUtils.AddAll(this.changeTree, trackerA.IndexChanges); CollectionMemoryUtils.AddAllIfNotNull(functionChages, trackerA.FunctionChanges); CollectionMemoryUtils.AddAllIfNotNull(classChanges, trackerA.ClassChanges); if (swapped) { foreach (MemoryIndexTree tree in changes) { CollectionMemoryUtils.AddAll(tree, trackerA.IndexChanges); } } trackerA = trackerA.PreviousTracker; } return(trackerA); }
protected void collectChanges <T>( IReadonlyChangeTracker <T> trackerA, IReadonlyChangeTracker <T> trackerB, ICollection <MemoryIndex> indexChanges, ICollection <QualifiedName> functionChanges, ICollection <QualifiedName> classChanges) where T : class { while (trackerA != trackerB) { if (trackerA == null || trackerB != null && trackerA.TrackerId < trackerB.TrackerId) { var swap = trackerA; trackerA = trackerB; trackerB = swap; } CollectionMemoryUtils.AddAll(indexChanges, trackerA.IndexChanges); CollectionMemoryUtils.AddAllIfNotNull(functionChanges, trackerA.FunctionChanges); CollectionMemoryUtils.AddAllIfNotNull(classChanges, trackerA.ClassChanges); trackerA = trackerA.PreviousTracker; } }