/*! * This function refreshes the job list. It queries the server for the required * information and then updates the list control. * * \par Notes on the implementation of RefreshList() * For efficiency reasons, after the initial refresh, all refreshes are * incremental. Because IPC is the slowest part of the whole program the client * only gathers the only the information that is subject to have changed from * the server. The list control is also left alone during the process so that * it is greyed out for as short a period as possible. * * \par * The list control is also updated incrementally, yet for a completely * different reason. Whenever the list control is cleared entirely, it not only * takes time to reload the entire list, but it resets the current position of * the list in the scroller, so every time the client refreshes the user is * looking at the top (and most likely irrelevant) portion of the queue again. * * \par * Due to the incremental nature of this code, it is rather complicated and * should be left alone, unless there is a good reason to change it. */ void GamessQFrame::RefreshList() { int *ids = mQueueManager.GetJobIds(); int num = ids[0]; wxString name; int procs; Job::Status status; Job *job; // update any jobs that are out of date, and remove any jobs that no longer // exist on the server JobList::compatibility_iterator node = mJobList.GetFirst(); int i = 1; while (node) { job = node->GetData(); if (i <= num && job->GetId() == ids[i]) { // update the status status = job->GetStatus(); if (status != Job::STATUS_DONE && status != Job::STATUS_ERROR && status != Job::STATUS_CANCELED) { job->SetStatus(mQueueManager.GetStatus(ids[i])); } node = node->GetNext(); i++; } else { JobList::compatibility_iterator nextNode = node->GetNext(); mJobList.DeleteNode(node); node = nextNode; } } // add any new jobs for which we do not yet have local copies for (; i <= num; i++) { name = mQueueManager.GetName(ids[i]); procs = mQueueManager.GetNumProcessors(ids[i]); status = mQueueManager.GetStatus(ids[i]); job = new Job(ids[i], name, wxT(""), status, procs); mJobList.Append(job); } // update the interface jobListCtrl->Hide(); // update the jobs that are in the control and delete any jobs that no // longer exist node = mJobList.GetFirst(); i = 0; while (i < jobListCtrl->GetItemCount()) { if (node && jobListCtrl->GetItemData(i) == node->GetData()->GetId()) { jobListCtrl->SetItem(i, 0, node->GetData()->GetName()); jobListCtrl->SetItem(i, 2, node->GetData()->GetStatusString()); node = node->GetNext(); i++; } else { jobListCtrl->DeleteItem(i); } } // add new entries to the control for the new jobs for (;node; i ++, node = node->GetNext()) { Job *job = node->GetData(); int index = jobListCtrl->InsertItem(i, job->GetName()); jobListCtrl->SetItemData(index, job->GetId()); wxString procs; procs << job->GetNumProcessors(); jobListCtrl->SetItem(index, 1, procs); jobListCtrl->SetItem(index, 2, job->GetStatusString()); } jobListCtrl->Show(); delete ids; mRefreshTimer->Start(mRefreshFrequency, wxTIMER_ONE_SHOT); }
void GridManager::Update(uint32 diff) { for (auto machine : _machines) machine->Update(diff); for (auto pMachine : _priorityMachines) pMachine->Update(diff); if (!_waitingJobs.empty()) { Job* job = _waitingJobs.front(); if (job->GetPriority() == 0) { std::vector<Machine*> machineVector; // TODO: Every time a job is added this sorted vector is being rebuilt; change that machineVector.reserve(_machines.size()); // put machines in the map into a vector so we can sort them std::transform(_machines.begin(), _machines.end(), std::back_inserter(machineVector), [](MachineSet::value_type val) { return val; }); // sort of load balancing, better machines get assigned jobs first std::sort(machineVector.begin(), machineVector.end(), [](Machine* m1, Machine* m2) { double score1 = ((m1->GetMaxJobs() - m1->GetNumberOfCurrentJobs()) + m1->GetAvailableDiskSpace() + m1->GetAvailableRAM()); double score2 = ((m2->GetMaxJobs() - m2->GetNumberOfCurrentJobs()) + m2->GetAvailableDiskSpace() + m2->GetAvailableRAM()); return score1 > score2; }); for (auto& mach : machineVector) { if (mach->AddJob(job)) { sLog(Console)->Log("Job %s added to machine %s", job->GetName().c_str(), mach->GetName().c_str()); _waitingJobs.pop(); } } } else { std::vector<PriorityMachine*> machineVector; // TODO: Every time a job is added this sorted vector is being rebuilt; change that machineVector.reserve(_priorityMachines.size()); // put machines in the map into a vector so we can sort them std::transform(_priorityMachines.begin(), _priorityMachines.end(), std::back_inserter(machineVector), [](PriorityMachineSet::value_type val) { return val; }); // sort of load balancing, better machines get assigned jobs first std::sort(machineVector.begin(), machineVector.end(), [](PriorityMachine* m1, PriorityMachine* m2) { double score1 = ((m1->GetMaxJobs() - m1->GetNumberOfCurrentJobs()) + m1->GetAvailableDiskSpace() + m1->GetAvailableRAM()); double score2 = ((m2->GetMaxJobs() - m2->GetNumberOfCurrentJobs()) + m2->GetAvailableDiskSpace() + m2->GetAvailableRAM()); return score1 > score2; }); for (auto& mach : machineVector) { if (mach->AddJob(job)) { sLog(Console)->Log("Job %s added to machine %s", job->GetName().c_str(), mach->GetName().c_str()); _waitingJobs.pop(); } } } } _idleUsers.Update(diff); }