private void Resume(object state) { lock (this.mdsAgentStateLock) { switch (this.mdsAgentState) { case MdsAgentState.Paused: this.StartWorker(); this.mdsAgentState = MdsAgentState.Running; break; case MdsAgentState.Stopped: // The MDS agent exited on its own and before we could restart it, // we ourselves were asked to stop. Therefore, we tried to cancel // the restart timer that we had started, but it was too late. Just // ignore the resume instructions in this case. break; default: this.trace.Error( "MdsAgentManager.Resume: Could not resume MonAgentLauncher because we were in an unexpected state {0}.", this.mdsAgentState); break; } } }
internal void Start() { lock (this.mdsAgentStateLock) { switch (this.mdsAgentState) { case MdsAgentState.Initialized: this.StartWorker(); this.mdsAgentState = MdsAgentState.Running; break; default: var unexpectedStateMessage = string.Format( "MdsAgentManager.Start: MonAgentLauncher could not be started because we were in an unexpected state {0}.", this.mdsAgentState); this.trace.Error(unexpectedStateMessage); Environment.FailFast(unexpectedStateMessage); break; } } }
internal Task StopAsync() { Task stopTask = null; lock (this.mdsAgentStateLock) { switch (this.mdsAgentState) { case MdsAgentState.Paused: this.PreventResume(); this.mdsAgentState = MdsAgentState.Stopped; // Create a task that is already completed stopTask = Utility.CreateCompletedTask <object>(null); break; case MdsAgentState.Running: this.SendCtrlBreak(); this.mdsAgentState = MdsAgentState.Stopping; // Create a task that will be completed when we have fully stopped this.stopTaskCompletionSource = new TaskCompletionSource <object>(); stopTask = this.stopTaskCompletionSource.Task; break; default: var unexpectedStateMessage = string.Format( "MdsAgentManager.StopAsync: Could not trigger MonAgentLauncher stop because we were in an unexpected state {0}.", this.mdsAgentState); this.trace.Error(unexpectedStateMessage); Environment.FailFast(unexpectedStateMessage); break; } } return(stopTask); }
internal MdsAgentManager( StatelessServiceInitializationParameters initializationParameters, MonitoringAgentServiceEvent trace) { this.stopTaskCompletionSource = null; this.initializationParameters = initializationParameters; this.trace = trace; this.codePackageActivationContext = this.initializationParameters.CodePackageActivationContext; this.codePackageActivationContext.ConfigurationPackageModifiedEvent += ConfigPackageModified; this.codePackageActivationContext.DataPackageModifiedEvent += DataPackageModified; string maConfigFileName = ConfigReader.GetConfigValue( Constants.ConfigSectionName, Constants.MAConfigFileParamName, Constants.DefaultMAConfigFileName); DataPackage maDataPackage = this.codePackageActivationContext.GetDataPackageObject(Constants.MdsAgentDataPackageName); this.maDataPackagePath = maDataPackage.Path; this.maConfigFileFullPath = Path.Combine(this.maDataPackagePath, maConfigFileName); this.maWorkFolder = Path.Combine(this.codePackageActivationContext.WorkDirectory, Constants.MdsAgentWorkSubFolderName); Directory.CreateDirectory(this.maWorkFolder); this.maTenant = ConfigReader.GetConfigValue( Constants.ConfigSectionName, Constants.ClusterNameParamName, Constants.DefaultClusterName); this.maDataCenter = ConfigReader.GetConfigValue( Constants.ConfigSectionName, Constants.DataCenterParamName, Constants.DefaultDataCenterName); // FixDisallowedCharacters replaces special chars in application name with underscore. // This is required since MA cannot handle all special chars in identity fields. // MA usually allows chars that are supported in a URI. this.maApp = this.codePackageActivationContext.ApplicationName.FixDisallowedCharacters(); this.maRole = this.maApp; // The actual nodeName as reported by the FabricClient. This may contain chars like '.' (dot). // In current MA identity, the dot is replaced by and underscore in Role and RoleInstance value // however, the node name itself needs to retain its original value to match that reported by the HM for consistency in downstream processing. this.maNodeName = FabricRuntime.GetNodeContext().NodeName; this.maRoleInstance = this.maNodeName.FixDisallowedCharacters(); this.maDeploymentId = AzureRegistryStore.DeploymentId; this.maXStoreAccounts = ConfigReader.GetConfigValue( Constants.ConfigSectionName, Constants.MAXStoreAccountsParamName, string.Empty); using (var fc = new FabricClient()) { this.mdsLogDirectoryFullPath = ClusterManifestParser.ParseMdsUploaderPath(fc.ClusterManager.GetClusterManifestAsync().Result); } if (!string.IsNullOrEmpty(this.mdsLogDirectoryFullPath)) { this.trace.Message( "MdsAgentManager.ctor: Fabric Geneva Warm Path event generation detected at {0}.", this.mdsLogDirectoryFullPath); } this.maMdmAccountName = ConfigReader.GetConfigValue( Constants.ConfigSectionName, Constants.MAMdmAccountNameParamName, string.Empty); this.maMdmNamespace = ConfigReader.GetConfigValue( Constants.ConfigSectionName, Constants.MAMdmNamespaceParamName, string.Empty); int maRestartDelaySeconds = ConfigReader.GetConfigValue( Constants.ConfigSectionName, Constants.MARestartDelayInSecondsParamName, Constants.DefaultMARestartDelayInSeconds); this.maRestartDelay = TimeSpan.FromSeconds(maRestartDelaySeconds); this.mdsAgentState = MdsAgentState.Initialized; this.mdsAgentStateLock = new object(); this.healthReporter = new HealthReporter(initializationParameters.PartitionId, initializationParameters.InstanceId, initializationParameters.ServiceTypeName); this.maStoppedEventHandleName = string.Format( "MAStoppedEvent{0}{1}", this.initializationParameters.PartitionId, this.initializationParameters.InstanceId); this.maStartedEventHandleName = string.Format( "MAStartedEvent{0}{1}", this.initializationParameters.PartitionId, this.initializationParameters.InstanceId); this.maStoppedEvent = new EventWaitHandle(false, EventResetMode.AutoReset, this.maStoppedEventHandleName); this.maStartedEvent = new EventWaitHandle(false, EventResetMode.AutoReset, this.maStartedEventHandleName); this.maStatusHealthMonitor = new Thread(this.MAStatusHealthMonitor) { IsBackground = false }; this.maStatusHealthMonitor.Start(); this.maResumeTimer = new Timer(this.Resume); }
private void MdsAgentLauncherProcessExited(object sender, EventArgs e) { var message = string.Format( "MdsAgentManager: MonAgentLauncher has exited with error code {0}.", this.mdsAgentLauncherProcess.ExitCode); this.trace.Error(message); bool completeStopTask = false; lock (this.mdsAgentStateLock) { switch (this.mdsAgentState) { case MdsAgentState.Running: // The MonAgentLauncher exited even though we didn't ask it to. This // means that it was asked to exit by some external entity. Most likely, // it was because of a Fabric upgrade, which includes installing the // MSI (among other things). The MSI installation likely needed to replace // some Windows Fabric file that the MA had an open handle to. Therefore, // the Restart Manager probably caused the MA and hence the MonAgentLauncher // to exit, so that the MSI installation can replace that file. // // In the above situation, the Fabric upgrade will soon cause us to exit and // when we come back up we will start the MonAgentLauncher/MA again as always. // // However, we cannot be 100% sure that the MonAgentLauncher really exited due // to Fabric upgrade. Therefore, to be on the safe side, we schedule the // MonAgentLauncher to be started again after a delay. This is to cover for // the possibility that our assumption about the Fabric upgrade is wrong. this.ScheduleResume(); this.mdsAgentLauncherProcess.Dispose(); this.mdsAgentState = MdsAgentState.Paused; this.healthReporter.ReportHealth( HealthState.Error, MonAgentLauncherHealthProperty, message); break; case MdsAgentState.Stopping: this.mdsAgentLauncherProcess.Dispose(); completeStopTask = true; this.mdsAgentState = MdsAgentState.Stopped; break; default: var unexpectedStateMessage = string.Format( "MdsAgentManager: MonAgentLauncher exit notification was received when we were in an unexpected state {0}.", this.mdsAgentState); this.trace.Error(unexpectedStateMessage); Environment.FailFast(unexpectedStateMessage); break; } } if (completeStopTask) { this.stopTaskCompletionSource.SetResult(null); } }