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 }); }
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 }