ClassAd *CollectorEngine:: collect (int command, Sock *sock, const condor_sockaddr& from, int &insert) { ClassAd *clientAd; ClassAd *rval; _condor_auto_accum_runtime<collector_runtime_probe> rt(CollectorEngine_ruc_runtime); double rt_last = rt.begin; // Avoid lengthy blocking on communication with our peer. // This command-handler should not get called until data // is ready to read. sock->timeout(1); // get the ad clientAd = new ClassAd; if (!clientAd) return 0; if( !getClassAdEx(sock, *clientAd, m_get_ad_options) ) { dprintf (D_ALWAYS,"Command %d on Sock not followed by ClassAd (or timeout occured)\n", command); delete clientAd; sock->end_of_message(); return 0; } double delta_time = rt.tick(rt_last); CollectorEngine_ruc_getAd_runtime.Add(delta_time); // insert the authenticated user into the ad itself const char* authn_user = sock->getFullyQualifiedUser(); if (authn_user) { clientAd->Assign("AuthenticatedIdentity", authn_user); clientAd->Assign("AuthenticationMethod", sock->getAuthenticationMethodUsed()); } else { // remove it from the ad if it's not authenticated. clientAd->Delete("AuthenticatedIdentity"); clientAd->Delete("AuthenticationMethod"); } CollectorEngine_ruc_authid_runtime.Add(rt.tick(rt_last)); rval = collect(command, clientAd, from, insert, sock); CollectorEngine_ruc_collect_runtime.Add(rt.tick(rt_last)); // Don't leak the ad on error! if ( ! rval ) { delete clientAd; } // get the end_of_message() if (!sock->end_of_message()) { dprintf(D_FULLDEBUG,"Warning: Command %d; maybe shedding data on eom\n", command); } return rval; }
void ScheddStatistics::Unpublish(ClassAd & ad) const { ad.Delete("StatsLifetime"); ad.Delete("StatsLastUpdateTime"); ad.Delete("RecentStatsLifetime"); ad.Delete("RecentStatsTickTime"); ad.Delete("RecentWindowMax"); Pool.Unpublish(ad); }
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 stats_entry_sum_ema_rate<T>::Unpublish(ClassAd & ad, const char * pattr) const { ad.Delete(pattr); for(size_t i=ema.size(); i--;) { stats_ema_config::horizon_config &config = ema_config->horizons[i]; std::string attr_name; size_t pattr_len; if( (pattr_len=strlen(pattr)) >= 7 && strcmp(pattr+pattr_len-7,"Seconds")==0 ) { formatstr(attr_name,"%.*sLoad_%s",(int)(pattr_len-7),pattr,config.horizon_name.c_str()); } else { formatstr(attr_name,"%sPerSecond_%s",pattr,config.horizon_name.c_str()); } ad.Delete(attr_name.c_str()); } }
int LogDeleteAttribute::Play(void *data_structure) { ClassAdHashTable *table = (ClassAdHashTable *)data_structure; ClassAd *ad = 0; if (table->lookup(HashKey(key), ad) < 0) return -1; #if defined(HAVE_DLOPEN) ClassAdLogPluginManager::DeleteAttribute(key, name); #endif return ad->Delete(name); }
ClassAd *CollectorEngine:: collect (int command, Sock *sock, const condor_sockaddr& from, int &insert) { ClassAd *clientAd; ClassAd *rval; // Avoid lengthy blocking on communication with our peer. // This command-handler should not get called until data // is ready to read. sock->timeout(1); clientAd = new ClassAd; if (!clientAd) return 0; // get the ad if( !clientAd->initFromStream(*sock) ) { dprintf (D_ALWAYS,"Command %d on Sock not follwed by ClassAd (or timeout occured)\n", command); delete clientAd; sock->end_of_message(); return 0; } // insert the authenticated user into the ad itself const char* authn_user = sock->getFullyQualifiedUser(); if (authn_user) { clientAd->Assign("AuthenticatedIdentity", authn_user); } else { // remove it from the ad if it's not authenticated. clientAd->Delete("AuthenticatedIdentity"); } rval = collect(command, clientAd, from, insert, sock); // Don't leak the ad on error! if ( ! rval ) { delete clientAd; } // get the end_of_message() if (!sock->end_of_message()) { dprintf(D_FULLDEBUG,"Warning: Command %d; maybe shedding data on eom\n", command); } return rval; }
void DaemonCore::Stats::Unpublish(ClassAd & ad) const { ad.Delete("DCStatsLifetime"); ad.Delete("DCStatsLastUpdateTime"); ad.Delete("DCRecentStatsLifetime"); ad.Delete("DCRecentStatsTickTime"); ad.Delete("DCRecentWindowMax"); ad.Delete("DaemonCoreDutyCycle"); ad.Delete("RecentDaemonCoreDutyCycle"); Pool.Unpublish(ad); }
void StatisticsPool::Unpublish(ClassAd & ad) const { pubitem item; MyString name; // boo! HashTable doesn't support const, so I have to remove const from this // to make the compiler happy. StatisticsPool * pthis = const_cast<StatisticsPool*>(this); pthis->pub.startIterations(); while (pthis->pub.iterate(name,item)) { const char * pattr = item.pattr ? item.pattr : name.Value(); if (item.Unpublish) { stats_entry_base * probe = (stats_entry_base *)item.pitem; (probe->*(item.Unpublish))(ad, pattr); } else ad.Delete(pattr); } }
/*! 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; }
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)); } }
template <> void stats_entry_recent<Probe>::Unpublish(ClassAd& ad, const char * pattr) const { MyString attr; ad.Delete(pattr); attr.sprintf("Recent%s", pattr); ad.Delete(attr.Value()); attr.sprintf("Recent%sCount", pattr); ad.Delete(attr.Value()); ad.Delete(attr.Value()+6); attr.sprintf("Recent%sSum", pattr); ad.Delete(attr.Value()); ad.Delete(attr.Value()+6); attr.sprintf("Recent%sAvg", pattr); ad.Delete(attr.Value()); ad.Delete(attr.Value()+6); attr.sprintf("Recent%sMin", pattr); ad.Delete(attr.Value()); ad.Delete(attr.Value()+6); attr.sprintf("Recent%sMax", pattr); ad.Delete(attr.Value()); ad.Delete(attr.Value()+6); attr.sprintf("Recent%sStd", pattr); ad.Delete(attr.Value()); ad.Delete(attr.Value()+6); }
int CondorQ::fetchQueueFromHostAndProcessV2(const char *host, const char *constraint, StringList &attrs, int fetch_opts, int match_limit, condor_q_process_func process_func, void * process_func_data, int connect_timeout, int useFastPath, CondorError *errstack, ClassAd ** psummary_ad) { classad::ClassAdParser parser; classad::ExprTree *expr = NULL; parser.ParseExpression(constraint, expr); if (!expr) return Q_INVALID_REQUIREMENTS; classad::ClassAd request_ad; // query ad to send to schedd ClassAd *ad = NULL; // job ad result request_ad.Insert(ATTR_REQUIREMENTS, expr); char *projection = attrs.print_to_delimed_string("\n"); if (projection) { request_ad.InsertAttr(ATTR_PROJECTION, projection); free(projection); } bool want_authentication = false; if (fetch_opts == fetch_DefaultAutoCluster) { request_ad.InsertAttr("QueryDefaultAutocluster", true); request_ad.InsertAttr("MaxReturnedJobIds", 2); // TODO: make this settable by caller of this function. } else if (fetch_opts == fetch_GroupBy) { request_ad.InsertAttr("ProjectionIsGroupBy", true); request_ad.InsertAttr("MaxReturnedJobIds", 2); // TODO: make this settable by caller of this function. } else { if (fetch_opts & fetch_MyJobs) { const char * owner = my_username(); if (owner) { request_ad.InsertAttr("Me", owner); } request_ad.InsertAttr("MyJobs", owner ? "(Owner == Me)" : "true"); want_authentication = true; } if (fetch_opts & fetch_SummaryOnly) { request_ad.InsertAttr("SummaryOnly", true); } if (fetch_opts & fetch_IncludeClusterAd) { request_ad.InsertAttr("IncludeClusterAd", true); } } if (match_limit >= 0) { request_ad.InsertAttr(ATTR_LIMIT_RESULTS, match_limit); } // determine if authentication can/will happen. three reasons why it might not: // 1) security negotiation is disabled (NEVER or OPTIONAL for outgoing connections) // 2) Authentication is disabled (NEVER) by the client // 3) Authentication is disabled (NEVER) by the server. this is actually impossible to // get correct without actually querying the server but we make an educated guess by // paraming the READ auth level. bool can_auth = true; char *paramer = NULL; paramer = SecMan::getSecSetting ("SEC_%s_NEGOTIATION", CLIENT_PERM); if (paramer != NULL) { char p = toupper(paramer[0]); free(paramer); if (p == 'N' || p == 'O') { // authentication will not happen since no security negotiation will occur can_auth = false; } } paramer = SecMan::getSecSetting ("SEC_%s_AUTHENTICATION", CLIENT_PERM); if (paramer != NULL) { char p = toupper(paramer[0]); free(paramer); if (p == 'N') { // authentication will not happen since client doesn't allow it. can_auth = false; } } // authentication will not happen since server probably doesn't allow it. // on the off chance that someone's config manages to trick us, leave an // undocumented knob as a last resort to disable our inference. if (param_boolean("CONDOR_Q_INFER_SCHEDD_AUTHENTICATION", true)) { paramer = SecMan::getSecSetting ("SEC_%s_AUTHENTICATION", READ); if (paramer != NULL) { char p = toupper(paramer[0]); free(paramer); if (p == 'N') { can_auth = false; } } paramer = SecMan::getSecSetting ("SCHEDD.SEC_%s_AUTHENTICATION", READ); if (paramer != NULL) { char p = toupper(paramer[0]); free(paramer); if (p == 'N') { can_auth = false; } } } if (!can_auth) { dprintf (D_ALWAYS, "detected that authentication will not happen. falling back to QUERY_JOB_ADS without authentication.\n"); } DCSchedd schedd(host); int cmd = QUERY_JOB_ADS; if (want_authentication && can_auth && (useFastPath > 2)) { cmd = QUERY_JOB_ADS_WITH_AUTH; } Sock* sock; if (!(sock = schedd.startCommand(cmd, Stream::reli_sock, connect_timeout, errstack))) return Q_SCHEDD_COMMUNICATION_ERROR; classad_shared_ptr<Sock> sock_sentry(sock); if (!putClassAd(sock, request_ad) || !sock->end_of_message()) return Q_SCHEDD_COMMUNICATION_ERROR; dprintf(D_FULLDEBUG, "Sent classad to schedd\n"); int rval = 0; do { ad = new ClassAd(); if ( ! getClassAd(sock, *ad) || ! sock->end_of_message()) { rval = Q_SCHEDD_COMMUNICATION_ERROR; break; } dprintf(D_FULLDEBUG, "Got classad from schedd.\n"); long long intVal; if (ad->EvaluateAttrInt(ATTR_OWNER, intVal) && (intVal == 0)) { // Last ad. sock->close(); dprintf(D_FULLDEBUG, "Ad was last one from schedd.\n"); std::string errorMsg; if (ad->EvaluateAttrInt(ATTR_ERROR_CODE, intVal) && intVal && ad->EvaluateAttrString(ATTR_ERROR_STRING, errorMsg)) { if (errstack) errstack->push("TOOL", intVal, errorMsg.c_str()); rval = Q_REMOTE_ERROR; } if (psummary_ad && rval == 0) { std::string val; if (ad->LookupString(ATTR_MY_TYPE, val) && val == "Summary") { ad->Delete(ATTR_OWNER); // remove the bogus owner attribute *psummary_ad = ad; // return the final ad, because it has summary information ad = NULL; // so we don't delete it below. } } break; } // Note: According to condor_q.h, process_func() will return false if taking // ownership of ad, so only delete if it returns true, else set to NULL // so we don't delete it here. Either way, next set ad to NULL since either // it has been deleted or will be deleted later by process_func(). if (process_func(process_func_data, ad)) { delete ad; } ad = NULL; } while (true); // Make sure ad is not leaked no matter how we break out of the above loop. delete ad; return rval; }