/// <summary> /// Adds a new jobs to the queue. This implies that the slave /// will be in charge of executing this particular job. /// </summary> public virtual void ScheduleJob(IJob job) { lock (_jobs) { if (job.Sent) { // just in case State.Output.Fatal("Tried to reschedule an existing job"); } _jobs.Insert(_jobs.Count, job); SlaveMonitor.NotifyMonitor(_jobs); } }
public virtual void Shutdown(IEvolutionState state) { // prevent me from hitting this multiple times lock (_shutDownLock) { if (ShuttingDown) { return; } ShuttingDown = true; } // don't want to miss any of these so we'll wrap them individually try { // BRS: TODO : Not sure if shutdown status was intended here? DataOut.Write((byte)SlaveEvaluationType.Shutdown); } catch (Exception) { } // exception, not IOException, because JZLib throws some array exceptions try { DataOut.Flush(); } catch (Exception) { } try { DataOut.Close(); } catch (Exception) { } try { DataIn.Close(); } catch (Exception) { } try { EvalSocket.Close(); } catch (IOException) { } State.Output.SystemMessage(ToString() + " Slave is shutting down...."); SlaveMonitor.UnregisterSlave(this); // unregister me BEFORE I reschedule my jobs RescheduleJobs(State); lock (_jobs) { // notify my threads now that I've closed stuff in case they're still waiting SlaveMonitor.NotifyMonitor(_jobs); Reader.Interrupt(); // not important right now but... Writer.Interrupt(); // very important that we be INSIDE the jobs synchronization here so the writer doesn't try to wait on the monitor again. } State.Output.SystemMessage(ToString() + " Slave exits...."); }
/// <summary> /// Reschedules the jobs in this job queue to other slaves in the system. It assumes that the slave associated /// with this queue has already been removed from the available slaves, such that it is not assigned its own jobs. /// </summary> /// <remarks>Only called when we're shutting down, so we're not waiting for any notification.</remarks> public virtual void RescheduleJobs(IEvolutionState state) { while (true) { IJob job; lock (_jobs) { if ((_jobs.Count == 0)) { return; } var tempObject = _jobs[0]; _jobs.RemoveAt(0); job = tempObject; } Debug(ThreadClass.Current().Name + " Waiting for a slave to reschedule the evaluation."); job.Sent = false; // reuse SlaveMonitor.ScheduleJobForEvaluation(State, job); Debug(ThreadClass.Current().Name + " Got a slave to reschedule the evaluation."); } }
public virtual bool ReadLoop() { IJob job; try { // block on an incoming job var val = (sbyte)DataIn.ReadByte(); Debug(ToString() + " Incoming Job"); // okay, we've got a job. Grab the earliest job, that's what's coming in lock (_jobs) { job = _jobs[0]; // NO SUCH ELEMENT EXCEPTION } Debug("Got job: " + job); ///// NEXT STEP: COPY THE INDIVIDUALS FORWARD INTO NEWINDS. ///// WE DO THIS SO WE CAN LOAD THE INDIVIDUALS BACK INTO NEWINDS ///// AND THEN COPY THEM BACK INTO THE ORIGINAL INDS, BECAUSE ECJ ///// DOESN'T HAVE A COPY(INDIVIDUAL,INTO_INDIVIDUAL) FUNCTION job.CopyIndividualsForward(); // now start reading. Remember that we've already got a byte. for (var i = 0; i < job.NewInds.Length; i++) { Debug(ToString() + " Individual# " + i); Debug(ToString() + " Reading Byte"); if (i > 0) { val = (sbyte)DataIn.ReadByte(); // otherwise we've got it already } Debug(ToString() + " Reading Individual"); if (val == (sbyte)SlaveReturnType.Individual) { job.NewInds[i].ReadIndividual(State, DataIn); } else if (val == (sbyte)SlaveReturnType.Fitness) { job.NewInds[i].Evaluated = DataIn.ReadBoolean(); job.NewInds[i].Fitness.ReadFitness(State, DataIn); } else if (val == (sbyte)SlaveReturnType.Nothing) { // do nothing } Debug(ToString() + " Read Individual"); } ///// NEXT STEP: COPY THE NEWLY-READ INDIVIDUALS BACK INTO THE ORIGINAL ///// INDIVIDUALS. THIS IS QUITE A HACK, IF YOU READ JOB.JAVA // Now we have all the individuals in so we're good. Copy them back into the original individuals job.CopyIndividualsBack(State); ///// LAST STEP: LET OTHERS KNOW WE'RE DONE AND AVAILABLE FOR ANOTHER JOB // we're all done! Yank the job from the queue so others think we're available lock (_jobs) { _jobs.RemoveAt(0); } // And let the slave monitor we just finished a job SlaveMonitor.NotifySlaveAvailability(this, job, State); } catch (IOException) { Shutdown(State); // will redistribute jobs return(false); } return(true); }
public virtual bool WriteLoop() { IJob job; try { lock (_jobs) { // check for an unsent job if ((job = OldestUnsentJob()) == null) // automatically marks as sent { // failed -- wait and drop out of the loop and come in again Debug("" + ThreadClass.Current().Name + "Waiting for a job to send"); SlaveMonitor.WaitOnMonitor(_jobs); } } if (job != null) // we got a job inside our synchronized wait { // send the job Debug("" + ThreadClass.Current().Name + "Sending Job"); if (job.Type == SlaveEvaluationType.Simple) { // Tell the server we're evaluating a SimpleProblemForm DataOut.Write((byte)SlaveEvaluationType.Simple); } else { // Tell the server we're evaluating a IGroupedProblem DataOut.Write((byte)SlaveEvaluationType.Grouped); // Tell the server whether to count victories only or not. DataOut.Write(job.CountVictoriesOnly); } // transmit number of individuals DataOut.Write(job.Inds.Length); // Transmit the subpops to the slave foreach (var t in job.Subpops) { DataOut.Write(t); } Debug("Starting to transmit individuals"); // Transmit the individuals to the server for evaluation... for (var i = 0; i < job.Inds.Length; i++) { job.Inds[i].WriteIndividual(State, DataOut); DataOut.Write(job.UpdateFitness[i]); } DataOut.Flush(); } } catch (Exception) { Shutdown(State); return(false); } return(true); }