void test_user_policy_periodic_exit_yes(void) { int val; int action; char buf[4096]; ClassAd *result; ClassAd *jad = new ClassAd; if (jad == NULL) { printf("Out of memory!\n"); exit(EXIT_FAILURE); } printf("=========================================\n"); printf("Testing User Policy on Periodic Exit: YES\n"); /* set up the classad */ sprintf(buf, "%s = 42", ATTR_TOTAL_SUSPENSIONS); jad->Insert(buf); sprintf(buf, "%s = FALSE", ATTR_PERIODIC_HOLD_CHECK); jad->Insert(buf); sprintf(buf, "%s = TotalSuspensions == 42", ATTR_PERIODIC_REMOVE_CHECK); jad->Insert(buf); sprintf(buf, "%s = FALSE", ATTR_ON_EXIT_HOLD_CHECK); jad->Insert(buf); sprintf(buf, "%s = TRUE", ATTR_ON_EXIT_REMOVE_CHECK); jad->Insert(buf); jad->Assign(ATTR_JOB_STATUS, RUNNING); result = user_job_policy(jad); result->EvalBool(ATTR_USER_POLICY_ERROR, result, val); if(val == true) { printf("An error happened\n"); delete result; return; } result->EvalBool(ATTR_TAKE_ACTION, result, val); if (val == true) { printf("%s was true.\n", ATTR_TAKE_ACTION); result->LookupInteger(ATTR_USER_POLICY_ACTION, action); printf("Action is: %s\n", action==REMOVE_JOB?"REMOVE_JOB":action==HOLD_JOB?"HOLD_JOB": "UNKNOWN"); result->LookupString(ATTR_USER_POLICY_FIRING_EXPR, buf); printf("Reason for action: %s\n", buf); } else { printf("Something went wrong. I should have had an action to take.\n"); } }
void test_user_policy_periodic_hold_no(void) { int val; char buf[4096]; ClassAd *result; ClassAd *jad = new ClassAd; if (jad == NULL) { printf("Out of memory!\n"); exit(EXIT_FAILURE); } printf("========================================\n"); printf("Testing User Policy on Periodic Hold: NO\n"); /* set up the classad */ sprintf(buf, "%s = 40", ATTR_TOTAL_SUSPENSIONS); jad->Insert(buf); sprintf(buf, "%s = TotalSuspensions == 42", ATTR_PERIODIC_HOLD_CHECK); jad->Insert(buf); sprintf(buf, "%s = FALSE", ATTR_PERIODIC_REMOVE_CHECK); jad->Insert(buf); sprintf(buf, "%s = FALSE", ATTR_ON_EXIT_HOLD_CHECK); jad->Insert(buf); sprintf(buf, "%s = TRUE", ATTR_ON_EXIT_REMOVE_CHECK); jad->Insert(buf); jad->Assign(ATTR_JOB_STATUS, RUNNING); result = user_job_policy(jad); result->EvalBool(ATTR_USER_POLICY_ERROR, result, val); if(val == true) { printf("An error happened\n"); delete result; return; } result->EvalBool(ATTR_TAKE_ACTION, result, val); if (val == true) { printf("Something went wrong. I should not have had an action.\n"); } else { printf("Ignoring correctly.\n"); } }
int LogSetAttribute::Play(void *data_structure) { ClassAdHashTable *table = (ClassAdHashTable *)data_structure; int rval; ClassAd *ad = 0; if (table->lookup(HashKey(key), ad) < 0) return -1; if (value_expr) { // Such a shame, do we really need to make a // copy of value_expr here? Seems like we could just // assign it and then set value_expr to NULL and avoid // copying a parse tree, since after we Play it I doubt // this class does anything more with value_expr beyond // deallocating it. - Todd 11/13 <*****@*****.**> ExprTree * pTree = value_expr->Copy(); rval = ad->Insert(name, pTree, false); } else { rval = ad->AssignExpr(name, value); } ad->SetDirtyFlag(name, is_dirty); #if defined(HAVE_DLOPEN) ClassAdLogPluginManager::SetAttribute(key, name, value); #endif return rval; }
// convert list of expressions into a classad // static void printJobIfConstraint(std::vector<std::string> & exprs, const char* constraint, ExprTree *constraintExpr) { if ( ! exprs.size()) return; ClassAd ad; size_t ix; // convert lines vector into classad. while ((ix = exprs.size()) > 0) { const char * pexpr = exprs[ix-1].c_str(); if ( ! ad.Insert(pexpr)) { dprintf(D_ALWAYS,"failed to create classad; bad expr = '%s'\n", pexpr); printf( "\t*** Warning: Bad history file; skipping malformed ad(s)\n" ); exprs.clear(); return; } exprs.pop_back(); } if (!constraint || constraint[0]=='\0' || EvalBool(&ad, constraintExpr)) { printJob(ad); matchCount++; // if control reached here, match has occured } }
int classad_put_string_list_attribute (classad_context *cad, const char *name, char **value) { if (value == NULL) return C_CLASSAD_INVALID_VALUE; ClassAd *ad; if ((*cad) == NULL) { ad = new ClassAd; (*cad) = (classad_context) ad; } else ad = (ClassAd *)(*cad); char **str_val; std::vector<ExprTree*> et_ads; // Traverse NULL-terminated string array. for(str_val=value; (*str_val) != NULL; str_val++) { Value v; v.SetStringValue(*str_val); et_ads.push_back(Literal::MakeLiteral(v)); } ExprList *et_value; et_value = ExprList::MakeExprList(et_ads); if (ad->Insert (name, et_value)) return C_CLASSAD_NO_ERROR; else return C_CLASSAD_INSERT_FAILED; }
bool View:: SetConstraintExpr( ClassAdCollection *coll, ExprTree *constraint ) { ClassAd *ad; ViewMembers::iterator vmi; bool match; string key; // insert expression into ad in left context if( !( ad=evalEnviron.GetLeftAd() ) || !ad->Insert( ATTR_REQUIREMENTS, constraint ) ) { CondorErrMsg += "; failed to set constraint on view"; return( false ); } // check if all members still belong to the view for( vmi = viewMembers.begin( ); vmi != viewMembers.end( ); vmi++ ) { vmi->GetKey( key ); if( ( ad = coll->GetClassAd( key ) ) == NULL ) { CLASSAD_EXCEPT( "internal error: classad in view but not in collection" ); } evalEnviron.ReplaceRightAd( ad ); match = evalEnviron.EvaluateAttrBool("RightMatchesLeft",match) && match; evalEnviron.RemoveRightAd( ); // if classad doesn't match constraint remove from view if( !match ) { ClassAdDeleted( coll, key, ad ); } } return( true ); }
View:: View( View *parentView ) { Value val; vector<ExprTree*> vec; ClassAd *ad = evalEnviron.GetLeftAd( ); parent = parentView; ExprTree* pExp; ad->InsertAttr( ATTR_REQUIREMENTS, true ); ad->Insert( ATTR_RANK, (pExp=Literal::MakeLiteral( val )) ); ad->Insert( ATTR_PARTITION_EXPRS, (pExp=ExprList::MakeExprList( vec )) ); if( parentView ) { ad->InsertAttr( "ParentViewName", parentView->GetViewName( ) ); } }
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; } }
Starter* StarterMgr::makeStarter( const char* path ) { Starter* new_starter; FILE* fp; char *args[] = { const_cast<char*>(path), const_cast<char*>("-classad"), NULL }; char buf[1024]; // first, try to execute the given path with a "-classad" // option, and grab the output as a ClassAd // note we run the starter here as root if possible, // since that is how the starter will be invoked for real, // and the real uid of the starter may influence the // list of capabilities the "-classad" option returns. { TemporaryPrivSentry sentry(PRIV_ROOT); fp = my_popenv( args, "r", FALSE ); } if( ! fp ) { dprintf( D_ALWAYS, "Failed to execute %s, ignoring\n", path ); return NULL; } ClassAd* ad = new ClassAd; bool read_something = false; while( fgets(buf, 1024, fp) ) { read_something = true; if( ! ad->Insert(buf) ) { dprintf( D_ALWAYS, "Failed to insert \"%s\" into ClassAd, " "ignoring invalid starter\n", buf ); delete( ad ); pclose( fp ); return NULL; } } my_pclose( fp ); if( ! read_something ) { dprintf( D_ALWAYS, "\"%s -classad\" did not produce any output, ignoring\n", path ); delete( ad ); return NULL; } new_starter = new Starter(); new_starter->setAd( ad ); new_starter->setPath( path ); int is_dc = 0; ad->LookupBool( ATTR_IS_DAEMON_CORE, is_dc ); new_starter->setIsDC( (bool)is_dc ); return new_starter; }
Starter* StarterMgr::makeStarter( const char* path ) { Starter* new_starter; FILE* fp; char *args[] = { const_cast<char*>(path), const_cast<char*>("-classad"), NULL }; char buf[1024]; // first, try to execute the given path with a "-classad" // option, and grab the output as a ClassAd fp = my_popenv( args, "r", FALSE ); if( ! fp ) { dprintf( D_ALWAYS, "Failed to execute %s, ignoring\n", path ); return NULL; } ClassAd* ad = new ClassAd; bool read_something = false; while( fgets(buf, 1024, fp) ) { read_something = true; if( ! ad->Insert(buf) ) { dprintf( D_ALWAYS, "Failed to insert \"%s\" into ClassAd, " "ignoring invalid starter\n", buf ); delete( ad ); pclose( fp ); return NULL; } } my_pclose( fp ); if( ! read_something ) { dprintf( D_ALWAYS, "\"%s -classad\" did not produce any output, ignoring\n", path ); delete( ad ); return NULL; } new_starter = new Starter(); new_starter->setAd( ad ); new_starter->setPath( path ); int is_dc = 0; ad->LookupBool( ATTR_IS_DAEMON_CORE, is_dc ); new_starter->setIsDC( (bool)is_dc ); return new_starter; }
bool View:: SetRankExpr( ClassAdCollection *coll, ExprTree *rank ) { ClassAd *ad; ViewMember vm; MemberIndex::iterator mIdxItr; ViewMembers::iterator vmi; string key; Value rankValue; // insert expression into ad in left context if( !( ad=evalEnviron.GetLeftAd() ) ) { CLASSAD_EXCEPT( "internal error: view has no view info" ); } if( !ad->Insert( ATTR_RANK, rank ) ) { CondorErrMsg += "failed to set rank on view"; return( false ); } // clear out member list viewMembers.clear( ); // re-order content by new rank expression for( mIdxItr=memberIndex.begin(); mIdxItr!=memberIndex.end(); mIdxItr++ ) { key = mIdxItr->first; if( ( ad = coll->GetClassAd( key ) ) == NULL || !evalEnviron.ReplaceRightAd( ad ) || !evalEnviron.EvaluateAttr( "LeftRankValue", rankValue ) ) { // internal error CLASSAD_EXCEPT( "internal error: could not determine 'Rank' value" ); } // insert into member list vm.SetKey( key ); vm.SetRankValue( rankValue ); viewMembers.insert( vm ); } // now re-do the index memberIndex.clear( ); for( vmi = viewMembers.begin( ); vmi != viewMembers.end( ); vmi++ ) { vmi->GetKey( key ); memberIndex[key] = vmi; } return( true ); }
void test_oldstyle_with_exit(void) { int val; int action; char buf[4096]; ClassAd *result; ClassAd *jad = new ClassAd; if (jad == NULL) { printf("Out of memory!\n"); exit(EXIT_FAILURE); } printf("==================================================\n"); printf("Testing OldStyle job where it is marked as exited.\n"); /* An oldstyle classad would have this */ sprintf(buf, "%s = %d", ATTR_COMPLETION_DATE, 10); /* non zero */ jad->Insert(buf); result = user_job_policy(jad); result->EvalBool(ATTR_USER_POLICY_ERROR, result, val); if(val == true) { printf("An error happened\n"); delete result; return; } result->EvalBool(ATTR_TAKE_ACTION, result, val); if (val == true) { printf("%s was true.\n", ATTR_TAKE_ACTION); result->LookupInteger(ATTR_USER_POLICY_ACTION, action); printf("Action is: %s\n", action==REMOVE_JOB?"REMOVE_JOB":action==HOLD_JOB?"HOLD_JOB": "UNKNOWN"); result->LookupString(ATTR_USER_POLICY_FIRING_EXPR, buf); printf("Reason for action: %s\n", buf); } else { printf("Something went wrong. I should have had an action to take.\n"); } }
ClassAd *ClassAdCollectionInterface:: _ModifyClassAd( const string &xactionName, const string &key, ClassAd *ad ) { ClassAd *rec; if( !( rec = new ClassAd( ) ) ) { CondorErrno = ERR_MEM_ALLOC_FAILED; CondorErrMsg = ""; return( (ClassAd*) NULL ); } if( ( !xactionName.empty( ) && !rec->InsertAttr( ATTR_XACTION_NAME, xactionName ) ) || !rec->InsertAttr( "OpType",ClassAdCollOp_ModifyClassAd )|| !rec->InsertAttr( "Key", key ) || !rec->Insert( "Ad", ad ) ) { CondorErrMsg += "; failed to make modify classad " + key + " record"; delete rec; return( (ClassAd*) NULL ); } return( rec ); }
void test_oldstyle_with_no_exit(void) { int val; char buf[4096]; ClassAd *result; ClassAd *jad = new ClassAd; if (jad == NULL) { printf("Out of memory!\n"); exit(EXIT_FAILURE); } printf("======================================================\n"); printf("Testing OldStyle job where it is NOT marked as exited.\n"); /* An oldstyle classad would have this */ sprintf(buf, "%s = %d", ATTR_COMPLETION_DATE, 0); jad->Insert(buf); result = user_job_policy(jad); result->EvalBool(ATTR_USER_POLICY_ERROR, result, val); if(val == true) { printf("An error happened\n"); delete result; return; } result->EvalBool(ATTR_TAKE_ACTION, result, val); if (val == true) { printf("Something went wrong. I should not have had an action.\n"); } else { printf("Ignoring correctly.\n"); } delete result; }
int LogSetAttribute::Play(void *data_structure) { ClassAdHashTable *table = (ClassAdHashTable *)data_structure; int rval; ClassAd *ad = 0; if (table->lookup(HashKey(key), ad) < 0) return -1; if (value_expr) { ExprTree * pTree = value_expr->Copy(); rval = ad->Insert(name, pTree, false); } else { rval = ad->AssignExpr(name, value); } ad->SetDirtyFlag(name, is_dirty); #if defined(HAVE_DLOPEN) ClassAdLogPluginManager::SetAttribute(key, name, value); #endif return rval; }
Shadow* ShadowMgr::makeShadow( const char* path ) { Shadow* new_shadow; FILE* fp; const char *args[] = {const_cast<char*>(path), "-classad", NULL}; char buf[1024]; // first, try to execute the given path with a "-classad" // option, and grab the output as a ClassAd fp = my_popenv( args, "r", FALSE ); if( ! fp ) { dprintf( D_ALWAYS, "Failed to execute %s, ignoring\n", path ); return NULL; } ClassAd* ad = new ClassAd; bool read_something = false; while( fgets(buf, 1024, fp) ) { read_something = true; if( ! ad->Insert(buf) ) { dprintf( D_ALWAYS, "Failed to insert \"%s\" into ClassAd, " "ignoring invalid shadow\n", buf ); delete( ad ); my_pclose( fp ); return NULL; } } my_pclose( fp ); if( ! read_something ) { dprintf( D_ALWAYS, "\"%s -classad\" did not produce any output, " "ignoring\n", path ); delete( ad ); return NULL; } new_shadow = new Shadow( path, ad ); return new_shadow; }
ClassAd *ClassAdXMLParser:: ParseClassAd(ClassAd *classad_in) { bool in_classad; ClassAd *classad = NULL; ClassAd *local_ad = NULL; XMLLexer::Token token; classad = NULL; in_classad = false; while (lexer.PeekToken(&token)) { if (!in_classad) { lexer.ConsumeToken(NULL); if ( token.token_type == XMLLexer::tokenType_Tag && token.tag_id == XMLLexer::tagID_ClassAd) { // We have a ClassAd tag if (token.tag_type == XMLLexer::tagType_Start) { in_classad = true; if ( classad_in ) { classad_in->Clear(); classad = classad_in; } else { local_ad = new ClassAd(); classad = local_ad; } classad->DisableDirtyTracking(); } else { // We're done, return the ClassAd we got, if any. in_classad = false; break; } } } else { if (token.token_type == XMLLexer::tokenType_Tag) { if (token.tag_id == XMLLexer::tagID_Attribute) { if (token.tag_type == XMLLexer::tagType_Invalid) { delete local_ad; return NULL; } else if( token.tag_type == XMLLexer::tagType_Start) { string attribute_name; ExprTree *tree; tree = ParseAttribute(attribute_name); if (tree != NULL) { classad->Insert(attribute_name, tree); } else { delete local_ad; return NULL; } } else { lexer.ConsumeToken(NULL); } } else if (token.tag_id == XMLLexer::tagID_ClassAd) { lexer.ConsumeToken(NULL); if (token.tag_type == XMLLexer::tagType_End) { in_classad = false; break; } else { // This is invalid, but we'll just ignore it. } } else if ( token.tag_id != XMLLexer::tagID_XML && token.tag_id != XMLLexer::tagID_XMLStylesheet && token.tag_id != XMLLexer::tagID_Doctype && token.tag_id != XMLLexer::tagID_ClassAds) { // We got a non-attribute, non-xml thingy within a // ClassAd. That must be an error, but we'll just skip // it in the hopes of recovering. lexer.ConsumeToken(NULL); break; } } else { lexer.ConsumeToken(NULL); } } } if (classad != NULL) { classad->EnableDirtyTracking(); } return classad; }
ClassAd* readJobAd( void ) { ClassAd* ad = NULL; bool is_stdin = false; bool read_something = false; ASSERT( job_ad_file ); if( job_ad_file[0] == '-' && job_ad_file[1] == '\0' ) { fp = stdin; is_stdin = true; } else { if (fp == NULL) { fp = safe_fopen_wrapper_follow( job_ad_file, "r" ); if( ! fp ) { EXCEPT( "Failed to open ClassAd file (%s): %s (errno %d)", job_ad_file, strerror(errno), errno ); } } } dprintf( D_FULLDEBUG, "Reading job ClassAd from %s\n", is_stdin ? "STDIN" : job_ad_file ); ad = new ClassAd; MyString line; while( line.readLine(fp) ) { read_something = true; line.chomp(); if( line[0] == '#' ) { dprintf( D_JOB, "IGNORING COMMENT: %s\n", line.Value() ); continue; } if( line == "***" ) { dprintf( D_JOB, "Saw ClassAd delimitor, stopping\n" ); break; } if( ! ad->Insert(line.Value()) ) { EXCEPT( "Failed to insert \"%s\" into ClassAd!", line.Value() ); } } if( ! read_something ) { EXCEPT( "reading ClassAd from (%s): file is empty", is_stdin ? "STDIN" : job_ad_file ); } if( IsDebugVerbose(D_JOB) ) { ad->dPrint( D_JOB ); } // For debugging, see if there's a special attribute in the // job ad that sends us into an infinite loop, waiting for // someone to attach with a debugger int shadow_should_wait = 0; ad->LookupInteger( ATTR_SHADOW_WAIT_FOR_DEBUG, shadow_should_wait ); if( shadow_should_wait ) { dprintf( D_ALWAYS, "Job requested shadow should wait for " "debugger with %s=%d, going into infinite loop\n", ATTR_SHADOW_WAIT_FOR_DEBUG, shadow_should_wait ); while( shadow_should_wait ) { } } return ad; }
void XferSummary::time_out(time_t now, char *hostaddr) { ClassAd info; char line[128], *tmp; char *str = NULL; info.SetMyTypeName("CkptServer"); info.SetTargetTypeName("CkptFile"); sprintf(line, "%s = \"%s\"", ATTR_NAME, my_full_hostname() ); info.Insert(line); sprintf(line, "%s = \"%s\"", ATTR_MACHINE, hostaddr ); info.Insert(line); sprintf(line, "%s = \"%s\"", ATTR_VERSION, CondorVersion() ); info.Insert(line); sprintf(line, "%s = \"%s\"", ATTR_PLATFORM, CondorPlatform() ); info.Insert(line); sprintf(line, "NumSends = %d", num_sends); info.Insert(line); sprintf(line, "BytesSent = %d", (int) bytes_sent); info.Insert(line); sprintf(line, "TimeSending = %d", time_sending); info.Insert(line); sprintf(line, "AvgSendBandwidth = %f", num_sends ? tot_send_bandwidth / num_sends : 0.0); info.Insert(line); sprintf(line, "NumRecvs = %d", num_recvs); info.Insert(line); sprintf(line, "BytesReceived = %d", (int) bytes_recv); info.Insert(line); sprintf(line, "TimeReceiving = %d", time_recving); info.Insert(line); sprintf(line, "AvgReceiveBandwidth = %f", num_recvs ? tot_recv_bandwidth / num_recvs : 0.0); info.Insert(line); /* ctime adds a newline at the end of the ascii conversion.... */ str = ctime(&start_time); sprintf(line, "CkptServerIntervalStart = \"%s\"", str ? str : "Unknown\n"); tmp = strchr( line, '\n' ); if (tmp != NULL) { /* delete the newline */ *tmp = '\"'; tmp++; *tmp = '\0'; } info.Insert(line); /* ctime adds a newline at the end of the ascii conversion.... */ str = ctime(&now); sprintf(line, "CkptServerIntervalEnd = \"%s\"", str ? str : "Unknown\n"); tmp = strchr( line, '\n' ); if (tmp != NULL) { /* delete the newline */ *tmp = '\"'; tmp++; *tmp = '\0'; } info.Insert(line); sprintf(line, "Disk = %d", sysapi_disk_space(pwd.Value()) ); info.Insert(line); // Send to collector if ( Collectors ) { dprintf(D_NETWORK, "Sending CkptServer ClassAd:\n"); info.dPrint(D_NETWORK); Collectors->sendUpdates (UPDATE_CKPT_SRVR_AD, &info, NULL, true); } init(); }
bool View:: DeletePartitionedView( ClassAdCollection *coll, const ViewName &vName ) { PartitionedViews::iterator mi; for( mi = partitionedViews.begin( ); mi != partitionedViews.end( ); mi++ ) { if( mi->second->GetViewName( ) == vName ) { // check if the partition is non-empty ... if( mi->second->Size( ) != 0 ) { // remove all child views and reset view info View *view = mi->second; SubordinateViews::iterator svi; PartitionedViews::iterator pvi; // delete subordinate views for( svi = view->subordinateViews.begin( ); svi != view->subordinateViews.end( ); svi++ ) { (*svi)->DeleteView( coll ); delete (*svi); } view->subordinateViews.clear( ); // delete partitioned views for( pvi = view->partitionedViews.begin( ); pvi != view->partitionedViews.end( ); pvi++ ) { pvi->second->DeleteView( coll ); delete pvi->second; } view->partitionedViews.clear( ); // reset name of view coll->UnregisterView( vName ); coll->RegisterView( viewName + ":" + mi->first, view ); // reset other view info vector<ExprTree*> vec; ExprTree * pExpr=0; ClassAd *ad = new ClassAd( ); if( !ad ) { CondorErrno = ERR_MEM_ALLOC_FAILED; CondorErrMsg = ""; return( false ); } if( !ad->InsertAttr( ATTR_REQUIREMENTS, true ) || !ad->InsertAttr( ATTR_RANK, 0 ) || !ad->Insert(ATTR_PARTITION_EXPRS, (pExpr=ExprList::MakeExprList( vec )) ) || !view->SetViewInfo( coll, ad ) ) { CondorErrMsg += "; failed to delete partition view " + vName; return( false ); } return( true ); } // empty partition ... can just delete it mi->second->DeleteView( coll ); delete mi->second; partitionedViews.erase( mi ); return( true ); } } CondorErrno = ERR_NO_SUCH_VIEW; CondorErrMsg = "no partition child view named " + vName + " in view"; return( false ); }
bool doMatch(const char *name, const ArgumentList &arguments, EvalState &state, Value &result) { bool eval_successful = false; result.SetErrorValue(); // We check to make sure that we passed exactly two arguments... if (arguments.size() == 2) { Value arg1; const ExprList *adList; // ...the first argument should evaluate to a list... if (arguments[0] -> Evaluate(state, arg1) && arg1.IsListValue(adList)) { // ...the second argument should be either an expression // operand node or a function call node... if (arguments[1] -> GetKind() == ExprTree::OP_NODE || arguments[1] -> GetKind() == ExprTree::FN_CALL_NODE) { // Now we prepare the match context used while looking for // any matching ad in the adList.In order to evaluate correctly // any attribute reference involved in the second argument we // should use the same classad containing the anyMatch statement // while matching. Moreover we should make a copy of the requirements // expression passed as second argument and set the parent scope by // inserting it into the just copied classad. Finally, we set the left // context which will be constant for any further match. MatchClassAd match; ClassAd* al = static_cast<classad::ClassAd*>(arguments[1]->GetParentScope()->Copy()); al->Insert("requirements", arguments[1]->Copy()); match.ReplaceLeftAd(al); std::vector<ExprTree*> ads, matching; adList->GetComponents(ads); for(std::vector<ExprTree*>::const_iterator it = ads.begin(); it != ads.end(); it++) { // Each expression in the list should be a classad... if (!utils::is_classad(*it)) { result.SetErrorValue(); eval_successful = false; break; } ClassAd* ar = static_cast<ClassAd*>((*it)->Copy()); match.ReplaceRightAd(ar); // If requirements does not evaluate to a boolean there is // something seriously wrong and exit... if (!match.EvaluateAttrBool("rightMatchesLeft", eval_successful)) { result.SetErrorValue(); eval_successful = false; break; } // ...otherwise we have to set the result and exit depending // on which function was called. if ( (!strcasecmp(name, "anyMatch") && eval_successful) || (!strcasecmp(name, "allMatch") && !eval_successful)) { result.SetBooleanValue(eval_successful); break; } if (!strcasecmp(name, "whichMatch") && eval_successful) { matching.push_back(dynamic_cast<ClassAd*>(*it)); } } // if the whichMatch was called we have to set the result to // the classad which matched... if (!strcasecmp(name, "whichMatch")) { eval_successful = !matching.empty(); // if there is no matching ad then the evaluation was successful // and we have to set the result to undefined... // ...otherwise we have to set the result to the matching ad(s) if (!eval_successful) result.SetUndefinedValue(); else result.SetListValue(ExprList::MakeExprList(matching)); } } } } return eval_successful; }
ClassAd *CollectorEngine:: collect (int command,ClassAd *clientAd,const condor_sockaddr& from,int &insert,Sock *sock) { ClassAd *retVal; ClassAd *pvtAd; int insPvt; AdNameHashKey hk; HashString hashString; static int repeatStartdAds = -1; // for debugging ClassAd *clientAdToRepeat = NULL; _condor_auto_accum_runtime<collector_runtime_probe> rt(CollectorEngine_rucc_runtime); double rt_last = rt.begin; if (repeatStartdAds == -1) { repeatStartdAds = param_integer("COLLECTOR_REPEAT_STARTD_ADS",0); } if( !ValidateClassAd(command,clientAd,sock) ) { return NULL; } CollectorEngine_rucc_validateAd_runtime.Add(rt.tick(rt_last)); // mux on command switch (command) { case UPDATE_STARTD_AD: case UPDATE_STARTD_AD_WITH_ACK: if ( repeatStartdAds > 0 ) { clientAdToRepeat = new ClassAd(*clientAd); } if (!makeStartdAdHashKey (hk, clientAd)) { dprintf (D_ALWAYS, "Could not make hashkey --- ignoring ad\n"); insert = -3; retVal = 0; break; } hashString.Build( hk ); CollectorEngine_rucc_makeHashKey_runtime.Add(rt.tick(rt_last)); retVal=updateClassAd (StartdAds, "StartdAd ", "Start", clientAd, hk, hashString, insert, from ); if (last_updateClassAd_was_insert) { CollectorEngine_rucc_insertAd_runtime.Add(rt.tick(rt_last)); } else { CollectorEngine_rucc_updateAd_runtime.Add(rt.tick(rt_last)); } // if we want to store private ads if (!sock) { dprintf (D_ALWAYS, "Want private ads, but no socket given!\n"); break; } else { if (!(pvtAd = new ClassAd)) { EXCEPT ("Memory error!"); } if( !getClassAd(sock, *pvtAd) ) { dprintf(D_FULLDEBUG,"\t(Could not get startd's private ad)\n"); delete pvtAd; break; } // Fix up some stuff in the private ad that we depend on. // We started doing this in 7.2.0, so once we no longer // care about compatibility with stuff from before then, // the startd could stop bothering to send these attributes. // Queries of private ads depend on the following: SetMyTypeName( *pvtAd, STARTD_ADTYPE ); // Negotiator matches up private ad with public ad by // using the following. if( retVal ) { CopyAttribute( ATTR_MY_ADDRESS, *pvtAd, *retVal ); CopyAttribute( ATTR_NAME, *pvtAd, *retVal ); } CollectorEngine_rucc_getPvtAd_runtime.Add(rt.tick(rt_last)); // insert the private ad into its hashtable --- use the same // hash key as the public ad (void) updateClassAd (StartdPrivateAds, "StartdPvtAd ", "StartdPvt", pvtAd, hk, hashString, insPvt, from ); if (last_updateClassAd_was_insert) { CollectorEngine_rucc_insertPvtAd_runtime.Add(rt.tick(rt_last)); } else { CollectorEngine_rucc_updatePvtAd_runtime.Add(rt.tick(rt_last)); } } // create fake duplicates of this ad, each with a different name, if // we are told to do so. this feature exists for developer // scalability testing. if ( repeatStartdAds > 0 && clientAdToRepeat ) { ClassAd *fakeAd; int n; char newname[150],oldname[130]; oldname[0] = '\0'; clientAdToRepeat->LookupString("Name",oldname,sizeof(oldname)); for (n=0;n<repeatStartdAds;n++) { fakeAd = new ClassAd(*clientAdToRepeat); snprintf(newname,sizeof(newname), "Name=\"fake%d-%s\"",n,oldname); fakeAd->Insert(newname); makeStartdAdHashKey (hk, fakeAd); hashString.Build( hk ); if (! updateClassAd (StartdAds, "StartdAd ", "Start", fakeAd, hk, hashString, insert, from ) ) { // don't leak memory if there is some failure delete fakeAd; } } delete clientAdToRepeat; clientAdToRepeat = NULL; CollectorEngine_rucc_repeatAd_runtime.Add(rt.tick(rt_last)); } break; case MERGE_STARTD_AD: if (!makeStartdAdHashKey (hk, clientAd)) { dprintf (D_ALWAYS, "Could not make hashkey --- ignoring ad\n"); insert = -3; retVal = 0; break; } hashString.Build( hk ); retVal=mergeClassAd (StartdAds, "StartdAd ", "Start", clientAd, hk, hashString, insert, from ); break; case UPDATE_SCHEDD_AD: if (!makeScheddAdHashKey (hk, clientAd)) { dprintf (D_ALWAYS, "Could not make hashkey --- ignoring ad\n"); insert = -3; retVal = 0; break; } hashString.Build( hk ); retVal=updateClassAd (ScheddAds, "ScheddAd ", "Schedd", clientAd, hk, hashString, insert, from ); break; case UPDATE_SUBMITTOR_AD: // use the same hashkey function as a schedd ad if (!makeScheddAdHashKey (hk, clientAd)) { dprintf (D_ALWAYS, "Could not make hashkey --- ignoring ad\n"); insert = -3; retVal = 0; break; } // since submittor ads always follow a schedd ad, and a master check is // performed for schedd ads, we don't need a master check in here hashString.Build( hk ); retVal=updateClassAd (SubmittorAds, "SubmittorAd ", "Submittor", clientAd, hk, hashString, insert, from ); break; case UPDATE_LICENSE_AD: // use the same hashkey function as a schedd ad if (!makeLicenseAdHashKey (hk, clientAd)) { dprintf (D_ALWAYS, "Could not make hashkey --- ignoring ad\n"); insert = -3; retVal = 0; break; } // since submittor ads always follow a schedd ad, and a master check is // performed for schedd ads, we don't need a master check in here hashString.Build( hk ); retVal=updateClassAd (LicenseAds, "LicenseAd ", "License", clientAd, hk, hashString, insert, from ); break; case UPDATE_MASTER_AD: if (!makeMasterAdHashKey (hk, clientAd)) { dprintf (D_ALWAYS, "Could not make hashkey --- ignoring ad\n"); insert = -3; retVal = 0; break; } hashString.Build( hk ); retVal=updateClassAd (MasterAds, "MasterAd ", "Master", clientAd, hk, hashString, insert, from ); break; case UPDATE_CKPT_SRVR_AD: if (!makeCkptSrvrAdHashKey (hk, clientAd)) { dprintf (D_ALWAYS, "Could not make hashkey --- ignoring ad\n"); insert = -3; retVal = 0; break; } hashString.Build( hk ); retVal=updateClassAd (CkptServerAds, "CkptSrvrAd ", "CkptSrvr", clientAd, hk, hashString, insert, from ); break; case UPDATE_COLLECTOR_AD: if (!makeCollectorAdHashKey (hk, clientAd)) { dprintf (D_ALWAYS, "Could not make hashkey --- ignoring ad\n"); insert = -3; retVal = 0; break; } hashString.Build( hk ); retVal=updateClassAd (CollectorAds, "CollectorAd ", "Collector", clientAd, hk, hashString, insert, from ); break; case UPDATE_STORAGE_AD: if (!makeStorageAdHashKey (hk, clientAd)) { dprintf (D_ALWAYS, "Could not make hashkey --- ignoring ad\n"); insert = -3; retVal = 0; break; } hashString.Build( hk ); retVal=updateClassAd (StorageAds, "StorageAd ", "Storage", clientAd, hk, hashString, insert, from ); break; case UPDATE_ACCOUNTING_AD: if (!makeAccountingAdHashKey (hk, clientAd)) { dprintf (D_ALWAYS, "Could not make hashkey --- ignoring ad\n"); insert = -3; retVal = 0; break; } hashString.Build( hk ); retVal=updateClassAd (AccountingAds, "AccountingAd ", "Accouting", clientAd, hk, hashString, insert, from ); break; case UPDATE_NEGOTIATOR_AD: if (!makeNegotiatorAdHashKey (hk, clientAd)) { dprintf (D_ALWAYS, "Could not make hashkey --- ignoring ad\n"); insert = -3; retVal = 0; break; } hashString.Build( hk ); if (m_allowOnlyOneNegotiator) { // first, purge all the existing negotiator ads, since we // want to enforce that *ONLY* 1 negotiator is in the // collector any given time. purgeHashTable( NegotiatorAds ); } retVal=updateClassAd (NegotiatorAds, "NegotiatorAd ", "Negotiator", clientAd, hk, hashString, insert, from ); break; case UPDATE_HAD_AD: if (!makeHadAdHashKey (hk, clientAd)) { dprintf (D_ALWAYS, "Could not make hashkey --- ignoring ad\n"); insert = -3; retVal = 0; break; } hashString.Build( hk ); retVal=updateClassAd (HadAds, "HadAd ", "HAD", clientAd, hk, hashString, insert, from ); break; case UPDATE_GRID_AD: if (!makeGridAdHashKey(hk, clientAd)) { dprintf (D_ALWAYS, "Could not make hashkey --- ignoring ad\n"); insert = -3; retVal = 0; break; } hashString.Build( hk ); retVal=updateClassAd (GridAds, "GridAd ", "Grid", clientAd, hk, hashString, insert, from ); break; case UPDATE_AD_GENERIC: { const char *type_str = GetMyTypeName(*clientAd); if (type_str == NULL) { dprintf(D_ALWAYS, "collect: UPDATE_AD_GENERIC: ad has no type\n"); insert = -3; retVal = 0; break; } MyString type(type_str); CollectorHashTable *cht = findOrCreateTable(type); if (cht == NULL) { dprintf(D_ALWAYS, "collect: findOrCreateTable failed\n"); insert = -3; retVal = 0; break; } if (!makeGenericAdHashKey (hk, clientAd)) { dprintf(D_ALWAYS, "Could not make hashkey --- ignoring ad\n"); insert = -3; retVal = 0; break; } hashString.Build(hk); retVal = updateClassAd(*cht, type_str, type_str, clientAd, hk, hashString, insert, from); break; } case QUERY_STARTD_ADS: case QUERY_SCHEDD_ADS: case QUERY_MASTER_ADS: case QUERY_SUBMITTOR_ADS: case QUERY_CKPT_SRVR_ADS: case QUERY_STARTD_PVT_ADS: case QUERY_COLLECTOR_ADS: case QUERY_NEGOTIATOR_ADS: case QUERY_HAD_ADS: case QUERY_GENERIC_ADS: case INVALIDATE_STARTD_ADS: case INVALIDATE_SCHEDD_ADS: case INVALIDATE_MASTER_ADS: case INVALIDATE_CKPT_SRVR_ADS: case INVALIDATE_SUBMITTOR_ADS: case INVALIDATE_COLLECTOR_ADS: case INVALIDATE_NEGOTIATOR_ADS: case INVALIDATE_HAD_ADS: case INVALIDATE_ADS_GENERIC: // these are not implemented in the engine, but we allow another // daemon to detect that these commands have been given insert = -2; retVal = 0; break; default: dprintf (D_ALWAYS, "Received illegal command: %d\n", command); insert = -1; retVal = 0; } if (command != UPDATE_STARTD_AD && command != UPDATE_STARTD_AD_WITH_ACK) { CollectorEngine_rucc_other_runtime.Add(rt.tick(rt_last)); } // return the updated ad return retVal; }
/* This function determines what should be done with a job given the user policy specifed in the job ad. If no policy is specified, then a classad is returned detailing that nothing should be done because there wasn't a user policy. You are responsible for freeing the classad you get back from this function. It can be used in a periodic fashion on job ads and has the notion of "nothing should be done to this job" present in the classad result you get back. */ ClassAd* user_job_policy(ClassAd *jad) { ClassAd *result; char buf[4096]; /* old classads needs to go away */ int on_exit_hold = 0, on_exit_remove = 0; int cdate = 0; int adkind; if (jad == NULL) { EXCEPT( "Could not evaluate user policy due to job ad being NULL!\n" ); } /* Set up the default response of do nothing. The caller should just check for this attribute and ATTR_USER_POLICY_ERROR and do nothing to the rest of the classad of ATTR_TAKE_ACTION is false. */ result = new ClassAd; if (result == NULL) { EXCEPT("Out of memory!"); /* XXX should this be here? */ } sprintf(buf, "%s = FALSE", ATTR_TAKE_ACTION); result->Insert(buf); sprintf(buf, "%s = FALSE", ATTR_USER_POLICY_ERROR); result->Insert(buf); /* figure out the ad kind and then do something with it */ adkind = JadKind(jad); switch(adkind) { case USER_ERROR_NOT_JOB_AD: dprintf(D_ALWAYS, "user_job_policy(): I have something that " "doesn't appear to be a job ad! Ignoring.\n"); sprintf(buf, "%s = TRUE", ATTR_USER_POLICY_ERROR); result->Insert(buf); sprintf(buf, "%s = %u", ATTR_USER_ERROR_REASON, USER_ERROR_NOT_JOB_AD); result->Insert(buf); return result; break; case USER_ERROR_INCONSISTANT: dprintf(D_ALWAYS, "user_job_policy(): Inconsistant jobad state " "with respect to user_policy. Detail " "follows:\n"); { ExprTree *ph_expr = jad->LookupExpr(ATTR_PERIODIC_HOLD_CHECK); ExprTree *pr_expr = jad->LookupExpr(ATTR_PERIODIC_REMOVE_CHECK); ExprTree *pl_expr = jad->LookupExpr(ATTR_PERIODIC_RELEASE_CHECK); ExprTree *oeh_expr = jad->LookupExpr(ATTR_ON_EXIT_HOLD_CHECK); ExprTree *oer_expr = jad->LookupExpr(ATTR_ON_EXIT_REMOVE_CHECK); EmitExpression(D_ALWAYS, ATTR_PERIODIC_HOLD_CHECK, ph_expr); EmitExpression(D_ALWAYS, ATTR_PERIODIC_REMOVE_CHECK, pr_expr); EmitExpression(D_ALWAYS, ATTR_PERIODIC_RELEASE_CHECK, pl_expr); EmitExpression(D_ALWAYS, ATTR_ON_EXIT_HOLD_CHECK, oeh_expr); EmitExpression(D_ALWAYS, ATTR_ON_EXIT_REMOVE_CHECK, oer_expr); } sprintf(buf, "%s = TRUE", ATTR_USER_POLICY_ERROR); result->Insert(buf); sprintf(buf, "%s = %u", ATTR_USER_ERROR_REASON, USER_ERROR_INCONSISTANT); result->Insert(buf); return result; break; case KIND_OLDSTYLE: jad->LookupInteger(ATTR_COMPLETION_DATE, cdate); if (cdate > 0) { sprintf(buf, "%s = TRUE", ATTR_TAKE_ACTION); result->Insert(buf); sprintf(buf, "%s = %d", ATTR_USER_POLICY_ACTION, REMOVE_JOB); result->Insert(buf); sprintf(buf, "%s = \"%s\"", ATTR_USER_POLICY_FIRING_EXPR, old_style_exit); result->Insert(buf); } return result; break; case KIND_NEWSTYLE: { /* The user_policy is checked in this order. The first one to succeed is the winner: periodic_hold periodic_exit on_exit_hold on_exit_remove */ UserPolicy userpolicy; userpolicy.Init(jad); int analyze_result = userpolicy.AnalyzePolicy(PERIODIC_ONLY); /* should I perform a periodic hold? */ if(analyze_result == HOLD_IN_QUEUE) { /* make a result classad explaining this and return it */ sprintf(buf, "%s = TRUE", ATTR_TAKE_ACTION); result->Insert(buf); sprintf(buf, "%s = %d", ATTR_USER_POLICY_ACTION, HOLD_JOB); result->Insert(buf); sprintf(buf, "%s = \"%s\"", ATTR_USER_POLICY_FIRING_EXPR, userpolicy.FiringExpression()); result->Insert(buf); return result; } /* Should I perform a periodic remove? */ if(analyze_result == REMOVE_FROM_QUEUE) { /* make a result classad explaining this and return it */ sprintf(buf, "%s = TRUE", ATTR_TAKE_ACTION); result->Insert(buf); sprintf(buf, "%s = %d", ATTR_USER_POLICY_ACTION, REMOVE_JOB); result->Insert(buf); sprintf(buf, "%s = \"%s\"", ATTR_USER_POLICY_FIRING_EXPR, userpolicy.FiringExpression()); result->Insert(buf); return result; } /* Should I perform a periodic release? */ if(analyze_result == RELEASE_FROM_HOLD) { /* make a result classad explaining this and return it */ sprintf(buf, "%s = TRUE", ATTR_TAKE_ACTION); result->Insert(buf); sprintf(buf, "%s = %d", ATTR_USER_POLICY_ACTION, REMOVE_JOB); result->Insert(buf); sprintf(buf, "%s = \"%s\"", ATTR_USER_POLICY_FIRING_EXPR, userpolicy.FiringExpression()); result->Insert(buf); return result; } /* Check to see if ExitSignal or ExitCode are defined, if not, then assume the job hadn't exited and don't check the policy. This could hide a mistake of the caller to insert those attributes correctly but allows checking of the job ad in a periodic context. */ if (jad->LookupExpr(ATTR_ON_EXIT_CODE) == 0 && jad->LookupExpr(ATTR_ON_EXIT_SIGNAL) == 0) { return result; } /* Should I hold on exit? */ jad->EvalBool(ATTR_ON_EXIT_HOLD_CHECK, jad, on_exit_hold); if (on_exit_hold == 1) { /* make a result classad explaining this and return it */ sprintf(buf, "%s = TRUE", ATTR_TAKE_ACTION); result->Insert(buf); sprintf(buf, "%s = %d", ATTR_USER_POLICY_ACTION, HOLD_JOB); result->Insert(buf); sprintf(buf, "%s = \"%s\"", ATTR_USER_POLICY_FIRING_EXPR, ATTR_ON_EXIT_HOLD_CHECK); result->Insert(buf); return result; } /* Should I remove on exit? */ jad->EvalBool(ATTR_ON_EXIT_REMOVE_CHECK, jad, on_exit_remove); if (on_exit_remove == 1) { /* make a result classad explaining this and return it */ sprintf(buf, "%s = TRUE", ATTR_TAKE_ACTION); result->Insert(buf); sprintf(buf, "%s = %d", ATTR_USER_POLICY_ACTION, REMOVE_JOB); result->Insert(buf); sprintf(buf, "%s = \"%s\"", ATTR_USER_POLICY_FIRING_EXPR, ATTR_ON_EXIT_REMOVE_CHECK); result->Insert(buf); return result; } /* just return the default of leaving the job in idle state */ return result; break; } default: dprintf(D_ALWAYS, "JadKind() returned unknown ad kind\n"); /* just return the default of leaving the job in idle state. This is safest. */ return result; break; } /* just return the default of leaving the job in idle state */ return result; }
ClassAd * ProcAd::dumpToAd( piPTR pi ) { char line[128]; ClassAd *ad = new ClassAd; SetMyTypeName( *ad, "PROCESS_INFORMATION" ); SetTargetTypeName( *ad, "ENQUIRING_MINDS_WANT_TO_KNOW" ); sprintf ( line, "THIS_PID = %d", pi->pid ); ad->Insert(line); sprintf ( line, "PARENT_PID = %ld", (long)pi->ppid ); ad->Insert(line); sprintf ( line, "IMAGE_SIZE = %ld", (long)pi->imgsize ); ad->Insert(line); sprintf ( line, "RESIDENT_SET_SIZE = %ld", (long)pi->rssize ); ad->Insert(line); #if HAVE_PSS if( pi->pssize_available ) { sprintf ( line, "PROPORTIONAL_SET_SIZE = %ld", (long)pi->pssize ); ad->Insert(line); } #endif sprintf ( line, "MAJOR_PAGE_FAULTS = %ld", (long)pi->majfault ); ad->Insert(line); sprintf ( line, "MINOR_PAGE_FAULTS = %ld", (long)pi->minfault ); ad->Insert(line); sprintf ( line, "USER_TIME = %ld", (long)pi->user_time ); ad->Insert(line); sprintf ( line, "SYSTEM_TIME = %ld", (long)pi->sys_time ); ad->Insert(line); sprintf ( line, "PROCESS_AGE = %ld", (long)pi->age ); ad->Insert(line); sprintf ( line, "PERCENT_CPU_USAGE = %6.2f", pi->cpuusage ); ad->Insert(line); return ad; }
void test_user_policy_on_exit_hold_no(void) { int val; int action; char buf[4096]; ClassAd *result; ClassAd *jad = new ClassAd; if (jad == NULL) { printf("Out of memory!\n"); exit(EXIT_FAILURE); } printf("=======================================\n"); printf("Testing User Policy on On Exit Hold: NO\n"); /* set up the classad */ sprintf(buf, "%s = %d", ATTR_ON_EXIT_CODE, 0); jad->Insert(buf); sprintf(buf, "%s = 40", ATTR_TOTAL_SUSPENSIONS); jad->Insert(buf); sprintf(buf, "%s = FALSE", ATTR_PERIODIC_HOLD_CHECK); jad->Insert(buf); sprintf(buf, "%s = FALSE", ATTR_PERIODIC_REMOVE_CHECK); jad->Insert(buf); sprintf(buf, "%s = TotalSuspensions == 42", ATTR_ON_EXIT_HOLD_CHECK); jad->Insert(buf); sprintf(buf, "%s = TRUE", ATTR_ON_EXIT_REMOVE_CHECK); jad->Insert(buf); result = user_job_policy(jad); result->EvalBool(ATTR_USER_POLICY_ERROR, result, val); if(val == true) { printf("An error happened\n"); delete result; return; } result->EvalBool(ATTR_TAKE_ACTION, result, val); if (val == true) { printf("%s was true.\n", ATTR_TAKE_ACTION); result->LookupInteger(ATTR_USER_POLICY_ACTION, action); printf("Action is: %s\n", action==REMOVE_JOB?"REMOVE_JOB":action==HOLD_JOB?"HOLD_JOB": "UNKNOWN"); result->LookupString(ATTR_USER_POLICY_FIRING_EXPR, buf); printf("Reason for action: %s\n", buf); if (strcmp(ATTR_USER_POLICY_FIRING_EXPR, ATTR_ON_EXIT_HOLD_CHECK) == 0) { printf("Failed. I got removed because exit_hold was true.\n"); } else { printf("Success. I was removed because of %s, not because of %s\n", ATTR_ON_EXIT_REMOVE_CHECK, ATTR_ON_EXIT_HOLD_CHECK); } } else { printf("Ignoring correctly.\n"); } }
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)); } }
bool DCSchedd::receiveJobSandbox(const char* constraint, CondorError * errstack, int * numdone /*=0*/) { if(numdone) { *numdone = 0; } ExprTree *tree = NULL; const char *lhstr; int reply; int i; ReliSock rsock; int JobAdsArrayLen; bool use_new_command = true; if ( version() ) { CondorVersionInfo vi( version() ); if ( vi.built_since_version(6,7,7) ) { use_new_command = true; } else { use_new_command = false; } } // // // // // // // // // On the wire protocol // // // // // // // // rsock.timeout(20); // years of research... :) if( ! rsock.connect(_addr) ) { dprintf( D_ALWAYS, "DCSchedd::receiveJobSandbox: " "Failed to connect to schedd (%s)\n", _addr ); return false; } if ( use_new_command ) { if( ! startCommand(TRANSFER_DATA_WITH_PERMS, (Sock*)&rsock, 0, errstack) ) { dprintf( D_ALWAYS, "DCSchedd::receiveJobSandbox: " "Failed to send command (TRANSFER_DATA_WITH_PERMS) " "to the schedd\n" ); return false; } } else { if( ! startCommand(TRANSFER_DATA, (Sock*)&rsock, 0, errstack) ) { dprintf( D_ALWAYS, "DCSchedd::receiveJobSandbox: " "Failed to send command (TRANSFER_DATA) " "to the schedd\n" ); return false; } } // First, if we're not already authenticated, force that now. if (!forceAuthentication( &rsock, errstack )) { dprintf( D_ALWAYS, "DCSchedd::receiveJobSandbox: authentication failure: %s\n", errstack ? errstack->getFullText().c_str() : "" ); return false; } rsock.encode(); // Send our version if using the new command if ( use_new_command ) { // Need to use a named variable, else the wrong version of // code() is called. char *my_version = strdup( CondorVersion() ); if ( !rsock.code(my_version) ) { dprintf(D_ALWAYS,"DCSchedd:receiveJobSandbox: " "Can't send version string to the schedd\n"); free( my_version ); return false; } free( my_version ); } // Send the constraint char * nc_constraint = strdup( constraint ); // de-const if ( !rsock.code(nc_constraint) ) { free( nc_constraint ); dprintf(D_ALWAYS,"DCSchedd:receiveJobSandbox: " "Can't send JobAdsArrayLen to the schedd\n"); return false; } free( nc_constraint ); if ( !rsock.end_of_message() ) { std::string errmsg; formatstr(errmsg, "Can't send initial message (version + constraint) to schedd (%s)", _addr); dprintf(D_ALWAYS,"DCSchedd::receiveJobSandbox: %s\n", errmsg.c_str()); if( errstack ) { errstack->push( "DCSchedd::receiveJobSandbox", CEDAR_ERR_EOM_FAILED, errmsg.c_str()); } return false; } // Now, read how many jobs matched the constraint. rsock.decode(); if ( !rsock.code(JobAdsArrayLen) ) { std::string errmsg; formatstr(errmsg, "Can't receive JobAdsArrayLen from the schedd (%s)", _addr); dprintf(D_ALWAYS,"DCSchedd::receiveJobSandbox: %s\n", errmsg.c_str()); if( errstack ) { errstack->push( "DCSchedd::receiveJobSandbox", CEDAR_ERR_GET_FAILED, errmsg.c_str()); } return false; } rsock.end_of_message(); dprintf(D_FULLDEBUG,"DCSchedd:receiveJobSandbox: " "%d jobs matched my constraint (%s)\n", JobAdsArrayLen, constraint); // Now read all the files via the file transfer object for (i=0; i<JobAdsArrayLen; i++) { FileTransfer ftrans; ClassAd job; // grab job ClassAd if ( !getClassAd(&rsock, job) ) { std::string errmsg; formatstr(errmsg, "Can't receive job ad %d from the schedd", i); dprintf(D_ALWAYS, "DCSchedd::receiveJobSandbox: %s\n", errmsg.c_str()); if( errstack ) { errstack->push( "DCSchedd::receiveJobSandbox", CEDAR_ERR_GET_FAILED, errmsg.c_str()); } return false; } rsock.end_of_message(); // translate the job ad by replacing the // saved SUBMIT_ attributes job.ResetExpr(); while( job.NextExpr(lhstr, tree) ) { if ( lhstr && strncasecmp("SUBMIT_",lhstr,7)==0 ) { // this attr name starts with SUBMIT_ // compute new lhs (strip off the SUBMIT_) const char *new_attr_name = strchr(lhstr,'_'); ExprTree * pTree; ASSERT(new_attr_name); new_attr_name++; // insert attribute pTree = tree->Copy(); job.Insert(new_attr_name, pTree, false); } } // while next expr if ( !ftrans.SimpleInit(&job,false,false,&rsock) ) { if( errstack ) { int cluster = -1, proc = -1; job.LookupInteger(ATTR_CLUSTER_ID,cluster); job.LookupInteger(ATTR_PROC_ID,proc); errstack->pushf( "DCSchedd::receiveJobSandbox", FILETRANSFER_INIT_FAILED, "File transfer initialization failed for target job %d.%d", cluster, proc ); } return false; } // We want files to be copied to their final places, so apply // any filename remaps when downloading. if ( !ftrans.InitDownloadFilenameRemaps(&job) ) { return false; } if ( use_new_command ) { ftrans.setPeerVersion( version() ); } if ( !ftrans.DownloadFiles() ) { if( errstack ) { FileTransfer::FileTransferInfo ft_info = ftrans.GetInfo(); int cluster = -1, proc = -1; job.LookupInteger(ATTR_CLUSTER_ID,cluster); job.LookupInteger(ATTR_PROC_ID,proc); errstack->pushf( "DCSchedd::receiveJobSandbox", FILETRANSFER_DOWNLOAD_FAILED, "File transfer failed for target job %d.%d: %s", cluster, proc, ft_info.error_desc.Value() ); } return false; } } rsock.end_of_message(); rsock.encode(); reply = OK; rsock.code(reply); rsock.end_of_message(); if(numdone) { *numdone = JobAdsArrayLen; } return true; }
// download the files associated with the jobads to the sandbox at td_sinful // with the supplied capability. // The work_ad should contain: // ATTR_TREQ_CAPABILITY // ATTR_TREQ_FTP // ATTR_TREQ_JOBID_ALLOW_LIST bool DCTransferD::download_job_files(ClassAd *work_ad, CondorError * errstack) { ReliSock *rsock = NULL; int timeout = 60 * 60 * 8; // transfers take a long time... int i; ClassAd reqad, respad; std::string cap; int ftp; int invalid; int protocol; std::string reason; int num_transfers; ClassAd jad; const char *lhstr = NULL; ExprTree *tree = NULL; ////////////////////////////////////////////////////////////////////////// // Connect to the transferd and authenticate ////////////////////////////////////////////////////////////////////////// // This call with automatically connect to _addr, which was set in the // constructor of this object to be the transferd in question. rsock = (ReliSock*)startCommand(TRANSFERD_READ_FILES, Stream::reli_sock, timeout, errstack); if( ! rsock ) { dprintf( D_ALWAYS, "DCTransferD::download_job_files: " "Failed to send command (TRANSFERD_READ_FILES) " "to the schedd\n" ); errstack->push("DC_TRANSFERD", 1, "Failed to start a TRANSFERD_READ_FILES command."); return false; } // First, if we're not already authenticated, force that now. if (!forceAuthentication( rsock, errstack )) { dprintf( D_ALWAYS, "DCTransferD::download_job_files() authentication " "failure: %s\n", errstack->getFullText().c_str() ); errstack->push("DC_TRANSFERD", 1, "Failed to authenticate properly."); return false; } rsock->encode(); ////////////////////////////////////////////////////////////////////////// // Query the transferd about the capability/protocol and see if I can // download my files. It will respond with a classad saying good or bad. ////////////////////////////////////////////////////////////////////////// work_ad->LookupString(ATTR_TREQ_CAPABILITY, cap); work_ad->LookupInteger(ATTR_TREQ_FTP, ftp); reqad.Assign(ATTR_TREQ_CAPABILITY, cap); reqad.Assign(ATTR_TREQ_FTP, ftp); // This request ad to the transferd should contain: // ATTR_TREQ_CAPABILITY // ATTR_TREQ_FTP reqad.put(*rsock); rsock->end_of_message(); rsock->decode(); // This response ad from the transferd should contain: // ATTR_TREQ_INVALID_REQUEST (set to true) // ATTR_TREQ_INVALID_REASON // // OR // // ATTR_TREQ_INVALID_REQUEST (set to false) // ATTR_TREQ_NUM_TRANSFERS // respad.initFromStream(*rsock); rsock->end_of_message(); respad.LookupInteger(ATTR_TREQ_INVALID_REQUEST, invalid); if (invalid == TRUE) { // The transferd rejected my attempt to upload the fileset delete rsock; respad.LookupString(ATTR_TREQ_INVALID_REASON, reason); errstack->push("DC_TRANSFERD", 1, reason.c_str()); return false; } respad.LookupInteger(ATTR_TREQ_NUM_TRANSFERS, num_transfers); ////////////////////////////////////////////////////////////////////////// // Based upon the protocol I've chosen, use that method to download the // files. When using the FileTrans protocol, a child process on the // transferd side will be sending me individual job ads and then // instantiating a filetransfer object for that ad. ////////////////////////////////////////////////////////////////////////// dprintf(D_ALWAYS, "Receiving fileset"); work_ad->LookupInteger(ATTR_TREQ_FTP, protocol); switch(protocol) { case FTP_CFTP: // download the files using the FileTransfer Object for (i = 0; i < num_transfers; i++) { // Grab a job ad the server is sending us so we know what // to receive. jad.initFromStream(*rsock); rsock->end_of_message(); // translate the job ad by replacing the // saved SUBMIT_ attributes so the download goes into the // correct place. jad.ResetExpr(); while( jad.NextExpr(lhstr, tree) ) { if ( lhstr && strncasecmp("SUBMIT_",lhstr,7)==0 ) { // this attr name starts with SUBMIT_ // compute new lhs (strip off the SUBMIT_) const char *new_attr_name = strchr(lhstr,'_'); ExprTree * pTree; ASSERT(new_attr_name); new_attr_name++; // insert attribute pTree = tree->Copy(); jad.Insert(new_attr_name, pTree, false); } } // while next expr // instantiate a filetransfer object and have it accept the // files. FileTransfer ftrans; if ( !ftrans.SimpleInit(&jad, false, false, rsock) ) { delete rsock; errstack->push("DC_TRANSFERD", 1, "Failed to initate uploading of files."); return false; } // We want files to be copied to their final places, so apply // any filename remaps when downloading. if ( !ftrans.InitDownloadFilenameRemaps(&jad) ) { return false; } ftrans.setPeerVersion( version() ); if ( !ftrans.DownloadFiles() ) { delete rsock; errstack->push("DC_TRANSFERD", 1, "Failed to download files."); return false; } dprintf(D_ALWAYS | D_NOHEADER, "."); } rsock->end_of_message(); dprintf(D_ALWAYS | D_NOHEADER, "\n"); break; default: // Bail due to user error. This client doesn't support the unknown // protocol. delete rsock; errstack->push("DC_TRANSFERD", 1, "Unknown file transfer protocol selected."); return false; break; } ////////////////////////////////////////////////////////////////////////// // Get the response from the transferd once it sees a completed // movement of files to the child process. ////////////////////////////////////////////////////////////////////////// rsock->decode(); respad.initFromStream(*rsock); rsock->end_of_message(); // close up shop delete rsock; respad.LookupInteger(ATTR_TREQ_INVALID_REQUEST, invalid); if ( invalid == TRUE ) { respad.LookupString(ATTR_TREQ_INVALID_REASON, reason); errstack->push("DC_TRANSFERD", 1, reason.c_str()); return false; } return true; }
/*! handle a log Entry: work with a job queue collection. * (not with DBMS directry) */ QuillErrCode JobQueueDBManager::processLogEntry(int op_type, JobQueueCollection* jobQueue) { char *key, *mytype, *targettype, *name, *value; key = mytype = targettype = name = value = NULL; QuillErrCode st = QUILL_SUCCESS; int job_id_type; char cid[512]; char pid[512]; // REMEMBER: // each get*ClassAdBody() funtion allocates the memory of // parameters. Therefore, they all must be deallocated here, // and they are at the end of the routine switch(op_type) { case CondorLogOp_NewClassAd: { if (caLogParser->getNewClassAdBody(key, mytype, targettype) == QUILL_FAILURE) { st = QUILL_FAILURE; break; } job_id_type = getProcClusterIds(key, cid, pid); ClassAd* ad = new ClassAd(); SetMyTypeName(*ad, "Job"); SetTargetTypeName(*ad, "Machine"); switch(job_id_type) { case IS_CLUSTER_ID: jobQueue->insertClusterAd(cid, ad); break; case IS_PROC_ID: jobQueue->insertProcAd(cid, pid, ad); break; default: dprintf(D_ALWAYS, "[QUILL++] New ClassAd --- ERROR\n"); st = QUILL_FAILURE; break; } break; } case CondorLogOp_DestroyClassAd: { if (caLogParser->getDestroyClassAdBody(key) == QUILL_FAILURE) { st = QUILL_FAILURE; break; } job_id_type = getProcClusterIds(key, cid, pid); switch(job_id_type) { case IS_CLUSTER_ID: jobQueue->removeClusterAd(cid); break; case IS_PROC_ID: { ClassAd *clusterad = jobQueue->find(cid); ClassAd *procad = jobQueue->find(cid,pid); if(!clusterad || !procad) { dprintf(D_ALWAYS, "[QUILL++] Destroy ClassAd --- Cannot find clusterad " "or procad in memory job queue"); st = QUILL_FAILURE; break; } jobQueue->removeProcAd(cid, pid); break; } default: dprintf(D_ALWAYS, "[QUILL++] Destroy ClassAd --- ERROR\n"); st = QUILL_FAILURE; break; } break; } case CondorLogOp_SetAttribute: { if (caLogParser->getSetAttributeBody(key, name, value) == QUILL_FAILURE) { st = QUILL_FAILURE; break; } job_id_type = getProcClusterIds(key, cid, pid); char tmp[512]; snprintf(tmp, 512, "%s = %s", name, value); switch (job_id_type) { case IS_CLUSTER_ID: { ClassAd* ad = jobQueue->findClusterAd(cid); if (ad != NULL) { ad->Insert(tmp); } else { dprintf(D_ALWAYS, "[QUILL++] ERROR: There is no such Cluster Ad[%s]\n", cid); } break; } case IS_PROC_ID: { ClassAd* ad = jobQueue->findProcAd(cid, pid); if (ad != NULL) { ad->Insert(tmp); } else { dprintf(D_ALWAYS, "[QUILL++] ERROR: There is no such Proc Ad[%s.%s]\n", cid, pid); } break; } default: dprintf(D_ALWAYS, "[QUILL++] Set Attribute --- ERROR\n"); st = QUILL_FAILURE; break; } break; } case CondorLogOp_DeleteAttribute: { if (caLogParser->getDeleteAttributeBody(key, name) == QUILL_FAILURE) { st = QUILL_FAILURE; break; } job_id_type = getProcClusterIds(key, cid, pid); switch(job_id_type) { case IS_CLUSTER_ID: { ClassAd* ad = jobQueue->findClusterAd(cid); ad->Delete(name); break; } case IS_PROC_ID: { ClassAd* ad = jobQueue->findProcAd(cid, pid); ad->Delete(name); break; } default: dprintf(D_ALWAYS, "[QUILL++] Delete Attribute --- ERROR\n"); st = QUILL_FAILURE; } break; } case CondorLogOp_BeginTransaction: st = processBeginTransaction(true); break; case CondorLogOp_EndTransaction: st = processEndTransaction(true); break; // skip the log historical sequence number command case CondorLogOp_LogHistoricalSequenceNumber: break; default: printf("[QUILL++] Unsupported Job Queue Command\n"); st = QUILL_FAILURE; break; } // pointers are release if (key != NULL) free(key); if (mytype != NULL) free(mytype); if (targettype != NULL) free(targettype); if (name != NULL) free(name); if (value != NULL) free(value); return st; }
// 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; }