public virtual ReadOnlyCollection <LinkChangeGroup> GenerateNextLinkDeltaSlice( LinkService linkService, int maxDeltaSliceSize) { try { var linkChangeGroups = new List <LinkChangeGroup>(); if (null == ExtractLinkChangeActionsCallback) { return(linkChangeGroups.AsReadOnly()); } // load main Highwater Mark m_hwmLink.Reload(); DateTime hwmLinkValue = m_hwmLink.Value; string hwmLinkValueStr = hwmLinkValue.ToString(CultureInfo.InvariantCulture); // load Work Items for extracting links string sourceId = m_migrationSource.UniqueId; string storeName = m_migrationSource.WorkItemStore.StoreName; // Get items based on primary Highwater Mark TraceManager.TraceInformation(TfsWITAdapterResources.GettingModifiedItems, sourceId, storeName); IEnumerable <TfsMigrationWorkItem> items = m_migrationSource.WorkItemStore.GetItems(ref hwmLinkValueStr); TraceManager.TraceInformation(TfsWITAdapterResources.ReceivedModifiedItems, sourceId, storeName); // Record the updated HWM value DateTime newHwmLinkValue = Convert.ToDateTime(hwmLinkValueStr, CultureInfo.InvariantCulture); // store to be used to analyze deleted links WorkItemLinkStore store = new WorkItemLinkStore(new Guid(sourceId)); // extract links var inMaxDeltaSliceSize = maxDeltaSliceSize; foreach (TfsMigrationWorkItem tfsMigrationWorkItem in items) { if (tfsMigrationWorkItem.WorkItem == null) { continue; } TraceManager.TraceInformation("Generating linking delta for Work Item: {0}", tfsMigrationWorkItem.WorkItem.Id.ToString()); var perWorkItemlinkChangeGroups = new List <LinkChangeGroup>(); ExtractLinkChangeActionsCallback(tfsMigrationWorkItem, perWorkItemlinkChangeGroups, store); if (perWorkItemlinkChangeGroups.Count == 0) { TraceManager.TraceInformation("Number of links: {0}", 0); continue; } LinkChangeGroup consolidatedLinkChangeGroup = perWorkItemlinkChangeGroups[0]; for (int i = 1; i < perWorkItemlinkChangeGroups.Count; ++i) { foreach (LinkChangeAction action in perWorkItemlinkChangeGroups[i].Actions) { consolidatedLinkChangeGroup.AddChangeAction(action); } } TraceManager.TraceInformation("Number of links: {0}", consolidatedLinkChangeGroup.Actions.Count.ToString()); // VERY IMPORTANT: use the RelatedArtifactsStore to detect link deletion store.UpdatePerItemLinkChangeGroupsByCheckingRelatedItemRecords( tfsMigrationWorkItem.Uri, consolidatedLinkChangeGroup, this); if (consolidatedLinkChangeGroup.Actions.Count > 0) { linkChangeGroups.Add(consolidatedLinkChangeGroup); } maxDeltaSliceSize -= consolidatedLinkChangeGroup.Actions.Count; if (maxDeltaSliceSize <= 0) { // size limit reached - persist groups to DB linkService.AddChangeGroups(linkChangeGroups); linkChangeGroups.Clear(); maxDeltaSliceSize = inMaxDeltaSliceSize; } } // persist remaining groups to DB linkService.AddChangeGroups(linkChangeGroups); // clean up the returned link change group collection // when the caller (toolkit) receives an empty collection, it understands there is no more // delta to generate for the moment, and proceeds to next phase linkChangeGroups.Clear(); // update primary Highwater Mark m_hwmLink.Update(newHwmLinkValue); TraceManager.TraceInformation("Persisted WIT linking HWM: {0}", Toolkit.Constants.HwmDeltaLink); TraceManager.TraceInformation(TfsWITAdapterResources.UpdatedHighWatermark, hwmLinkValueStr); return(linkChangeGroups.AsReadOnly()); } catch (Exception exception) { ErrorManager errMgr = m_serviceContainer.GetService(typeof(ErrorManager)) as ErrorManager; errMgr.TryHandleException(exception); return(new List <LinkChangeGroup>().AsReadOnly()); } }
public ReadOnlyCollection <LinkChangeGroup> GenerateNextLinkDeltaSlice( LinkService linkService, int maxDeltaSliceSize) { try { var linkChangeGroups = new List <LinkChangeGroup>(); if (null == ExtractLinkChangeActionsCallback) { return(linkChangeGroups.AsReadOnly()); } // load high watermark; as for CQ, we store local time for queries m_hwmLink.Reload(); DateTime hwmDeltaValue = m_hwmLink.Value; if (hwmDeltaValue.Equals(default(DateTime))) { hwmDeltaValue = new DateTime(1900, 1, 1); } hwmDeltaValue = hwmDeltaValue.AddSeconds(-1); // go back 1 second as we'll drop the millisec below string hwmDeltaValueStr = hwmDeltaValue.ToString(m_migrationContext.CQQueryDateTimeFormat, CultureInfo.InvariantCulture); // record current time to update HWM after processing DateTime newHwmValue = CQUtilityMethods.GetTimeForNewHighWaterMark(m_migrationContext.CQTimeOffsetFromServerHistoryTimesInMinutes); // store to be used for analysis WorkItemLinkStore store = new WorkItemLinkStore(m_configurationService.SourceId); // extract links var inMaxDeltaSliceSize = maxDeltaSliceSize; foreach (CQRecordFilter filter in m_filters) { CQRecordQueryBase recordQuery = CQRecordQueryFactory.CreateQuery(m_userSession, filter, hwmDeltaValueStr, this); foreach (ClearQuestOleServer.OAdEntity record in recordQuery) { // HACK HACK if (record == null) { continue; } // HACK HACK string recDispName = CQWrapper.GetEntityDisplayName(record); TraceManager.TraceInformation("Generating linking delta for CQ Record: {0}", recDispName); var perWorkItemlinkChangeGroups = new List <LinkChangeGroup>(); ExtractLinkChangeActionsCallback(m_userSession, record, perWorkItemlinkChangeGroups); if (perWorkItemlinkChangeGroups.Count == 0) { TraceManager.TraceInformation("Number of links: {0}", 0); continue; } LinkChangeGroup consolidatedLinkChangeGroup = perWorkItemlinkChangeGroups[0]; for (int i = 1; i < perWorkItemlinkChangeGroups.Count; ++i) { foreach (LinkChangeAction action in perWorkItemlinkChangeGroups[i].Actions) { consolidatedLinkChangeGroup.AddChangeAction(action); } } TraceManager.TraceInformation("Number of links: {0}", consolidatedLinkChangeGroup.Actions.Count.ToString()); // VERY IMPORTANT STEP: update the link delta to store string hostRecMigrItemId = UtilityMethods.CreateCQRecordMigrationItemId(record); store.UpdatePerItemLinkChangeGroupsByCheckingRelatedItemRecords( hostRecMigrItemId, consolidatedLinkChangeGroup, this); if (consolidatedLinkChangeGroup.Actions.Count > 0) { linkChangeGroups.Add(consolidatedLinkChangeGroup); } maxDeltaSliceSize -= consolidatedLinkChangeGroup.Actions.Count; if (maxDeltaSliceSize <= 0) { // size limit reached - persist groups to DB, then empty the slice and process next slice linkService.AddChangeGroups(linkChangeGroups); linkChangeGroups.Clear(); maxDeltaSliceSize = inMaxDeltaSliceSize; } } } // persist remaining groups to DB linkService.AddChangeGroups(linkChangeGroups); // clean up the returned link change group collection // when the caller (toolkit) receives an empty collection, it understands there is no more // delta to generate for the moment, and proceeds to next phase linkChangeGroups.Clear(); // update primary Highwater Mark m_hwmLink.Update(newHwmValue); TraceManager.TraceInformation("Persisted CQ linking HWM: {0}", ClearQuestConstants.CqLinkHwm); TraceManager.TraceInformation("Updated CQ linking HWM: {0}", newHwmValue.ToString()); return(linkChangeGroups.AsReadOnly()); } catch (Exception exception) { // [teyang] TODO CONFLICT HANDLING //MigrationConflict genericeConflict = WitGeneralConflictType.CreateConflict(exception); //var conflictManager = m_conflictManager.GetService(typeof(ConflictManager)) as ConflictManager; //Debug.Assert(null != conflictManager); //List<MigrationAction> resolutionActions; //ConflictResolutionResult resolveRslt = // conflictManager.TryResolveNewConflict(conflictManager.SourceId, genericeConflict, out resolutionActions); //Debug.Assert(!resolveRslt.Resolved); TraceManager.TraceException(exception); return(new List <LinkChangeGroup>().AsReadOnly()); } }
public override System.Collections.ObjectModel.ReadOnlyCollection <LinkChangeGroup> GenerateNextLinkDeltaSlice( LinkService linkService, int maxDeltaSliceSize) { try { var linkChangeGroups = new List <LinkChangeGroup>(); if (null == ExtractLinkChangeActionsCallback) { return(linkChangeGroups.AsReadOnly()); } // load main Highwater Mark m_hwmLink.Reload(); DateTime hwmLinkValue = m_hwmLink.Value; // search back 60 seconds to deal with potential WIT race condition if (!hwmLinkValue.Equals(default(DateTime))) { hwmLinkValue = hwmLinkValue.AddSeconds(-60); } string hwmLinkValueStr = hwmLinkValue.ToString(CultureInfo.InvariantCulture); // load Work Items for extracting links string sourceId = m_migrationSource.UniqueId; string storeName = m_migrationSource.WorkItemStore.StoreName; // Get items based on primary Highwater Mark TraceManager.TraceInformation(TfsWITAdapterResources.GettingModifiedItems, sourceId, storeName); IEnumerable <TfsMigrationWorkItem> items = m_migrationSource.WorkItemStore.GetItems(ref hwmLinkValueStr); TraceManager.TraceInformation(TfsWITAdapterResources.ReceivedModifiedItems, sourceId, storeName); // Record the updated HWM value DateTime wiqlExecutionTime = Convert.ToDateTime(hwmLinkValueStr, CultureInfo.InvariantCulture); // store to be used to analyze deleted links WorkItemLinkStore store = new WorkItemLinkStore(new Guid(sourceId)); // extract links DateTime lastWorkITemUpdateTime = DateTime.MinValue; var inMaxDeltaSliceSize = maxDeltaSliceSize; foreach (TfsMigrationWorkItem tfsMigrationWorkItem in items) { if (tfsMigrationWorkItem.WorkItem == null) { continue; } TraceManager.TraceInformation("Generating linking delta for Work Item: {0}", tfsMigrationWorkItem.WorkItem.Id.ToString()); var detectedLinkChangeGroups = new List <LinkChangeGroup>(); ExtractLinkChangeActionsCallback(tfsMigrationWorkItem, detectedLinkChangeGroups, store); if (detectedLinkChangeGroups.Count == 0) { TraceManager.TraceInformation("Number of links: {0}", 0); continue; } Dictionary <string, LinkChangeGroup> perWorkItemConsolidatedLinkChangeGroup = new Dictionary <string, LinkChangeGroup>(); for (int i = 0; i < detectedLinkChangeGroups.Count; ++i) { foreach (LinkChangeAction action in detectedLinkChangeGroups[i].Actions) { if (!perWorkItemConsolidatedLinkChangeGroup.ContainsKey(action.Link.SourceArtifact.Uri)) { var linkChangeGroup = new LinkChangeGroup( action.Link.SourceArtifactId, LinkChangeGroup.LinkChangeGroupStatus.Created, false); perWorkItemConsolidatedLinkChangeGroup.Add(action.Link.SourceArtifact.Uri, linkChangeGroup); } perWorkItemConsolidatedLinkChangeGroup[action.Link.SourceArtifact.Uri].AddChangeAction(action); } } // always make sure that the currently analyzed work item has a link change group to represent it // even though the group can be empty if (!perWorkItemConsolidatedLinkChangeGroup.ContainsKey(tfsMigrationWorkItem.Uri)) { perWorkItemConsolidatedLinkChangeGroup.Add( tfsMigrationWorkItem.Uri, new LinkChangeGroup(TfsWorkItemHandler.IdFromUri(tfsMigrationWorkItem.Uri), LinkChangeGroup.LinkChangeGroupStatus.Created, false)); } foreach (var workItemLinkGroup in perWorkItemConsolidatedLinkChangeGroup) { string workItemIdStr = TfsWorkItemHandler.IdFromUri(workItemLinkGroup.Key); TraceManager.TraceInformation("Detected {0} links for Work Item '{1}'", workItemLinkGroup.Value.Actions.Count, workItemIdStr); if (workItemLinkGroup.Key.Equals(tfsMigrationWorkItem.Uri, StringComparison.OrdinalIgnoreCase)) { // VERY IMPORTANT: use the RelatedArtifactsStore to detect link deletion store.UpdatePerItemLinkChangeGroupsByCheckingRelatedItemRecords( workItemLinkGroup.Key, workItemLinkGroup.Value, this); } else { store.UpdatePerItemLinkChangeGroupsByCheckingRelatedItemRecordsWithoutImplicitDelete( workItemLinkGroup.Key, workItemLinkGroup.Value, this); } if (workItemLinkGroup.Value.Actions.Count > 0) { linkChangeGroups.Add(workItemLinkGroup.Value); } maxDeltaSliceSize -= workItemLinkGroup.Value.Actions.Count; if (maxDeltaSliceSize <= 0) { // size limit reached - persist groups to DB linkService.AddChangeGroups(linkChangeGroups); linkChangeGroups.Clear(); maxDeltaSliceSize = inMaxDeltaSliceSize; } } DateTime lastRevChangedDate = tfsMigrationWorkItem.WorkItem.ChangedDate; if (lastWorkITemUpdateTime.CompareTo(lastRevChangedDate) <= 0) { lastWorkITemUpdateTime = lastRevChangedDate; } } // persist remaining groups to DB linkService.AddChangeGroups(linkChangeGroups); // clean up the returned link change group collection // when the caller (toolkit) receives an empty collection, it understands there is no more // delta to generate for the moment, and proceeds to next phase linkChangeGroups.Clear(); // update primary Highwater Mark //m_hwmLink.Update(newHwmLinkValue); string newHwmValueStr = hwmLinkValueStr; if (lastWorkITemUpdateTime.Equals(DateTime.MinValue)) { // no changes in this sync cycle, record the wiql query execution time m_hwmLink.Update(wiqlExecutionTime); } else { // hwm is recorded in UTC, so does the WIQL query asof time lastWorkITemUpdateTime = lastWorkITemUpdateTime.ToUniversalTime(); if (lastWorkITemUpdateTime.CompareTo(wiqlExecutionTime) <= 0) { // last work item rev time is earlier than wiql query execution time, use it as hwm m_hwmLink.Update(lastWorkITemUpdateTime); newHwmValueStr = lastWorkITemUpdateTime.ToString(); } else { m_hwmLink.Update(wiqlExecutionTime); } } TraceManager.TraceInformation("Persisted WIT linking HWM: {0}", Toolkit.Constants.HwmDeltaLink); TraceManager.TraceInformation(TfsWITAdapterResources.UpdatedHighWatermark, newHwmValueStr); return(linkChangeGroups.AsReadOnly()); } catch (Exception exception) { MigrationConflict genericeConflict = WitGeneralConflictType.CreateConflict(exception); var conflictManager = m_conflictManager.GetService(typeof(ConflictManager)) as ConflictManager; Debug.Assert(null != conflictManager); List <MigrationAction> resolutionActions; ConflictResolutionResult resolveRslt = conflictManager.TryResolveNewConflict(conflictManager.SourceId, genericeConflict, out resolutionActions); Debug.Assert(!resolveRslt.Resolved); return(new List <LinkChangeGroup>().AsReadOnly()); } }