static int do_utilization_test(lListElem *cr, test_array_t *ta) { int ret = 0; double uti; int i; for (i = 0; ta[i].start_time != 0; i++) { uti = utilization_max(cr, ta[i].start_time, ta[i].duration, false); if (uti != ta[i].uti) { printf("failed: utilization(cr, "sge_U32CFormat", "sge_U32CFormat") returned %f, expected %f\n", sge_u32c(ta[i].start_time), sge_u32c(ta[i].duration), uti, ta[i].uti); ret++; } else { printf("success: utilization(cr, "sge_U32CFormat", "sge_U32CFormat") returned %f\n", sge_u32c(ta[i].start_time), sge_u32c(ta[i].duration), uti); } } return ret; }
/****** sge_select_queue/get_attribute() *************************************** * NAME * get_attribute() -- looks for an attribut, but only for one level (for host, global, or queue) * * SYNOPSIS * static lListElem* get_attribute(const char *attrname, lList *config_attr, * lList *actual_attr, lList *load_attr, lList *centry_list, lListElem * *queue, lListElem *rep, u_long32 layer, double lc_factor, dstring *reason) * * FUNCTION * Extracts the attribut specified with 'attrname' and finds the * more important one, if it is defined multiple times on the same * level. It only cares about one level. * If the attribute is a consumable, one can specify a point in time and a duration. * This will get the caller the min amount of that resource during the time frame. * * INPUTS * const char *attrname - attribute name one is looking for * lList *config_attr - user defined attributes (CE_Type) * lList *actual_attr - current usage of consumables (RUE_Type) * lList *load_attr - load attributes * lList *centry_list - the system wide attribute configuration * lListElem *queue - the current queue, or null, if one works on hosts * u_long32 layer - the current layer * double lc_factor - the load correction value * dstring *reason - space for error messages or NULL * bool zero_utilization - ??? * u_long32 start_time - begin of the time interval, one asks for the resource * u_long32 duration - the duration the interval * * RESULT * static lListElem* - the element one was looking for or NULL * *******************************************************************************/ lListElem* get_attribute(const char *attrname, lList *config_attr, lList *actual_attr, lList *load_attr, const lList *centry_list, lListElem *queue, u_long32 layer, double lc_factor, dstring *reason, bool zero_utilization, u_long32 start_time, u_long32 duration) { lListElem *actual_el=NULL; lListElem *load_el=NULL; lListElem *cplx_el=NULL; DENTER(BASIS_LAYER, "get_attribute"); /* resource_attr is a complex_entry (CE_Type) */ if (config_attr) { lListElem *temp = lGetElemStr(config_attr, CE_name, attrname); if (temp){ cplx_el = lCopyElem(lGetElemStr(centry_list, CE_name, attrname)); if(!cplx_el){ /* error */ DRETURN(NULL); } lSetUlong(cplx_el, CE_dominant, layer | DOMINANT_TYPE_FIXED); lSetUlong(cplx_el, CE_pj_dominant, DOMINANT_TYPE_VALUE); /* default, no value set */ lSetDouble(cplx_el, CE_doubleval, lGetDouble(temp,CE_doubleval) ); lSetString(cplx_el, CE_stringval, lGetString(temp,CE_stringval) ); } } if (cplx_el && lGetUlong(cplx_el, CE_consumable) != CONSUMABLE_NO) { lSetUlong(cplx_el, CE_pj_dominant, layer | DOMINANT_TYPE_CONSUMABLE); lSetUlong(cplx_el, CE_dominant, DOMINANT_TYPE_VALUE); /* treat also consumables as fixed attributes when assuming an empty queuing system */ if (sconf_get_qs_state() == QS_STATE_FULL) { if (actual_attr && (actual_el = lGetElemStr(actual_attr, RUE_name, attrname))){ dstring ds; char as_str[20]; double utilized = zero_utilization ? 0 : utilization_max(actual_el, start_time, duration, false); switch (lGetUlong(cplx_el, CE_relop)) { case CMPLXGE_OP: case CMPLXGT_OP: lSetDouble(cplx_el, CE_pj_doubleval, utilized); break; case CMPLXEQ_OP: case CMPLXLT_OP: case CMPLXLE_OP: case CMPLXNE_OP: default: lSetDouble(cplx_el, CE_pj_doubleval, lGetDouble(cplx_el, CE_doubleval) - utilized); break; } sge_dstring_init(&ds, as_str, sizeof(as_str)); sge_dstring_sprintf(&ds, "%8.3f", (float)lGetDouble(cplx_el, CE_pj_doubleval)); lSetString(cplx_el,CE_pj_stringval, as_str); } else{ sge_dstring_sprintf(reason, MSG_ATTRIB_ACTUALELEMENTTOATTRIBXMISSING_S, attrname); lFreeElem(&cplx_el); DRETURN(NULL); } } else{ lSetDouble(cplx_el, CE_pj_doubleval, lGetDouble(cplx_el, CE_doubleval)); lSetString(cplx_el,CE_pj_stringval, lGetString(cplx_el, CE_stringval)); } } /** check for a load value */ if (load_attr && (load_el = lGetElemStr(load_attr, HL_name, attrname)) && (sconf_get_qs_state()==QS_STATE_FULL || lGetBool(load_el, HL_static)) && (!is_attr_prior(cplx_el, cplx_el))) { lListElem *ep_nproc=NULL; int nproc=1; if (!cplx_el){ cplx_el = lCopyElem(lGetElemStr(centry_list, CE_name, attrname)); if (!cplx_el){ /* error */ DRETURN(NULL); } lSetUlong(cplx_el, CE_dominant, DOMINANT_TYPE_VALUE); lSetUlong(cplx_el, CE_pj_dominant, DOMINANT_TYPE_VALUE); } if ((ep_nproc = lGetElemStr(load_attr, HL_name, LOAD_ATTR_NUM_PROC))) { const char *cp = lGetString(ep_nproc, HL_value); if (cp) nproc = MAX(1, atoi(lGetString(ep_nproc, HL_value))); } { const char *load_value=NULL; u_long32 type; double dval; load_value = lGetString(load_el, HL_value); /* are we working on string values? if though, than it is easy */ if ( (type = lGetUlong(cplx_el, CE_valtype)) == TYPE_STR || type == TYPE_CSTR || type == TYPE_HOST || type == TYPE_RESTR) { lSetString(cplx_el, CE_stringval, load_value); lSetUlong(cplx_el, CE_dominant, layer | DOMINANT_TYPE_LOAD); } else { /* working on numerical values */ lListElem *job_load; char err_str[256]; char sval[100]; u_long32 dom_type = DOMINANT_TYPE_LOAD; lList *load_adjustments = sconf_get_job_load_adjustments(); job_load=lGetElemStr(load_adjustments, CE_name, attrname); if (parse_ulong_val(&dval, NULL, type, load_value, NULL, 0)) { sge_strlcpy(sval, load_value, 100); /* -------------------------------- look for 'name' in our load_adjustments list */ if (job_load) { const char *s; double load_correction; s = lGetString(job_load, CE_stringval); if (!parse_ulong_val(&load_correction, NULL, type, s, err_str, 255)) { ERROR((SGE_EVENT, MSG_SCHEDD_LOADADJUSTMENTSVALUEXNOTNUMERIC_S , attrname)); } else if (lc_factor) { double old_dval; u_long32 relop; if (!strncmp(attrname, "np_", 3) && nproc != 1 ) { DPRINTF(("fillComplexFromHost: dividing lc_factor for \"%s\" with value %f by %d to %f\n", attrname, lc_factor, nproc, lc_factor / nproc)); lc_factor /= nproc; } load_correction *= lc_factor; /* it depends on relop in complex config whether load_correction is pos/neg */ if ( (relop = lGetUlong(cplx_el, CE_relop)) == CMPLXGE_OP || relop == CMPLXGT_OP){ old_dval = dval; dval += load_correction; } else{ old_dval = dval; dval -= load_correction; } sprintf(sval, "%8.3f", dval); DPRINTF(("%s: uc: %f c(%f): %f\n", attrname, old_dval, lc_factor, dval)); dom_type = DOMINANT_TYPE_CLOAD; } } /* we can have a user, who wants to override the incomming load value. This is no problem for consumables, but for fixed values. A custom fixed value is a per slot value (stored in CE_doubleval) and a load value is a per job value (stored in CE_pj_doubleval). This code changes a fixed custom value from a per slot to a per job value!! */ if ( !(lGetUlong(cplx_el, CE_dominant) == DOMINANT_TYPE_VALUE) && (lGetUlong(cplx_el, CE_pj_dominant) == DOMINANT_TYPE_VALUE)){ lSetDouble(cplx_el, CE_pj_doubleval, lGetDouble(cplx_el, CE_doubleval)); lSetString(cplx_el, CE_pj_stringval, lGetString(cplx_el, CE_stringval)); lSetUlong(cplx_el, CE_dominant, DOMINANT_TYPE_VALUE); lSetUlong(cplx_el, CE_pj_dominant, layer | DOMINANT_TYPE_FIXED); } if (!is_attr_prior2(cplx_el, dval, CE_pj_doubleval, CE_pj_dominant)){ lSetString(cplx_el, CE_pj_stringval, load_value); lSetUlong(cplx_el, CE_pj_dominant, layer | dom_type); lSetDouble(cplx_el, CE_pj_doubleval, dval ); } } /* end numerical load value */ lFreeList(&load_adjustments); }/* end block */ } } /* we are working on queue level, so we have to check for queue resource values */ if (queue){ bool created=false; if(!cplx_el){ cplx_el = lCopyElem(lGetElemStr(centry_list, CE_name, attrname)); if(!cplx_el){ /* error */ DRETURN(NULL); } lSetUlong(cplx_el, CE_dominant, DOMINANT_TYPE_VALUE); lSetUlong(cplx_el, CE_pj_dominant, DOMINANT_TYPE_VALUE); created = true; } if (!get_queue_resource(cplx_el, queue, attrname) && created) { lFreeElem(&cplx_el); } } DRETURN(cplx_el); }