static void set_usageAd (ClassAd* jobAd, ClassAd ** ppusageAd) { std::string resslist; if ( ! jobAd->LookupString("ProvisionedResources", resslist)) resslist = "Cpus, Disk, Memory"; StringList reslist(resslist.c_str()); if (reslist.number() > 0) { ClassAd * puAd = new ClassAd(); puAd->Clear(); // get rid of default "CurrentTime = time()" value. reslist.rewind(); while (const char * resname = reslist.next()) { std::string attr; std::string res = resname; title_case(res); // capitalize it to make it print pretty. const int copy_ok = classad::Value::ERROR_VALUE | classad::Value::BOOLEAN_VALUE | classad::Value::INTEGER_VALUE | classad::Value::REAL_VALUE; classad::Value value; attr = res + "Provisioned"; // provisioned value if (jobAd->EvalAttr(attr.c_str(), NULL, value) && (value.GetType() & copy_ok) != 0) { classad::ExprTree * plit = classad::Literal::MakeLiteral(value); if (plit) { puAd->Insert(resname, plit); // usage ad has attribs like they appear in Machine ad } } // /*for debugging*/ else { puAd->Assign(resname, 42); } attr = "Request"; attr += res; // requested value if (jobAd->EvalAttr(attr.c_str(), NULL, value)&& (value.GetType() & copy_ok) != 0) { classad::ExprTree * plit = classad::Literal::MakeLiteral(value); if (plit) { puAd->Insert(attr.c_str(), plit); } } // /*for debugging*/ else { puAd->Assign(attr.Value(), 99); } attr = res + "Usage"; // usage value if (jobAd->EvalAttr(attr.c_str(), NULL, value) && (value.GetType() & copy_ok) != 0) { classad::ExprTree * plit = classad::Literal::MakeLiteral(value); if (plit) { puAd->Insert(attr.c_str(), plit); } } } *ppusageAd = puAd; } }
// kind defaults to US_NORMAL. void BaseShadow::logTerminateEvent( int exitReason, update_style_t kind ) { struct rusage run_remote_rusage; JobTerminatedEvent event; MyString corefile; memset( &run_remote_rusage, 0, sizeof(struct rusage) ); switch( exitReason ) { case JOB_EXITED: case JOB_COREDUMPED: break; default: dprintf( D_ALWAYS, "UserLog logTerminateEvent with unknown reason (%d), aborting\n", exitReason ); return; } if (kind == US_TERMINATE_PENDING) { int exited_by_signal = FALSE; int exit_signal = 0; int exit_code = 0; getJobAdExitedBySignal(jobAd, exited_by_signal); if (exited_by_signal == TRUE) { getJobAdExitSignal(jobAd, exit_signal); event.normal = false; event.signalNumber = exit_signal; } else { getJobAdExitCode(jobAd, exit_code); event.normal = true; event.returnValue = exit_code; } /* grab usage information out of job ad */ double real_value; if( jobAd->LookupFloat(ATTR_JOB_REMOTE_SYS_CPU, real_value) ) { run_remote_rusage.ru_stime.tv_sec = (time_t) real_value; } if( jobAd->LookupFloat(ATTR_JOB_REMOTE_USER_CPU, real_value) ) { run_remote_rusage.ru_utime.tv_sec = (time_t) real_value; } event.run_remote_rusage = run_remote_rusage; event.total_remote_rusage = run_remote_rusage; /* we want to log the events from the perspective of the user job, so if the shadow *sent* the bytes, then that means the user job *received* the bytes */ jobAd->LookupFloat(ATTR_BYTES_SENT, event.recvd_bytes); jobAd->LookupFloat(ATTR_BYTES_RECVD, event.sent_bytes); event.total_recvd_bytes = event.recvd_bytes; event.total_sent_bytes = event.sent_bytes; if( exited_by_signal == TRUE ) { jobAd->LookupString(ATTR_JOB_CORE_FILENAME, corefile); event.setCoreFile( corefile.Value() ); } if (!uLog.writeEvent (&event,jobAd)) { dprintf (D_ALWAYS,"Unable to log " "ULOG_JOB_TERMINATED event\n"); EXCEPT("UserLog Unable to log ULOG_JOB_TERMINATED event"); } return; } // the default kind == US_NORMAL path run_remote_rusage = getRUsage(); if( exitedBySignal() ) { event.normal = false; event.signalNumber = exitSignal(); } else { event.normal = true; event.returnValue = exitCode(); } // TODO: fill in local/total rusage // event.run_local_rusage = r; event.run_remote_rusage = run_remote_rusage; // event.total_local_rusage = r; event.total_remote_rusage = run_remote_rusage; /* we want to log the events from the perspective of the user job, so if the shadow *sent* the bytes, then that means the user job *received* the bytes */ event.recvd_bytes = bytesSent(); event.sent_bytes = bytesReceived(); event.total_recvd_bytes = prev_run_bytes_recvd + bytesSent(); event.total_sent_bytes = prev_run_bytes_sent + bytesReceived(); if( exitReason == JOB_COREDUMPED ) { event.setCoreFile( core_file_name ); } #if 1 set_usageAd(jobAd, &event.pusageAd); #else std::string resslist; if ( ! jobAd->LookupString("PartitionableResources", resslist)) resslist = "Cpus, Disk, Memory"; StringList reslist(resslist.c_str()); if (reslist.number() > 0) { int64_t int64_value = 0; ClassAd * puAd = new ClassAd(); reslist.rewind(); char * resname = NULL; while ((resname = reslist.next()) != NULL) { MyString attr; int64_value = -1; attr.formatstr("%s", resname); // provisioned value if (jobAd->LookupInteger(attr.Value(), int64_value)) { puAd->Assign(resname, int64_value); } // /*for debugging*/ else { puAd->Assign(resname, 42); } int64_value = -2; attr.formatstr("Request%s", resname); // requested value if (jobAd->LookupInteger(attr.Value(), int64_value)) { puAd->Assign(attr.Value(), int64_value); } // /*for debugging*/ else { puAd->Assign(attr.Value(), 99); } int64_value = -3; attr.formatstr("%sUsage", resname); // usage value if (jobAd->LookupInteger(attr.Value(), int64_value)) { puAd->Assign(attr.Value(), int64_value); } } event.pusageAd = puAd; } #endif if (!uLog.writeEvent (&event,jobAd)) { dprintf (D_ALWAYS,"Unable to log " "ULOG_JOB_TERMINATED event\n"); EXCEPT("UserLog Unable to log ULOG_JOB_TERMINATED event"); } }
void MachAttributes::init_machine_resources() { // defines the space of local machine resources, and their quantity m_machres_map.clear(); // this may be filled from resource inventory scripts m_machres_attr.Clear(); // these are reserved for standard/fixed resources std::set<string> fixedRes; fixedRes.insert("cpu"); fixedRes.insert("cpus"); fixedRes.insert("disk"); fixedRes.insert("swap"); fixedRes.insert("mem"); fixedRes.insert("memory"); fixedRes.insert("ram"); // get the list of defined local resource names: char* ptmp = param("MACHINE_RESOURCE_NAMES"); string resnames; if (NULL != ptmp) { // if admin defined MACHINE_RESOURCE_NAMES, then use this list // as the source of expected custom machine resources resnames = ptmp; free(ptmp); } else { // otherwise, build the list of custom machine resources from // all occurrences of MACHINE_RESOURCE_<resname> std::set<string> resset; Regex re; int err = 0; const char* pszMsg = 0; const string prefix = "MACHINE_RESOURCE_"; const string invprefix = "INVENTORY_"; const string restr = prefix + "(.+)"; ASSERT(re.compile(restr.c_str(), &pszMsg, &err, PCRE_CASELESS)); std::vector<std::string> resdef; const int n = param_names_matching(re, resdef); for (int j = 0; j < n; ++j) { string rname = resdef[j].substr(prefix.length()); string testinv = rname.substr(0, invprefix.length()); if (0 == strcasecmp(testinv.c_str(), invprefix.c_str())) { // if something was defined via MACHINE_RESOURCE_INVENTORY_<rname>, strip "INVENTORY_" rname = rname.substr(invprefix.length()); } std::transform(rname.begin(), rname.end(), rname.begin(), ::tolower); resset.insert(rname); } for (std::set<string>::iterator j(resset.begin()); j != resset.end(); ++j) { resnames += " "; resnames += *j; } } // scan the list of local resources, to obtain their quantity and associated attributes (if any) StringList reslist(resnames.c_str()); reslist.rewind(); while (const char* rnp = reslist.next()) { string rname(rnp); std::transform(rname.begin(), rname.end(), rname.begin(), ::tolower); if (fixedRes.count(rname) > 0) { EXCEPT("pre-defined resource name '%s' is reserved", rname.c_str()); } // If MACHINE_RESOURCE_<rname> is present, use that and move on: string pname; formatstr(pname, "MACHINE_RESOURCE_%s", rname.c_str()); char* machresp = param(pname.c_str()); if (machresp) { int v = param_integer(pname.c_str(), 0, 0, INT_MAX); m_machres_map[rname] = v; free(machresp); continue; } // current definition of REMIND macro is not working with gcc #pragma message("MACHINE_RESOURCE_INVENTORY_<rname> is deprecated, and will be removed when a solution using '|' in config files is fleshed out") // if we didn't find MACHINE_RESOURCE_<rname>, then try MACHINE_RESOURCE_INVENTORY_<rname> formatstr(pname, "MACHINE_RESOURCE_INVENTORY_%s", rname.c_str()); char* invscriptp = param(pname.c_str()); if (NULL == invscriptp) { EXCEPT("Missing configuration for local machine resource %s", rname.c_str()); } // if there is an inventory script, then attempt to execute it and use its output to // identify the local resource quantity, and any associated attributes: string invscript = invscriptp; free(invscriptp); ArgList invcmd; StringList invcmdal(invscript.c_str()); invcmdal.rewind(); while (char* invarg = invcmdal.next()) { invcmd.AppendArg(invarg); } FILE* fp = my_popen(invcmd, "r", FALSE); if (NULL == fp) { EXCEPT("Failed to execute local resource inventory script \"%s\"\n", invscript.c_str()); } ClassAd invad; char invline[1000]; while (fgets(invline, sizeof(invline), fp)) { if (!invad.Insert(invline)) { dprintf(D_ALWAYS, "Failed to insert \"%s\" into machine resource attributes: ignoring\n", invline); } } my_pclose(fp); // require the detected machine resource to be present as an attribute string ccname(rname.c_str()); *(ccname.begin()) = toupper(*(ccname.begin())); string detname; formatstr(detname, "%s%s", ATTR_DETECTED_PREFIX, ccname.c_str()); int v = 0; if (!invad.LookupInteger(detname.c_str(), v)) { EXCEPT("Missing required attribute \"%s = <n>\" from output of %s\n", detname.c_str(), invscript.c_str()); } // success m_machres_map[rname] = v; invad.Delete(rname.c_str()); m_machres_attr.Update(invad); } for (slotres_map_t::iterator j(m_machres_map.begin()); j != m_machres_map.end(); ++j) { dprintf(D_ALWAYS, "Local machine resource %s = %d\n", j->first.c_str(), int(j->second)); } }