Example #1
0
        public void ClearJobsQueue()
        {
            lock (_jobsQueue)
                _jobsQueue.Clear();

            // Generate log
            Log log = new Log();

            log.Message = "All jobs removed from the jobs queue.";
            EventExtensions.Raise(NewLogItem, new[] { log });
        }
Example #2
0
        public void Start()
        {
            Log log = null;

            if (IsListening)
            {
                throw new InvalidOperationException("Worker agent is started alerady.");
            }

            try {
                // Start Listening
                _listener = new TcpListener(IPAddress.Any, ListenDataChannelPortNumber);
                _listener.Start();
                _listener.BeginAcceptTcpClient(AcceptConnectionCallBack, _listener);
                IsListening = true;

                // Create worker thread
                Thread t = new Thread(WorkerThread);
                t.IsBackground = true;
                t.Start();
                IsListening = true;

                // Generate Log
                log         = new WorkerStartedLog();
                log.Message = "Worker started.";
                EventExtensions.Raise(NewLogItem, new[] { log });
            }
            catch (Exception e) {
                // Generate Log
                log         = new WorkerCouldNotStartLog();
                log.Message = "Worker could not start.";
                ((WorkerCouldNotStartLog)log).ErrorMessage = e.Message;
                EventExtensions.Raise(NewLogItem, new[] { log });
            }

            // Try to register worker
            if (IsListening)
            {
                bool registerd;
                _controlUnit.JobServerControlUnit = new IPEndPoint(JobServerIPAddress, JobServerControlChannelPortNumber);
                registerd = _controlUnit.RegisterWorker(this.ID, this.ListenDataChannelPortNumber, this.ListenControlChannelPortNumber);

                // If registration has failed, we should stop listening
                if (!registerd)
                {
                    try {
                        IsListening = false; // This line should comes before "_listener.stop()"
                        _listener.Stop();
                    }
                    catch {
                    }
                }
            }
        }
Example #3
0
        public void Stop()
        {
            Log log;

            try {
                IsListening = false; // This line should comes before "_listener.stop()"
                _listener.Stop();

                // Generate Log
                log         = new WorkerStoppedLog();
                log.Message = "Worker stopped.";
            }
            catch (Exception e) {
                // Generate Log
                log         = new WorkerCouldNotStopLog();
                log.Message = "Worker could not stop.";
                ((WorkerCouldNotStopLog)log).ErrorMessage = e.Message;
            }

            // Raise "NewLogItem" event
            EventExtensions.Raise(NewLogItem, new[] { log });
        }
Example #4
0
 void _controlUnit_OnNewLogItem(WorkerAgent.Log log)
 {
     // Raise "this.NewLogItem" event
     EventExtensions.Raise(NewLogItem, new[] { log });
 }
Example #5
0
        private void AcceptConnectionCallBack(IAsyncResult ar)
        {
            byte[] message      = null; // buffer
            byte   numberOfJobs = 0;
            byte   flags;
            uint   payloadSize;
            bool   isLittleEndianArchitecture;

            // Accept Connection
            TcpClient client;

            // After invoking TcpListener.Stop(), this method is invoked and we must return from this method
            // if IsListening is false.
            if (IsListening)
            {
                client = _listener.EndAcceptTcpClient(ar);
            }
            else
            {
                return;
            }

            #region Start reciving data from network and store it in buffer

            const int     HEADER_JOB_ID_FIELD_SIZE = 8;                 // 8 Byte
            const int     HEADER_JOB_EXECUTABLE_ADDRESS_FIELD_SIZE = 4; // 4 Byte
            const int     HEADER_JOB_INPUT_ADDRESS_FIELD_SIZE      = 4; // 4 Byte
            const int     JOB_HEADER_SIZE         = HEADER_JOB_ID_FIELD_SIZE + HEADER_JOB_EXECUTABLE_ADDRESS_FIELD_SIZE + HEADER_JOB_INPUT_ADDRESS_FIELD_SIZE;
            NetworkStream netStream               = null;
            bool          dataRecivedSuccessfully = true;

            try {
                netStream = client.GetStream();

                // Reads field "Flags"
                flags = (byte)netStream.ReadByte();
                isLittleEndianArchitecture = (flags == 0) ? true : false;

                // Reads field "Number Of Jobs"
                numberOfJobs = (byte)netStream.ReadByte();

                // Reads field "Payload Size"
                byte[] payloadSizeBytes = new byte[4];
                netStream.Read(payloadSizeBytes, 0, 4);
                if (!isLittleEndianArchitecture)
                {
                    payloadSizeBytes.Reverse();
                }
                payloadSize = BitConverter.ToUInt32(payloadSizeBytes, 0);
                //

                // Allocate memory for the rest of message (without fileds "Flags", "Number of jobs" and "Payload Size")
                // And read rest of the message from the NetworkStream
                int messageSize = (numberOfJobs * JOB_HEADER_SIZE) + (int)payloadSize;
                message = new byte[messageSize];
                netStream.Read(message, 0, messageSize);
            }
            catch {
                dataRecivedSuccessfully = false;
            }
            finally {
                if (netStream != null)
                {
                    netStream.Close();
                }
                if (client != null)
                {
                    client.Close();
                }
            }

            // Start listening for new connections
            try {
                //_listener.Start(1);
                _listener.BeginAcceptTcpClient(AcceptConnectionCallBack, _listener);
            }
            catch {
                // Generate WorkerCouldNotStartLog log
                WorkerStoppedLog log = new WorkerStoppedLog();
                log.Message = "Worker could not continue to listen for new jobs, so it has stopped.";
                EventExtensions.Raise(NewLogItem, new[] { log });
            }

            #endregion

            #region Create job objects and save theam to the "JobsDirectoryName" directory

            // numberOfJobs = 1
            List <Job> recivedJobs = new List <Job>(10);
            if (dataRecivedSuccessfully)
            {
                for (int i = 0; i < numberOfJobs; i++)
                {
                    #region Create job object
                    Job    newJob = new Job();
                    UInt32 jobExecutableStartLocation;
                    UInt32 jobInputStartLocation;

                    // ID
                    newJob.ID = BitConverter.ToUInt64(message, 0);

                    // InputFileName
                    StringBuilder filename = new StringBuilder(50);
                    DateTime      now      = DateTime.Now;
                    Random        rnd      = new Random();

                    filename.Append(JobsDirectoryName);
                    filename.Append("\\job");
                    filename.Append(newJob.ID.ToString());
                    filename.Append("_");
                    filename.Append(now.Hour.ToString("D2"));
                    filename.Append(now.Minute.ToString("D2"));
                    filename.Append(now.Second.ToString("D2"));
                    filename.Append("_");
                    filename.Append(rnd.Next(1000000).ToString("D6"));

                    newJob.InputFileName = filename.ToString() + ".in";

                    // OutputFileName
                    newJob.OutputFileName = filename.ToString() + ".out";

                    // ExecuteableFileName
                    newJob.ExecuteableFileName = filename.ToString() + ".exe";

                    #endregion

                    #region Write job's Executable and input files to disk
                    jobExecutableStartLocation  = BitConverter.ToUInt32(message, 8);  // in payload address space
                    jobInputStartLocation       = BitConverter.ToUInt32(message, 12); // in payload address space
                    jobExecutableStartLocation += 16;
                    jobInputStartLocation      += 16;
                    newJob.ExecutableFileLength = jobInputStartLocation - jobExecutableStartLocation;
                    newJob.InputFileLength      = (UInt32)message.Length - newJob.ExecutableFileLength - JOB_HEADER_SIZE;

                    System.IO.FileStream fsExe   = null;
                    System.IO.FileStream fsInput = null;
                    try {
                        // Create "jobs directory" if it is not exists
                        if (!System.IO.Directory.Exists(JobsDirectoryName))
                        {
                            System.IO.Directory.CreateDirectory(JobsDirectoryName);
                        }

                        // Create job's executable file
                        fsExe = System.IO.File.Create(newJob.ExecuteableFileName);
                        fsExe.Write(message, (int)jobExecutableStartLocation, (int)newJob.ExecutableFileLength);

                        // Create job's input file
                        fsInput = System.IO.File.Create(newJob.InputFileName);
                        fsInput.Write(message, (int)jobInputStartLocation, (int)newJob.InputFileLength);

                        // Add jobs to the jobs queue
                        lock (_jobsQueue) {
                            _jobsQueue.Enqueue(newJob);
                        }

                        // Add jobs to the recieved jobs list
                        recivedJobs.Add(newJob);
                    }
                    catch (Exception e) {
                        // Error in writing jobs to the disk
                        // Generate log and Raise "NewLogItem" event
                        WorkerAgent.ErrorInWritingJobToDiskLog log = new WorkerAgent.ErrorInWritingJobToDiskLog();
                        log.Job          = newJob;
                        log.Message      = "Could not write the job to the jobs directory, please verify jobs directory.";
                        log.ErrorMessage = e.Message;
                        EventExtensions.Raise(NewLogItem, new[] { log });
                    }
                    finally {
                        if (fsExe != null)
                        {
                            fsExe.Close();
                        }
                        if (fsInput != null)
                        {
                            fsInput.Close();
                        }
                    }
                    #endregion
                }
            }

            // Generate Log
            WorkerAgent.JobsRecivedLog recivelog = new WorkerAgent.JobsRecivedLog();
            ((WorkerAgent.JobsRecivedLog)recivelog).Jobs = recivedJobs.ToArray();
            recivelog.Message = "A batch of jobs recieved.";

            // Raise "NewLogItem" event
            EventExtensions.Raise(NewLogItem, new[] { recivelog });

            #endregion
        }
Example #6
0
        private bool SendResultToJobServer(Job j, out bool errorInReadingOutputFile)
        {
            const int HEADER_FLAGS_FIELD_SIZE        = 1; // 1 Byte
            const int HEADER_PAYLOAD_SIZE_FIELD_SIZE = 4; // 4 Byte
            const int HEADER_WORKER_ID_FIELD_SIZE    = 2; // 2 Byte
            const int HEADER_JOB_ID_FIELD_SIZE       = 8; // 8 Byte
            const int HEADER_PAYLOAD_START_INDEX     = HEADER_FLAGS_FIELD_SIZE + HEADER_PAYLOAD_SIZE_FIELD_SIZE +
                                                       HEADER_WORKER_ID_FIELD_SIZE + HEADER_JOB_ID_FIELD_SIZE;

            byte[] message     = null;
            long   messageSize = 0;
            bool   jobOutputFileReadSuccessfully = true;
            uint   jobOutputFileLength           = 0;

            #region Read Job's output file
            System.IO.FileStream        fs             = null;
            ErrorInReadingJobOutputFile fileReadErrLog = null;
            try {
                // Open Job's result file for reading
                fs = System.IO.File.OpenRead(j.OutputFileName);

                // allocate memory for message
                jobOutputFileLength = (uint)fs.Length;
                messageSize         = HEADER_FLAGS_FIELD_SIZE + HEADER_PAYLOAD_SIZE_FIELD_SIZE + HEADER_WORKER_ID_FIELD_SIZE +
                                      HEADER_JOB_ID_FIELD_SIZE + jobOutputFileLength;
                message = new byte[messageSize];
                //

                // Read file and close it
                fs.Read(message, HEADER_PAYLOAD_START_INDEX, (int)jobOutputFileLength);
                errorInReadingOutputFile = false;
            }
            catch (System.IO.FileNotFoundException fileNotFoundExcp) {
                jobOutputFileReadSuccessfully = false;
                fileReadErrLog              = new WorkerAgent.ErrorInReadingJobOutputFile();
                fileReadErrLog.Job          = j;
                fileReadErrLog.Message      = "Job's output file not found.";
                fileReadErrLog.ErrorMessage = fileNotFoundExcp.Message;
                errorInReadingOutputFile    = true;
                EventExtensions.Raise(NewLogItem, new[] { fileReadErrLog });
            }
            catch (Exception e) {
                jobOutputFileReadSuccessfully = false;
                fileReadErrLog              = new WorkerAgent.ErrorInReadingJobOutputFile();
                fileReadErrLog.Job          = j;
                fileReadErrLog.Message      = "Error in reading job's output file.";
                fileReadErrLog.ErrorMessage = e.Message;
                errorInReadingOutputFile    = true;
                EventExtensions.Raise(NewLogItem, new[] { fileReadErrLog });
            }
            finally {
                if (fs != null)
                {
                    fs.Close();
                }
            }
            #endregion

            if (!jobOutputFileReadSuccessfully)
            {
                return(false);
            }

            #region Send job result(message) to the job server
            // Set Header's fields of the message
            byte[] payloadSizeBytes = new byte[4]; // UInt32
            byte[] workerIDBytes    = new byte[2]; // UInt16
            byte[] jobIDBytes       = new byte[8]; // UInt64

            // Flags
            message[0] = 0; // This field is reserved for future use.

            // Payload Size, UInt32
            payloadSizeBytes = BitConverter.GetBytes(jobOutputFileLength);
            for (int i = 0; i < 4; i++)
            {
                message[i + HEADER_FLAGS_FIELD_SIZE] = payloadSizeBytes[i];
            }

            // Worker ID, UInt16
            workerIDBytes = BitConverter.GetBytes(ID);
            for (int i = 0; i < 2; i++)
            {
                message[i + HEADER_FLAGS_FIELD_SIZE + HEADER_PAYLOAD_SIZE_FIELD_SIZE] = workerIDBytes[i];
            }

            // JobID, UInt64
            jobIDBytes = BitConverter.GetBytes(j.ID);
            for (int i = 0; i < 8; i++)
            {
                message[i + HEADER_FLAGS_FIELD_SIZE + HEADER_PAYLOAD_SIZE_FIELD_SIZE + HEADER_WORKER_ID_FIELD_SIZE] = jobIDBytes[i];
            }

            // Try "AttemptsToSendResult" times to send the message
            bool          successfullySent = false;
            TcpClient     client           = new TcpClient();
            NetworkStream netStream        = null;

            for (int i = 1; (i <= AttemptsToSendResult) && (!successfullySent); i++)
            {
                try {
                    client.Connect(new IPEndPoint(JobServerIPAddress, JobServerDataChannelPortNumber));
                    netStream = client.GetStream();
                    netStream.Write(message, 0, (int)messageSize);
                    successfullySent = true;

                    // Generate log
                    WorkerAgent.JobResultSentLog log = new JobResultSentLog();
                    log.Job     = j;
                    log.Message = "Job's output file sent to the job server.";
                    EventExtensions.Raise(NewLogItem, new[] { log });
                }
                catch (Exception e) {
                    successfullySent = false;
                    WorkerAgent.ErrorInConnectingToJobServerLog log = new ErrorInConnectingToJobServerLog();
                    log.Message      = "[ Attempt " + (i).ToString() + " ]   Could not connect to the job server to transfer the results.";
                    log.ErrorMessage = e.Message;
                    EventExtensions.Raise(NewLogItem, new[] { log });
                }

                if ((!successfullySent) && (i < AttemptsToSendResult))
                {
                    // if an error has occured in sending, Wait 1 second and then try to send again
                    System.Threading.Thread.Sleep(3000);
                }
            }

            if (netStream != null)
            {
                netStream.Close();
            }
            client.Close();
            #endregion

            return(successfullySent);
        }
Example #7
0
        private void WorkerThread()
        {
            while (IsListening)
            {
                Job j = null;
                lock (_jobsQueue) {
                    if (_jobsQueue.Count > 0)
                    {
                        j = _jobsQueue.Dequeue();
                    }
                    else
                    {
                        Monitor.Wait(_jobsQueue, 3000);
                    }
                }

                if (j != null)
                {
                    #region Run the job (if it is never executed before)
                    bool jobSuccessfullyExecuted = false;

                    if (System.IO.File.Exists(j.OutputFileName))
                    {
                        // job is executed in past,and becuse of a send error it returned to the jobs queue
                        // we shouldn't execute it again
                        jobSuccessfullyExecuted = true;
                    }
                    else
                    {
                        // Execute the job
                        ProcessStartInfo startInfo = new ProcessStartInfo();
                        startInfo.FileName       = j.ExecuteableFileName;
                        startInfo.Arguments      = "\"" + j.InputFileName + "\" \"" + j.OutputFileName + "\"";
                        startInfo.WindowStyle    = ProcessWindowStyle.Hidden;
                        startInfo.CreateNoWindow = true;

                        // Raise
                        WorkerAgent.JobExecutionStartedLog executionStartedLog = new JobExecutionStartedLog();
                        executionStartedLog.Job     = j;
                        executionStartedLog.Message = "Job execution has started.";
                        EventExtensions.Raise(NewLogItem, new object[] { executionStartedLog });

                        Log executionLog;
                        try {
                            // Try execute the job
                            Process proc = Process.Start(startInfo);
                            proc.WaitForExit();
                            jobSuccessfullyExecuted = true;
                            executionLog            = new JobExecutedSuccessfullyLog();
                            ((JobExecutedSuccessfullyLog)executionLog).Job = j;
                            executionLog.Message = "Job successfully executed.";
                        }
                        catch (System.ComponentModel.Win32Exception win32Exception) {
                            executionLog         = new ErrorInJobExecutionLog();
                            executionLog.Message = "An error occurred while running the job.";
                            ((ErrorInJobExecutionLog)executionLog).Job            = j;
                            ((ErrorInJobExecutionLog)executionLog).IsWin32Error   = true;
                            ((ErrorInJobExecutionLog)executionLog).Win32ErrorCode = win32Exception.ErrorCode;
                            ((ErrorInJobExecutionLog)executionLog).ErrorMessage   = win32Exception.Message;
                        }
                        catch (Exception e) {
                            executionLog         = new ErrorInJobExecutionLog();
                            executionLog.Message = "An error occurred while running the job.";
                            ((ErrorInJobExecutionLog)executionLog).Job          = j;
                            ((ErrorInJobExecutionLog)executionLog).ErrorMessage = e.Message;
                        }
                        EventExtensions.Raise(NewLogItem, new object[] { executionLog });
                    }
                    #endregion

                    // Send job result to the job server
                    bool successfullySent         = false;
                    bool errorInReadingOutputFile = false;
                    if (IsListening && jobSuccessfullyExecuted)
                    {
                        successfullySent = SendResultToJobServer(j, out errorInReadingOutputFile);
                    }

                    if (!successfullySent && jobSuccessfullyExecuted && !errorInReadingOutputFile && IsListening)
                    {
                        // Sending job to the job server failed becuse of a network problem
                        // We should restore the job to the jobs queue and stop.
                        lock (_jobsQueue) {
                            _jobsQueue.Enqueue(j); // Restore the job to the jobs queue
                            Stop();                // Stop listening
                        }
                    }
                }
            }
        }