ClassAd *ClassAdCollectionInterface:: _CreateSubView( const ViewName &viewName, const ViewName &parentViewName, const string &constraint, const string &rank, const string &partitionExprs ) { ClassAd *rec; string buffer; buffer = "[ ViewName = \""; buffer += viewName; buffer += "\" ; ParentViewName = \""; buffer += parentViewName; buffer += "\" ; Requirements = "; buffer += constraint=="" ? "true" : constraint; buffer += " ; PartitionExprs = "; if (string_is_empty(partitionExprs)) { buffer += "{}"; } else { buffer += partitionExprs; } buffer += " ; Rank = "; if (string_is_empty(rank)) { buffer += "undefined"; } else { buffer += rank; } buffer += " ] ]"; if( !( rec = parser.ParseClassAd( buffer ) ) ) { return( NULL ); } rec->InsertAttr( "OpType", ClassAdCollOp_CreateSubView ); return( rec ); }
void Defrag::loadState() { FILE *fp; if( !(fp = safe_fopen_wrapper_follow(m_state_file.c_str(), "r")) ) { if( errno == ENOENT ) { dprintf(D_ALWAYS,"State file %s does not yet exist.\n",m_state_file.c_str()); } else { EXCEPT("failed to load state from %s",m_state_file.c_str()); } } else { int isEOF=0, errorReadingAd=0, adEmpty=0; ClassAd *ad = new ClassAd(fp, "...", isEOF, errorReadingAd, adEmpty); fclose( fp ); if( errorReadingAd ) { dprintf(D_ALWAYS,"WARNING: failed to parse state from %s\n",m_state_file.c_str()); } int timestamp = (int)m_last_poll; ad->LookupInteger(ATTR_LAST_POLL,timestamp); m_last_poll = (time_t)timestamp; dprintf(D_ALWAYS,"Last poll: %d\n",(int)m_last_poll); delete ad; } }
Manageable::status_t Triggerd::AddTrigger(std::string name, std::string query, std::string triggerText, std::string& text) { std::string attr; ClassAd* ad = new ClassAd(); Manageable::status_t ret_val; char* tmp; SetMyTypeName(*ad, "EventTrigger"); SetTargetTypeName(*ad, "Trigger"); tmp = strdup(name.c_str()); ReplaceAllChars(tmp, '"', '\''); ad->Assign(ATTR_TRIGGER_NAME, tmp); free(tmp); tmp = strdup(query.c_str()); ReplaceAllChars(tmp, '"', '\''); ad->Assign(ATTR_TRIGGER_QUERY, tmp); free(tmp); tmp = strdup(triggerText.c_str()); ReplaceAllChars(tmp, '"', '\''); ad->Assign(ATTR_TRIGGER_TEXT, tmp); free(tmp); ret_val = AddTrigger(ad, text); delete ad; return ret_val; }
bool ClientTransaction:: LogAbort( FILE *fp, ClassAdUnParser *unp ) { if( state != PENDING ) { CondorErrno = ERR_BAD_TRANSACTION_STATE; CondorErrMsg = "transaction expected to be in COMMITTED state"; return( false ); } ClassAd rec; string buf; if(!rec.InsertAttr(ATTR_OP_TYPE, ClassAdCollectionInterface::ClassAdCollOp_AbortTransaction) || !rec.InsertAttr( "XactionName", xactionName.c_str( ) ) ) { CondorErrMsg += "FATAL ERROR: failed to log transaction"; return( false ); } unp->Unparse( buf, &rec ); if( fprintf( fp, "%s\n", buf.c_str( ) ) < 0 ) { CondorErrno = ERR_FILE_WRITE_FAILED; CondorErrMsg = "FATAL ERROR: failed fprintf()"; return( false ); } fsync( fileno( fp ) ); return( true ); }
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; }
// // JobExit() is called after file transfer. // bool DockerProc::JobExit() { dprintf( D_ALWAYS, "DockerProc::JobExit()\n" ); { TemporaryPrivSentry sentry(PRIV_ROOT); ClassAd dockerAd; CondorError error; int rv = DockerAPI::inspect( containerName, & dockerAd, error ); if( rv < 0 ) { dprintf( D_ALWAYS | D_FAILURE, "Failed to inspect (for removal) container '%s'.\n", containerName.c_str() ); return VanillaProc::JobExit(); } bool running; if( ! dockerAd.LookupBool( "Running", running ) ) { dprintf( D_ALWAYS | D_FAILURE, "Inspection of container '%s' failed to reveal its running state.\n", containerName.c_str() ); return VanillaProc::JobExit(); } if( running ) { dprintf( D_ALWAYS | D_FAILURE, "Inspection reveals that container '%s' is still running.\n", containerName.c_str() ); return VanillaProc::JobExit(); } rv = DockerAPI::rm( containerName, error ); if( rv < 0 ) { dprintf( D_ALWAYS | D_FAILURE, "Failed to remove container '%s'.\n", containerName.c_str() ); } } return VanillaProc::JobExit(); }
void cp_compute_consumption(ClassAd& job, ClassAd& resource, consumption_map_t& consumption) { consumption.clear(); string mrv; if (!resource.LookupString(ATTR_MACHINE_RESOURCES, mrv)) { EXCEPT("Resource ad missing %s attribute", ATTR_MACHINE_RESOURCES); } StringList alist(mrv.c_str()); alist.rewind(); while (char* asset = alist.next()) { if (MATCH == strcasecmp(asset, "swap")) continue; string ra; string coa; formatstr(ra, "%s%s", ATTR_REQUEST_PREFIX, asset); formatstr(coa, "_condor_%s", ra.c_str()); bool override = false; double ov=0; if (job.EvalFloat(coa.c_str(), NULL, ov)) { // Allow _condor_RequestedXXX to override RequestedXXX // this case is intended to be operative when a scheduler has set // such values and sent them on to the startd that owns this resource // (e.g. I'd not expect this case to arise elsewhere, like the negotiator) string ta; formatstr(ta, "_cp_temp_%s", ra.c_str()); job.CopyAttribute(ta.c_str(), ra.c_str()); job.Assign(ra.c_str(), ov); override = true; }
void PandadClassAdLogPlugin::setAttribute( const char * key, const char * attribute, const char * value ) { int cluster = 0, proc = 0; if( shouldIgnoreJob( key, cluster, proc ) ) { return; } dprintf( D_FULLDEBUG, "PANDA: setAttribute( %s, %s, %s ).\n", key, attribute, value ); std::string globalJobID; if( ! getGlobalJobID( cluster, proc, globalJobID ) ) { return; } // See comment in newClassAd(), above. if( strcmp( attribute, "ProcId" ) == 0 ) { ClassAd * clusterAd = ScheddGetJobAd( cluster, -1 ); if( clusterAd != NULL ) { ExprTree * valueExpr = NULL; const char * attribute = NULL; clusterAd->ResetExpr(); while( clusterAd->NextExpr( attribute, valueExpr ) ) { dprintf( D_FULLDEBUG, "PANDA: found %s in cluster ad.\n", attribute ); if( shouldIgnoreAttribute( attribute ) ) { continue; } std::string valueString; classad::ClassAdUnParser unparser; unparser.Unparse( valueString, valueExpr ); updatePandaJob( globalJobID.c_str(), attribute, valueString.c_str() ); } } else { dprintf( D_FULLDEBUG, "PANDA: Failed to find cluster ad for %d.%d\n", cluster, proc ); } } if( shouldIgnoreAttribute( attribute ) ) { return; } updatePandaJob( globalJobID.c_str(), attribute, value ); }
void assign_preserve_integers(ClassAd& ad, const char* attr, double v) { if ((v - floor(v)) > 0.0) { ad.Assign(attr, v); } else { ad.Assign(attr, (long long)(v)); } }
bool cp_supports_policy(ClassAd& resource, bool strict) { // currently, only p-slots can support a functional consumption policy if (strict) { bool part = false; if (!resource.LookupBool(ATTR_SLOT_PARTITIONABLE, part)) part = false; if (!part) return false; } // must support MachineResources attribute string mrv; if (!resource.LookupString(ATTR_MACHINE_RESOURCES, mrv)) return false; // must define ConsumptionXxx for all resources Xxx (including extensible resources) StringList alist(mrv.c_str()); alist.rewind(); while (char* asset = alist.next()) { if (MATCH == strcasecmp(asset, "swap")) continue; string ca; formatstr(ca, "%s%s", ATTR_CONSUMPTION_PREFIX, asset); ClassAd::iterator f(resource.find(ca)); if (f == resource.end()) return false; } return true; }
bool CCBListener::RegisterWithCCBServer(bool blocking) { ClassAd msg; if( m_waiting_for_connect || m_reconnect_timer != -1 || m_waiting_for_registration || m_registered) { // already registered or being registered return m_registered; } msg.Assign( ATTR_COMMAND, CCB_REGISTER ); if( !m_ccbid.IsEmpty() ) { // we are reconnecting; trying to preserve ccbid so that prospective // clients with stale information can still contact us msg.Assign( ATTR_CCBID, m_ccbid.Value() ); msg.Assign( ATTR_CLAIM_ID, m_reconnect_cookie.Value() ); } // for debugging purposes only, identify ourselves to the CCB server MyString name; name.formatstr("%s %s",get_mySubSystem()->getName(),daemonCore->publicNetworkIpAddr()); msg.Assign( ATTR_NAME, name.Value() ); bool success = SendMsgToCCB(msg,blocking); if( success ) { if( blocking ) { success = ReadMsgFromCCB(); } else { // now we wait for CCB server to respond with our CCBID m_waiting_for_registration = true; } } return success; }
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 ); }
void CCBListener::ReportReverseConnectResult(ClassAd *connect_msg,bool success,char const *error_msg) { ClassAd msg = *connect_msg; MyString request_id; MyString address; connect_msg->LookupString(ATTR_REQUEST_ID,request_id); connect_msg->LookupString(ATTR_MY_ADDRESS,address); if( !success ) { dprintf(D_ALWAYS, "CCBListener: failed to create reversed connection for " "request id %s to %s: %s\n", request_id.Value(), address.Value(), error_msg ? error_msg : ""); } else { dprintf(D_FULLDEBUG|D_NETWORK, "CCBListener: created reversed connection for " "request id %s to %s: %s\n", request_id.Value(), address.Value(), error_msg ? error_msg : ""); } msg.Assign(ATTR_RESULT,success); if( error_msg ) { msg.Assign(ATTR_ERROR_STRING,error_msg); } WriteMsgToCCB( msg ); }
bool CCBListener::HandleCCBRequest( ClassAd &msg ) { MyString address; MyString connect_id; MyString request_id; MyString name; if( !msg.LookupString( ATTR_MY_ADDRESS, address) || !msg.LookupString( ATTR_CLAIM_ID, connect_id) || !msg.LookupString( ATTR_REQUEST_ID, request_id) ) { MyString msg_str; msg.sPrint(msg_str); EXCEPT("CCBListener: invalid CCB request from %s: %s\n", m_ccb_address.Value(), msg_str.Value() ); } msg.LookupString( ATTR_NAME, name ); if( name.find(address.Value())<0 ) { name.formatstr_cat(" with reverse connect address %s",address.Value()); } dprintf(D_FULLDEBUG|D_NETWORK, "CCBListener: received request to connect to %s, request id %s.\n", name.Value(), request_id.Value()); return DoReversedCCBConnect( address.Value(), connect_id.Value(), request_id.Value(), name.Value() ); }
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; }
int CondorQ::fetchQueueFromDB (ClassAdList &list, char *&lastUpdate, const char *dbconn, CondorError* /*errstack*/) { #ifndef HAVE_EXT_POSTGRESQL (void) list; (void) lastUpdate; (void) dbconn; #else int result; JobQueueSnapshot *jqSnapshot; const char *constraint; ClassAd *ad; QuillErrCode rv; ExprTree *tree; 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) { ad->ChainCollapse(); list.Insert(ad); ad = getDBNextJobByConstraint(constraint, jqSnapshot); } delete jqSnapshot; #endif /* HAVE_EXT_POSTGRESQL */ return Q_OK; }
// For now, just return true if the constraint worked on at least // one job, false if not. Someday, we can fix up the tool to take // advantage of all the slick info the schedd gives us back about this // request. bool doWorkByConstraint( const char* constraint, CondorError * errstack ) { ClassAd* ad = 0; int total_jobs = -1; bool rval = true; switch( mode ) { case JA_RELEASE_JOBS: ad = schedd->releaseJobs( constraint, actionReason, errstack ); break; case JA_REMOVE_X_JOBS: ad = schedd->removeXJobs( constraint, actionReason, errstack ); break; case JA_VACATE_JOBS: ad = schedd->vacateJobs( constraint, VACATE_GRACEFUL, errstack ); break; case JA_VACATE_FAST_JOBS: ad = schedd->vacateJobs( constraint, VACATE_FAST, errstack ); break; case JA_REMOVE_JOBS: ad = schedd->removeJobs( constraint, actionReason, errstack ); break; case JA_HOLD_JOBS: ad = schedd->holdJobs( constraint, actionReason, holdReasonSubCode, errstack ); break; case JA_SUSPEND_JOBS: ad = schedd->suspendJobs( constraint, actionReason, errstack ); break; case JA_CONTINUE_JOBS: ad = schedd->continueJobs( constraint, actionReason, errstack ); break; default: EXCEPT( "impossible: unknown mode in doWorkByConstraint" ); } if( ! ad ) { had_error = true; rval = false; } else { int result = FALSE; if( !ad->LookupInteger(ATTR_ACTION_RESULT, result) ) { had_error = true; rval = false; } else if( !result ) { // There were no ads acted upon, but that doesn't // mean there was an error. It's possible the schedd // had no jobs if( !ad->LookupInteger(ATTR_TOTAL_JOB_ADS, total_jobs) || total_jobs > 0 ) { had_error = true; } else { // There were no jobs in the queue, so add a // more meaningful error message errstack->push("condor_rm", 0, "There are no jobs in the queue"); } rval = false; } } return rval; }
bool VMUniverseMgr::allocVM(pid_t s_pid, ClassAd &ad, char const *execute_dir) { if( canCreateVM(&ad) == false ) { return false; } // Find memory for VM int vm_mem = 0; if( (ad.LookupInteger(ATTR_JOB_VM_MEMORY, vm_mem) != 1) && (ad.LookupInteger(ATTR_REQUEST_MEMORY, vm_mem) != 1) ) { dprintf(D_ALWAYS, "Can't find VM memory in Job ClassAd\n"); return false; } int vcpus = 0; if( (ad.LookupInteger(ATTR_JOB_VM_VCPUS, vcpus) != 1) && (ad.LookupInteger(ATTR_REQUEST_CPUS, vcpus) != 1) ) { dprintf(D_FULLDEBUG, "Defaulting to one CPU\n"); vcpus = 1; } // check whether this pid already exists VMStarterInfo *oldinfo = findVMStarterInfoWithStarterPid(s_pid); if( oldinfo ) { freeVM(s_pid); // oldinfo is freed oldinfo = NULL; } VMStarterInfo *newinfo = new VMStarterInfo; ASSERT(newinfo); m_vm_used_memory += vm_mem; newinfo->m_pid = s_pid; newinfo->m_memory = vm_mem; newinfo->m_job_ad = ad; newinfo->m_execute_dir = execute_dir; newinfo->m_vcpus = vcpus; // If there exists MAC or IP address for a checkpointed VM, // we use them as initial values. MyString string_value; if( ad.LookupString(ATTR_VM_CKPT_MAC, string_value) == 1 ) { newinfo->m_vm_mac = string_value; } /* string_value = ""; if( ad.LookupString(ATTR_VM_CKPT_IP, string_value) == 1 ) { newinfo->m_vm_ip = string_value; } */ m_vm_starter_list.Append(newinfo); return true; }
// specialization: this GetFullAd has to retrieve its classad attributes // from the history file based on index pointers void HistoryJobImpl::GetFullAd ( ClassAd& _ad) const { // fseek to he.start // ClassAd method to deserialize from a file with "***" FILE * hFile; int end = 0; int error = 0; int empty = 0; std::ostringstream buf; // placeholder in case we want to expose error details to UI std::string text; // TODO: move the ClassAd/file deserialize back to HistoryFile??? const char* fName = m_he.file.c_str(); if ( ! ( hFile = safe_fopen_wrapper ( fName, "r" ) ) ) { buf << "unable to open history file " << m_he.file; text = buf.str(); dprintf ( D_ALWAYS, "%s\n", text.c_str()); _ad.Assign("JOB_AD_ERROR",text.c_str()); return; } if ( fseek ( hFile , m_he.start , SEEK_SET ) ) { buf << "bad seek in " << m_he.file << " at " << m_he.start; text = buf.str(); dprintf ( D_ALWAYS, "%s\n", text.c_str()); _ad.Assign("JOB_AD_ERROR",text.c_str()); return; } ClassAd myJobAd ( hFile, "***", end, error, empty ); fclose ( hFile ); // TODO: debug logging and error to i/f for now // we might not have our original history file anymore if ( error ) { buf << "malformed ad for job '" << m_job->GetKey() << "' in " << m_he.file; text = buf.str(); dprintf ( D_FULLDEBUG, "%s\n", text.c_str()); _ad.Assign("JOB_AD_ERROR",text.c_str()); return; } if ( empty ) { buf << "empty ad for job '" << m_job->GetKey() << "' in " << m_he.file; text = buf.str(); dprintf ( D_FULLDEBUG,"%s\n", text.c_str()); _ad.Assign("JOB_AD_ERROR",text.c_str()); return; } _ad = myJobAd; }
ULogEventOutcome ReadUserLog::readEventXML( ULogEvent *& event ) { classad::ClassAdXMLParser xmlp; // we obtain a write lock here not because we want to write // anything, but because we want to ensure we don't read // mid-way through someone else's write Lock( true ); // store file position so that if we are unable to read the event, we can // rewind to this location long filepos; if (!m_fp || ((filepos = ftell(m_fp)) == -1L)) { Unlock( true ); event = NULL; return ULOG_UNK_ERROR; } ClassAd* eventad = new ClassAd(); if ( !xmlp.ParseClassAd(m_fp, *eventad) ) { delete eventad; eventad = NULL; } Unlock( true ); if( !eventad ) { // we don't have the full event in the stream yet; restore file // position and return if( fseek(m_fp, filepos, SEEK_SET) ) { dprintf(D_ALWAYS, "fseek() failed in ReadUserLog::readEvent"); return ULOG_UNK_ERROR; } clearerr(m_fp); event = NULL; return ULOG_NO_EVENT; } int enmbr; if( !eventad->LookupInteger("EventTypeNumber", enmbr) ) { event = NULL; delete eventad; return ULOG_NO_EVENT; } if( !(event = instantiateEvent((ULogEventNumber) enmbr)) ) { event = NULL; delete eventad; return ULOG_UNK_ERROR; } event->initFromClassAd(eventad); delete eventad; return ULOG_OK; }
void ScheddStatistics::Unpublish(ClassAd & ad) const { ad.Delete("StatsLifetime"); ad.Delete("StatsLastUpdateTime"); ad.Delete("RecentStatsLifetime"); ad.Delete("RecentStatsTickTime"); ad.Delete("RecentWindowMax"); Pool.Unpublish(ad); }
int do_command_upload_sandbox(void *arg, Stream*) { dprintf(D_ALWAYS, "FTGAHP: upload sandbox\n"); Gahp_Args args; parse_gahp_command ((char*)arg, &args); // first two args: result id and sandbox id: std::string rid = args.argv[1]; std::string sid = args.argv[2]; // third arg: job ad ClassAd ad; classad::ClassAdParser my_parser; if (!(my_parser.ParseClassAd(args.argv[3], ad))) { // FAIL write_to_pipe( ChildErrorPipe, "Failed to parse job ad" ); return 1; } // rewrite the IWD to the actual sandbox dir std::string iwd; define_sandbox_path(sid, iwd); ad.Assign(ATTR_JOB_IWD, iwd.c_str()); char ATTR_SANDBOX_ID[] = "SandboxId"; ad.Assign(ATTR_SANDBOX_ID, sid.c_str()); // directory was created, let's set up the FileTransfer object FileTransfer ft; if (!ft.Init(&ad)) { // FAIL write_to_pipe( ChildErrorPipe, "Failed to initialize FileTransfer" ); return 1; } // lookup ATTR_VERSION and set it. this changes the wire // protocol and it is important that this happens before // calling UploadFiles. char* peer_version = NULL; ad.LookupString(ATTR_VERSION, &peer_version); ft.setPeerVersion(peer_version); free (peer_version); dprintf(D_ALWAYS, "BOSCO: calling upload files\n"); // the "true" param to UploadFiles here means blocking (i.e. "in the foreground") if (!ft.UploadFiles(true)) { // FAIL write_to_pipe( ChildErrorPipe, ft.GetInfo().error_desc.Value() ); return 1; } // SUCCEED return 0; }
bool Defrag::drain(const ClassAd &startd_ad) { std::string name; startd_ad.LookupString(ATTR_NAME,name); dprintf(D_ALWAYS,"Initiating %s draining of %s.\n", m_draining_schedule_str.c_str(),name.c_str()); DCStartd startd( &startd_ad ); int graceful_completion = 0; startd_ad.LookupInteger(ATTR_EXPECTED_MACHINE_GRACEFUL_DRAINING_COMPLETION,graceful_completion); int quick_completion = 0; startd_ad.LookupInteger(ATTR_EXPECTED_MACHINE_QUICK_DRAINING_COMPLETION,quick_completion); int graceful_badput = 0; startd_ad.LookupInteger(ATTR_EXPECTED_MACHINE_GRACEFUL_DRAINING_BADPUT,graceful_badput); int quick_badput = 0; startd_ad.LookupInteger(ATTR_EXPECTED_MACHINE_QUICK_DRAINING_BADPUT,quick_badput); time_t now = time(NULL); std::string draining_check_expr; double badput_growth_tolerance = 1.25; // for now, this is hard-coded int negligible_badput = 1200; int negligible_deadline_slippage = 1200; if( m_draining_schedule <= DRAIN_GRACEFUL ) { dprintf(D_ALWAYS,"Expected draining completion time is %ds; expected draining badput is %d cpu-seconds\n", (int)(graceful_completion-now),graceful_badput); sprintf(draining_check_expr,"%s <= %d && %s <= %d", ATTR_EXPECTED_MACHINE_GRACEFUL_DRAINING_COMPLETION, graceful_completion + negligible_deadline_slippage, ATTR_EXPECTED_MACHINE_GRACEFUL_DRAINING_BADPUT, (int)(badput_growth_tolerance*graceful_badput) + negligible_badput); } else { // DRAIN_FAST and DRAIN_QUICK are effectively equivalent here dprintf(D_ALWAYS,"Expected draining completion time is %ds; expected draining badput is %d cpu-seconds\n", (int)(quick_completion-now),quick_badput); sprintf(draining_check_expr,"%s <= %d && %s <= %d", ATTR_EXPECTED_MACHINE_QUICK_DRAINING_COMPLETION, quick_completion + negligible_deadline_slippage, ATTR_EXPECTED_MACHINE_QUICK_DRAINING_BADPUT, (int)(badput_growth_tolerance*quick_badput) + negligible_badput); } std::string request_id; bool resume_on_completion = true; bool rval = startd.drainJobs( m_draining_schedule, resume_on_completion, draining_check_expr.c_str(), request_id ); if( !rval ) { dprintf(D_ALWAYS,"Failed to send request to drain %s: %s\n",startd.name(),startd.error()); m_stats.DrainFailures += 1; return false; } m_stats.DrainSuccesses += 1; return true; }
void CollectorEngine:: cleanHashTable (CollectorHashTable &hashTable, time_t now, HashFunc makeKey) { ClassAd *ad; int timeStamp; int max_lifetime; AdNameHashKey hk; double timeDiff; MyString hkString; hashTable.startIterations (); while (hashTable.iterate (ad)) { // Read the timestamp of the ad if (!ad->LookupInteger (ATTR_LAST_HEARD_FROM, timeStamp)) { dprintf (D_ALWAYS, "\t\tError looking up time stamp on ad\n"); continue; } // how long has it been since the last update? timeDiff = difftime( now, timeStamp ); if( !ad->LookupInteger( ATTR_CLASSAD_LIFETIME, max_lifetime ) ) { max_lifetime = machineUpdateInterval; } // check if it has expired if ( timeDiff > (double) max_lifetime ) { // then remove it from the segregated table (*makeKey) (hk, ad); hk.sprint( hkString ); if( timeStamp == 0 ) { dprintf (D_ALWAYS,"\t\t**** Removing invalidated ad: \"%s\"\n", hkString.Value() ); } else { dprintf (D_ALWAYS,"\t\t**** Removing stale ad: \"%s\"\n", hkString.Value() ); /* let the off-line plug-in know we are about to expire this ad, so it can potentially mark the ad absent. if expire() returns false, then delete the ad as planned; if it return true, it was likely marked as absent, so then this ad should NOT be deleted. */ if ( CollectorDaemon::offline_plugin_.expire( *ad ) == true ) { // plugin say to not delete this ad, so continue continue; } else { dprintf (D_ALWAYS,"\t\t**** Removing stale ad: \"%s\"\n", hkString.Value() ); } } if (hashTable.remove (hk) == -1) { dprintf (D_ALWAYS, "\t\tError while removing ad\n"); } delete ad; } } }
int classad_get_string_list_attribute (classad_context cad, const char *attribute_name, char ***result) { if (cad == NULL) return C_CLASSAD_INVALID_CONTEXT; int n_results = 0; (*result) = (char **)malloc(sizeof(char **)); if ((*result) == NULL) return C_CLASSAD_OUT_OF_MEMORY; (*result)[0] = NULL; ClassAd *ad = (ClassAd *)cad; Value vl; ad->EvaluateAttr(attribute_name, vl); const ExprList *et_result; if (vl.IsListValue(et_result)) { std::vector<ExprTree*> ads; et_result->GetComponents(ads); // Get string values. for(std::vector<ExprTree*>::const_iterator it = ads.begin(); it != ads.end(); ++it) { if ((*it)->GetKind() == ExprTree::LITERAL_NODE) { Value v; EvalState state; state.SetScopes( ad ); (*it)->Evaluate(state,v); std::string res_str; if (v.IsStringValue( res_str )) { // add string value to result, which is a NULL-terminated // string array. n_results++; (*result) = (char **)realloc(*result, (n_results+1)*sizeof(char *)); if ((*result) == NULL) return C_CLASSAD_OUT_OF_MEMORY; (*result)[n_results-1] = strdup(res_str.c_str()); (*result)[n_results] = NULL; } } } return C_CLASSAD_NO_ERROR; } // The result list needs to be freed on success only. classad_free_string_list(*result); (*result) = NULL; return C_CLASSAD_VALUE_NOT_FOUND; }
bool BaseShadow::jobWantsGracefulRemoval() { bool job_wants_graceful_removal = false; ClassAd *thejobAd = getJobAd(); if( thejobAd ) { thejobAd->LookupBool( ATTR_WANT_GRACEFUL_REMOVAL, job_wants_graceful_removal ); } return job_wants_graceful_removal; }
void classad_dump (classad_context cad) { ClassAd *ad; if (cad != NULL) { ad = (ClassAd *)cad; ad->Puke(); } }
void stats_recent_counter_timer::Unpublish(ClassAd & ad, const char * pattr) const { ad.Delete(pattr); MyString attr; attr.sprintf("Recent%s",pattr); ad.Delete(attr.Value()); attr.sprintf("Recent%sRuntime",pattr); ad.Delete(attr.Value()); ad.Delete(attr.Value()+6); // +6 to skip "Recent" prefix }
void StarterStatistics::Publish(ClassAd& ad, int flags) const { if ((flags & IF_PUBLEVEL) > 0) { ad.Assign("StatsLifetime", (int)StatsLifetime); if (flags & IF_VERBOSEPUB) ad.Assign("StatsLastUpdateTime", (int)StatsLastUpdateTime); if (flags & IF_RECENTPUB) { ad.Assign("RecentStatsLifetime", (int)RecentStatsLifetime); if (flags & IF_VERBOSEPUB) { ad.Assign("RecentWindowMax", (int)RecentWindowMax); ad.Assign("RecentStatsTickTime", (int)RecentStatsTickTime); } } } Pool.Publish(ad, flags); if ((flags & IF_PUBLEVEL) > 0) { ad.Assign(ATTR_BLOCK_READ_KBYTES, this->BlockReadBytes.value / 1024); ad.Assign(ATTR_BLOCK_WRITE_KBYTES, this->BlockWriteBytes.value / 1024); if (flags & IF_RECENTPUB) { ad.Assign("Recent" ATTR_BLOCK_WRITE_KBYTES, this->BlockWriteBytes.recent / 1024); ad.Assign("Recent" ATTR_BLOCK_READ_KBYTES, this->BlockReadBytes.recent / 1024); } } }
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; }