Example #1
0
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;
	}
}
Example #2
0
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;
}
Example #3
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;
}
Example #4
0
// 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");
	}
}
Example #5
0
//  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;
}
Example #6
0
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;
}