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); } }
/// <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); } }