/// <summary> /// Call if one worker is available /// </summary> /// <param name="workerUrl">worker url</param> /// <returns></returns> public bool FinishProcessing(string workerUrl, WorkStatus workerStatus) { TestFrozenC(); jobsAssigmentMutex.WaitOne(); foreach (WorkStatus iWorkStatus in jobsAssigment) { if (iWorkStatus.getWorkerId() == workerStatus.getWorkerId() && iWorkStatus.getBeginIndex() == workerStatus.getBeginIndex()) { iWorkStatus.setLastModification(workerStatus.getLastModification()); iWorkStatus.setNumberLinesComputed(workerStatus.getNumberLinesComputed()); iWorkStatus.setTotalNumberOfLines(workerStatus.getTotalNumberLines()); iWorkStatus.setWorkerId(workerStatus.getWorkerId()); //Console.WriteLine("FINISH " + workerStatus.getWorkerId()); break; } } jobsAssigmentMutex.ReleaseMutex(); availableWorkerToJobMutex.WaitOne(); bool exists = availableWorkerToJob.Contains(workerUrl); availableWorkerToJobMutex.ReleaseMutex(); if (!exists) { availableWorkerToJobMutex.WaitOne(); availableWorkerToJob.Add(workerUrl); availableWorkerToJobMutex.ReleaseMutex(); queueWorkersSemaphore.Release(1); } return(true); }
/// <summary> /// Distributes the split by the workers as new workers are available /// </summary> /// <param name="className">ClassName to run</param> /// <param name="dllCode">Class dll to run</param> /// <param name="clientUrl">Client Url to communicate answer</param> public void DistributeWorkAsync(string className, byte[] dllCode, string clientUrl) { while (!jobDone) { TestFrozenC(); //Get first job available jobsAssigmentMutex.WaitOne(); //All jobs concluded bool isCompleted = true; foreach (WorkStatus iWorkStatus in jobsAssigment) { if (!iWorkStatus.isWorkCompleted()) { isCompleted = false; break; } } if (isCompleted) { jobsAssigmentMutex.ReleaseMutex(); jobDone = true; break; } //Still work to do WorkStatus freeWorkStatus = null; foreach (WorkStatus iWorkStatus in jobsAssigment) { //Console.WriteLine(iWorkStatus.isWorkerAssigned() + " => " + iWorkStatus.getBeginIndex()); if (!iWorkStatus.isWorkerAssigned()) { freeWorkStatus = iWorkStatus; break; } } //No more works to be done if (freeWorkStatus == null) { jobsAssigmentMutex.ReleaseMutex(); continue; } //temporary assignment freeWorkStatus.setWorkerId(-2); long freeWorkStatusBeginIndex = freeWorkStatus.getBeginIndex(); jobsAssigmentMutex.ReleaseMutex(); //Get first free worker queueWorkersSemaphore.WaitOne(); //Send the job to worker availableWorkerToJobMutex.WaitOne(); String workerUrl = (string)availableWorkerToJob[0]; availableWorkerToJob.RemoveAt(0); availableWorkerToJobMutex.ReleaseMutex(); if (workerUrl == null) { throw new ArgumentNullException(); } //System.Console.WriteLine("[DISTRIBUTE_WORK] Sending job to " + workerUrl + " with split [" + freeWorkStatus.getBeginIndex() + ", " + freeWorkStatus.getEndIndex() + "] ... "); IWorker workerObj = (IWorker)Activator.GetObject(typeof(IWorker), workerUrl); try { //Get id from url int workerID = 0; //Get id by url workersIDUrlMutex.WaitOne(); foreach (KeyValuePair <int, string> workerPair in workersIDUrl) { if (workerPair.Value == workerUrl) { workerID = workerPair.Key; break; } } workersIDUrlMutex.ReleaseMutex(); //Assign that job to this worker jobsAssigmentMutex.WaitOne(); foreach (WorkStatus ws in jobsAssigment) { if (freeWorkStatusBeginIndex == ws.getBeginIndex()) { freeWorkStatus = ws; } } freeWorkStatus.setWorkerId(workerID); workerObj.RunJob(className, dllCode, freeWorkStatus.getBeginIndex(), freeWorkStatus.getEndIndex(), clientUrl, ownUrl); jobsAssigmentMutex.ReleaseMutex(); } catch (Exception e) { System.Console.WriteLine("[ERROR_DISTRIBUTE_WORK1] Cant send work to " + workerUrl); jobsAssigmentMutex.WaitOne(); freeWorkStatus.removeWorker(); jobsAssigmentMutex.ReleaseMutex(); availableWorkerToJobMutex.WaitOne(); availableWorkerToJob.Add(workerUrl); availableWorkerToJobMutex.ReleaseMutex(); queueWorkersSemaphore.Release(1); } } }
// ============================================= // Threads Section // ============================================= /// <summary> /// Async method to keep tracking of alive workers /// </summary> public void IsAliveAsync() { while (!jobDone) { TestFrozenC(); //Is alive interval Thread.Sleep(2000); //Create a copy of the workersUrl workersIDUrlMutex.WaitOne(); HashSet <KeyValuePair <int, string> > clonedWorkersUrl = new HashSet <KeyValuePair <int, string> >(workersIDUrl); workersIDUrlMutex.ReleaseMutex(); jobsAssigmentMutex.WaitOne(); HashSet <WorkStatus> clonedJobAssigments = new HashSet <WorkStatus>(jobsAssigment); jobsAssigmentMutex.ReleaseMutex(); foreach (KeyValuePair <int, string> worker in clonedWorkersUrl) { //Get the worker IWorker workerObj = (IWorker)Activator.GetObject(typeof(IWorker), worker.Value); try { //Retrive the workStatus of the worker WorkStatus workerStatus = workerObj.IsAlive(clonedWorkersUrl, clonedJobAssigments); //Update the workStatus of that worker jobsAssigmentMutex.WaitOne(); foreach (WorkStatus iWorkStatus in jobsAssigment) { if (iWorkStatus.getWorkerId() == workerStatus.getWorkerId() && iWorkStatus.getBeginIndex() == workerStatus.getBeginIndex()) { iWorkStatus.setLastModification(workerStatus.getLastModification()); iWorkStatus.setNumberLinesComputed(workerStatus.getNumberLinesComputed()); iWorkStatus.setTotalNumberOfLines(workerStatus.getTotalNumberLines()); iWorkStatus.setWorkerId(workerStatus.getWorkerId()); //Console.WriteLine("isalive" + workerStatus.getWorkerId()); break; } } jobsAssigmentMutex.ReleaseMutex(); //TODO: test if the worker is too slow } catch (Exception) { //The worker didn't anwser Console.WriteLine("***************" + worker.Value + "dead"); //Remove the worker from the workersList workersIDUrlMutex.WaitOne(); workersIDUrl.Remove(worker); workersIDUrlMutex.ReleaseMutex(); //Removes all the works not done and assigned to it jobsAssigmentMutex.WaitOne(); foreach (WorkStatus iWorkStatus in jobsAssigment) { if (iWorkStatus.getWorkerId() == worker.Key && !iWorkStatus.isWorkCompleted()) { iWorkStatus.removeWorker(); } } jobsAssigmentMutex.ReleaseMutex(); //Remove from available worker availableWorkerToJobMutex.WaitOne(); availableWorkerToJob.Remove(worker.Value); availableWorkerToJobMutex.ReleaseMutex(); } } } }