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; } }
ClassAd* getDBNextJobByConstraint(const char* constraint, JobQueueSnapshot *jqSnapshot) { ClassAd *ad; while(jqSnapshot->iterateAllClassAds(ad) != DONE_JOBS_CURSOR) { if ((!constraint || !constraint[0] || EvalBool(ad, constraint))) { return ad; } if (ad != (ClassAd *) 0) { ad->Clear(); delete ad; ad = (ClassAd *) 0; } } return (ClassAd *) 0; }
bool ClassAdParser:: ParseClassAd(LexerSource *lexer_source, ClassAd &classad, bool full) { bool success; success = false; if (lexer.Initialize(lexer_source)) { success = parseClassAd(classad, full); } if (success) { // The lexer swallows one extra character, so if we have // two classads back to back we need to make sure to unread // one of the characters. if (lexer_source->ReadPreviousCharacter() != -1) { lexer_source->UnreadCharacter(); } } else { classad.Clear(); } return success; }
// 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) { float float_value; 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 */ if( jobAd->LookupFloat(ATTR_JOB_REMOTE_SYS_CPU, float_value) ) { run_remote_rusage.ru_stime.tv_sec = (int) float_value; } if( jobAd->LookupFloat(ATTR_JOB_REMOTE_USER_CPU, float_value) ) { run_remote_rusage.ru_utime.tv_sec = (int) float_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(); puAd->Clear(); // get rid of default "CurrentTime = time()" value. 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"); } }
// ClassAd ::= '[' AttributeList ']' // AttributeList ::= (epsilon) // | Attribute ';' AttributeList // Attribute ::= Identifier '=' Expression bool ClassAdParser:: parseClassAd( ClassAd &ad , bool full ) { Lexer::TokenType tt; Lexer::TokenValue tv; ExprTree *tree = NULL; string s; ad.Clear( ); ad.DisableDirtyTracking(); if( ( tt = lexer.ConsumeToken() ) != Lexer::LEX_OPEN_BOX ) return false; tt = lexer.PeekToken(); while( tt != Lexer::LEX_CLOSE_BOX ) { // Get the name of the expression tt = lexer.ConsumeToken( &tv ); if( tt == Lexer::LEX_SEMICOLON ) { // We allow empty expressions, so if someone give a double semicolon, it doesn't // hurt. Technically it's not right, but we shouldn't make users pay the price for // a meaningless mistake. See condor-support #1881 for a user that was bitten by this. continue; } if( tt != Lexer::LEX_IDENTIFIER ) { CondorErrno = ERR_PARSE_ERROR; CondorErrMsg = "while parsing classad: expected LEX_IDENTIFIER " " but got " + string( Lexer::strLexToken( tt ) ); return false; } // consume the intermediate '=' if( ( tt = lexer.ConsumeToken() ) != Lexer::LEX_BOUND_TO ) { CondorErrno = ERR_PARSE_ERROR; CondorErrMsg = "while parsing classad: expected LEX_BOUND_TO " " but got " + string( Lexer::strLexToken( tt ) ); return false; } // parse the expression parseExpression( tree ); if( tree == NULL ) { return false; } // insert the attribute into the classad tv.GetStringValue( s ); if( !ad.Insert( s, tree ) ) { delete tree; return false; } // the next token must be a ';' or a ']' tt = lexer.PeekToken(); if( tt != Lexer::LEX_SEMICOLON && tt != Lexer::LEX_CLOSE_BOX ) { CondorErrno = ERR_PARSE_ERROR; CondorErrMsg = "while parsing classad: expected LEX_SEMICOLON or " "LEX_CLOSE_BOX but got " + string( Lexer::strLexToken( tt ) ); return( false ); } // Slurp up any extra semicolons. This does not duplicate the work at the top of the loop // because it accounts for the case where the last expression has extra semicolons, // while the first case accounts for optional beginning semicolons. while( tt == Lexer::LEX_SEMICOLON ) { lexer.ConsumeToken(); tt = lexer.PeekToken(); } } lexer.ConsumeToken(); // if a full parse was requested, ensure that input is exhausted if( full && ( lexer.ConsumeToken() != Lexer::LEX_END_OF_INPUT ) ) { CondorErrno = ERR_PARSE_ERROR; CondorErrMsg = "while parsing classad: expected LEX_END_OF_INPUT for " "full parse but got " + string( Lexer::strLexToken( tt ) ); return false; } ad.EnableDirtyTracking(); return true; }
int CondorQ::fetchQueueFromDBAndProcess ( const char *dbconn, char *&lastUpdate, condor_q_process_func process_func, void * process_func_data, CondorError* /*errstack*/ ) { #ifndef HAVE_EXT_POSTGRESQL (void) dbconn; (void) lastUpdate; (void) process_func; (void) process_func_data; #else int result; JobQueueSnapshot *jqSnapshot; const char *constraint; ClassAd *ad; QuillErrCode rv; ExprTree *tree; ASSERT(process_func); jqSnapshot = new JobQueueSnapshot(dbconn); rv = jqSnapshot->startIterateAllClassAds(clusterarray, numclusters, procarray, numprocs, schedd, FALSE, scheddBirthdate, lastUpdate); if (rv == QUILL_FAILURE) { delete jqSnapshot; return Q_COMMUNICATION_ERROR; } else if (rv == JOB_QUEUE_EMPTY) { delete jqSnapshot; return Q_OK; } // make the query ad if ((result = query.makeQuery (tree)) != Q_OK) { delete jqSnapshot; return result; } constraint = ExprTreeToString(tree); delete tree; ad = getDBNextJobByConstraint(constraint, jqSnapshot); while (ad != (ClassAd *) 0) { // Process the data and insert it into the list if ((*process_func) (ad, process_func_data) ) { ad->Clear(); delete ad; } ad = getDBNextJobByConstraint(constraint, jqSnapshot); } delete jqSnapshot; #endif /* HAVE_EXT_POSTGRESQL */ return Q_OK; }