/// <summary> /// Register an analysis provider with the analysis engine, /// 1. Intialize analysis service container and services. /// 2. Call analysis provider to register supported change actions. /// </summary> /// <param name="sourceId"></param> /// <param name="analysisProvider"></param> internal void RegisterAnalysisProvider( Guid sourceId, Session sessionConfig, IAnalysisProvider analysisProvider, IProvider adapter) { ServiceContainer serviceContainer; Debug.Assert(m_serviceContainers.ContainsKey(sourceId), string.Format(MigrationToolkitResources.UnknownSourceId, sourceId)); if (!m_serviceContainers.TryGetValue(sourceId, out serviceContainer)) { throw new MigrationException(string.Format( MigrationToolkitResources.Culture, MigrationToolkitResources.UnknownSourceId, sourceId)); } m_serviceContainers[sourceId].AddService(typeof(IAnalysisProvider), analysisProvider); m_analysisProviders.Add(sourceId, analysisProvider); // Call analysis provider to initialize basic services analysisProvider.InitializeServices(m_serviceContainers[sourceId]); // Call analysis provider to register supported content types ContentTypeRegistrationService contentTypeRegService = m_serviceContainers[sourceId].GetService(typeof(ContentTypeRegistrationService)) as ContentTypeRegistrationService; Debug.Assert(null != contentTypeRegService, "contentTypeRegService == NULL"); analysisProvider.RegisterSupportedContentTypes(contentTypeRegService); // Call analysis provider to register supported change actions ChangeActionRegistrationService changeActionRegistrationService = m_serviceContainers[sourceId].GetService(typeof(ChangeActionRegistrationService)) as ChangeActionRegistrationService; Debug.Assert(null != changeActionRegistrationService, "changeActionRegistrationService == NULL"); analysisProvider.RegisterSupportedChangeActions(changeActionRegistrationService); // Call analysis provider to register supported conflict types ConflictManager conflictManagementService = m_serviceContainers[sourceId].GetService(typeof(ConflictManager)) as ConflictManager; Debug.Assert(null != conflictManagementService, "conflictManager == NULL"); analysisProvider.RegisterConflictTypes(conflictManagementService); IServerPathTranslationService serverPathTranslationService = adapter.GetService(typeof(IServerPathTranslationService)) as IServerPathTranslationService; if (serverPathTranslationService != null) { m_serviceContainers[sourceId].AddService(typeof(IServerPathTranslationService), serverPathTranslationService); } foreach (AnalysisAddin analysisAddin in m_addinManagementService.GetMigrationSourceAnalysisAddins(sourceId)) { Debug.Assert(m_serviceContainers.ContainsKey(sourceId), "No ServiceContainer found for MigrationSource with Id: " + sourceId); AnalysisContext analysisContext = new AnalysisContext(m_serviceContainers[sourceId]); m_analysisContextsByMigrationSource.Add(sourceId, analysisContext); // Just need to create one AnalysisContext that can be shared by all of the Addins for a migration source since the contents are read-only // to the Addin break; } }
/// <summary> /// Registers the supported change actions. /// </summary> /// <param name="contentActionRegistrationService">The content action registration service.</param> public override void RegisterSupportedChangeActions(ChangeActionRegistrationService contentActionRegistrationService) { TraceManager.TraceInformation("WSSVC:AP:RegisterSupportedChangeActions"); this.changeActionRegistrationService = contentActionRegistrationService; foreach (KeyValuePair <Guid, ChangeActionHandler> supportedChangeAction in supportedChangeActions) { foreach (ContentType contentType in ((IAnalysisProvider)this).SupportedContentTypes) { changeActionRegistrationService.RegisterChangeAction(supportedChangeAction.Key, contentType.ReferenceName, supportedChangeAction.Value); } } }
/// <summary> /// Registers the supported change actions. /// </summary> /// <param name="changeActionRegistrationService">The change action registration service.</param> public override void RegisterSupportedChangeActions(ChangeActionRegistrationService changeActionRegistrationService) { TraceManager.TraceInformation("WSSWIT:AP:RegisterSupportedChangeActions"); changeActionRegistrationService = (ChangeActionRegistrationService)this.analysisServiceContainer.GetService(typeof(ChangeActionRegistrationService)); foreach (KeyValuePair <Guid, ChangeActionHandler> supportedChangeAction in this.supportedChangeActions) { foreach (ContentType contentType in ((IAnalysisProvider)this).SupportedContentTypes) { changeActionRegistrationService.RegisterChangeAction(supportedChangeAction.Key, contentType.ReferenceName, supportedChangeAction.Value); } } }
/// <summary> /// Register all change actions supported by this adapter. /// </summary> /// <param name="changeActionRegistrationService"></param> public void RegisterSupportedChangeActions(ChangeActionRegistrationService changeActionRegistrationService) { if (changeActionRegistrationService == null) { throw new ArgumentNullException("changeActionRegistrationService"); } LoadSupportedChangeActions(); m_changeActionRegistrationService = changeActionRegistrationService; foreach (KeyValuePair <Guid, ChangeActionHandler> supportedChangeAction in m_supportedChangeActions) { // note: for now, CQ adapter uses a single change action handler for all content types foreach (ContentType contentType in SupportedContentTypes) { m_changeActionRegistrationService.RegisterChangeAction( supportedChangeAction.Key, contentType.ReferenceName, supportedChangeAction.Value); } } }
/// <summary> /// Initialize analysis services /// </summary> private void RegisterServices(Guid sourceId, RuntimeSession session) { Debug.Assert(m_serviceContainers.ContainsKey(sourceId), string.Format(MigrationToolkitResources.UnknownSourceId, sourceId)); ChangeActionRegistrationService changeActionRegistrationService = new ChangeActionRegistrationService(); m_serviceContainers[sourceId].AddService(typeof(ChangeActionRegistrationService), changeActionRegistrationService); ContentTypeRegistrationService contentTypeRegistrationService = new ContentTypeRegistrationService(); m_serviceContainers[sourceId].AddService(typeof(ContentTypeRegistrationService), contentTypeRegistrationService); ConflictManager conflictManagementService = new ConflictManager(sourceId); conflictManagementService.ScopeId = new Guid(m_session.Configuration.SessionUniqueId); m_serviceContainers[sourceId].AddService(typeof(ConflictManager), conflictManagementService); conflictManagementService.InitializePhase1(m_serviceContainers[sourceId]); RegisterGenericeConflicts(conflictManagementService); RegisterSessionSpecificConflicts(conflictManagementService, session.Configuration.SessionType); ICommentDecorationService commentDecorationService = new CommentDecorationService(m_session, m_serviceContainers[sourceId]); m_serviceContainers[sourceId].AddService(typeof(ICommentDecorationService), commentDecorationService); ChangeGroupService changeGroupService = m_serviceContainers[sourceId].GetService(typeof(ChangeGroupService)) as ChangeGroupService; if (changeGroupService != null) { changeGroupService.PreChangeGroupSaved += new EventHandler <ChangeGroupEventArgs>(changeGroupService_PreChangeGroupSaved); if (!m_changeGroupServices.ContainsKey(sourceId)) { m_changeGroupServices.Add(sourceId, changeGroupService); } } }
/// <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); } }
public abstract void RegisterSupportedChangeActions(ChangeActionRegistrationService changeActionRegistrationService);