Example #1
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);
                    }
                }
            }
        }
Example #2
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);

                // Mark the items provided by the ForceSyncItemService processed at this time
                IForceSyncItemService forceSyncItemService = AnalysisEngine[sourceMigrationSourceId].GetService(typeof(IForceSyncItemService)) as IForceSyncItemService;
                if (forceSyncItemService != null)
                {
                    forceSyncItemService.MarkCurrentItemsProcessed();
                }

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

                    // Mark the items provided by the ForceSyncItemService (if any) processed at this time
                    forceSyncItemService = AnalysisEngine[targetMigrationSourceId].GetService(typeof(IForceSyncItemService)) as IForceSyncItemService;
                    if (forceSyncItemService != null)
                    {
                        forceSyncItemService.MarkCurrentItemsProcessed();
                    }
                }

                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());
                }
            }
        }
Example #3
0
        private void ProcessPipeline(WorkFlowType workFlowType)
        {
            bool bidirection = IsBidirectionalWorkFlowType(workFlowType);
            bool leftToRightContextSyncNeeded = IsLeftToRightContextSyncNeeded(workFlowType);
            bool rightToLeftContextSyncNeeded = IsRightToLeftContextSyncNeeded(workFlowType);

            // Don't start processing the pipeline if the session was previously paused by conflicts until they are resolved
            if (m_syncStateMachine.CurrentState == PipelineState.PausedByConflict)
            {
                m_orchPolicy.PauseSessionUntilConflictsResolved(this);
            }

            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.PauseConflictedSessionException)
                {
                    // When PausedConflictedSession is requested, we continue and TryNextRoundTrip will delay
                    // until the conflicts are resolved
                    TraceManager.TraceInformation("{0}: Session paused until conflicts are resolved!", m_thread.Name);
                    continue;
                }
                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(this, MilliSecondsSyncWaitInterval));
        }
Example #4
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);
            }
        }
Example #5
0
        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}, change {1}", nextChangeGroup.ChangeGroupId, nextChangeGroup.Name);
                        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);
            }
        }
        public void UpdatePerItemAttachmentChangesByCheckingRelatedItemRecords(
            string workItemId,
            ChangeGroup attachmentChangeGroup,
            out List <FileAttachmentMetadata> additionalAttachmentToDelete)
        {
            if (string.IsNullOrEmpty(workItemId))
            {
                throw new ArgumentNullException("workItemId");
            }

            additionalAttachmentToDelete = new List <FileAttachmentMetadata>();

            var queryByItem = QueryByItem(workItemId);
            var perItemExistingAttachments =
                from attch in queryByItem
                where attch.RelationshipExistsOnServer
                select attch;

            if (attachmentChangeGroup.Actions == null ||
                attachmentChangeGroup.Actions.Count == 0)
            {
                GenericSerializer <FileAttachmentMetadata> serializer = new GenericSerializer <FileAttachmentMetadata>();
                foreach (var attch in perItemExistingAttachments)
                {
                    if (!attch.OtherProperty.HasValue)
                    {
                        continue;
                    }
                    for (int i = 0; i < attch.OtherProperty.Value; ++i)
                    {
                        try
                        {
                            additionalAttachmentToDelete.Add(serializer.Deserialize(attch.RelatedArtifactId));
                        }
                        catch (Exception e)
                        {
                            TraceManager.TraceVerbose(e.ToString());
                        }
                    }
                }

                foreach (var attch in perItemExistingAttachments)
                {
                    attch.OtherProperty = 0;
                    attch.RelationshipExistsOnServer = false;
                }

                m_context.TrySaveChanges();
            }
            else
            {
                Dictionary <IMigrationFileAttachment, List <IMigrationAction> > perAttachmentChangeActions =
                    GroupAttachmentByMetadata(attachmentChangeGroup);

                List <IMigrationAction> skippedActions = new List <IMigrationAction>(attachmentChangeGroup.Actions.Count);
                foreach (var attchSpecificActions in perAttachmentChangeActions)
                {
                    if (attchSpecificActions.Value.Count == 0)
                    {
                        continue;
                    }

                    string attachmentStorageId    = attchSpecificActions.Key.ToString();
                    int    deltaAttachmentCount   = GetAttachmentCountInDelta(attchSpecificActions.Value);
                    var    attachmentInStore      = QueryItemSpecificAttachment(perItemExistingAttachments, attachmentStorageId);
                    int    attachmentInStoreCount = GetAttachmentInStoreCount(attachmentInStore);

                    int serverStoreCountDiff = deltaAttachmentCount - attachmentInStoreCount;
                    if (serverStoreCountDiff >= 0)
                    {
                        int redundantAttachmentActionCount = deltaAttachmentCount - serverStoreCountDiff;
                        var addAttachmentActionToSkip      =
                            attchSpecificActions.Value.Where(a => a.Action == WellKnownChangeActionId.AddAttachment).Take(redundantAttachmentActionCount);
                        skippedActions.AddRange(addAttachmentActionToSkip);
                    }
                    else if (serverStoreCountDiff < 0)
                    {
                        IMigrationAction action = attchSpecificActions.Value[0];
                        do
                        {
                            attachmentChangeGroup.Actions.Add(CreateDeleteAttachmentAction(action));
                        }while (++serverStoreCountDiff < 0);
                    }

                    int countAfterUpdateStore = UpdateStore(workItemId, attachmentStorageId, serverStoreCountDiff);
                    foreach (IMigrationAction action in attchSpecificActions.Value)
                    {
                        XmlElement attachmentNode =
                            action.MigrationActionDescription.DocumentElement.SelectSingleNode("/WorkItemChanges/Attachment") as XmlElement;
                        System.Diagnostics.Debug.Assert(null != attachmentNode, "attachmentNode is NULL");
                        attachmentNode.SetAttribute("CountInSourceSideStore", countAfterUpdateStore.ToString());
                    }
                }

                foreach (IMigrationAction skippedAction in skippedActions)
                {
                    attachmentChangeGroup.Actions.Remove(skippedAction);
                }
            }
        }
        public static int TryGetSidsOfLocalGroupMembers(string serverName, string localGroupName, out List <SecurityIdentifier> sids)
        {
            if (string.IsNullOrEmpty(localGroupName))
            {
                throw new ArgumentNullException("localGroupName");
            }

            sids = new List <SecurityIdentifier>();

            // Note: serverName can be (and usually is) null.
            uint   entriesRead;
            uint   totalEntries;
            IntPtr resumeHandle = IntPtr.Zero;
            IntPtr bufPtr       = IntPtr.Zero;

            try
            {
                int returnCode = Win32GroupInterop.NetLocalGroupGetMembers(serverName,
                                                                           localGroupName,
                                                                           0,             // level 0. return the security identifier (SID) associated with the local group member. The bufptr parameter points to an array of LOCALGROUP_MEMBERS_INFO_0 structures
                                                                           out bufPtr,
                                                                           uint.MaxValue, // maximum preferred length. The method MUST allocate as much space as the data requires.
                                                                           out entriesRead,
                                                                           out totalEntries,
                                                                           out resumeHandle);

                if (returnCode != Win32GroupInterop.ReturnCode.S_OK)
                {
                    return(returnCode);
                    //if (returnCode == Win32GroupInterop.ReturnCode.ERROR_ACCESS_DENIED)
                    //{
                    //    //throw new UnauthorizedAccessException(AdminResources.AccessDenied());
                    //}
                    //else if (returnCode == Win32GroupInterop.ReturnCode.NERR_GroupNotFound ||
                    //         returnCode == Win32GroupInterop.ReturnCode.ERROR_NO_SUCH_ALIAS)
                    //{
                    //    //throw new ArgumentException(AdminResources.GroupNotExist(), "localGroupName");
                    //}

                    ////throw new ConfigurationException(AdminResources.ErrorOperationWithReturnCode("NetLocalGroupGetMembers", returnCode.ToString(CultureInfo.CurrentCulture)));
                }

                for (int index = 0; index < entriesRead; ++index)
                {
                    IntPtr ptr = new IntPtr((long)bufPtr + Marshal.SizeOf(typeof(Win32GroupInterop.LocalGroupMemberInfo0)) * index);

                    Win32GroupInterop.LocalGroupMemberInfo0 groupMemberInfo =
                        (Win32GroupInterop.LocalGroupMemberInfo0)Marshal.PtrToStructure(ptr, typeof(Win32GroupInterop.LocalGroupMemberInfo0));

                    SecurityIdentifier sid = new SecurityIdentifier(groupMemberInfo.Sid);

                    sids.Add(sid);
                }

                return(Win32GroupInterop.ReturnCode.S_OK);
            }
            finally
            {
                if (bufPtr != IntPtr.Zero)
                {
                    int rc = Win32GroupInterop.NetApiBufferFree(bufPtr);

                    if (rc != Win32GroupInterop.ReturnCode.S_OK)
                    {
                        TraceManager.TraceError("Failed to free buffer returned by NetLocalGroupGetMembers(). Error: {0}", rc);
                    }
                }
            }
        }
Example #8
0
        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)
                {
                    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)
                    {
                        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);

                            Debug.Assert(linkProvider.SupportedLinkTypes.ContainsKey(recordedExistingLink.Relationship),
                                         "linkProvider.SupportedLinkTypes.ContainsKey(recordedExistingLink.Relationship) returns false");
                            LinkType         linkType         = linkProvider.SupportedLinkTypes[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();
        }