Example #1
0
 private void DeveloperRestartWorkerAgentsMenuItem_Click(object sender, EventArgs e)
 {
     if (AgentApplication.Options.EnableStandaloneMode)
     {
         AgentApplication.Log(EVerbosityLevel.Informative, ELogColour.Green, "[Network] Not restarting worker agents, standalone mode enabled");
     }
     else
     {
         AgentApplication.Log(EVerbosityLevel.Informative, ELogColour.Green, "[Network] Restarting worker agents...");
         AgentApplication.RequestRestartWorkerAgents();
     }
 }
Example #2
0
 private void SwarmAgentWindowClosing(object sender, FormClosingEventArgs e)
 {
     if (e.CloseReason == CloseReason.UserClosing)
     {
         e.Cancel = true;
         Hide();
     }
     else
     {
         AgentApplication.RequestQuit();
     }
 }
Example #3
0
 private void NetworkPingRemoteAgentsMenuItem_Click(object sender, EventArgs e)
 {
     if (AgentApplication.Options.EnableStandaloneMode)
     {
         AgentApplication.Log(EVerbosityLevel.Informative, ELogColour.Green, "[Network] Not pinging remote agents, standalone mode enabled");
     }
     else
     {
         AgentApplication.Log(EVerbosityLevel.Informative, ELogColour.Green, "[Network] Pinging remote agents...");
         AgentApplication.RequestPingRemoteAgents();
         AgentApplication.Log(EVerbosityLevel.Informative, ELogColour.Green, "[Network] Remote Agent ping complete");
     }
 }
Example #4
0
 private void NetworkPingCoordinatorMenuItem_Click(object sender, EventArgs e)
 {
     if (AgentApplication.Options.EnableStandaloneMode)
     {
         AgentApplication.Log(EVerbosityLevel.Informative, ELogColour.Green, "[Network] Not pinging coordinator, standalone mode enabled");
     }
     else
     {
         AgentApplication.Log(EVerbosityLevel.Informative, ELogColour.Green, "[Network] Pinging Coordinator...");
         if (AgentApplication.RequestPingCoordinator())
         {
             AgentApplication.Log(EVerbosityLevel.Informative, ELogColour.Green, "[Network]     Coordinator has responded normally");
         }
         else
         {
             AgentApplication.Log(EVerbosityLevel.Informative, ELogColour.Orange, "[Network]     Coordinator has failed to respond");
         }
         AgentApplication.Log(EVerbosityLevel.Informative, ELogColour.Green, "[Network] Coordinator ping complete");
     }
 }
Example #5
0
        private void OptionsValueChanged(object s, PropertyValueChangedEventArgs e)
        {
            GridItem ChangedProperty = e.ChangedItem;

            if (ChangedProperty != null)
            {
                Type T = ChangedProperty.Value.GetType();
                if (T == typeof(SwarmAgentWindow.DialogFont))
                {
                    UpdateFonts();
                }
                else if (T == typeof(Color))
                {
                    CreateBarColours(this);
                }
                else if ((ChangedProperty.Label == "EnableStandaloneMode") ||
                         (ChangedProperty.Label == "AgentGroupName"))
                {
                    AgentApplication.RequestPingCoordinator();
                }
                else if (ChangedProperty.Label == "CoordinatorRemotingHost")
                {
                    AgentApplication.RequestInitCoordinator();
                }
                else if (ChangedProperty.Label == "ShowDeveloperMenu")
                {
                    DeveloperMenuItem.Visible = ( bool )ChangedProperty.Value;
                }
                else if (ChangedProperty.Label == "CacheFolder")
                {
                    AgentApplication.RequestCacheRelocation();
                }

                // Always write out the latest options when anything changes
                SaveOptions();
            }
        }
Example #6
0
        /**
         * Takes messages off the internal message queue and handles them by either
         * sending responses, forwarding the message on, or processing it internally
         */
        private void ProcessMessagesThreadProc()
        {
            // A response message queue used to send messages back to the one which sent it
            Queue <AgentMessage> ResponseMessageQueue = new Queue <AgentMessage>();

            while (AgentHasShutDown == false)
            {
                StartTiming("ProcessMessage-Internal", true);

                lock ( MessageQueueLock )
                {
                    // Swap the SM and PM message queue to keep things moving at full speed
                    Queue <AgentMessage> Temp = MessageQueuePM;
                    MessageQueuePM = MessageQueueSM;
                    MessageQueueSM = Temp;
                }

                // Process all messages currently in the queue
                while (MessageQueuePM.Count > 0)
                {
                    Debug.Assert(ResponseMessageQueue.Count == 0);

                    // Get and process the next message
                    AgentMessage NextMessage = MessageQueuePM.Dequeue();
                    Debug.Assert(NextMessage != null);

                    bool bMessageHandled = false;
                    switch (NextMessage.Type)
                    {
                    case EMessageType.SIGNAL:
                    {
                        if (NextMessage is DisconnectionSignalMessage)
                        {
                            // Mark the connection as inactive
                            DisconnectionSignalMessage DisconnectMessage = NextMessage as DisconnectionSignalMessage;
                            Log(EVerbosityLevel.Informative,ELogColour.Green,String.Format("[CloseConnection] Connection disconnected {0:X8}",DisconnectMessage.ConnectionToDisconnect.Handle));
                            DisconnectMessage.ConnectionToDisconnect.CurrentState     = ConnectionState.DISCONNECTED;
                            DisconnectMessage.ConnectionToDisconnect.DisconnectedTime = DateTime.UtcNow;
                        }

                        // Signal the message and move on
                        AgentSignalMessage SignalMessage = NextMessage as AgentSignalMessage;
                        SignalMessage.ResetEvent.Set();
                        bMessageHandled = true;
                    }
                    break;

                    case EMessageType.TIMING:
                    {
                        Connection FromConnection;
                        if ((Connections.TryGetValue(NextMessage.From,out FromConnection)))
                        {
                            Connection ToConnection;
                            if ((Connections.TryGetValue(NextMessage.To,out ToConnection)) &&
                                (ToConnection is LocalConnection))
                            {
                                // Handle message
                                AgentTimingMessage TimingMessage = NextMessage as AgentTimingMessage;
                                AgentApplication.UpdateMachineState(MachineNameFromConnection(FromConnection),TimingMessage.ThreadNum,TimingMessage.State);
                                bMessageHandled = true;
                            }
                        }
                    }
                    break;

                    case EMessageType.TASK_REQUEST:
                    {
                        // Look up the requesting connection
                        Debug.Assert(NextMessage.From != Constants.INVALID);
                        Connection RequestingConnection;
                        if (Connections.TryGetValue(NextMessage.From,out RequestingConnection))
                        {
                            // Look up the specified Job
                            AgentJob JobToAskForTasks = RequestingConnection.Job;
                            if (JobToAskForTasks != null)
                            {
                                // If we get a valid response back, add it to the queue
                                AgentTaskRequestResponse Response = JobToAskForTasks.GetNextTask(RequestingConnection);
                                if (Response != null)
                                {
                                    ResponseMessageQueue.Enqueue(Response);

                                    // Specifications and releases are always handled here, but
                                    // reservations are special in that we will send a reservation
                                    // back to local connections but we'll need to make sure the
                                    // message continues on to remote connections.
                                    if ((Response.ResponseType == ETaskRequestResponseType.SPECIFICATION) ||
                                        (Response.ResponseType == ETaskRequestResponseType.RELEASE) ||
                                        ((Response.ResponseType == ETaskRequestResponseType.RESERVATION) &&
                                         (JobToAskForTasks.Owner is LocalConnection)))
                                    {
                                        bMessageHandled = true;
                                    }
                                }
                            }
                            else
                            {
                                // Unable to find the Job, just send back a release message
                                Log(EVerbosityLevel.Verbose,ELogColour.Orange,"[ProcessMessage] Unable to find Job for Task Request; may have been closed");
                                //ResponseMessageQueue.Enqueue( new AgentTaskRequestResponse( RequestingConnection.Job.JobGuid,
                                //															ETaskRequestResponseType.RELEASE ) );
                                bMessageHandled = true;
                            }
                        }
                        else
                        {
                            // Unable to find the connection, swallow the request
                            Log(EVerbosityLevel.Verbose,ELogColour.Orange,"[ProcessMessage] Unable to find owning Connection for Task Request");
                            bMessageHandled = true;
                        }
                    }
                    break;

                    case EMessageType.TASK_STATE:
                    {
                        // Look up the sending connection
                        Debug.Assert(NextMessage.From != Constants.INVALID);
                        Connection SendingConnection;
                        if ((Connections.TryGetValue(NextMessage.From,out SendingConnection)) &&
                            (SendingConnection.Job != null))
                        {
                            // Look up the specified Job
                            AgentJob UpdatedJob;
                            if (ActiveJobs.TryGetValue(SendingConnection.Job.JobGuid,out UpdatedJob))
                            {
                                AgentTaskState UpdatedTaskState = NextMessage as AgentTaskState;
                                UpdatedJob.UpdateTaskState(UpdatedTaskState);

                                if (UpdatedJob.Owner is LocalConnection)
                                {
                                    // If the Task state change is of a type potentially interesting to
                                    // the Instigator, return it
                                    switch (UpdatedTaskState.TaskState)
                                    {
                                    case EJobTaskState.TASK_STATE_INVALID:
                                    case EJobTaskState.TASK_STATE_COMPLETE_SUCCESS:
                                    case EJobTaskState.TASK_STATE_COMPLETE_FAILURE:
                                        // For these message types, allow the message to continue on
                                        break;

                                    default:
                                        // Nothing to do otherwise, mark the message as handled
                                        bMessageHandled = true;
                                        break;
                                    }
                                }
                                else
                                {
                                    // Always send messages on for remote connections
                                }
                            }
                            else
                            {
                                // Unable to find the Job, swallow the request
                                Log(EVerbosityLevel.Verbose,ELogColour.Orange,"[ProcessMessage] Unable to find Job for Task Request");
                                bMessageHandled = true;
                            }
                        }
                        else
                        {
                            // Unable to find the connection, swallow the request
                            Log(EVerbosityLevel.Verbose,ELogColour.Orange,"[ProcessMessage] Unable to find owning Connection for Task Request");
                            bMessageHandled = true;
                        }
                    }
                    break;
                    }

                    // If the message was not handled completely, send it on
                    if (bMessageHandled == false)
                    {
                        // Look up who the message is being sent to and make sure they're
                        // still active and if not, ignore the message
                        Connection Recipient;
                        Debug.Assert(NextMessage.To != Constants.INVALID);
                        if (Connections.TryGetValue(NextMessage.To,out Recipient))
                        {
                            if (Recipient is LocalConnection)
                            {
                                // If the recipient is local, place it in the proper queue
                                // and signal that a message is ready
                                LocalConnection LocalRecipient = Recipient as LocalConnection;
                                lock (LocalRecipient.MessageQueue)
                                {
                                    LocalRecipient.MessageQueue.Enqueue(NextMessage);

                                    string NewLogMessage = String.Format("Step 2 of 4 for message: ({0:X8} -> {1:X8}), {2}, Message Count {3} (Local Connection)",
                                                                         NextMessage.To,
                                                                         NextMessage.From,
                                                                         NextMessage.Type,
                                                                         LocalRecipient.MessageQueue.Count);

                                    Log(EVerbosityLevel.SuperVerbose,ELogColour.Green,NewLogMessage);

                                    LocalRecipient.MessageAvailableSignal();
                                }
                            }
                            else
                            {
                                Debug.Assert(Recipient is RemoteConnection);

                                // If the recipient is remote, send the message via SendMessage
                                // unless the message is a Task being sent back, which is sent
                                // via the dedicated Task API
                                RemoteConnection RemoteRecipient = Recipient as RemoteConnection;
                                if (NextMessage is AgentTaskSpecification)
                                {
                                    // All new Tasks are sent via the dedicated Task API
                                    AgentTaskSpecification TaskSpecification = NextMessage as AgentTaskSpecification;

                                    Hashtable RemoteInParameters = new Hashtable();
                                    RemoteInParameters["Version"]       = ESwarmVersionValue.VER_1_0;
                                    RemoteInParameters["Specification"] = TaskSpecification;
                                    Hashtable RemoteOutParameters = null;

                                    Int32 Error = RemoteRecipient.Interface.AddTask(RemoteRecipient.Handle,RemoteInParameters,ref RemoteOutParameters);
                                    if (Error >= 0)
                                    {
                                        // Perhaps we should be sending an accept message back?
                                    }
                                    else
                                    {
                                        AgentTaskState UpdateMessage;
                                        if (Error == Constants.ERROR_CONNECTION_DISCONNECTED)
                                        {
                                            // Special case of the connection dropping while we're adding the
                                            // task, say it's been killed to requeue
                                            UpdateMessage = new AgentTaskState(TaskSpecification.JobGuid,
                                                                               TaskSpecification.TaskGuid,
                                                                               EJobTaskState.TASK_STATE_KILLED);
                                        }
                                        else
                                        {
                                            // All other error cases will be rejections
                                            UpdateMessage = new AgentTaskState(TaskSpecification.JobGuid,
                                                                               TaskSpecification.TaskGuid,
                                                                               EJobTaskState.TASK_STATE_REJECTED);
                                        }
                                        AgentJob Job;
                                        if (ActiveJobs.TryGetValue(TaskSpecification.JobGuid,out Job))
                                        {
                                            Job.UpdateTaskState(UpdateMessage);
                                        }
                                    }
                                }
                                else
                                {
                                    // All standard messages are sent via the SendMessage API
                                    Hashtable RemoteInParameters = new Hashtable();
                                    RemoteInParameters["Version"] = ESwarmVersionValue.VER_1_0;
                                    RemoteInParameters["Message"] = NextMessage;
                                    Hashtable RemoteOutParameters = null;

                                    RemoteRecipient.Interface.SendMessage(NextMessage.To,RemoteInParameters,ref RemoteOutParameters);
                                }

                                string NewLogMessage = String.Format("Step 2 of 2 for message: ({0:X8} -> {1:X8}), {2}, (Remote Connection)",
                                                                     NextMessage.To,
                                                                     NextMessage.From,
                                                                     NextMessage.Type);

                                Log(EVerbosityLevel.SuperVerbose,ELogColour.Green,NewLogMessage);
                            }
                        }
                        else
                        {
                            Log(EVerbosityLevel.Informative,ELogColour.Orange,"ProcessMessage: Message sent to invalid connection, ignoring: " + NextMessage.Type.ToString());
                        }
                    }

                    // If there are any responses to the message, send them
                    if (ResponseMessageQueue.Count > 0)
                    {
                        foreach (AgentMessage NextResponse in ResponseMessageQueue)
                        {
                            // For each one of the messages, set the routing fields properly
                            NextResponse.To   = NextMessage.From;
                            NextResponse.From = NextMessage.To;

                            // And then queue the message back up immediately
                            MessageQueuePM.Enqueue(NextResponse);
                        }
                        ResponseMessageQueue.Clear();
                    }
                }

                StopTiming();

                // Wait for a message to become available and once unlocked, swap the queues
                // and check for messages to process. Set a timeout, so we'll wake up every
                // now and then to check for a quit signal at least
                MessageQueueReady.WaitOne(500);
            }
        }
Example #7
0
		static void Main( string[] args )
		{
            // Read args
            ParseArgs(args);

            // Start up the GUI thread
            InitGUIThread();

			AgentApplication.Log( EVerbosityLevel.Informative, ELogColour.Green, "Starting up SwarmAgent ..." );
			AgentApplication.Log( EVerbosityLevel.Informative, ELogColour.Green, " ... registering SwarmAgent with remoting service" );

			// Register the local agent singleton
			RemotingConfiguration.RegisterWellKnownServiceType( typeof( Agent ), "SwarmAgent", WellKnownObjectMode.Singleton );

            AgentApplication.Log( EVerbosityLevel.Informative, ELogColour.Green, " ... registering SwarmAgent network channels" );

			// We're going to have two channels for the Agent: one for the actual Agent
			// application (IPC with infinite timeout) and one for all other remoting
			// traffic (TCP with infinite timeout that we monitor for drops)
			IpcChannel AgentIPCChannel = null;
            TcpChannel AgentTCPChannel = null;
            while( ( Ticking == true ) &&
				   ( ( AgentIPCChannel == null ) ||
				     ( AgentTCPChannel == null ) ) )
			{
				try
				{
					if( AgentIPCChannel == null )
					{
						// Register the IPC connection to the local agent
						string IPCChannelPortName = String.Format( "127.0.0.1:{0}", Properties.Settings.Default.AgentRemotingPort );
						AgentIPCChannel = new IpcChannel( IPCChannelPortName );
						ChannelServices.RegisterChannel( AgentIPCChannel, false );
					}

					if( AgentTCPChannel == null )
					{
						// Register the TCP connection to the local agent
						AgentTCPChannel = new TcpChannel( Properties.Settings.Default.AgentRemotingPort );
						ChannelServices.RegisterChannel( AgentTCPChannel, false );
					}
				}
				catch (RemotingException Ex)
				{
					AgentApplication.Log(EVerbosityLevel.Informative, ELogColour.Orange, "[ERROR] Channel already registered, suggesting another SwarmAgent or client is running.");
					AgentApplication.Log(EVerbosityLevel.Informative, ELogColour.Orange, "[ERROR] If you feel this is in error, check your running process list for additional copies of");
					AgentApplication.Log(EVerbosityLevel.Informative, ELogColour.Orange, "[ERROR] SwarmAgent or UnrealLightmass (or other client) and consider killing them.");
					AgentApplication.Log(EVerbosityLevel.Informative, ELogColour.Orange, "[ERROR] Sleeping for a few seconds and trying again...");
					AgentApplication.Log(EVerbosityLevel.Informative, ELogColour.Orange, string.Format("[ERROR] Channel registration failed. Reason: {0}\n, Callstack: {1}.", Ex.Message, Ex.StackTrace));
					Thread.Sleep(3000);
				}
				catch (Exception Ex)
				{
					AgentApplication.Log(EVerbosityLevel.Informative, ELogColour.Orange, string.Format("[ERROR] Channel registration failed. Reason: {0}\n, Callstack: {1}.", Ex.Message, Ex.StackTrace));
					Thread.Sleep(3000);
				}
			}

			// if we're still ticking, we should have both of our channels initialized
			if( Ticking )
			{
				Debug.Assert( AgentIPCChannel != null );
				Debug.Assert( AgentTCPChannel != null );
			}
			else
			{
				// Otherwise, we can simply return to exit
				return;
			}

			// Get the agent interface object using the IPC channel
			string LocalAgentURL = String.Format( "ipc://127.0.0.1:{0}/SwarmAgent", Properties.Settings.Default.AgentRemotingPort.ToString() );
			LocalAgent = ( Agent )Activator.GetObject( typeof( Agent ), LocalAgentURL );

			AgentApplication.Log( EVerbosityLevel.Informative, ELogColour.Green, " ... initializing SwarmAgent" );
            
            // Init the local agent object (if this is the first call to it, it will be created now)
			bool AgentInitializedSuccessfully = false;
			try
			{
				AgentInitializedSuccessfully = LocalAgent.Init( Process.GetCurrentProcess().Id );
			}
			catch( Exception Ex )
			{
				AgentApplication.Log( EVerbosityLevel.Informative, ELogColour.Red, "[ERROR] Local agent failed to initialize with an IPC channel! Falling back to TCP..." );
				AgentApplication.Log( EVerbosityLevel.Verbose, ELogColour.Red, "[ERROR] Exception details: " + Ex.ToString() );

				// Try again with the TCP channel, which is slower but should work
				LocalAgentURL = String.Format( "tcp://127.0.0.1:{0}/SwarmAgent", Properties.Settings.Default.AgentRemotingPort.ToString() );
				LocalAgent = ( Agent )Activator.GetObject( typeof( Agent ), LocalAgentURL );

				try
				{
					AgentInitializedSuccessfully = LocalAgent.Init( Process.GetCurrentProcess().Id );
					if( AgentInitializedSuccessfully )
					{
						AgentApplication.Log( EVerbosityLevel.Informative, ELogColour.Red, "[ERROR] RECOVERED by using TCP channel!" );
					}
				}
				catch( Exception Ex2 )
				{
					AgentApplication.Log( EVerbosityLevel.Informative, ELogColour.Red, "[ERROR] Local agent failed to initialize with a TCP channel! Fatal error." );
					AgentApplication.Log( EVerbosityLevel.Verbose, ELogColour.Red, "[ERROR] Exception details: " + Ex2.ToString() );

					ChannelServices.UnregisterChannel( AgentTCPChannel );
					ChannelServices.UnregisterChannel( AgentIPCChannel );
					return;
				}
			}

			// Only continue if we have a fully initialized agent
			if( ( LocalAgent != null ) && AgentInitializedSuccessfully )
			{
				AgentApplication.Log( EVerbosityLevel.Informative, ELogColour.Green, " ... initialization successful, SwarmAgent now running" );
                
                // Loop until a quit/restart event has been requested
				while( !LocalAgent.ShuttingDown() )
				{
					try
					{
						// If we've stopped ticking, notify the agent that we want to shutdown
						if( !Ticking )
						{
							LocalAgent.RequestShutdown();
						}

						// Maintain the agent itself
						LocalAgent.MaintainAgent();

						// Maintain any running active connections
						LocalAgent.MaintainConnections();

						// Maintain the Agent's cache
						if( CacheRelocationRequested )
						{
							LocalAgent.RequestCacheRelocation();
							CacheRelocationRequested = false;
						}
						if( CacheClearRequested )
						{
							LocalAgent.RequestCacheClear();
							CacheClearRequested = false;
						}
						if( CacheValidateRequested )
						{
							LocalAgent.RequestCacheValidate();
							CacheValidateRequested = false;
						}
						LocalAgent.MaintainCache();

						// Maintain any running jobs
						LocalAgent.MaintainJobs();

						// If this is a deployed application which is configured to auto-update,
						// we'll check for any updates and, if there are any, request a restart
						// which will install them prior to restarting
#if !__MonoCS__
						if( ( AgentApplication.DeveloperOptions.UpdateAutomatically ) &&
							( ApplicationDeployment.IsNetworkDeployed ) &&
                            (DateTime.UtcNow > NextUpdateCheckTime))
						{
							if( CheckForUpdates() )
							{
								LocalAgent.RequestRestart();
							}
                            NextUpdateCheckTime = DateTime.UtcNow + TimeSpan.FromMinutes(1);
						}
#endif
					}
					catch( Exception Ex )
					{
                        AgentApplication.Log( EVerbosityLevel.Informative, ELogColour.Red, "[ERROR] UNHANDLED EXCEPTION: " + Ex.Message );
						AgentApplication.Log( EVerbosityLevel.ExtraVerbose, ELogColour.Red, "[ERROR] UNHANDLED EXCEPTION: " + Ex.ToString() );
					}

					// Sleep for a little bit
					Thread.Sleep( 500 );
				}

				// Let the GUI destroy itself
				RequestQuit();
				
				bool AgentIsRestarting = LocalAgent.Restarting();

				// Do any required cleanup
				LocalAgent.Destroy();

				ChannelServices.UnregisterChannel( AgentTCPChannel );
				ChannelServices.UnregisterChannel( AgentIPCChannel );

				// Now that everything is shut down, restart if requested
				if( AgentIsRestarting )
				{
					ClearCache();
					InstallAllUpdates();
					Application.Restart();
				}
			}
		}
        ///////////////////////////////////////////////////////////////////////////

        /*
         * Logs a line of text to the agent log window
         */
        public Int32 Log(EVerbosityLevel Verbosity, ELogColour TextColour, string Line)
        {
            AgentApplication.Log(Verbosity, TextColour, Line);
            return(Constants.SUCCESS);
        }
Example #9
0
 private void CacheValidateClick(object sender, EventArgs e)
 {
     AgentApplication.RequestCacheValidation();
 }
Example #10
0
 private void CacheClearClick(object sender, EventArgs e)
 {
     AgentApplication.RequestCacheClear();
 }
Example #11
0
 private void ClickExitMenu(object sender, EventArgs e)
 {
     Hide();
     AgentApplication.RequestQuit();
 }