/****** sge_complex_schedd/is_attr_prior2() ************************************ * NAME * is_attr_prior2() -- checks, if the set value in the structure has a higher priority * than the new one * * SYNOPSIS * static bool is_attr_prior2(lListElem *upper_el, double lower_value, int * t_value, int t_dominant) * * FUNCTION * Computes the priority between a given structure and its values and a new value. This * is done on some basic rules. If the value is not set (dominant == DOMINANT_TYPE_VALUE) * or which relational opperator is used. If this is not enough, the two values are compared * and based on the opperator, it returns a true or false: * if no value is set in the structure: false * if the relops are == or != : true * if the relops are >= or > : true, when the new value is smaller than the old one * if the relops are <= or < : true, when the new value is bigger than the old one * * INPUTS * lListElem *upper_el - target structure * double lower_value - new value * int t_value - which field to use (CE_doubleval or CE_pj_doubleval) * int t_dominant - which dominant field to use (CE_dominant, CE_pj_dominant) * * RESULT * static bool - true, if the value in the structure has the higher priority * *******************************************************************************/ static bool is_attr_prior2(lListElem *upper_el, double lower_value, int t_value, int t_dominant ){ u_long32 relop; u_long32 dom; bool ret; double upper_value; DENTER(BASIS_LAYER, "is_attr_prior2"); if ((dom = lGetUlong(upper_el, t_dominant)) == 0 || (dom & DOMINANT_TYPE_VALUE) ){ DRETURN(false); } relop = lGetUlong(upper_el, CE_relop); if ((relop == CMPLXEQ_OP || relop == CMPLXNE_OP)) { DRETURN(true); } upper_value = lGetDouble(upper_el, t_value); if (relop == CMPLXGE_OP || relop == CMPLXGT_OP ){ ret = upper_value >= lower_value ? true : false; } else { ret = upper_value <= lower_value ? true : false; } DRETURN(ret); }
/****** sgeobj/usage/usage_list_get_ulong_usage() ***************************** * NAME * usage_list_get_ulong_usage() -- return ulong usage value * * SYNOPSIS * u_long64 * usage_list_get_ulong_usage(const lList *usage_list, const char *name, * u_long64 def) * * FUNCTION * Searches for a usage object with the given name in the given usage * list. If such an element is found, returns the value of the * usage object as u_long64 value. * If no such element is found, return the given default value. * * INPUTS * const lList *usage_list - the usage list * const char *name - name of the element to search * u_long64 def - default value * * RESULT * u_long64 - value of found object or default * * SEE ALSO * gdi/usage/usage_list_get_double_usage() *******************************************************************************/ u_long64 usage_list_get_ulong_usage(const lList *usage_list, const char *name, u_long64 def) { lListElem *ep = lGetElemStr(usage_list, UA_name, name); if (ep != NULL) { return (u_long64)lGetDouble(ep, UA_value); } else { return def; } }
/****** sgeobj/usage/usage_list_get_double_usage() **************************** * NAME * usage_list_get_double_usage() -- return double usage value * * SYNOPSIS * double * usage_list_get_double_usage(const lList *usage_list, const char *name, * double def) * * FUNCTION * Searches a usage object with the given name in the given usage * list. If such an element is found, returns the value of the * usage object as double value. * If no such element is found, return the given default value. * * INPUTS * const lList *usage_list - the usage list * const char *name - name of the element to search * double def - default value * * RESULT * double - value of found object or default * * SEE ALSO * gdi/usage/usage_list_get_ulong_usage() *******************************************************************************/ double usage_list_get_double_usage(const lList *usage_list, const char *name, double def) { lListElem *ep = lGetElemStr(usage_list, UA_name, name); if(ep != NULL) { return lGetDouble(ep, UA_value); } else { return def; } }
/****** 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); } } }
/****** sgeobj/report/job_report_print_usage() ******************************* * NAME * job_report_print_usage() -- Print usage contained in job report * * SYNOPSIS * void job_report_print_usage(const lListElem *job_report, * FILE *fp) * * FUNCTION * Print usage information conatines in "job_report". Print the * information to the given file stream "fp" or as debug messages. * * INPUTS * const lListElem *job_report - JR_Type element * FILE *fp - file stream or NULL ******************************************************************************/ void job_report_print_usage(const lListElem *job_report, FILE *fp) { lListElem *uep; DENTER(TOP_LAYER, "job_report_print_usage"); if (!job_report) { DEXIT; return; } for_each(uep, lGetList(job_report, JR_usage)) { if (fp) { fprintf(fp, " \"%s\" = %.99g\n", lGetString(uep, UA_name), lGetDouble(uep, UA_value)); } else { DPRINTF((" \"%s\" = %.99g\n", lGetString(uep, UA_name), lGetDouble(uep, UA_value))); } } DEXIT; return; }
/****** sge_usage/usage_list_sum() ********************************************* * NAME * usage_list_sum() -- sum up usage of two lists * * SYNOPSIS * void * usage_list_sum(lList *usage_list, const lList *add_usage_list) * * FUNCTION * Add the usage reported in add_usage_list to usage_list. * Summing up of usage will only be done for certain attributes: * - cpu * - io * - iow * - mem * - vmem * - maxvmem * - all ru_* attributes (see man getrusage.2) * * INPUTS * lList *usage_list - the usage list to contain all usage * const lList *add_usage_list - usage to add to usage_list * * NOTES * MT-NOTE: usage_list_sum() is MT safe *******************************************************************************/ void usage_list_sum(lList *usage_list, const lList *add_usage_list) { const lListElem *usage; for_each(usage, add_usage_list) { const char *name = lGetString(usage, UA_name); /* Sum up all usage attributes. */ if (strcmp(name, USAGE_ATTR_CPU) == 0 || strcmp(name, USAGE_ATTR_IO) == 0 || strcmp(name, USAGE_ATTR_IOW) == 0 || strcmp(name, USAGE_ATTR_VMEM) == 0 || strcmp(name, USAGE_ATTR_MEM) == 0 || strncmp(name, "acct_", 5) == 0 || strncmp(name, "ru_", 3) == 0) { lListElem *sum = lGetElemStr(usage_list, UA_name, name); if (sum == NULL) { lAppendElem(usage_list, lCopyElem(usage)); } else { lAddDouble(sum, UA_value, lGetDouble(usage, UA_value)); } } } }
/* 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; }
/*-------------------------------------------------------------------------*/ void qmonSet2xN( Widget w, lList *lp, int field1, int field2 ) { lListElem *ep; int row; int max_rows; const char *col1 = NULL, *col2 = NULL; int val; double dval; char buf[128]; DENTER(GUI_LAYER, "qmonSet2xN"); /* clear the area */ XtVaSetValues(w, XmNcells, NULL, NULL); if (!lp) { DEXIT; return; } XtVaGetValues(w, XmNrows, &max_rows, NULL); for (ep = lFirst(lp), row = 0; ep; ep = lNext(ep), row++) { if (row == max_rows) { XbaeMatrixAddRows(w, max_rows, NULL, /* empty rows */ NULL, /* no lables */ NULL, /* no different colors */ 1); /* we add 1 rows */ max_rows++; } /* ** the first column of the matrix can be string or host type ** */ switch (lGetType(lGetListDescr(lp), field1)) { case lStringT: col1 = (StringConst)lGetString(ep, field1); break; case lHostT: col1 = (StringConst)lGetHost(ep,field1); break; } /* ** the second column can be of different type */ switch (lGetType(lGetListDescr(lp), field2)) { case lStringT: col2 = (StringConst)lGetString(ep, field2); break; case lHostT: col2 = (StringConst)lGetHost(ep,field2); break; case lUlongT: val = (int)lGetUlong(ep, field2); if (val) { sprintf(buf, "%d", val); col2 = buf; } else col2 = NULL; break; case lDoubleT: dval = lGetDouble(ep, field2); sprintf(buf, "%.2f", dval); col2 = buf; break; } if (col1) { /* FIX_CONST_GUI */ XbaeMatrixSetCell(w, row, 0 , col1 ? (String)col1 : ""); /* FIX_CONST_GUI */ XbaeMatrixSetCell(w, row, 1 , col2 ? (String)col2 : ""); } } DEXIT; }
/*-------------------------------------------------------------------------*/ void qmonSetNxN(Widget w, lList *lp, int num_fields, ...) { lListElem *ep; int i, row; int max_rows; int val; double dval; char buf[128]; int *field; const char **col; va_list ap; DENTER(GUI_LAYER, "qmonSetNxN"); /* clear the area */ XtVaSetValues(w, XmNcells, NULL, NULL); if (!lp) { DEXIT; return; } 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 (ep = lFirst(lp), row = 0; ep; ep = lNext(ep), row++) { if (row == max_rows) { XbaeMatrixAddRows(w, max_rows, NULL, /* empty rows */ NULL, /* no lables */ NULL, /* no different colors */ 1); /* we add 1 rows */ max_rows++; } memset(col, 0, num_fields*sizeof(char *)); /* * get column values */ for(i=0; i<num_fields; i++) { switch (lGetType(lGetListDescr(lp), field[i])) { case lStringT: col[i] = (StringConst)lGetString(ep, field[i]); break; case lHostT: col[i] = (StringConst)lGetHost(ep,field[i]); break; case lUlongT: val = (int)lGetUlong(ep, field[i]); #if 0 if (val) { sprintf(buf, "%d", val); col[i] = buf; } else col[i] = NULL; #else sprintf(buf, "%d", val); col[i] = buf; #endif break; case lDoubleT: dval = lGetDouble(ep, field[i]); sprintf(buf, "%.2f", dval); col[i] = buf; break; } } if (col[0]) { /* FIX_CONST_GUI */ for(i=0; i<num_fields; i++) XbaeMatrixSetCell(w, row, i, col[i] ? (String)col[i] : ""); } } va_end(ap); free(field); free(col); DEXIT; }
/****** 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_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)));