Exemplo n.º 1
0
        internal void PauseSessionUntilConflictsResolved(SessionWorker worker)
        {
            bool unresolvedConflictsFound = false;

            while (m_syncStateMachine.CurrentState == PipelineState.PausedByConflict)
            {
                if (ConflictManager.DoesSessionHaveUnresolvedConflicts(worker.LeftMigrationSourceid, worker.RightMigrationSourceid))
                {
                    if (!unresolvedConflictsFound)
                    {
                        TraceManager.TraceWarning("Session paused due to blocking conflict(s); resolve conflicts for this session to resume");
                        unresolvedConflictsFound = true;
                    }
                    // sleep at "PausedByConflict"
                    Thread.Sleep(ResumeAfterConflictPollingMilliSecs);
                }
                else
                {
                    if (unresolvedConflictsFound)
                    {
                        TraceManager.TraceInformation("Resuming session {0} that was previously paused by one or more conflicts", m_syncStateMachine.OwnerUniqueId);
                    }
                    break;
                }
            }
            m_syncStateMachine.TryTransit(PipelineSyncCommand.START_NEW_TRIP);
        }
Exemplo n.º 2
0
        private void Run()
        {
            TraceManager.TraceInformation(String.Format("Session worker thread [{0}] started", m_thread.Name));

            bool sessionFinishesSuccessfully = false;

            while (!sessionFinishesSuccessfully)
            {
                try
                {
                    MarkSessionRunning();
                    ProcessPipeline(WorkFlowType);
                    sessionFinishesSuccessfully = true;
                }
                catch (Exception ex)
                {
                    TraceManager.TraceError(String.Format("Session worker thread [{0}] exception: {1}",
                                                          m_thread.Name, ex is MissingErrorRouterException ? ex.InnerException : ex));

                    TraceManager.TraceInformation(string.Format("Restarting session in session worker thread [{0}]", m_thread.Name));
                }
            }

            TraceManager.TraceInformation(String.Format("Session worker thread [{0}] completed", m_thread.Name));
            // Signal SyncOrchestrator that this thread is done
            Event.Set();
        }
Exemplo n.º 3
0
        private void GenerateDeltaForForceSync(
            IForceSyncItemService forceSyncItemService,
            IForceSyncAnalysisProvider forceSyncAnalysisProvider)
        {
            int           batchSize        = 100;
            List <string> forceSyncItemIds = new List <string>();

            foreach (string forceSyncItemId in forceSyncItemService.GetItemsForForceSync())
            {
                TraceManager.TraceInformation(String.Format(CultureInfo.InvariantCulture,
                                                            "Will attempt to force sync work item {0} from migration source {1}",
                                                            forceSyncItemId, forceSyncItemService.MigrationSourceid));

                forceSyncItemIds.Add(forceSyncItemId);
                if (forceSyncItemIds.Count == batchSize)
                {
                    forceSyncAnalysisProvider.GenerateDeltaForForceSync(forceSyncItemIds);
                    forceSyncItemIds.Clear();
                }
            }
            if (forceSyncItemIds.Count > 0)
            {
                forceSyncAnalysisProvider.GenerateDeltaForForceSync(forceSyncItemIds);
            }
        }
Exemplo n.º 4
0
        public static ICollection <ProviderHandler> LoadProvider(params DirectoryInfo[] probingDirectories)
        {
            if (s_providers == null || s_providers.Count == 0)
            {
                // Initialize a list that will contain all plugin types discovered
                s_providers = new List <ProviderHandler>();

                if (probingDirectories != null)
                {
                    // Iterate over the probing directories and look for plugins
                    foreach (DirectoryInfo directory in probingDirectories)
                    {
                        Debug.Assert(directory.Exists, string.Format("Plugins directory does not exist: {0}", directory.FullName));
                        if (directory.Exists)
                        {
                            // Try to load plugins from each dll
                            foreach (FileInfo file in directory.GetFiles("*.dll"))
                            {
                                try
                                {
                                    // Load the dll into an assembly
                                    Assembly assembly = Assembly.LoadFrom(file.FullName);

                                    // Iterate over all types contained in the assembly
                                    foreach (Type type in assembly.GetTypes())
                                    {
                                        // Only consider public, concrete types that implement IProvider
                                        if (type.IsPublic && !type.IsAbstract && (type.GetInterface(typeof(IProvider).Name) != null))
                                        {
                                            ProviderHandler handler = ProviderHandler.FromType(type);
                                            if (null == handler ||
                                                handler.ProviderId == null ||
                                                handler.ProviderId == Guid.Empty)
                                            {
                                                continue;
                                            }

                                            s_providers.Add(handler);
                                            TraceManager.TraceInformation("Provider {0} {1} is available", handler.ProviderName, handler.ProviderId.ToString());
                                        }
                                    }
                                }
                                catch (ReflectionTypeLoadException)
                                {
                                    TraceManager.TraceInformation("Provider {0} is unavailable.  One or more of the requested types cannot be loaded.", file.FullName);
                                }
                                catch (Exception)
                                {
                                    // We try to load all .dll files and some of them just are not providers.
                                    // Just log a warning and move along
                                    TraceManager.TraceWarning("Failed to load the possible provider file: {0}", file.FullName);
                                }
                            }
                        }
                    }
                }
            }
            return(s_providers);
        }
 /// <summary>
 /// Remove all change groups in current session which are in progress.
 /// For delta table, this includes status of Delta, DeltaPending.
 /// For migration instruction, this includes Pending or Inprogress.
 /// </summary>
 private void RemoveInProgressChangeGroupsInSession(Guid sessionId)
 {
     using (RuntimeEntityModel context = RuntimeEntityModel.CreateInstance())
     {
         TraceManager.TraceInformation(
             "Deleting cached data for session '{0}'", sessionId);
         context.DeleteSessionCachedData(sessionId);
     }
 }
Exemplo n.º 6
0
        /// <summary>
        /// PostProcessing Delta Table entries after GeneratingMigrationInstruction
        /// </summary>
        /// <param name="targetSystemId">the target system SourceId of the current run through the pipeline</param>
        /// <param name="isBidirectional">true if the current session is bi-directional</param>
        internal void PostProcessDeltaTableEntries(Guid targetSystemId, bool isBidirectional)
        {
            Debug.Assert(
                DeltaTableMaintenanceService != null,
                "DeltaTableMaintenanceService is not properly initialized.");

            if (!isBidirectional)
            {
                TraceManager.TraceInformation("Marking as 'DeltaComplete' the target-side delta table for uni-directional session");
                DeltaTableMaintenanceService.BatchMarkDeltaTableEntriesAsDeltaCompleted(targetSystemId);
            }
        }
Exemplo n.º 7
0
        /// <summary>
        /// Discovers providers under the specified directories and loads them if used in MigrationSources
        /// defined in the configuration. It instantiates a unique provider instance for each MigrationSource.
        /// </summary>
        public Dictionary <Guid, ProviderHandler> LoadProvider(params DirectoryInfo[] probingDirectories)
        {
            IEnumerable <ProviderHandler> providers = Utility.LoadProvider(probingDirectories);

            // Initialize a list that will contain all plugin types discovered
            Dictionary <Guid, ProviderHandler> providerHandlers = new Dictionary <Guid, ProviderHandler>();

            foreach (ProviderHandler handler in providers)
            {
                try
                {
                    #region Register Add-Ins
                    IProvider provider = handler.Provider;
                    IAddin    addIn    = provider.GetService(typeof(IAddin)) as IAddin;
                    if (null != addIn)
                    {
                        m_AddinManagementService.RegisterAddin(addIn);
                    }
                    #endregion

                    Guid[] sourceIds = GetMigrationSourceId(handler.ProviderId);
                    if (sourceIds == null || sourceIds.Length == 0)
                    {
                        continue;
                    }

                    // try persist provider information to db
                    handler.FindSaveProvider();

                    // create a unique provider instance for each migration source
                    foreach (Guid migrationSource in sourceIds)
                    {
                        ProviderHandler providerHandler = new ProviderHandler(handler);

                        if (!providerHandlers.ContainsKey(migrationSource))
                        {
                            providerHandlers.Add(migrationSource, providerHandler);
                            TraceManager.TraceInformation("Provider {0} {1} is loaded", providerHandler.ProviderName, handler.ProviderId.ToString());
                        }
                    }
                }
                catch (Exception ex)
                {
                    TraceManager.TraceError("A failure occurred while trying to load the {0} Provider: {1}{2}",
                                            handler.ProviderName, Environment.NewLine, ex.ToString());
                }
            }

            return(providerHandlers);
        }
        /// <summary>
        /// Try saving the managed configuration (always check whether the configuration can be saved or not)
        /// </summary>
        /// <returns>The Id of the saved configuration</returns>
        /// <exception cref="Microsoft.TeamFoundation.Migration.BusinessModel.DuplicateConfigurationException" />
        public int TrySave()
        {
            if (CanEditAndSave)
            {
                return(SaveConfigWithoutCanSaveCheck());
            }
            else
            {
                var  pipeProxy = new MigrationServiceClient();
                bool sessionWasRunningBeforeSavingConfig = false;
                try
                {
                    var runningGroups = pipeProxy.GetRunningSessionGroups();
                    sessionWasRunningBeforeSavingConfig = runningGroups.Contains(Configuration.SessionGroupUniqueId);

                    if (sessionWasRunningBeforeSavingConfig)
                    {
                        pipeProxy.StopSessionGroup(Configuration.SessionGroupUniqueId);

                        if (!WaitForSessionGroupToStop(pipeProxy, TimeSpan.TicksPerMinute * 10))
                        {
                            throw new SavingUnsavableConfigurationException(Configuration);
                        }
                    }
                }
                catch (MigrationServiceEndpointNotFoundException)
                {
                    // WCF service is not active - session group shouldn't be running either
                }

                int saveResult = SaveConfigWithoutCanSaveCheck();

                if (sessionWasRunningBeforeSavingConfig)
                {
                    try
                    {
                        pipeProxy.StartSessionGroup(Configuration.SessionGroupUniqueId);
                    }
                    catch (MigrationServiceEndpointNotFoundException)
                    {
                        TraceManager.TraceInformation("Cannot restart Session Group '{0}' after updating its configuration.",
                                                      Configuration.SessionGroupUniqueId.ToString());
                    }
                }

                return(saveResult);
            }
        }
Exemplo n.º 9
0
        internal SessionWorker(
            Guid sessionId,
            ManualResetEvent sessionEvent,
            AnalysisEngine analysisEngine,
            MigrationEngine migrationEngine,
            LinkEngine linkEngine,
            Guid leftMigrationSourceId,
            Guid rightMigrationSourceId,
            WorkFlowType workFlowType,
            int secondsSyncWaitInterval,
            string threadName)
        {
            SessionId              = sessionId;
            Event                  = sessionEvent;
            AnalysisEngine         = analysisEngine;
            MigrationEngine        = migrationEngine;
            LinkEngine             = linkEngine;
            LeftMigrationSourceid  = leftMigrationSourceId;
            RightMigrationSourceid = rightMigrationSourceId;
            WorkFlowType           = workFlowType;
            m_threadName           = threadName;

            SqlSyncStateManager manager = SqlSyncStateManager.GetInstance();

            m_syncStateManager = manager;
            m_syncCommandQueue = manager;

            m_syncStateMachine = new SyncStateMachine(PipelineState.Default, new SyncStateTransitionAlgorithm(),
                                                      OwnerType.Session, sessionId, m_syncStateManager);
            m_orchPolicy = new SessionOrchestrationPolicy(WorkFlowType, m_syncStateMachine);

            try
            {
                checked
                {
                    MilliSecondsSyncWaitInterval = secondsSyncWaitInterval * 1000;
                }
            }
            catch (OverflowException)
            {
                MilliSecondsSyncWaitInterval = int.MaxValue;
                TraceManager.TraceInformation(
                    "The speicified interval of {0} minutes is too long for the system to handle. The interval is now changed to {1} minutes.",
                    secondsSyncWaitInterval / 60,
                    (int)(MilliSecondsSyncWaitInterval / 1000 / 60));
            }
        }
Exemplo n.º 10
0
        private void DetectBasicConflicts(ChangeGroupService targetChangeGroupService, Guid targetSystemId, Guid sourceSystemId)
        {
            TraceManager.TraceInformation("Starting basic conflict detection");
            if (null == m_basicConflictAnalysisService)
            {
                return;
            }

            m_basicConflictAnalysisService.Configuration            = m_session.Configuration;
            m_basicConflictAnalysisService.TargetChangeGroupService = targetChangeGroupService;
            m_basicConflictAnalysisService.ConflictManager          = m_serviceContainers[targetSystemId].GetService(typeof(ConflictManager)) as ConflictManager;
            m_basicConflictAnalysisService.TranslationService       = m_translationService;
            m_basicConflictAnalysisService.TargetSystemId           = targetSystemId;
            m_basicConflictAnalysisService.SourceSystemId           = sourceSystemId;
            m_basicConflictAnalysisService.Analyze();
            TraceManager.TraceInformation("Finishing basic conflict detection");
        }
Exemplo n.º 11
0
        private void ProviderDetectConflicts(Guid targetSystemId, ChangeGroupService targetChangeGroupService)
        {
            Debug.Assert(m_serviceContainers.ContainsKey(targetSystemId),
                         string.Format(MigrationToolkitResources.UnknownSourceId, targetSystemId));

            IAnalysisProvider targetAnalysisProvider;

            if (!m_analysisProviders.TryGetValue(targetSystemId, out targetAnalysisProvider))
            {
                throw new MigrationException(string.Format(
                                                 MigrationToolkitResources.Culture,
                                                 MigrationToolkitResources.UnknownSourceId,
                                                 targetSystemId));
            }

            try
            {
                int pageNumber = 0;
                IEnumerable <ChangeGroup> changeGroups;
                do
                {
                    TraceManager.TraceInformation("Loading {0} ChangeGroup(s)", m_pageSize);
                    changeGroups = targetChangeGroupService.NextMigrationInstructionTablePage(pageNumber++, m_pageSize, true, false);

                    foreach (ChangeGroup nextChangeGroup in changeGroups)
                    {
                        TraceManager.TraceInformation("Target AnalysisProvider detecting conflicts in ChangeGroup #{0}", nextChangeGroup.ChangeGroupId);
                        targetAnalysisProvider.DetectConflicts(nextChangeGroup);
                    }
                }while (changeGroups.Count() == m_pageSize);
            }
            catch (MigrationUnresolvedConflictException)
            {
                // We have already created an unresolved conflict, just return.
                return;
            }
            catch (Exception e)
            {
                ConflictManager manager = m_serviceContainers[targetSystemId].GetService(typeof(ConflictManager)) as ConflictManager;
                ErrorManager.TryHandleException(e, manager);
            }
        }
Exemplo n.º 12
0
        /// <summary>
        /// Remove all change groups in current session which are in progress.
        /// For delta table, this includes status of Delta, DeltaPending.
        /// For migration instruction, this includes Pending or Inprogress.
        /// </summary>
        public override void RemoveInProgressChangeGroups()
        {
            Guid sessionUniqueId = new Guid(Session.SessionUniqueId);

            using (RuntimeEntityModel context = RuntimeEntityModel.CreateInstance())
            {
                IQueryable <RTChangeGroup> query;

                query = (from cg in context.RTChangeGroupSet
                         where cg.SessionUniqueId.Equals(sessionUniqueId) &&
                         ((cg.SourceUniqueId.Equals(SourceId) && (cg.Status == (int)ChangeStatus.Delta || cg.Status == (int)ChangeStatus.DeltaPending)) ||
                          (cg.SourceUniqueId.Equals(OtherSideChangeGroupManager.SourceId) &&
                           (cg.Status == (int)ChangeStatus.InProgress || cg.Status == (int)ChangeStatus.Pending ||
                            cg.Status == (int)ChangeStatus.PendingConflictDetection || cg.Status == (int)ChangeStatus.AnalysisMigrationInstruction)))
                         select cg);
                foreach (RTChangeGroup rtChangeGroup in query)
                {
                    rtChangeGroup.Status = (int)ChangeStatus.Obsolete;
                    TraceManager.TraceInformation("In-progress changegroup {0} will be marked as obselete", rtChangeGroup.Id);
                }
                context.TrySaveChanges();
            }
        }
        private void UpdatePerItemLinkChangeGroupsByCheckingRelatedItemRecords(
            string sourceItemUri,
            LinkChangeGroup group,
            ILinkProvider linkProvider,
            bool createDeleteActionImplicitly)
        {
            var queryByItem          = QueryByItem(sourceItemUri);
            var perItemExistingLinks = from link in queryByItem
                                       where link.RelationshipExistsOnServer
                                       select link;

            if (perItemExistingLinks.Count() == 0)
            {
                // no link existed before, all 'add' link actions should be pushed to the other side
                // AND we are going to record these links as existing on this side now
                AddLinks(group.Actions);
            }
            else
            {
                // check the delta link change actions

                // this list contains all the actions that do not need to push into the pipeline
                List <LinkChangeAction> actionThatEstablishExistingLinkRelationship = new List <LinkChangeAction>();
                foreach (LinkChangeAction action in group.Actions)
                {
                    if (action.Link.LinkType.GetsActionsFromLinkChangeHistory)
                    {
                        // For link types that can provide a history of link changes, we don't need to keep track of related artifact metadata
                        // so continue to the next LinkChangeAction
                        continue;
                    }
                    Debug.Assert(sourceItemUri.Equals(action.Link.SourceArtifact.Uri), "link of different action exists in the same group");
                    var linkQuery = from l in perItemExistingLinks
                                    where l.Relationship.Equals(action.Link.LinkType.ReferenceName) &&
                                    l.RelatedArtifactId.Equals(action.Link.TargetArtifact.Uri)
                                    select l;

                    if (action.ChangeActionId.Equals(WellKnownChangeActionId.Add))
                    {
                        if (linkQuery.Count() > 0)
                        {
                            if (!linkQuery.First().OtherProperty.HasValue)
                            {
                                // link lock property is not available - required by backward-compability
                                UpdateLink(action, true);
                            }
                            else
                            {
                                bool linkInStoreHasLock = (((WorkItemLinkStore.LinkLockStatus)linkQuery.First().OtherProperty.Value) == WorkItemLinkStore.LinkLockStatus.Locked);

                                if (action.Link.IsLocked == linkInStoreHasLock)
                                {
                                    // link already exist and lock-property matches - no need to push to the other side
                                    actionThatEstablishExistingLinkRelationship.Add(action);
                                }
                                else
                                {
                                    UpdateLink(action, true);
                                }
                            }
                        }
                        else
                        {
                            // link does not exist, keep it and push through the pipeline
                            // AND we are going to record these links as existing on this side now
                            UpdateLink(action, true);
                        }
                    }
                    else // delete
                    {
                        if (linkQuery.Count() > 0)
                        {
                            // link exists, so we will mark in our store that it no longer exists
                            UpdateLink(action, false);
                        }
                        else
                        {
                            // link does not exist, no need to migrate this action
                            actionThatEstablishExistingLinkRelationship.Add(action);
                        }
                    }
                }

                // make sure we generate "Delete Link" action for ones that exist in the our recorded link table but is not included
                // in delta link actions
                List <LinkChangeAction> deletionActions = new List <LinkChangeAction>();
                if (createDeleteActionImplicitly)
                {
                    foreach (var recordedExistingLink in perItemExistingLinks)
                    {
                        Debug.Assert(linkProvider.SupportedLinkTypes.ContainsKey(recordedExistingLink.Relationship),
                                     "linkProvider.SupportedLinkTypes.ContainsKey(recordedExistingLink.Relationship) returns false");
                        LinkType linkType = linkProvider.SupportedLinkTypes[recordedExistingLink.Relationship];
                        if (linkType.GetsActionsFromLinkChangeHistory)
                        {
                            // The link type is one that support link change history, so we ignore the contents of the
                            // RelatedArtifactTable and rely on the link change history instead.
                            continue;
                        }

                        bool recordedActionInGroup = false;
                        foreach (LinkChangeAction action in group.Actions)
                        {
                            if (action.Link.LinkType.ReferenceName.Equals(recordedExistingLink.Relationship, StringComparison.OrdinalIgnoreCase) &&
                                action.Link.TargetArtifact.Uri.Equals(recordedExistingLink.RelatedArtifactId, StringComparison.OrdinalIgnoreCase))
                            {
                                recordedActionInGroup = true;
                                break;
                            }
                        }

                        if (!recordedActionInGroup)
                        {
                            TraceManager.TraceInformation("Link '{0}'->'{1}' ({2}) appears to have been deleted - generating link deletion action to be migrated",
                                                          recordedExistingLink.ItemId, recordedExistingLink.RelatedArtifactId, recordedExistingLink.Relationship);

                            LinkChangeAction linkDeleteAction = linkType.CreateLinkDeletionAction(
                                recordedExistingLink.ItemId, recordedExistingLink.RelatedArtifactId, recordedExistingLink.Relationship);

                            if (null != linkDeleteAction)
                            {
                                deletionActions.Add(linkDeleteAction);
                            }

                            recordedExistingLink.RelationshipExistsOnServer = false;
                        }
                    }
                }

                if (actionThatEstablishExistingLinkRelationship.Count > 0)
                {
                    foreach (LinkChangeAction actionToDelete in actionThatEstablishExistingLinkRelationship)
                    {
                        group.DeleteChangeAction(actionToDelete);
                    }
                }

                if (deletionActions.Count > 0)
                {
                    group.PrependActions(deletionActions);
                }
            }

            m_context.TrySaveChanges();
        }
        internal void Migrate(Guid targetSideSourceId, SessionOrchestrationPolicy orchPolicy)
        {
            try
            {
                Debug.Assert(m_serviceContainers.ContainsKey(targetSideSourceId), string.Format(MigrationToolkitResources.UnknownSourceId, targetSideSourceId));

                ChangeGroupService changegroupService = (ChangeGroupService)m_serviceContainers[targetSideSourceId].GetService(
                    typeof(ChangeGroupService));
                Debug.Assert(changegroupService != null, string.Format("Change group service on {0} is not loaded", targetSideSourceId));

                changegroupService.DemoteInProgressActionsToPending();

                int pageNumber = 0;
                IEnumerable <ChangeGroup> changeGroups = null;

                long?firstConflictedChangeGroupId = null;
                if (StopMigrationEngineOnBasicConflict)
                {
                    firstConflictedChangeGroupId = changegroupService.GetFirstConflictedChangeGroup(ChangeStatus.Pending);
                }

                do
                {
                    // NOTE: we do not increment pageNumber here, because the processed ChangeGroups are marked "Complete" and no longer
                    //       appear in the table
                    TraceManager.TraceInformation("Loading {0} ChangeGroup(s)", m_pageSize);
                    changeGroups = changegroupService.NextMigrationInstructionTablePage(pageNumber, m_pageSize, false, false);

                    foreach (ChangeGroup nextChangeGroup in changeGroups)
                    {
                        if (firstConflictedChangeGroupId.HasValue &&
                            firstConflictedChangeGroupId <= nextChangeGroup.ChangeGroupId)
                        {
                            // we should not process any conflicted change group or the following ones
                            // if StopMigrationEngineOnBasicConflict is the policy
                            return;
                        }

                        //ToDo Session.OnMigratingChangeStarting(args);
                        TraceManager.TraceInformation("Processing ChangeGroup #{0}", nextChangeGroup.ChangeGroupId);
                        ProcessMigrInstructionTableEntry(nextChangeGroup, targetSideSourceId);
                        nextChangeGroup.UpdateStatus(ChangeStatus.InProgress);

                        if (NoActiveMigrationInstructionInChangeGroup(nextChangeGroup))
                        {
                            nextChangeGroup.Complete();
                            continue;
                        }

                        ConversionResult result;
                        try
                        {
                            result = m_migrationProviders[targetSideSourceId].ProcessChangeGroup(nextChangeGroup);
                        }
                        catch (MigrationUnresolvedConflictException)
                        {
                            // We have already created an unresolved conflict, just return.
                            return;
                        }
                        catch (Exception e)
                        {
                            ConflictManager manager = m_serviceContainers[targetSideSourceId].GetService(typeof(ConflictManager)) as ConflictManager;
                            ErrorManager.TryHandleException(e, manager);
                            return;
                        }

                        if (!result.ContinueProcessing)
                        {
                            return;
                        }

                        if (!string.IsNullOrEmpty(result.ChangeId))
                        {
                            FinishChangeGroupMigration(nextChangeGroup, result);
                            InvokePostChangeGroupMigrationAddins(targetSideSourceId, nextChangeGroup);
                        }
                        orchPolicy.Check();
                    }
                }while (changeGroups.Count() == m_pageSize);
            }
            catch (Microsoft.TeamFoundation.Migration.Toolkit.SessionOrchestrationPolicy.StopSingleTripException)
            {
                throw;
            }
            catch (Microsoft.TeamFoundation.Migration.Toolkit.SessionOrchestrationPolicy.StopSessionException)
            {
                throw;
            }
            catch (Exception e)
            {
                ConflictManager manager = m_serviceContainers[targetSideSourceId].GetService(typeof(ConflictManager)) as ConflictManager;
                ErrorManager.TryHandleException(e, manager);
            }
        }
Exemplo n.º 15
0
        private void ProcessPipeline(WorkFlowType workFlowType)
        {
            bool bidirection = IsBidirectionalWorkFlowType(workFlowType);
            bool leftToRightContextSyncNeeded = IsLeftToRightContextSyncNeeded(workFlowType);
            bool rightToLeftContextSyncNeeded = IsRightToLeftContextSyncNeeded(workFlowType);

            do
            {
                // always notifying the listeners the pipeline is (re)starting
                SessionControlResume(this, new SessionControlEventArgs());

                try
                {
                    #region ----- LEFT TO RIGHT -----
                    OneDirectionProcessPipeline(true, LeftMigrationSourceid, RightMigrationSourceid, leftToRightContextSyncNeeded, bidirection);
                    #endregion

                    TraceManager.TraceInformation("");

                    #region ----- RIGHT TO LEFT -----
                    if (bidirection)
                    {
                        OneDirectionProcessPipeline(false, RightMigrationSourceid, LeftMigrationSourceid, rightToLeftContextSyncNeeded, bidirection);
                    }
                    else
                    {
                        CleanupDeltaTable(RightMigrationSourceid);
                    }
                    #endregion

                    #region ----- The current round-trip is stopping -----
                    if (m_syncStateMachine.TryTransit(PipelineSyncCommand.STOP_CURRENT_TRIP))
                    {
                        m_syncStateMachine.CommandTransitFinished(PipelineSyncCommand.STOP_CURRENT_TRIP);
                    }
                    #endregion
                }
                catch (SessionOrchestrationPolicy.StopSessionException)
                {
                    TraceManager.TraceInformation("{0}: Session aborted!", m_thread.Name);
                    return;
                }
                catch (SessionOrchestrationPolicy.StopSingleTripException)
                {
                    // When Stop is requested, we continue and let the policy to decide
                    // whether it should start another round trip or not
                    TraceManager.TraceInformation("{0}: Session stopped!", m_thread.Name);
                    continue;
                }
                catch (Exception)
                {
                    throw;
                }

                switch (workFlowType.Frequency)
                {
                case Frequency.ContinuousAutomatic:
                    TraceManager.TraceInformation("{0}: Sync is done!", m_thread.Name);
                    TraceManager.TraceInformation("{0}: Waiting {1} seconds before next synchronization",
                                                  m_thread.Name,
                                                  MilliSecondsSyncWaitInterval / 1000);
                    break;

                case Frequency.ContinuousManual:
                case Frequency.OneTime:
                    TraceManager.TraceInformation("{0}: Migration is done!", m_thread.Name);
                    MigrationSessionCompleted();
                    break;

                default:
                    throw new ArgumentException("m_orchPolicy.WorkFlowType.Frequency");
                }
            } while (m_orchPolicy.TryStartNextRoundTrip(MilliSecondsSyncWaitInterval));
        }
Exemplo n.º 16
0
        private void OneDirectionProcessPipeline(
            bool isLeftToRight,
            Guid sourceMigrationSourceId,
            Guid targetMigrationSourceId,
            bool contextSyncNeeded,
            bool bidirection)
        {
            try
            {
                m_orchPolicy.Check();
                AnalysisEngine.SourceMigrationSourceId = sourceMigrationSourceId;
                AnalysisEngine.InvokePreAnalysisAddins(sourceMigrationSourceId);

                if (!AnalysisEngine.InvokeProceedToAnalysisOnAnalysisAddins(sourceMigrationSourceId))
                {
                    // In case any of the AnalysisAddins perform cleanup in the PostAnalysis method
                    AnalysisEngine.InvokePostAnalysisAddins(sourceMigrationSourceId);
                    return;
                }

                TraceManager.TraceInformation("Pipeline flow from {0} to {1}", sourceMigrationSourceId, targetMigrationSourceId);
                if (contextSyncNeeded)
                {
                    TraceManager.TraceInformation("Generating context info tables for the migration source {0}", sourceMigrationSourceId);
                    AnalysisEngine.GenerateContextInfoTables(sourceMigrationSourceId);
                    m_orchPolicy.Check();
                }

                TraceManager.TraceInformation("Generating delta tables for the migration source {0}", sourceMigrationSourceId);
                AnalysisEngine.GenerateDeltaTables(sourceMigrationSourceId);
                m_orchPolicy.Check();

                AnalysisEngine.InvokePostDeltaComputationAddins(sourceMigrationSourceId);

                TraceManager.TraceInformation("Generating linking delta for the migration source {0}", sourceMigrationSourceId);
                LinkEngine.GenerateLinkDelta(SessionId, sourceMigrationSourceId);
                m_orchPolicy.Check();

                AnalysisEngine.InvokePostAnalysisAddins(sourceMigrationSourceId);

                //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                // Above: data collection at source side                                                                            //
                // Below: data migration/submission at target side                                                                  //
                //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

                MigrationEngine.InvokePreMigrationAddins(targetMigrationSourceId);

                if (contextSyncNeeded)
                {
                    TraceManager.TraceInformation("Establishing context for the migration source {0}", targetMigrationSourceId);
                    MigrationEngine.EstablishContext(targetMigrationSourceId);
                    m_orchPolicy.Check();
                }

                if (!AnalysisEngine.DisableTargetAnalysis)
                {
                    TraceManager.TraceInformation("Generating delta tables for the migration source {0}", targetMigrationSourceId);
                    AnalysisEngine.GenerateDeltaTables(targetMigrationSourceId);
                    m_orchPolicy.Check();
                }

                TraceManager.TraceInformation("Generating migration instructions for the migration source {0}", targetMigrationSourceId);
                AnalysisEngine.GenerateMigrationInstructions(targetMigrationSourceId);
                m_orchPolicy.Check();

                TraceManager.TraceInformation("Post-processing delta table entries from the migration source {0}", targetMigrationSourceId);
                AnalysisEngine.PostProcessDeltaTableEntries(targetMigrationSourceId, bidirection);
                m_orchPolicy.Check();

                TraceManager.TraceInformation("Migrating to the migration source {0}", targetMigrationSourceId);
                MigrationEngine.Migrate(targetMigrationSourceId, m_orchPolicy);
                m_orchPolicy.Check();

                MigrationEngine.InvokePostMigrationAddins(targetMigrationSourceId);

                TraceManager.TraceInformation("Processing linking delta");
                LinkEngine.AnalyzeLinkDelta(SessionId, sourceMigrationSourceId, bidirection);
                m_orchPolicy.Check();

                TraceManager.TraceInformation("Migrating links to the migration source {0}", targetMigrationSourceId);
                LinkEngine.MigrateLinks(SessionId, targetMigrationSourceId);
                m_orchPolicy.Check();
            }
            finally
            {
                // Record a sync point in the database
                try
                {
                    RecordSyncPoint(isLeftToRight, sourceMigrationSourceId, targetMigrationSourceId);
                }
                catch (Exception ex)
                {
                    TraceManager.TraceWarning("{0}: Unable to record SyncPoint data due to exception: {1}", m_thread.Name, ex.ToString());
                }
            }
        }
Exemplo n.º 17
0
        /// <summary>
        /// Generate migration instructions
        /// </summary>
        internal void GenerateMigrationInstructions(Guid targetSystemId)
        {
            try
            {
                // Given target system, find change group service for source and for ourselves...
                ConfigurationService configurationService = m_serviceContainers[targetSystemId].GetService(typeof(ConfigurationService)) as ConfigurationService;

                // ToDo, not sure, we can probably just pass in ource system id to let target change group service to load it. But source/target may be different, not sqlchangegroupmanager
                ChangeGroupService sourceChangeGroupService = m_serviceContainers[configurationService.MigrationPeer].GetService(typeof(ChangeGroupService)) as ChangeGroupService;
                ChangeGroupService targetChangeGroupService = m_serviceContainers[targetSystemId].GetService(typeof(ChangeGroupService)) as ChangeGroupService;

                // CopySourceDeltaTableToTarget
                //ChangeGroup deltaTableEntry;

                if (StopMigrationEngineOnBasicConflict)
                {
                    // if one of the delta table entry on source side is conflicted, we stop
                    long?firstConflictedChangeGroupId = sourceChangeGroupService.GetFirstConflictedChangeGroup(ChangeStatus.DeltaPending);
                    if (firstConflictedChangeGroupId.HasValue)
                    {
                        return;
                    }

                    // if one of the migration instruction for target side is conflict, we also stop
                    firstConflictedChangeGroupId = targetChangeGroupService.GetFirstConflictedChangeGroup(ChangeStatus.Pending);
                    if (firstConflictedChangeGroupId.HasValue)
                    {
                        return;
                    }
                }

                ChangeActionRegistrationService changeActionRegistrationService =
                    m_serviceContainers[targetSystemId].GetService(typeof(ChangeActionRegistrationService)) as ChangeActionRegistrationService;

                int pageNumber = 0;
                IEnumerable <ChangeGroup> changeGroups;
                do
                {
                    // NOTE: we do not increment pageNumber here, because the processed ChangeGroups are marked "DeltaComplete" and no longer
                    //       appear in the delta table
                    changeGroups = sourceChangeGroupService.NextDeltaTablePage(pageNumber, m_pageSize, false);
                    foreach (ChangeGroup deltaTableEntry in changeGroups)
                    {
                        TraceManager.TraceInformation(string.Format(
                                                          "Generating migration instruction for ChangeGroup {0}",
                                                          deltaTableEntry.ChangeGroupId));

                        ChangeGroup migrationInstructionChangeGroup = targetChangeGroupService.CreateChangeGroupForMigrationInstructionTable(deltaTableEntry);

                        // NOTE:
                        // migration instruction change group is created using the target change group manager/service
                        // however, the MigrationItems in it are created by the source-side adapter
                        // by setting the UseOtherSideMigrationItemSerializers flag, we tell this change group to use the source-side change group manager
                        // to find the registered IMigrationItem serializer to persist these MigrationItems
                        migrationInstructionChangeGroup.UseOtherSideMigrationItemSerializers = true;

                        migrationInstructionChangeGroup.ReflectedChangeGroupId = deltaTableEntry.ChangeGroupId;

                        foreach (MigrationAction action in deltaTableEntry.Actions)
                        {
                            try
                            {
                                BeforeCopyDeltaTableEntryToMigrationInstructionTable(action, configurationService.MigrationPeer);
                            }
                            catch (UnmappedWorkItemTypeException unmappedWITEx)
                            {
                                ConflictManager conflictManager =
                                    m_serviceContainers[configurationService.MigrationPeer].GetService(typeof(ConflictManager)) as ConflictManager;

                                var conflict = WITUnmappedWITConflictType.CreateConflict(unmappedWITEx.SourceWorkItemType, action);

                                List <MigrationAction> actions;
                                var result = conflictManager.TryResolveNewConflict(conflictManager.SourceId, conflict, out actions);

                                if (!result.Resolved)
                                {
                                    continue;
                                }
                                else
                                {
                                    if (result.ResolutionType == ConflictResolutionType.SkipConflictedChangeAction)
                                    {
                                        action.State = ActionState.Skipped;
                                        continue;
                                    }
                                    else
                                    {
                                        // NOTE:
                                        // So far this conflict can only be:
                                        // 1. manually resolved (skipped) AFTER
                                        //    the configuration is updated with the requirement WIT mapping;
                                        // 2. skipping the conflicted migration action (i.e. not migrating the source
                                        //    Work Item type.
                                        Debug.Assert(
                                            false,
                                            string.Format("WITUnmappedWITConflict is auto-resolved. Skipping this assertion will SKIP the original conflicted action '{0}'.",
                                                          action.ActionId.ToString()));
                                        action.State = ActionState.Skipped;
                                        continue;
                                    }
                                }
                            }

                            if (action.State == ActionState.Skipped || action.ChangeGroup.ContainsBackloggedAction)
                            {
                                continue;
                            }
                            ChangeActionHandler actionHandler;
                            if (changeActionRegistrationService.TryGetChangeActionHandler(action.Action, action.ItemTypeReferenceName, out actionHandler))
                            {
                                try
                                {
                                    actionHandler(action, migrationInstructionChangeGroup);
                                }
                                catch (MigrationUnresolvedConflictException)
                                {
                                    // We have already created an unresolved conflict, just return.
                                    return;
                                }
                                catch (Exception e)
                                {
                                    ConflictManager manager = m_serviceContainers[targetSystemId].GetService(typeof(ConflictManager)) as ConflictManager;
                                    ErrorManager.TryHandleException(e, manager);
                                }
                            }
                            else
                            {
                                string            analysisProviderName;
                                IAnalysisProvider analysisProvider;
                                if (m_analysisProviders.TryGetValue(targetSystemId, out analysisProvider))
                                {
                                    analysisProviderName = analysisProvider.GetType().ToString();
                                }
                                else
                                {
                                    Debug.Fail("Unable to find IAnalysisProvider with Id: " + targetSystemId);
                                    analysisProviderName = "Unknown";
                                }
                                throw new MigrationException(
                                          string.Format(MigrationToolkitResources.Culture, MigrationToolkitResources.UnknownChangeAction,
                                                        action.Action.ToString(), analysisProviderName));
                            }
                        }

                        if (!migrationInstructionChangeGroup.ContainsBackloggedAction &&
                            migrationInstructionChangeGroup.Actions.Count > 0)
                        {
                            ChangeStatus status = migrationInstructionChangeGroup.Status;
                            migrationInstructionChangeGroup.Status = ChangeStatus.ChangeCreationInProgress;
                            migrationInstructionChangeGroup.Owner  = deltaTableEntry.Owner; // owner may be translated too
                            // Save the partial Change group into DB.
                            migrationInstructionChangeGroup.Save();

                            // Commit the status change together.
                            migrationInstructionChangeGroup.Status = status;
                            deltaTableEntry.Status = ChangeStatus.DeltaComplete;
                            migrationInstructionChangeGroup.Manager.BatchUpdateStatus(
                                new ChangeGroup[] { migrationInstructionChangeGroup, deltaTableEntry });
                        }
                        else
                        {
                            // If all change actions in the delta table entry are skipped.
                            // Just mark the delta table entry as completed.
                            deltaTableEntry.UpdateStatus(ChangeStatus.DeltaComplete);
                        }

                        if (this.StopRequested)
                        {
                            return;
                        }
                    }
                }while (changeGroups.Count() == m_pageSize);

                DetectBasicConflicts(targetChangeGroupService, targetSystemId, configurationService.MigrationPeer);

                if (this.StopRequested)
                {
                    return;
                }

                ProviderDetectConflicts(targetSystemId, targetChangeGroupService);

                if (this.StopRequested)
                {
                    return;
                }

                // dispose the target side delta table entries after we've done all conflict analysis
                targetChangeGroupService.BatchMarkMigrationInstructionsAsPending();
            }
            catch (Exception e)
            {
                ConflictManager manager = m_serviceContainers[targetSystemId].GetService(typeof(ConflictManager)) as ConflictManager;
                ErrorManager.TryHandleException(e, manager);
            }
        }
Exemplo n.º 18
0
        // Insert a row into the SYNC_POINT table
        private void RecordSyncPoint(
            bool isLeftToRight,
            Guid sourceMigrationSourceId,
            Guid targetMigrationSourceId)
        {
            using (RuntimeEntityModel context = RuntimeEntityModel.CreateInstance())
            {
                // Get the current source high water mark
                var highWaterMarkQuery =
                            (from h in context.RTHighWaterMarkSet
                             where (h.SessionUniqueId == SessionId && h.SourceUniqueId == sourceMigrationSourceId)
                             select h).Take(1);

                if (highWaterMarkQuery.Count() > 0)
                {
                    RTHighWaterMark sourceHighWaterMark = highWaterMarkQuery.First();

                    // Get the corresponding target item
                    MigrationItemId lastMigratedTargetItem = MigrationEngine.TranslationService.GetLastMigratedItemId(targetMigrationSourceId);

                    // find last ChangeGroupId as of the sync point
                    var lastChangeGroupQuery =
                        (from g in context.RTChangeGroupSet
                         where g.SessionUniqueId.Equals(this.SessionId)
                         && (g.SourceUniqueId.Equals(sourceMigrationSourceId) || g.SourceUniqueId.Equals(targetMigrationSourceId))
                         orderby g.Id descending
                         select g.Id).Take(1);

                    long lastChangeGroupId = (lastChangeGroupQuery.Count() > 0 ? lastChangeGroupQuery.First() : 0);

                    // Use the previous sync point's values lastMigratedTargetItem the sync point if there is no value for lastMigratedTargetItem.ItemId
                    if (string.IsNullOrEmpty(lastMigratedTargetItem.ItemId))
                    {
                        IQueryable<RTSyncPoint> lastChangeSyncPointQuery =
                            (from syncPt in context.RTSyncPointSet
                             where syncPt.SessionUniqueId.Equals(this.SessionId)
                                && syncPt.SourceUniqueId.Equals(sourceMigrationSourceId)
                                && syncPt.SourceHighWaterMarkName.Equals(sourceHighWaterMark.Name)
                             orderby syncPt.Id descending
                             select syncPt).Take(1);
                        if (lastChangeSyncPointQuery.Count() > 0)
                        {
                            RTSyncPoint previousSyncPoint = lastChangeSyncPointQuery.First();
                            lastMigratedTargetItem.ItemId = previousSyncPoint.LastMigratedTargetItemId;
                            lastMigratedTargetItem.ItemVersion = previousSyncPoint.LastMigratedTargetItemVersion;
                        }
                    }

                    // Don't write the sync point if there is still no value for lastMigratedTargetItem.ItemId
                    if (!string.IsNullOrEmpty(lastMigratedTargetItem.ItemId))
                    {
                        // Populate and save the SyncPoint info
                        RTSyncPoint syncPoint =
                            RTSyncPoint.CreateRTSyncPoint(
                                0,                          // Id
                                SessionId,
                                sourceMigrationSourceId,
                                sourceHighWaterMark.Name,
                                lastMigratedTargetItem.ItemId,
                                lastMigratedTargetItem.ItemVersion
                            );

                        syncPoint.SourceHighWaterMarkValue = sourceHighWaterMark.Value;
                        syncPoint.LastChangeGroupId = lastChangeGroupId;

                        context.AddToRTSyncPointSet(syncPoint);

                        context.TrySaveChanges();

                        TraceManager.TraceInformation("Recorded sync point for migration source {0} of session {1} with Source High Water Mark '{2}' value of '{3}'",
                            sourceMigrationSourceId, SessionId, syncPoint.SourceHighWaterMarkName, syncPoint.SourceHighWaterMarkValue);
                    }
                }
            }
        }