void job_report_init_from_job_with_usage(lListElem *job_report, lListElem *job, lListElem *ja_task, lListElem *pe_task, u_long32 time_stamp) { lListElem *ep; lListElem *obj; int nm; DENTER(TOP_LAYER, "job_report_init_from_job_with_usage"); /* * initialize the job jeport like any other job report... */ job_report_init_from_job(job_report, job, ja_task, pe_task); /* * ... and now add the online usage plus some fileds which are needed for the accounting */ lSetUlong(job_report, JR_wait_status, SGE_SET_WEXITSTATUS(SGE_WEXITED_BIT, 0)); lSetUlong(job_report, JR_failed, SSTATE_QMASTER_ENFORCED_LIMIT); if (pe_task == NULL) { nm = JAT_scaled_usage_list; obj = ja_task; } else { nm = PET_scaled_usage; obj = pe_task; lSetString(job_report, JR_pe_task_id_str, lGetString(pe_task, PET_id)); } ep = lAddSubStr(obj, UA_name, "submission_time", nm, UA_Type); lSetDouble(ep, UA_value, lGetUlong(job, JB_submission_time)); ep = lAddSubStr(obj, UA_name, "start_time", nm, UA_Type); lSetDouble(ep, UA_value, lGetUlong(ja_task, JAT_start_time)); ep = lAddSubStr(obj, UA_name, "end_time", nm, UA_Type); lSetDouble(ep, UA_value, time_stamp); ep = lAddSubStr(obj, UA_name, "ru_wallclock", nm, UA_Type); lSetDouble(ep, UA_value, 0.0); lSetList(job_report, JR_usage, lCopyList("", lGetList(obj, nm))); DEXIT; }
/****** sgeobj/usage/usage_list_set_double_usage() ****************************** * NAME * usage_list_set_double_usage() -- create/update a usage record * * SYNOPSIS * void * usage_list_set_double_usage(lList *usage_list, const char *name, * double value) * * FUNCTION * Updates the value of a usage record. If no usage record exists with the * given name in usage_list, a new record is created. * * INPUTS * lList *usage_list - list containing the usage record to update * const char *name - name of the usage record to update * double value - the new value * * NOTES * MT-NOTE: usage_list_set_double_usage() is MT safe * * SEE ALSO * sgeobj/usage/usage_list_set_ulong_usage() * sgeobj/usage/usage_list_get_ulong_usage() * sgeobj/usage/usage_list_get_double_usage() *******************************************************************************/ void usage_list_set_double_usage(lList *usage_list, const char *name, double value) { lListElem *ep = lGetElemStr(usage_list, UA_name, name); if (ep == NULL) { ep = lAddElemStr(&usage_list, UA_name, name, UA_Type); } lSetDouble(ep, UA_value, value); }
/****** sge_orders/sge_create_orders() ***************************************** * NAME * sge_create_orders() -- Create a new order-list or add orders to an existing one * * SYNOPSIS * lList* sge_create_orders(lList *or_list, u_long32 type, lListElem *job, * lListElem *ja_task, lList *granted, bool update_execd) * * FUNCTION * - If the or_list is NULL, a new one will be generated * * - in case of a clear_pri order, teh ja_task is improtant. If NULL is put * in for ja_task, only the pendin tasks of the spedified job are set to NULL. * If a ja_task is put in, all tasks of the job are set to NULL * * INPUTS * lList *or_list - the order list * u_long32 type - order type * lListElem *job - job * lListElem *ja_task - ja_task ref or NULL(there is only one case, where it can be NULL) * lList *granted - granted queue list * bool update_execd - should the execd get new ticket values? * * RESULT * lList* - returns the orderlist * * NOTES * MT-NOTE: sge_create_orders() is MT safe * * SEE ALSO * ???/??? *******************************************************************************/ lList *sge_create_orders(lList *or_list, u_long32 type, lListElem *job, lListElem *ja_task, lList *granted , bool update_execd) { lList *ql = NULL; lListElem *gel, *ep, *ep2; u_long32 qslots; DENTER(TOP_LAYER, "sge_create_orders"); if (!job) { lFreeList(&or_list); DEXIT; return or_list; } /* create orders list if not existent */ if (!or_list) { or_list = lCreateList("orderlist", OR_Type); } /* build sublist of granted */ if (update_execd) { for_each(gel, granted) { qslots = lGetUlong(gel, JG_slots); if (qslots) { /* ignore Qs with slots==0 */ ep2=lCreateElem(OQ_Type); lSetUlong(ep2, OQ_slots, qslots); lSetString(ep2, OQ_dest_queue, lGetString(gel, JG_qname)); lSetUlong(ep2, OQ_dest_version, lGetUlong(gel, JG_qversion)); lSetDouble(ep2, OQ_ticket, lGetDouble(gel, JG_ticket)); lSetDouble(ep2, OQ_oticket, lGetDouble(gel, JG_oticket)); lSetDouble(ep2, OQ_fticket, lGetDouble(gel, JG_fticket)); lSetDouble(ep2, OQ_sticket, lGetDouble(gel, JG_sticket)); if (!ql) ql=lCreateList("orderlist",OQ_Type); lAppendElem(ql, ep2); } } }
int main(int argc, char *argv[]) { int pos_tests_failed = 0; int neg_tests_failed = 0; int i = 0; lList *answer_list = NULL; filter_test_t positiv_test[] = { {"num_proc", 4}, {"$num_proc", 4}, {"$num_proc*2", 8}, {"$num_proc*0.5", 2.0}, {"num_proc*2", 8}, {"num_proc+1", 5}, {"$num_proc-2", 2}, {"$num_proc+0.1", 4.1}, {"1+$num_proc+0.1", 5.1}, {NULL, 0} }; filter_test_t negativ_test[] = { {"2*num_proc", 0}, {"2,0+num_proc", 0}, {"none", 0}, {NULL, 0} }; lList *centry_list; lList *host_centry_list; lListElem *centry; lListElem *host; DENTER_MAIN(TOP_LAYER, "test_sge_load_formula"); lInit(nmv); /* set up centry */ centry_list = lCreateList("", CE_Type); centry = lCreateElem(CE_Type); lSetString(centry, CE_name, "num_proc"); lSetString(centry, CE_stringval, "4"); lSetDouble(centry, CE_doubleval, 4); lAppendElem(centry_list, centry); /* set up host */ host_centry_list = lCreateList("", CE_Type); lAppendElem(host_centry_list, lCopyElem(centry)); host = lCreateElem(EH_Type); lSetList(host, EH_consumable_config_list, host_centry_list); for (i=0; ; i++){ double val; if (positiv_test[i].formula == NULL) { break; } if (!validate_load_formula(positiv_test[i].formula, &answer_list, centry_list, "load_formula")) { answer_list_output(&answer_list); pos_tests_failed++; } val = scaled_mixed_load(positiv_test[i].formula, NULL, host, centry_list); if (val != positiv_test[i].value) { printf("got %f, but expected %f(%g,%g)\n", val, positiv_test[i].value, val, positiv_test[i].value); pos_tests_failed++; } } for (i=0; ; i++){ if (negativ_test[i].formula == NULL) { break; } if (validate_load_formula(negativ_test[i].formula, &answer_list, centry_list, "load_formula") == true) { printf("load_formula \"%s\" returned no error\n", negativ_test[i].formula); neg_tests_failed++; } lFreeList(&answer_list); } lFreeList(¢ry_list); lFreeElem(&host); printf("\n"); printf("%d positiv test(s) failed\n", pos_tests_failed); printf("%d negativ test(s) failed\n", neg_tests_failed); DRETURN(pos_tests_failed + neg_tests_failed); }
bool test_lWhat_lSelect(void) { bool ret = true; lEnumeration *what = lWhat("%T(%I %I -> %T( %I %I -> %T (%I %I %I %I) %I %I) %I -> %T(%I) %I)", TEST_Type, TEST_int, TEST_list, TEST1_Type, TEST1_int, TEST1_list, TEST_Type, TEST_int, TEST_list, TEST_object, TEST_string, TEST1_object, TEST1_string, TEST_object, TEST1_Type, TEST1_string, TEST_string); lListElem *elem; lListElem *elem1; lList *list = lCreateList("", TEST_Type); lList *list1 = NULL; int i; elem = lCreateElem(TEST_Type); lSetInt(elem, TEST_int, 0); lSetHost(elem, TEST_host, "zero"); lSetString(elem, TEST_string, "zero"); lSetFloat(elem, TEST_float, 0); lSetDouble(elem, TEST_double, 0); lSetChar(elem, TEST_char, 'z'); lSetLong(elem, TEST_long, 0); lSetUlong(elem, TEST_ulong, 0); lSetBool(elem, TEST_bool, false); elem1 = lCreateElem(TEST1_Type); lSetInt(elem1, TEST1_int, 1); lSetHost(elem1, TEST1_host, "one"); lSetString(elem1, TEST1_string, "one"); lSetFloat(elem1, TEST1_float, 1); lSetDouble(elem1, TEST1_double, 1); lSetChar(elem1, TEST1_char, 'o'); lSetLong(elem1, TEST1_long, 1); lSetUlong(elem1, TEST1_ulong, 1); lSetBool(elem1, TEST1_bool, true); for (i = 0; i < 5; i++) { lList *tmp_list = lCreateList("", TEST1_Type); lListElem *tmp_elem = lCopyElem(elem); int j; for (j = 0; j < 5; j++) { lList *tmp_list1 = lCreateList("", TEST_Type); lListElem *tmp_elem1 = lCopyElem(elem); int k; for (k = 0; k < 5; k++) { lList *tmp_list2 = lCreateList("", TEST1_Type); lListElem *tmp_elem2 = lCopyElem(elem); lSetList(tmp_elem2, TEST_list, tmp_list2); lAppendElem(tmp_list1, tmp_elem2); } lSetList(tmp_elem1, TEST_list, tmp_list1); lAppendElem(tmp_list, tmp_elem1); } lSetList(tmp_elem, TEST_list, tmp_list); lAppendElem(list, tmp_elem); } list1 = lSelect("", list, NULL, what); /* EB: Replace this function */ #if 0 lWriteListTo(list1, stderr); #endif lFreeWhat(&what); lFreeElem(&elem); lFreeElem(&elem1); lFreeList(&list); lFreeList(&list1); return ret; }
/* if the scaled usage list does not yet exist, it is created and returned */ lList *scale_usage( lList *scaling, /* HS_Type */ lList *prev_usage, /* HS_Type */ lList *scaled_usage /* UA_Type */ ) { lListElem *sep, *ep, *prev; if (!scaling) { return NULL; } if (scaled_usage == NULL) { scaled_usage = lCreateList("usage", UA_Type); } for_each (ep, scaled_usage) { if ((sep=lGetElemStr(scaling, HS_name, lGetString(ep, UA_name)))) { lSetDouble(ep, UA_value, lGetDouble(ep, UA_value) * lGetDouble(sep, HS_value)); } } if ((prev = lGetElemStr(prev_usage, UA_name, USAGE_ATTR_CPU)) != NULL) { if ((ep=lGetElemStr(scaled_usage, UA_name, USAGE_ATTR_CPU))) { lAddDouble(ep, UA_value, lGetDouble(prev, UA_value)); } else { lAppendElem(scaled_usage, lCopyElem(prev)); } } if ((prev = lGetElemStr(prev_usage, UA_name, USAGE_ATTR_IO)) != NULL) { if ((ep=lGetElemStr(scaled_usage, UA_name, USAGE_ATTR_IO))) { lAddDouble(ep, UA_value, lGetDouble(prev, UA_value)); } else { lAppendElem(scaled_usage, lCopyElem(prev)); } } if ((prev = lGetElemStr(prev_usage, UA_name, USAGE_ATTR_IOW)) != NULL) { if ((ep=lGetElemStr(scaled_usage, UA_name, USAGE_ATTR_IOW))) { lAddDouble(ep, UA_value, lGetDouble(prev, UA_value)); } else { lAppendElem(scaled_usage, lCopyElem(prev)); } } if ((prev = lGetElemStr(prev_usage, UA_name, USAGE_ATTR_VMEM)) != NULL) { if ((ep=lGetElemStr(scaled_usage, UA_name, USAGE_ATTR_VMEM))) { lAddDouble(ep, UA_value, lGetDouble(prev, UA_value)); } else { lAppendElem(scaled_usage, lCopyElem(prev)); } } if ((prev = lGetElemStr(prev_usage, UA_name, USAGE_ATTR_MAXVMEM)) != NULL) { if ((ep=lGetElemStr(scaled_usage, UA_name, USAGE_ATTR_MAXVMEM))) { lAddDouble(ep, UA_value, lGetDouble(prev, UA_value)); } else { lAppendElem(scaled_usage, lCopyElem(prev)); } } if ((prev = lGetElemStr(prev_usage, UA_name, USAGE_ATTR_MEM)) != NULL) { if ((ep=lGetElemStr(scaled_usage, UA_name, USAGE_ATTR_MEM))) { lAddDouble(ep, UA_value, lGetDouble(prev, UA_value)); } else { lAppendElem(scaled_usage, lCopyElem(prev)); } } return scaled_usage; }
/*-------------------------------------------------------------------------*/ lList* qmonGet2xN( Widget w, lDescr *dp, int field1, int field2 ) { lList *lp = NULL; lListElem *ep; int row; int max_rows; char *col1, *col2; DENTER(GUI_LAYER, "qmonGet2xN"); XtVaGetValues(w, XmNrows, &max_rows, NULL); for (row=0; row<max_rows; row++) { col1 = XbaeMatrixGetCell(w, row, 0); col2 = XbaeMatrixGetCell(w, row, 1); if (col1 && col1[0] != '\0') { if (!lp) lp = lCreateList(XtName(w), dp); ep = lCreateElem(dp); lAppendElem(lp, ep); /* ** the first field in the column can be host or string */ switch(lGetType(lGetListDescr(lp), field1)) { case lStringT: lSetString(ep, field1, col1 ? col1 : ""); break; case lHostT: lSetHost(ep, field1, col1 ? col1 : ""); break; } /* ** the second field can be of different type */ switch(lGetType(lGetListDescr(lp), field2)) { case lStringT: lSetString(ep, field2, col2 ? col2 : "" ); break; case lHostT: lSetHost(ep, field2, col2 ? col2 : ""); break; case lUlongT: lSetUlong(ep, field2, col2 ? atoi(col2) : 0); break; case lDoubleT: lSetDouble(ep, field2, col2 ? atof(col2) : 0.0); break; } } else continue; } DEXIT; return lp; }
/*-------------------------------------------------------------------------*/ lList* qmonGetNxN( Widget w, lDescr *dp, int num_fields, ... ) { lList *lp = NULL; lListElem *ep; int i, row; int max_rows; va_list ap; char **col; int *field; DENTER(GUI_LAYER, "qmonGetNxN"); field = malloc(num_fields*sizeof(int)); col = malloc(num_fields*sizeof(char *)); if (field == NULL || col == NULL) abort(); va_start(ap, num_fields); for(i=0; i<num_fields; i++) field[i] = va_arg(ap, int); XtVaGetValues(w, XmNrows, &max_rows, NULL); for (row=0; row<max_rows; row++) { memset(col, 0, num_fields*sizeof(char *)); for(i=0; i<num_fields; i++) col[i] = XbaeMatrixGetCell(w, row, i); if (col[0] && col[0][0] != '\0') { if (!lp) lp = lCreateList(XtName(w), dp); ep = lCreateElem(dp); lAppendElem(lp, ep); /* * retrieve values from columns */ for(i=0; i<num_fields; i++) { switch(lGetType(lGetListDescr(lp), field[i])) { case lStringT: lSetString(ep, field[i], col[i] ? col[i] : "" ); break; case lHostT: lSetHost(ep, field[i], col[i] ? col[i] : ""); break; case lUlongT: lSetUlong(ep, field[i], col[i] ? atoi(col[i]) : 0); break; case lDoubleT: lSetDouble(ep, field[i], col[i] ? atof(col[i]) : 0.0); break; } } } else continue; } va_end(ap); free(field); free(col); DEXIT; return lp; }
/****** sge_select_queue/is_attr_prior() *************************************** * NAME * is_attr_prior() -- compares two attribut instances with each other * * SYNOPSIS * static bool is_attr_prior(lListElem *upper_el, lListElem *lower_el) * * FUNCTION * checks if the first given attribut instance has a higher priority than * second instance. * if the first is NULL, it returns false * if the second or the second and first is NULL, it returns true * if the "==" or "!=" operators are used, it is true * if both are the same, it may returns false. * otherwise it computes the minimum or maximum between the values. * * INPUTS * lListElem *upper_el - attribut, which should be overridden by the second one. * lListElem *lower_el - attribut, which want to override the first one. * * RESULT * static bool - true, when the first attribut has a higher priority. * *******************************************************************************/ bool is_attr_prior(lListElem *upper_el, lListElem *lower_el){ u_long32 relop; bool ret; double upper_value; double lower_value; u_long32 dom; u_long32 used_dom; u_long32 used_dom_val; u_long32 used_dom_str; u_long32 unused_dom_val; u_long32 unused_dom_str; u_long32 unused_dom; DENTER(BASIS_LAYER, "is_attr_prior"); /* the order is important must not be changed */ if(!upper_el){ DRETURN(false); } if(!lower_el){ DRETURN(true); } relop = lGetUlong(upper_el, CE_relop); if ((relop == CMPLXEQ_OP || relop == CMPLXNE_OP)) { DRETURN(true); } /* if both elements are the same, than I can not say which one is more important */ if(upper_el == lower_el) { DRETURN(false); } if ((dom = lGetUlong(upper_el, CE_pj_dominant)) == 0 || (dom & DOMINANT_TYPE_VALUE) ){ used_dom_val = CE_doubleval; used_dom_str = CE_stringval; used_dom = CE_dominant; unused_dom_val = CE_pj_doubleval; unused_dom_str= CE_pj_stringval; unused_dom = CE_pj_dominant; } else { used_dom_val = CE_pj_doubleval; used_dom_str = CE_pj_stringval; used_dom = CE_pj_dominant; unused_dom_val = CE_doubleval; unused_dom_str = CE_stringval; unused_dom = CE_dominant; } if ((dom = lGetUlong(lower_el, used_dom)) == 0 || (dom & DOMINANT_TYPE_VALUE) ){ lSetDouble(lower_el, used_dom_val, lGetDouble(lower_el, unused_dom_val)); lSetString(lower_el, used_dom_str, lGetString(lower_el, unused_dom_str)); lSetUlong(lower_el, used_dom, lGetUlong(lower_el, unused_dom)); lSetUlong(lower_el, unused_dom, DOMINANT_TYPE_VALUE); } upper_value = lGetDouble(upper_el, used_dom_val); lower_value = lGetDouble(lower_el, used_dom_val); if (relop == CMPLXGE_OP || relop == CMPLXGT_OP ){ ret = upper_value >= lower_value ? true : false; } else { ret = upper_value <= lower_value ? true : false; } DRETURN(ret); }
/****** sge_select_queue/get_queue_resource() *************************************** * NAME * get_queue_resource() -- extracts attribut information from the queue * * SYNOPSIS * static lListElem* get_queue_resource(lListElem *queue, lList *centry_list, const char *attrname) * * FUNCTION * All fixed queue attributes are directly coded into the queue structure. These have to extraced * and formed into a CE structure. That is, what this function does. It takes a name for an attribut * and returns a full CE structure, if the attribut is set in the queue. Otherwise it returns NULL. * * INPUTS * lListElem *queue_elem - * lListElm *queue - * const char *attrname - name of the attribute. * RESULT * bool - * * *******************************************************************************/ bool get_queue_resource(lListElem *queue_elem, const lListElem *queue, const char *attrname){ double dval=0.0; const char *value=NULL; char as_str[100]; int type, field; DENTER(BASIS_LAYER, "get_queue_resource"); if(!queue_elem){ /* error */ DRETURN(false); } if (get_rsrc(attrname, true, &field, NULL, NULL, &type)!=0) { DPRINTF(("is not a system queue attribute: %s\n", attrname)); DRETURN(false); } /* read stuff from queue and set to new elements */ switch(type) { case TYPE_INT: dval = (double)lGetUlong(queue, field); snprintf(as_str, 100, sge_u32, lGetUlong(queue, field)); break; case TYPE_TIM: case TYPE_MEM: case TYPE_DOUBLE: if ((value = lGetString(queue, field))) { parse_ulong_val(&dval, NULL, type, value, NULL, 0); } break; case TYPE_BOO: dval = (double)lGetBool(queue, field); snprintf(as_str, 100, "%d", (int)lGetBool(queue, field)); break; case TYPE_STR: case TYPE_CSTR: case TYPE_RESTR: value = lGetString(queue, field); break; case TYPE_HOST: value = lGetHost(queue, field); break; } if (!is_attr_prior2(queue_elem, dval, CE_doubleval, CE_dominant)){ lSetUlong(queue_elem,CE_dominant , DOMINANT_LAYER_QUEUE|DOMINANT_TYPE_FIXED); lSetDouble(queue_elem,CE_doubleval , dval); if(value){ lSetString(queue_elem, CE_stringval, value); } else{ lSetString(queue_elem,CE_stringval , as_str); } } DRETURN(true); }
/****** 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); }
/****** qquota_output/qquota_output() ******************************************** * NAME * qquota_output() -- qquota output function * * SYNOPSIS * bool qquota_output(void *ctx, lList *host_list, lList *resource_match_list, * lList *user_list, lList *pe_list, lList *project_list, lList * *cqueue_list, lList **alpp, report_handler_t* report_handler) * * FUNCTION * print resource quota rule and the limit * * INPUTS * void *ctx - gdi handler * lList *host_list - selected hosts * lList *resource_match_list - selected resources * lList *user_list - selected users * lList *pe_list - selecte pes * lList *project_list - selected projects * lList *cqueue_list - selected cluster queues * lList **alpp - answer list * report_handler_t* report_handler - report handler for xml output * * RESULT * bool - true on success * false on error * * NOTES * MT-NOTE: qquota_output() is MT safe * *******************************************************************************/ bool qquota_output(sge_gdi_ctx_class_t *ctx, lList *host_list, lList *resource_match_list, lList *user_list, lList *pe_list, lList *project_list, lList *cqueue_list, lList **alpp, report_handler_t* report_handler) { lList *rqs_list = NULL; lList *centry_list = NULL; lList *userset_list = NULL; lList *hgroup_list = NULL; lList *exechost_list = NULL; lListElem* global_host = NULL; lListElem* exec_host = NULL; lList* printed_rules = NULL; /* Hash list of already printed resource quota rules (possible with -u user1,user2,user3...) */ bool ret = true; int xml_ret = 0; qquota_filter_t qquota_filter = { "*", "*", "*", "*", "*" }; dstring rule_name = DSTRING_INIT; DENTER(TOP_LAYER, "qquota_output"); /* If no user is requested on command line we set the current user as default */ qquota_filter.user = ctx->get_username(ctx); ret = get_all_lists(ctx, &rqs_list, ¢ry_list, &userset_list, &hgroup_list, &exechost_list, host_list, alpp); if (ret == true) { lListElem *rqs = NULL; printed_rules = lCreateList("rule_hash", ST_Type); global_host = host_list_locate(exechost_list, SGE_GLOBAL_NAME); if (report_handler != NULL) { xml_ret = report_handler->report_started(report_handler, alpp); if (xml_ret != QQUOTA_SUCCESS) { ret = false; goto qquota_output_error; } } for_each(rqs, rqs_list) { lListElem *rule = NULL; int rule_count = 1; if (lGetBool(rqs, RQS_enabled) == false) { continue; } for_each(rule, lGetList(rqs, RQS_rule)) { lListElem *user_ep = lFirst(user_list); lListElem *project_ep = lFirst(project_list); lListElem *pe_ep = lFirst(pe_list); lListElem *queue_ep = lFirst(cqueue_list); lListElem *host_ep = lFirst(host_list); do { if (user_ep != NULL) { qquota_filter.user = lGetString(user_ep, ST_name); } do { if (project_ep != NULL) { qquota_filter.project = lGetString(project_ep, ST_name); } do { if (pe_ep != NULL) { qquota_filter.pe = lGetString(pe_ep, ST_name); } do { if (queue_ep != NULL) { qquota_filter.queue = lGetString(queue_ep, ST_name); } do { if (host_ep != NULL) { qquota_filter.host = lGetString(host_ep, ST_name); } if (rqs_is_matching_rule(rule, qquota_filter.user, NULL, qquota_filter.project, qquota_filter.pe, qquota_filter.host, qquota_filter.queue, userset_list, hgroup_list)) { lListElem *limit = NULL; for_each(limit, lGetList(rule, RQR_limit)) { const char *limit_name = lGetString(limit, RQRL_name); lList *rue_list = lGetList(limit, RQRL_usage); lListElem *raw_centry = centry_list_locate(centry_list, limit_name); lListElem *rue_elem = NULL; if (raw_centry == NULL) { /* undefined centries can be ignored */ DPRINTF(("centry %s not defined -> IGNORING\n", limit_name)); continue; } if ((resource_match_list != NULL) && ((centry_list_locate(resource_match_list, limit_name) == NULL) && (centry_list_locate(resource_match_list, lGetString(raw_centry, CE_shortcut)) == NULL))) { DPRINTF(("centry %s was not requested on CLI -> IGNORING\n", limit_name)); continue; } if (lGetString(rule, RQR_name)) { sge_dstring_sprintf(&rule_name, "%s/%s", lGetString(rqs, RQS_name), lGetString(rule, RQR_name)); } else { sge_dstring_sprintf(&rule_name, "%s/%d", lGetString(rqs, RQS_name), rule_count); } if (lGetUlong(raw_centry, CE_consumable)) { /* for consumables we need to walk through the utilization and search for matching values */ DPRINTF(("found centry %s - consumable\n", limit_name)); for_each(rue_elem, rue_list) { u_long32 dominant = 0; const char *rue_name = lGetString(rue_elem, RUE_name); char *cp = NULL; stringT user, project, pe, queue, host; dstring limit_str = DSTRING_INIT; dstring value_str = DSTRING_INIT; qquota_filter_t qf = { NULL, NULL, NULL, NULL, NULL }; /* check user name */ cp = qquota_get_next_filter(user, rue_name); /* usergroups have the same beginning character @ as host groups */ if (is_hgroup_name(qquota_filter.user)) { lListElem *ugroup = NULL; if ((ugroup = userset_list_locate(userset_list, &qquota_filter.user[1])) != NULL) { if (sge_contained_in_access_list(user, NULL, ugroup, NULL) == 0) { continue; } } } else { if ((strcmp(user, "-") != 0) && (strcmp(qquota_filter.user, "*") != 0) && (fnmatch(qquota_filter.user, user, 0) != 0)) { continue; } } /* check project */ cp = qquota_get_next_filter(project, cp); if ((strcmp(project, "-") != 0) && (strcmp(qquota_filter.project, "*") != 0) && (fnmatch(qquota_filter.project, project, 0) != 0)) { continue; } /* check parallel environment */ cp = qquota_get_next_filter(pe, cp); if ((strcmp(pe, "-") != 0) && (strcmp(qquota_filter.pe, "*") != 0) && (fnmatch(qquota_filter.pe, pe, 0) != 0) ) { continue; } /* check cluster queue */ cp = qquota_get_next_filter(queue, cp); if ((strcmp(queue, "-") != 0) && (strcmp(qquota_filter.queue, "*") != 0) && (fnmatch(qquota_filter.queue, queue, 0) != 0)) { continue; } /* check host name */ cp = qquota_get_next_filter(host, cp); if (is_hgroup_name(qquota_filter.host)) { lListElem *hgroup = NULL; if ((hgroup = hgroup_list_locate(hgroup_list, qquota_filter.host)) != NULL) { lList *host_list = NULL; hgroup_find_all_references(hgroup, NULL, hgroup_list, &host_list, NULL); if (host_list == NULL && lGetElemHost(host_list, HR_name, host) == NULL) { lFreeList(&host_list); continue; } lFreeList(&host_list); } } else { if ((strcmp(host, "-") != 0) && (strcmp(qquota_filter.host, "*") != 0) && (fnmatch(qquota_filter.host, host, 0) != 0) ) { continue; } } if (lGetBool(limit, RQRL_dynamic)) { exec_host = host_list_locate(exechost_list, host); sge_dstring_sprintf(&limit_str, "%d", (int)scaled_mixed_load(lGetString(limit, RQRL_value), global_host, exec_host, centry_list)); } else { lSetDouble(raw_centry, CE_pj_doubleval, lGetDouble(limit, RQRL_dvalue)); sge_get_dominant_stringval(raw_centry, &dominant, &limit_str); } lSetDouble(raw_centry,CE_pj_doubleval, lGetDouble(rue_elem, RUE_utilized_now)); sge_get_dominant_stringval(raw_centry, &dominant, &value_str); qf.user = user; qf.project = project; qf.pe = pe; qf.queue = queue; qf.host = host; ret = qquota_print_out_rule(rule, rule_name, limit_name, sge_dstring_get_string(&value_str), sge_dstring_get_string(&limit_str), qf, raw_centry, report_handler, printed_rules, alpp); sge_dstring_free(&limit_str); sge_dstring_free(&value_str); } } else { /* static values */ qquota_filter_t qf = { NULL, NULL, NULL, NULL, NULL }; DPRINTF(("found centry %s - static value\n", limit_name)); ret = qquota_print_out_rule(rule, rule_name, limit_name, NULL, lGetString(limit, RQRL_value), qf, raw_centry, report_handler, printed_rules, alpp); } } } } while ((host_ep = lNext(host_ep))); } while ((queue_ep = lNext(queue_ep))); } while ((pe_ep = lNext(pe_ep))); } while ((project_ep = lNext(project_ep)));