/* * Registers an agent with the coordinator, or updates the ping time * * Returns true if a restart is required */ public static PingResponse Ping( AgentInfo UpdatedInfo ) { AgentsDirty = true; // Add a known set of configuration items UpdatedInfo.Configuration["LastPingTime"] = DateTime.UtcNow; // Retreive information the agent can provide for us and supply defaults if( !UpdatedInfo.Configuration.ContainsKey( "GroupName" ) ) { UpdatedInfo.Configuration["GroupName"] = "Default"; } // If the Agent is working for someone, replace the local user name with // the user name on the machine that it's working for if( UpdatedInfo.Configuration.ContainsKey( "WorkingFor" ) ) { // Look up the other user name string BossAgentName = UpdatedInfo.Configuration["WorkingFor"] as string; if( ( Agents.ContainsKey( BossAgentName ) ) && ( Agents[BossAgentName].Configuration.ContainsKey( "UserName" ) ) ) { UpdatedInfo.Configuration["UserName"] = Agents[BossAgentName].Configuration["UserName"]; } } else { UpdatedInfo.Configuration["WorkingFor"] = ""; } if( !UpdatedInfo.Configuration.ContainsKey( "AssignedTo" ) ) { UpdatedInfo.Configuration["AssignedTo"] = ""; UpdatedInfo.Configuration["AssignedTime"] = DateTime.UtcNow; } if( !UpdatedInfo.Configuration.ContainsKey( "UserName" ) ) { UpdatedInfo.Configuration["UserName"] = "******"; } // If the agent is remote, ping the machine to make sure we can talk to it // but only if the Agent didn't provide an IP address for us if( !UpdatedInfo.Configuration.ContainsKey( "IPAddress" ) ) { // By default, we'll set the IP address to the loopback value UpdatedInfo.Configuration["IPAddress"] = IPAddress.Loopback; bool IPAddressUpdateSuccess = false; if( UpdatedInfo.Name != Environment.MachineName ) { try { // Use the name, which can fail if DNS isn't enabled or if there's no host file Ping PingSender = new Ping(); PingReply Reply = PingSender.Send( UpdatedInfo.Name ); if( Reply.Status == IPStatus.Success ) { // With a success, update the known IP address for this agent UpdatedInfo.Configuration["IPAddress"] = Reply.Address; IPAddressUpdateSuccess = true; } } catch( Exception ) { // Any exception is a total failure } } // With a failure, update the agent's state to prevent usage if( !IPAddressUpdateSuccess ) { UpdatedInfo.State = AgentState.Blocked; } } PingResponse Response; lock( Agents ) { if( !Agents.ContainsKey( UpdatedInfo.Name ) ) { // If this is a new agent, tell it to restart itself to pick up the latest version Response = PingResponse.Restart; } else if( Agents[UpdatedInfo.Name].State == AgentState.Restarting ) { Response = PingResponse.Restart; // If this agent has been instructed to restart, keep overriding the // state until it's freed up to actually restart if( UpdatedInfo.State == AgentState.Available ) { UpdatedInfo.State = AgentState.Restarted; } else { // Keep us in this cycle on the next ping UpdatedInfo.State = AgentState.Restarting; } } else { Response = PingResponse.Success; AgentInfo PreviousInfo = Agents[UpdatedInfo.Name]; // If the WorkingFor changed, update the time string PreviousWorkingFor = PreviousInfo.Configuration["WorkingFor"] as string; string UpdatedWorkingFor = UpdatedInfo.Configuration["WorkingFor"] as string; DateTime UpdatedWorkingTime = DateTime.MaxValue; if( UpdatedWorkingFor != PreviousWorkingFor ) { UpdatedWorkingTime = DateTime.UtcNow; } else if( PreviousInfo.Configuration.ContainsKey( "WorkingTime" ) ) { UpdatedWorkingTime = ( DateTime )PreviousInfo.Configuration["WorkingTime"]; } UpdatedInfo.Configuration["WorkingTime"] = UpdatedWorkingTime; // Based on whether or not the agent is Working currently, update some state if( UpdatedInfo.State != AgentState.Working ) { // No other agent should be AssignedTo it foreach( AgentInfo Agent in Agents.Values ) { if( ( Agent.Configuration["AssignedTo"] as string ) == UpdatedInfo.Name ) { Agent.Configuration["AssignedTo"] = ""; Agent.Configuration["AssignedTime"] = DateTime.UtcNow; } } // If the previous state was Working for the same agent it's AssignedTo, // then we can clear the AssignedTo field if( PreviousInfo.State == AgentState.Working ) { string PreviousAssignedTo = PreviousInfo.Configuration["AssignedTo"] as string; if( PreviousAssignedTo == PreviousWorkingFor ) { PreviousInfo.Configuration["AssignedTo"] = ""; PreviousInfo.Configuration["AssignedTime"] = DateTime.UtcNow; } } } else { // If it's WorkingFor someone, but not AssignedTo anyone else, update the AssignedTo if( ( ( UpdatedInfo.Configuration["WorkingFor"] as string ) != "" ) && ( ( PreviousInfo.Configuration["AssignedTo"] as string ) == "" ) ) { PreviousInfo.Configuration["AssignedTo"] = UpdatedInfo.Configuration["WorkingFor"]; PreviousInfo.Configuration["AssignedTime"] = DateTime.UtcNow; } } string UpdatedAssignedTo = PreviousInfo.Configuration["AssignedTo"] as string; UpdatedInfo.Configuration["AssignedTo"] = UpdatedAssignedTo; UpdatedInfo.Configuration["AssignedTime"] = DateTime.UtcNow; } // Set or reset the agent info to the latest Agents[UpdatedInfo.Name] = UpdatedInfo; } return Response; }
public PingResponse Ping( AgentInfo Agent ) { return ( Coordinator.Ping( Agent ) ); }
// Available < Busy < Other (Working) private static int AliveAgentSorter( AgentInfo A, AgentInfo B ) { if( A.State == AgentState.Available ) { if( B.State == AgentState.Available ) { return 0; } else { return -1; } } else { if( B.State == AgentState.Available ) { return 1; } else { // Neither are Available, sort on Busy if( A.State == AgentState.Busy ) { if( B.State == AgentState.Busy ) { return 0; } else { return -1; } } else { if( B.State == AgentState.Busy ) { return 1; } else { return 0; } } } } }
private bool ValidateDeterministicDistributionRequirements() { // If there's no record of the last run, then fail immediately if( Manager.LastSuccessfulJobRecord == null ) { return false; } AgentJobRecord LastSuccessfulJobRecord = Manager.LastSuccessfulJobRecord; bool DeterministicModeValidated = false; // First, compare the job specification bool ExecutableNameMatches = false; string ThisOriginalExecutableName; if( Specification.DependenciesOriginalNames.TryGetValue( Specification.ExecutableName, out ThisOriginalExecutableName ) ) { string LastOriginalExecutableName; if( LastSuccessfulJobRecord.Specification.DependenciesOriginalNames.TryGetValue( LastSuccessfulJobRecord.Specification.ExecutableName, out LastOriginalExecutableName ) ) { if( ThisOriginalExecutableName == LastOriginalExecutableName ) { ExecutableNameMatches = true; } else { Manager.Log( EVerbosityLevel.Critical, ELogColour.Red, "[Deterministic] Failed to validate Job, executable name is different" ); } } } // If the executable name matches, check the set of tasks if( ExecutableNameMatches ) { bool AllTasksMatch = false; // Next, make sure that all the tasks in the current specification are in the last job List<AgentTask> ListOfTasks = new List<AgentTask>( PendingTasks.ToArray() ); if( ListOfTasks.Count == LastSuccessfulJobRecord.AllTasks.Count ) { AgentTask NextTask; Int32 MatchedTaskCount = 0; foreach( AgentTask Task in ListOfTasks ) { if( LastSuccessfulJobRecord.AllTasks.TryGetValue( Task.Specification.TaskGuid, out NextTask ) ) { // For now, just compare the parameters and the cost if( ( NextTask.Specification.Parameters == Task.Specification.Parameters ) && ( NextTask.Specification.Cost == Task.Specification.Cost ) ) { MatchedTaskCount++; } else { string OldTaskDetails = String.Format( "[Deterministic] Old Task: {0}, {1}, {2}", NextTask.Specification.TaskGuid, NextTask.Specification.Parameters, NextTask.Specification.Cost ); string NewTaskDetails = String.Format( "[Deterministic] New Task: {0}, {1}, {2}", Task.Specification.TaskGuid, Task.Specification.Parameters, Task.Specification.Cost ); Manager.Log( EVerbosityLevel.Critical, ELogColour.Red, "[Deterministic] Failed to validate Job, task is different" ); Manager.Log( EVerbosityLevel.Critical, ELogColour.Red, OldTaskDetails ); Manager.Log( EVerbosityLevel.Critical, ELogColour.Red, NewTaskDetails ); } } } if( MatchedTaskCount == LastSuccessfulJobRecord.AllTasks.Count ) { // Found all current tasks in the last job record AllTasksMatch = true; // Now verify and initialize the running work queues LastSuccessfulJobRecord.AgentToTaskQueueMapping.Clear(); foreach( string WorkerName in LastSuccessfulJobRecord.WorkerAgentNames ) { Queue<AgentTask> TaskQueue; if( LastSuccessfulJobRecord.AgentToGoldenTaskQueueMapping.TryGetValue( WorkerName, out TaskQueue ) ) { LastSuccessfulJobRecord.AgentToTaskQueueMapping.Add( WorkerName, new Queue<AgentTask>( TaskQueue ) ); } else { // If we fail to set the enumerators, fail to validate AllTasksMatch = false; } } } } else { Manager.Log( EVerbosityLevel.Critical, ELogColour.Red, "[Deterministic] Failed to validate Job, overall task count is different" ); } // If all tasks are the same (enough), make sure we can acquire the same set of agents for the job if( AllTasksMatch ) { // If all tasks match, try to connection to each of the // remote agents from the previous job Int32 WorkerAgentsEmployed = 0; for( Int32 i = 0; i < LastSuccessfulJobRecord.WorkerAgentNames.Count; i++ ) { string WorkerAgentName = LastSuccessfulJobRecord.WorkerAgentNames[i]; string WorkerAgentIPAddress = LastSuccessfulJobRecord.WorkerAgentIPAddresses[i]; // Don't try to connect to self and only if this name is allowed if( ( WorkerAgentName != Environment.MachineName ) && ( Manager.AgentNamePassesAllowedAgentsFilter( WorkerAgentName ) ) ) { // Make sure we can open the connection and get a valid remote connection back RemoteConnection Remote; AgentInfo NewWorkerInfo = new AgentInfo(); NewWorkerInfo.Name = WorkerAgentName; NewWorkerInfo.Configuration["IPAddress"] = WorkerAgentIPAddress; if( ( Manager.TryOpenRemoteConnection( Owner as LocalConnection, NewWorkerInfo, false, DateTime.MinValue, out Remote ) == Constants.SUCCESS ) && ( Remote != null ) ) { WorkerAgentsEmployed++; } else { Manager.Log( EVerbosityLevel.Critical, ELogColour.Red, "[Deterministic] Could not acquire connection to " + WorkerAgentName + " necessary for job" ); } } else { // We always count ourselves WorkerAgentsEmployed++; } } if( WorkerAgentsEmployed == LastSuccessfulJobRecord.WorkerAgentNames.Count ) { // If all necessary agents are employed, we've verified everything // we can -> success Manager.Log( EVerbosityLevel.Informative, ELogColour.Green, "[Deterministic] Job validated, deterministic distribution enabled" ); DeterministicModeValidated = true; } else { Manager.Log( EVerbosityLevel.Critical, ELogColour.Red, "[Deterministic] Failed to validate Job, could not acquire all agents necessary" ); } } } return DeterministicModeValidated; }
/** * Maintain a connection to the coordinator */ public bool PingCoordinator( bool ForcePing ) { StartTiming( "PingCoordinator-Internal", true ); bool CoordinatorPinged = false; // Determine if we should ping #if !__MonoCS__ // @todo Mac bool ShouldPing = ( ForcePing ) || (DateTime.UtcNow > LastCoordinatorPingTime + TimeSpan.FromMinutes(1)); #else bool ShouldPing = false; #endif if( ShouldPing ) { // Determine if we can ping bool CouldPing = ( Coordinator != null ) && ( CoordinatorResponding ) && ( PingRemoteHost( AgentApplication.Options.CoordinatorRemotingHost, AgentApplication.Options.CoordinatorRemotingHost ) ); if( CouldPing ) { LastCoordinatorPingTime = DateTime.UtcNow; // Try to ping the coordinator try { // The AgentInfo defaults cover almost everything, fill in the state AgentInfo AgentInfoUpdate = new AgentInfo(); AgentInfoUpdate.Version = CurrentVersion; // We'll only advertise the number of cores we'll have available for remote connections AgentInfoUpdate.Configuration["LocalAvailableCores"] = AgentApplication.DeveloperOptions.LocalJobsDefaultProcessorCount; AgentInfoUpdate.Configuration["RemoteAvailableCores"] = AgentApplication.DeveloperOptions.RemoteJobsDefaultProcessorCount; // Update with our build group, etc. AgentInfoUpdate.Configuration["UserName"] = Environment.UserName.ToUpperInvariant(); AgentInfoUpdate.Configuration["GroupName"] = AgentApplication.Options.AgentGroupName; AgentInfoUpdate.Configuration["WorkingFor"] = WorkingFor; #if !__MonoCS__ // @todo Mac IPAddress[] CoordinatorAddresses = Dns.GetHostAddresses(AgentApplication.Options.CoordinatorRemotingHost); IPAddress[] LocalAddresses = Dns.GetHostAddresses(Dns.GetHostName()); if(CoordinatorAddresses.Any(CoordinatorAddress => IPAddress.IsLoopback(CoordinatorAddress) || LocalAddresses.Contains(CoordinatorAddress))) { AgentInfoUpdate.Configuration["IPAddress"] = IPAddress.Loopback; } else { var NetworkInterface = NetworkUtils.GetBestInterface( CoordinatorAddresses.Where(CoordinatorAddress => CoordinatorAddress.AddressFamily == AddressFamily.InterNetwork).First() ); AgentInfoUpdate.Configuration["IPAddress"] = NetworkUtils.GetInterfaceIPv4Address(NetworkInterface); } #else AgentInfoUpdate.Configuration["IPAddress"] = "192.168.0.203";//.2.9"; #endif // Check if standalone mode is enabled and use that unless we're closing down if( ( CurrentState != AgentState.Closed ) && ( AgentApplication.Options.EnableStandaloneMode ) ) { AgentInfoUpdate.State = AgentState.Standalone; } else { // Otherwise, pass through the real state AgentInfoUpdate.State = CurrentState; } // A positive return value from the Ping is a request for restart PingResponse Response = Coordinator.Ping( AgentInfoUpdate ); if( Response == PingResponse.Restart ) { Log( EVerbosityLevel.Informative, ELogColour.Green, "[PingCoordinator] Restart has been requested" ); #if !__MonoCS__ // Only restart if we're running the published (and restartable) version if( ApplicationDeployment.IsNetworkDeployed ) { // Only update the value if we're not already restarting if( !AgentIsRestarting ) { // If we've got a signal to restart, request that the agent shutdown RequestRestart(); } } else { Log( EVerbosityLevel.Informative, ELogColour.Green, "[PingCoordinator] Restart request ignored for non-published agents" ); } #endif } CoordinatorPinged = true; } catch( Exception Ex ) { // If we fail for any reason, just log it and try again later Log( EVerbosityLevel.Informative, ELogColour.Orange, "[Ping] Communication with the coordinator failed, job distribution will be disabled until the connection is established" ); Log( EVerbosityLevel.ExtraVerbose, ELogColour.Orange, "Exception details: " + Ex.ToString() ); // Until all open connections are closed, the coordinator is abandoned CoordinatorResponding = false; } } else { AgentApplication.Log( EVerbosityLevel.ExtraVerbose, ELogColour.Green, "[PingCoordinator] Determined that we couldn't ping the coordinator" ); if( Coordinator == null ) { AgentApplication.Log( EVerbosityLevel.ExtraVerbose, ELogColour.Green, "[PingCoordinator] Coordinator is null" ); } else if( CoordinatorResponding == false ) { AgentApplication.Log( EVerbosityLevel.ExtraVerbose, ELogColour.Green, "[PingCoordinator] CoordinatorResponding is false" ); } else { AgentApplication.Log( EVerbosityLevel.ExtraVerbose, ELogColour.Green, "[PingCoordinator] Coordinator ping failed" ); } } } else { AgentApplication.Log( EVerbosityLevel.SuperVerbose, ELogColour.Green, "[PingCoordinator] Determined that we shouldn't ping the coordinator right now" ); } StopTiming(); return CoordinatorPinged; }
/////////////////////////////////////////////////////////////////////////// /** * Standard constructor */ public RemoteConnection( Int32 ConnectionHandle, AgentInfo NewRemoteAgentInfo, RemoteConnectionInterfaceWrapper NewRemoteInterface ) : base(ConnectionHandle) { Info = NewRemoteAgentInfo; Interface = NewRemoteInterface; }
/** * Used internally to try to open connections to remote agents */ public Int32 TryOpenRemoteConnection( LocalConnection ParentConnection, AgentInfo RemoteAgentInfo, bool IsAssigned, DateTime AssignedTimestamp, out RemoteConnection OpenedRemoteConnection ) { // Initialize the return values Int32 ErrorCode = Constants.INVALID; OpenedRemoteConnection = null; string RemoteAgentName = RemoteAgentInfo.Name; string RemoteAgentIPAddress = RemoteAgentInfo.Configuration["IPAddress"].ToString(); Log( EVerbosityLevel.Verbose, ELogColour.Green, "[Connect] Trying to open a remote connection to " + RemoteAgentName + " at " + RemoteAgentIPAddress ); bool bHostNameValid = true; try { ValidateHostName(RemoteAgentIPAddress); } catch (Exception) { ErrorCode = Constants.ERROR_EXCEPTION; bHostNameValid = false; } // First, ping the remote host to make sure we can talk to it if (bHostNameValid && PingRemoteHost(RemoteAgentName, RemoteAgentIPAddress)) { // Get the new unique handle that this connection will be known by Int32 NewConnectionHandle = GetUniqueHandle(); // Get the remote Agent interface object string RemoteAgentURL = String.Format( "tcp://{0}:{1}/SwarmAgent", RemoteAgentIPAddress, Properties.Settings.Default.AgentRemotingPort.ToString() ); Agent RemoteAgentInterface = ( Agent )Activator.GetObject( typeof( Agent ), RemoteAgentURL ); RemoteConnectionInterfaceWrapper WrappedRemoteAgentInterface = new RemoteConnectionInterfaceWrapper( NewConnectionHandle, RemoteAgentName, RemoteAgentIPAddress, RemoteAgentInterface ); Log( EVerbosityLevel.Verbose, ELogColour.Green, "[Connect] Remote agent interface object obtained for " + RemoteAgentName + " at " + RemoteAgentIPAddress ); // With the interface in hand, try to open a bi-directional connection. // Create the new RemoteConnection object and add it to the set // of pending connections, waiting for the incoming confirmation // which will move it to the active connection set. See // ConfirmRemoteConnection for where this happens. RemoteConnection NewRemoteConnection = new RemoteConnection( NewConnectionHandle, RemoteAgentInfo, WrappedRemoteAgentInterface ); PendingConnections.Add( NewConnectionHandle, NewRemoteConnection ); // Try to open the connection try { // Send the connection handle and the machine name that will // be used to construct the return URL for bi-directional // connection if( WrappedRemoteAgentInterface.OpenRemoteConnection( Environment.MachineName, NewConnectionHandle, LoggingFlags, IsAssigned, AssignedTimestamp ) >= 0 ) { // Successful confirmation, double check that the connection has moved if( PendingConnections.ContainsKey( NewConnectionHandle ) == false ) { if( Connections.ContainsKey( NewConnectionHandle ) ) { // Connection was successfully moved to the active connection set // thus the bi-directional communication link is established Log( EVerbosityLevel.Informative, ELogColour.Green, "[Connect] Successfully opened a remote connection with " + RemoteAgentName ); // Establish the parent-child relationship NewRemoteConnection.Parent = ParentConnection; NewRemoteConnection.Job = ParentConnection.Job; ParentConnection.RemoteChildren.Add( NewConnectionHandle, NewRemoteConnection ); ParentConnection.RemoteChildrenSeen++; ParentConnection.ChildrenSeen++; // Update the visualizer indicating that another remote connection is online if( NewRemoteConnection.Job.OwnerIsInstigator ) { AgentApplication.UpdateMachineState( RemoteAgentName, -1, EProgressionState.RemoteConnected ); } // Return the new handle for this connection OpenedRemoteConnection = NewRemoteConnection; ErrorCode = Constants.SUCCESS; } else { // Woah. Bad news. } } } else { // The connection failed to open, but didn't timeout and die, so it's likely just busy. // Return with a success code, but with no remote agent, signaling that it's possible // to try this one again later. ErrorCode = Constants.SUCCESS; } } catch( Exception Ex ) { Log( EVerbosityLevel.Verbose, ELogColour.Red, "[Connect] Exception: " + RemoteAgentName + ": " + Ex.ToString() ); ErrorCode = Constants.ERROR_EXCEPTION; } if( ErrorCode < 0 ) { Log( EVerbosityLevel.Verbose, ELogColour.Red, "[Connect] Failed to open a remote connection with " + RemoteAgentName ); } // Regardless of how we got here, make sure the connection has been removed // from the pending set (this is a safe call to make anytime) PendingConnections.Remove( NewConnectionHandle ); } else { // Failed to ping, simply return with an appropriate error code ErrorCode = Constants.ERROR_CONNECTION_NOT_FOUND; } return ErrorCode; }
/** * Maintain a connection to the coordinator */ public bool PingCoordinator( bool ForcePing ) { StartTiming( "PingCoordinator-Internal", true ); bool CoordinatorPinged = false; // Determine if we should ping #if !__MonoCS__ // @todo Mac bool ShouldPing = ( ForcePing ) || (DateTime.UtcNow > LastCoordinatorPingTime + TimeSpan.FromMinutes(1)); #else bool ShouldPing = false; #endif if( ShouldPing ) { // Determine if we can ping bool CouldPing = ( Coordinator != null ) && ( CoordinatorResponding ) && ( PingRemoteHost( AgentApplication.Options.CoordinatorRemotingHost, AgentApplication.Options.CoordinatorRemotingHost ) ); if( CouldPing ) { LastCoordinatorPingTime = DateTime.UtcNow; // Try to ping the coordinator try { // The AgentInfo defaults cover almost everything, fill in the state AgentInfo AgentInfoUpdate = new AgentInfo(); AgentInfoUpdate.Version = CurrentVersion; // We'll only advertise the number of cores we'll have available for remote connections AgentInfoUpdate.Configuration["LocalAvailableCores"] = AgentApplication.DeveloperOptions.LocalJobsDefaultProcessorCount; AgentInfoUpdate.Configuration["RemoteAvailableCores"] = AgentApplication.DeveloperOptions.RemoteJobsDefaultProcessorCount; // Update with our build group, etc. AgentInfoUpdate.Configuration["UserName"] = Environment.UserName.ToUpperInvariant(); AgentInfoUpdate.Configuration["GroupName"] = AgentApplication.Options.AgentGroupName; AgentInfoUpdate.Configuration["WorkingFor"] = WorkingFor; #if !__MonoCS__ // @todo Mac // Send our IP address for others to use ManagementObjectSearcher ObjectSearcher = new ManagementObjectSearcher( "SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = 'TRUE'" ); ManagementObjectCollection ObjectCollection = ObjectSearcher.Get(); bool bFoundAddress = false; bool bFoundAddressWithDNS = false; foreach( ManagementObject NextObject in ObjectCollection ) { // Get the first IP addresses of the first IPEnabled network adapter string[] AddressList = ( string[] )NextObject["IPAddress"]; string DNSDomain = (string)NextObject["DNSDomain"]; // Use the first address in the enumerator, or the first address with a DNS gateway if one exists // Checking the DNS gateway allows adapters connected to networks to win over adapters earlier in the enumeration that are on a private network, eg connected to console if (!bFoundAddress || !bFoundAddressWithDNS) { AgentInfoUpdate.Configuration["IPAddress"] = IPAddress.Parse(AddressList[0]); bFoundAddress = true; if (DNSDomain != null && DNSDomain.Length > 0) { bFoundAddressWithDNS = true; } } } #else AgentInfoUpdate.Configuration["IPAddress"] = "192.168.0.203";//.2.9"; #endif // Check if standalone mode is enabled and use that unless we're closing down if( ( CurrentState != AgentState.Closed ) && ( AgentApplication.Options.EnableStandaloneMode ) ) { AgentInfoUpdate.State = AgentState.Standalone; } else { // Otherwise, pass through the real state AgentInfoUpdate.State = CurrentState; } // A positive return value from the Ping is a request for restart PingResponse Response = Coordinator.Ping( AgentInfoUpdate ); if( Response == PingResponse.Restart ) { Log( EVerbosityLevel.Informative, ELogColour.Green, "[PingCoordinator] Restart has been requested" ); #if !__MonoCS__ // Only restart if we're running the published (and restartable) version if( ApplicationDeployment.IsNetworkDeployed ) { // Only update the value if we're not already restarting if( !AgentIsRestarting ) { // If we've got a signal to restart, request that the agent shutdown RequestRestart(); } } else { Log( EVerbosityLevel.Informative, ELogColour.Green, "[PingCoordinator] Restart request ignored for non-published agents" ); } #endif } CoordinatorPinged = true; } catch( Exception Ex ) { // If we fail for any reason, just log it and try again later Log( EVerbosityLevel.Informative, ELogColour.Orange, "[Ping] Communication with the coordinator failed, job distribution will be disabled until the connection is established" ); Log( EVerbosityLevel.ExtraVerbose, ELogColour.Orange, "Exception details: " + Ex.ToString() ); // Until all open connections are closed, the coordinator is abandoned CoordinatorResponding = false; } } else { AgentApplication.Log( EVerbosityLevel.ExtraVerbose, ELogColour.Green, "[PingCoordinator] Determined that we couldn't ping the coordinator" ); if( Coordinator == null ) { AgentApplication.Log( EVerbosityLevel.ExtraVerbose, ELogColour.Green, "[PingCoordinator] Coordinator is null" ); } else if( CoordinatorResponding == false ) { AgentApplication.Log( EVerbosityLevel.ExtraVerbose, ELogColour.Green, "[PingCoordinator] CoordinatorResponding is false" ); } else { AgentApplication.Log( EVerbosityLevel.ExtraVerbose, ELogColour.Green, "[PingCoordinator] Coordinator ping failed" ); } } } else { AgentApplication.Log( EVerbosityLevel.SuperVerbose, ELogColour.Green, "[PingCoordinator] Determined that we shouldn't ping the coordinator right now" ); } StopTiming(); return CoordinatorPinged; }