void KKJobManager::ProcessRestart () { log.Level (10) << "ProcessRestart" << endl; Block (); StatusFileLoad (); if (this->Status () != jsDone) { ofstream* statusFile = StatusFileOpen (ios::app); status = KKJob::jsOpen; *statusFile << "ReStart" << endl; *statusFile << "Status" << "\t" << StatusStr () << endl; KKJobList::iterator idx; for (idx = jobs->begin (); idx != jobs->end (); idx++) { KKJobPtr j = *idx; if (j->Status () == jsStarted) { j->Status (jsOpen); *statusFile << "JobStatusChange" << "\t" << j->JobId () << "\t" << j->StatusStr () << endl; } } statusFile->flush (); statusFile->close (); delete statusFile; } EndBlock (); } /* ProcessRestart */
void KKJobManager::StatusFileWrite () { log.Level (10) << "KKJobManager::StatusFileWrite" << endl; ofstream* statusFile = StatusFileOpen (ios::out); *statusFile << "// Date/Time [" << osGetLocalDateTime () << "]." << endl << "//" << endl << endl; *statusFile << "Status" << "\t" << KKJob::JobStatusToStr (status) << endl << "NextJobId" << "\t" << nextJobId << endl << "CurrentDateTime" << "\t" << osGetLocalDateTime () << endl << "ExpansionCount" << "\t" << expansionCount << endl << "ExpansionFirstJobId" << "\t" << expansionFirstJobId << endl << endl; kkint32 x; for (x = 0; x < jobs->QueueSize (); x++) { KKJobPtr j = jobs->IdxToPtr (x); *statusFile << "KKJob" << "\t" << j->JobType () << "\t" << j->ToStatusStr () << endl; } statusFile->flush (); statusFile->close (); delete statusFile; log.Level (10) << "KKJobManager::StatusFileWrite Exiting" << endl; } /* StatusFileWrite */
void KKJobManager::StatusFileProcessLineJobStatusChange (KKStr& statusLineStr) { kkint32 expandedJobId = statusLineStr.ExtractTokenInt ("\t"); KKJobPtr j = jobs->LookUpByJobId (expandedJobId); if (!j) { log.Level (-1) << endl << endl << endl << "ProcessStatusLineJobStatusChange ***Error*** Could not locate Expanded" << endl << endl << " JobId[" << expandedJobId << "]" << endl << endl; EndBlock (); osWaitForEnter (); exit (-1); } KKStr statusStr = statusLineStr.ExtractToken2 ("\t"); statusStr.TrimLeft (); statusStr.TrimRight (); KKJob::JobStatus status = KKJob::JobStatusFromStr (statusStr); if (status == jsNULL) { log.Level (-1) << endl << endl << endl << "ProcessStatusLineJobStatusChange ***Error*** Invalid Status Specified" << endl << endl << " JobId[" << expandedJobId << "]" << endl << " Status[" << statusStr << "]" << endl << endl; EndBlock (); osWaitForEnter (); exit (-1); } j->Status (status); } /* ProcessStatusLineJobStatusChange */
bool KKJobList::JobsStillRunning () { KKJobList::iterator idx; for (idx = begin (); idx != end (); ++idx) { KKJobPtr j = *idx; if (j->Status () == KKJob::jsStarted) return true; } return false; } /* JobsStillRunning */
bool KKJobList::AreAllJobsDone () { for (kkuint32 x = 0; x < QueueSize (); ++x) { KKJobPtr j = IdxToPtr (x); if ((j->Status () != KKJob::jsDone) && (j->Status () != KKJob::jsExpanded)) return false; } return true; } /* AreAllJobsAreDone */
KKJobPtr KKJobList::LocateOpenJob () { for (kkuint32 x = 0; x < QueueSize (); x++) { KKJobPtr j = IdxToPtr (x); if (j->Status () == KKJob::jsOpen) return j; } return NULL; } /* LocateOpenJob */
bool KKJobList::AllPrequisitesDone (KKJobPtr job) { const VectorInt& p = job->Prerequisites (); for (kkuint32 z = 0; z < p.size (); ++z) { kkint32 jobId = p[z]; KKJobPtr pj = LookUpByJobId (jobId); if ((pj->Status () != KKJob::jsDone) && (pj->Status () != KKJob::jsExpanded)) return false; } return true; } /* AllPrequisitesDone */
KKJobPtr KKJob::CallAppropriateConstructor (JobManagerPtr _manager, const KKStr& _jobTypeName, const KKStr& _statusStr ) { ConstructorIndex::iterator idx; idx = registeredConstructors.find (_jobTypeName); if (idx == registeredConstructors.end ()) return NULL; KKJobPtr j = idx->second (_manager); j->ProcessStatusStr (_statusStr); return j; } /* CallAppropriateConstructor */
KKJobList::KKJobList (const KKJobList& jobs): KKQueue<KKJob> (jobs.Owner ()), jobIdLookUpTable (), jobIdLookUpTableIdx (), log (jobs.log), manager (jobs.manager) { KKJobList::const_iterator idx; for (idx = jobs.begin (); idx != jobs.end (); idx++) { KKJobPtr j = *idx; if (Owner ()) PushOnBack (j->Duplicate ()); else PushOnBack (j); } }
void KKJobManager::StatusFileInitialize () { log.Level (10) << "KKJobManager::InializeStatusFile" << endl; delete jobs; jobs = new KKJobList (this); ofstream* statusFile = StatusFileOpen (ios::out); *statusFile << "// Date/Time [" << osGetLocalDateTime () << "]." << endl << "//" << endl << "//" << endl; *statusFile << "Status" << "\t" << KKJob::JobStatusToStr (status) << endl << "NextJobId" << "\t" << nextJobId << endl << "CurrentDateTime" << "\t" << osGetLocalDateTime () << endl << "ExpansionCount" << "\t" << expansionCount << endl << "ExpansionFirstJobId" << "\t" << expansionFirstJobId << endl; StatusFileInitialize (*statusFile); // Have derived classes do there initilization. delete jobs; jobs = NULL; jobs = JobsCreateInitialSet (); if (jobs) { KKJobList::iterator idx; for (idx = jobs->begin (); idx != jobs->end (); idx++) { KKJobPtr j = *idx; *statusFile << "KKJob" << "\t" << j->JobType () << "\t" << j->ToStatusStr () << endl; } } else { jobs = new KKJobList (this); } statusFile->flush (); statusFile->close (); delete statusFile; log.Level (10) << "KKJobManager::InializeStatusFile Exiting" << endl; } /* StatusFileInitialize */
void KKJobList::PushOnBack (KKJobPtr j) { jobIdLookUpTableIdx = jobIdLookUpTable.find (j->JobId ()); if (jobIdLookUpTableIdx != jobIdLookUpTable.end ()) { log.Level (-1) << endl << endl << "KKJobList::PushOnBack ***ERROR***" << endl << endl << "KKJobList::PushOnBack Duplicate JobId[" << j->JobId () << "]" << endl << endl; osWaitForEnter (); exit (-1); } KKQueue<KKJob>::PushOnBack (j); jobIdLookUpTable.insert (JobIdLookUpTablePair (j->JobId (), j)); return; } /* PushOnBack */
void KKJobManager::ProcessNextExpansion (ostream& o) { KKJobListPtr jobsJustCompleted = new KKJobList (this); jobsJustCompleted->Owner (false); { // Add jobs completed since last expansion to this list. KKJobList::iterator idx; for (idx = jobs->begin (); idx != jobs->end (); idx++) { KKJobPtr j = *idx; if (j->JobId () >= expansionFirstJobId) jobsJustCompleted->PushOnBack (j); } } // Derived class will now peform expansion. KKJobListPtr expandedJobs = JobsExpandNextSetOfJobs (jobsJustCompleted); { if (expandedJobs) { expandedJobs->Owner (false); KKJobList::iterator idx; for (idx = expandedJobs->begin (); idx != expandedJobs->end (); idx++) { KKJobPtr j = *idx; if (j->JobId () < expansionFirstJobId) expansionFirstJobId = j->JobId (); jobs->PushOnBack (j); o << "KKJob" << "\t" << j->JobType () << "\t" << j->ToStatusStr () << endl; } } delete expandedJobs; expandedJobs = NULL; } delete jobsJustCompleted; jobsJustCompleted = NULL; o << "NextJobId" << "\t" << nextJobId << endl << "ExpansionCount" << "\t" << expansionCount << endl << "ExpansionFirstJobId" << "\t" << expansionFirstJobId << endl; } /* ProcessNextExpansion */
void KKJobManager::Run () { log.Level (10) << "KKJobManager::Run." << endl; bool keepOnRunning = true; KKJobListPtr executedJobs = NULL; KKJobListPtr jobsToExecute = GetNextSetOfJobs (NULL); while (keepOnRunning && (!quitRunning)) { if (jobsToExecute) { delete executedJobs; executedJobs = NULL; executedJobs = new KKJobList (this); executedJobs->Owner (true); KKJobList::iterator idx; for (idx = jobsToExecute->begin (); idx != jobsToExecute->end (); idx++) { KKJobPtr j = *idx; j->ProcessNode (); executedJobs->PushOnBack (j->Duplicate ()); } delete jobsToExecute; jobsToExecute = NULL; } else { if (!(jobs->JobsStillRunning ())) { keepOnRunning = false; } else { // We will sleep for a bit until there are more jobs to run log.Level (10) << "KKJobManager::Run No jobs avaialble to run; will sleep a bit." << endl; osSleep ((float)(30 + rand () % 10)); } } if (keepOnRunning) jobsToExecute = GetNextSetOfJobs (executedJobs); delete executedJobs; executedJobs = NULL; } Block (); StatusFileRefresh (); if ((!quitRunning) && (status != KKJob::jsDone)) { if (status != KKJob::jsDone) { GenerateFinalResultsReport (); status = KKJob::jsDone; ofstream* statusFile = StatusFileOpen (ios::app); *statusFile << "Status" << "\t" << StatusStr () << endl; ReportCpuTimeUsed (statusFile); statusFile->close (); delete statusFile; } } EndBlock (); log.Level (10) << "KKJobManager::Run Exiting." << endl; } /* Run */
KKJobListPtr KKJobManager::GetNextSetOfJobs (KKJobListPtr completedJobs) { log.Level (20) << "KKJobManager::GetNextSetOfJobs." << endl; Block (); StatusFileRefresh (); if (completedJobs) { // We will first write out results of jobs that have been completed, ofstream* statusFile = StatusFileOpen (ios::app); KKJobList::iterator idx; for (idx = completedJobs->begin (); idx != completedJobs->end (); idx++) { KKJobPtr j = *idx; *statusFile << "KKJob" << "\t" << j->JobType () << "\t" << j->ToStatusStr () << endl; if (supportCompletedJobData) { *statusFile << "<KKJob JobType=" << j->JobType () << ", " << "JobId=" << j->JobId () << ">" << endl; j->CompletedJobDataWrite (*statusFile); *statusFile << "</job>" << endl; } KKJobPtr existingJob = jobs->LookUpByJobId (j->JobId ()); if (existingJob) { existingJob->ReFresh (*j); } else { log.Level (-1) << endl << endl << endl << "GetNextSetOfJobs *** ERROR ***" << endl << endl << " Could not locate KKJob[" << j->JobId () << "]" << endl << endl; return NULL; } } statusFile->close (); delete statusFile; statusFile = NULL; } KKJobListPtr jobsToExecute = new KKJobList (this); jobsToExecute->Owner (false); if (!quitRunning) { ofstream* statusFile = StatusFileOpen (ios::app); KKJobPtr nextJob = jobs->LocateOpenJob (); if (!nextJob) { if (jobs->AreAllJobsDone ()) { // There are no jobs to do; we will have to expand some existing jobs then ProcessNextExpansion (*statusFile); nextJob = jobs->LocateOpenJob (); } else { // There are still some jobs that are running. We are going to go to // for now and try again later. // // By leaving "nextJob = NULL" we will drop strait through the rest of // this method and return to the caller with 'jobsToExecute' empty // signaling that it will need to sleep for a while before calling // us again. } } while (nextJob && (jobsToExecute->QueueSize () < numJobsAtATime)) { jobsToExecute->PushOnBack (nextJob); nextJob->Status (jsStarted); *statusFile << "JobStatusChange" << "\t" << nextJob->JobId () << "\t" << nextJob->StatusStr () << endl; nextJob = jobs->LocateOpenJob (); } statusFile->close (); } if (jobsToExecute->QueueSize () < 1) { delete jobsToExecute; jobsToExecute = NULL; } EndBlock (); log.Level (20) << "KKJobManager::GetNextSetOfJobs Exiting." << endl; return jobsToExecute; } /* GetNextSetOfJobs */
void KKJobManager::ProcessJobXmlBlockOfText (const KKStr& startStr, istream& i ) { if ((startStr.SubStrPart (0, 4) != "<KKJob ") || (startStr.LastChar () != '>')) { log.Level (-1) << endl << "KKJobManager::ProcessJobXmlBlockOfText ***ERROR*** StartStr[" << startStr << "] is not a KKJob String." << endl << endl; return; } KKStr s = startStr.SubStrPart (5); s.TrimLeft (); s.ChopLastChar (); KKStr jobTypeStr = ""; kkint32 jobId = -1; VectorKKStr parameters = s.Split (','); for (kkuint32 x = 0; x < parameters.size (); ++x) { KKStr parameterStr = parameters[x]; parameterStr.TrimLeft (); parameterStr.TrimRight (); KKStr fieldName = parameterStr.ExtractToken2 ("="); fieldName.TrimLeft (); fieldName.TrimRight (); KKStr fieldValue = parameterStr.ExtractToken2 ("="); fieldValue.TrimLeft (); fieldValue.TrimRight (); if (fieldName.CompareIgnoreCase ("JobType") == 0) jobTypeStr = fieldValue; else if (fieldName.CompareIgnoreCase ("JobId") == 0) jobId = fieldValue.ToInt (); } if (jobTypeStr.Empty () || (jobId < 0)) { log.Level (-1) << endl << "KKJobManager::ProcessJobXmlBlockOfText ***ERROR*** StartStr[" << startStr << "]." << endl << " JobType and/or JobId were not provided." << endl << endl; return; } KKJobPtr j = jobs->LookUpByJobId (jobId); if (j == NULL) { // We do not have this job in memory yet. We will have to create it now. KKStr emptyStatusStr = "JobId\t" + StrFormatInt (jobId, "ZZZZ0"); j = KKJob::CallAppropriateConstructor (this, jobTypeStr, emptyStatusStr); } j->CompletedJobDataRead (i); } /* ProcessJobXmlBlockOfText */
void KKJobManager::StatusFileProcessLine (const KKStr& ln, istream& statusFile ) { if (ln.SubStrPart (0, 1) == "//") { // A coment line; we can ignore it. return; } KKStr statusStr (ln); KKStr fieldName = statusStr.ExtractToken2 ("\t"); if (fieldName.Empty ()) { // A empty line we will ignore it. return; } statusStr.TrimLeft ("\n\r\t "); statusStr.TrimRight ("\n\r\t "); if (fieldName.CompareIgnoreCase ("JOB") == 0) { // We have a KKJob entr line; the next field determines JobType fllowed by parameters for that JobType constructor. KKStr jobTypeName = fieldName = statusStr.ExtractToken2 ("\t"); KKJobPtr j = KKJob::CallAppropriateConstructor (this, jobTypeName, statusStr); KKJobPtr existingJob = jobs->LookUpByJobId (j->JobId ()); if (existingJob) { existingJob->ReFresh (*j); delete j; j = NULL; } else { jobs->PushOnBack (j); } } else if (fieldName.EqualIgnoreCase ("CPUTIMEUSED")) { double cpuTimeUsed = statusStr.ExtractTokenDouble ("\t"); cpuTimeTotalUsed += cpuTimeUsed; } else if (fieldName.EqualIgnoreCase ("CURRENTDATETIME")) { KKB::DateTime dateTime = KKB::DateTime (statusStr); if (!dateTimeFirstOneFound) { dateTimeFirstOneFound = true; dateTimeStarted = dateTime; } dateTimeEnded = dateTime; } else if (fieldName.EqualIgnoreCase ("ExpansionCount")) expansionCount = statusStr.ToInt (); else if (fieldName.EqualIgnoreCase ("ExpansionFirstJobId")) expansionFirstJobId = statusStr.ToInt (); else if (fieldName.EqualIgnoreCase ("JobStatusChange")) StatusFileProcessLineJobStatusChange (statusStr); else if (fieldName.EqualIgnoreCase ("NextJobId")) nextJobId = statusStr.ExtractTokenInt ("\t"); else if (fieldName.EqualIgnoreCase ("QuitRunning")) quitRunning = true; else if (fieldName.EqualIgnoreCase ("Restart")) restart = false; else if (fieldName.EqualIgnoreCase ("Status")) status = KKJob::JobStatusFromStr (statusStr); else { log.Level (-1) << "KKJobManager::StatusFileProcessLine Invalid Field Name[" << fieldName << "]." << endl; } } /* StatusFileProcessLine */