private void ComputeDeltaPerRecordType( CQRecordFilter filter, string hwmTime) { CQRecordQueryBase recordQuery = CQRecordQueryFactory.CreatQuery(m_userSession, filter, hwmTime, this); foreach (OAdEntity record in recordQuery) { // HACK HACK if (record != null) // this if check is HACK { try { ComputeDeltaPerRecord(record); } catch (Exception ex) // eating exception is HACK { TraceManager.TraceInformation(string.Format("Workaround for XML save exception : {0}", ex.Message)); TraceManager.TraceException(ex); } } // HACK HACK } }
/// <summary> /// Enumerate the diff items found based on the query passed in as well as the filterString and version passed /// to InitializeForDiff. The return type is IEnumerable<> so that adapter implementations do not need download and keep /// all of the IWITDiffItems in memory at once. /// </summary> /// <param name="queryCondition">A string that specifies a query used to select a subset of the work items defined by /// the set that the filter string identified.</param> /// <returns>An enumeration of IWITDiffItems each representing a work item to be compared by the WIT Diff operation</returns> public IEnumerable <IWITDiffItem> GetWITDiffItems(string queryCondition) { if (m_getWITDiffItemsDone) { yield break; } if (m_cqRecordFilter is CQRecordStoredQueryFilter) { if (!string.IsNullOrEmpty(queryCondition)) { throw new NotImplementedException("Query conditions on the ServerDiff operation are not supported with ClearQuest stored queries are used"); } } else { if (!string.IsNullOrEmpty(queryCondition)) { m_cqRecordFilter = new CQRecordFilter(m_cqRecordFilter.RecordType, m_cqRecordFilter.SelectFromTable, queryCondition); } } CQRecordQueryBase recordQuery = CQRecordQueryFactory.CreateQuery(m_userSession, m_cqRecordFilter, null, this); foreach (OAdEntity record in recordQuery) { if (record != null) // this if check is HACK { OAdHistoryFields histFields = CQWrapper.GetHistoryFields(record); int historyFldCount = CQWrapper.HistoryFieldsCount(histFields); yield return(new CQWITDiffItem(this, record, historyFldCount - 1)); } } m_getWITDiffItemsDone = true; }
public ChangeSummary GetSummaryOfChangesSince(string lastProcessedChangeItemId, List <string> filterStrings) { // lastProcessedChangeItemId is in a form such as "Defect:UCM0100019437:history:0" // Parse it and query for the record with that Id to get the time is was last changed string[] identity = UtilityMethods.ParseCQRecordMigrationItemId(lastProcessedChangeItemId); OAdEntity lastProcessedRecord = CQWrapper.GetEntity(m_userSession, identity[0], identity[1]); string lastProcessedRecordAuthor; DateTime lastProcessedRecordChangeDate; ClearQuestRecordItem.FindLastRevDtls(lastProcessedRecord, out lastProcessedRecordAuthor, out lastProcessedRecordChangeDate); string lastProcessedRecordChangeDateStr = lastProcessedRecordChangeDate.ToString("u").Replace("Z", ""); // using "ISO 8601" DateTime string format if (lastProcessedRecordChangeDateStr.LastIndexOf('.') >= 0) { lastProcessedRecordChangeDateStr = lastProcessedRecordChangeDateStr.Substring(0, lastProcessedRecordChangeDateStr.LastIndexOf('.')); // drop the millisec } ChangeSummary changeSummary = new ChangeSummary(); changeSummary.ChangeCount = 0; changeSummary.FirstChangeModifiedTimeUtc = DateTime.MinValue; foreach (CQRecordFilter filter in m_filters) { CQRecordQueryBase recordQuery = CQRecordQueryFactory.CreatQuery(m_userSession, filter, lastProcessedRecordChangeDateStr, this); foreach (OAdEntity record in recordQuery) { // HACK HACK if (record != null) // this if check is HACK { DateTime lastChangeDate; string lastAuthor; ClearQuestRecordItem.FindLastRevDtls(record, out lastAuthor, out lastChangeDate); // Make sure the lastChangeDate on this record is after the lastProcessedRecordChangeDate before counting it in the backclog // because the query issued above is imprecise because the milliseconds are dropped if (lastChangeDate > lastProcessedRecordChangeDate) { changeSummary.ChangeCount++; DateTime lastChangeDateUtc = lastChangeDate.ToUniversalTime(); if (changeSummary.FirstChangeModifiedTimeUtc == DateTime.MinValue || lastChangeDateUtc < changeSummary.FirstChangeModifiedTimeUtc) { changeSummary.FirstChangeModifiedTimeUtc = lastChangeDateUtc; } } } } } return(changeSummary); }
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()); } }