/* A wrapper for client side memory allocation to handle it all the same way * return indicates success, failure will exit the run */ void calloc_or_fail( memmgr **mm, /* memory manager */ char **dest, int alloc_size, const char *err_msg) { *dest = (char *)memmgr_calloc(mm, 1, alloc_size); if (*dest == NULL) { fprintf(stderr, "Allocation of %d bytes failed %s", alloc_size, err_msg); exit(1); } } /* END calloc_or_fail() */
int add_verify_resources( memmgr **mm, /* M */ job_data **res_attr, /* M */ char *resources, /* I */ int p_type) /* I */ { char *r; char *eq; char *v; char *e = NULL; char *str; char *name; char *value = NULL; int gpugres; int len; int vlen; char *qptr = NULL; int braces = 0; r = resources; while (*r != '\0') { /* skip leading whitespace */ while (isspace((int)*r)) r++; /* get resource name */ eq = r; while ((*eq != '=') && (*eq != ',') && (*eq != '\0')) eq++; /* make sure there is a resource name */ if (r == eq) { /* FAILURE */ return(1); } /* * Count the number of non-space characters that make up the * resource name. Count only up to the last character before the * separator ('\0', ',' or '='). */ for (str = r, len = 0;(str < eq) && !isspace((int)*str);str++) len++; /* if separated by an equal sign, get the value */ if (*eq == '=') { char *ptr; v = eq + 1; while (isspace((int)*v)) v++; /* FORMAT: <ATTR>=[{'"}]<VAL>,<VAL>[{'"}][,<ATTR>=...]... */ ptr = strchr(v, ','); if (((qptr = strchr(v, '\'')) != NULL) && ((ptr == NULL) || ((ptr != NULL) && (qptr < ptr)))) { /* skip quote if before ',' or at the end of the string */ v = qptr + 1; } else if (((qptr = strchr(v, '\"')) != NULL) && ((ptr == NULL) || ((ptr != NULL) && (qptr < ptr)))) { /* skip quote if before ',' or at the end of the string */ v = qptr + 1; } else { qptr = NULL; } e = v; while (*e != '\0') { /* FORMAT: <ATTR>=[{'"}]<VAL>,<VAL>[{'"}][,<ATTR>=...]... */ /* NOTE already tokenized by getopt() which will support quoted whitespace, do not fail on spaces */ if (*e=='[' && qptr == NULL) { braces = 1; } if (braces && (*e == ']')) { braces=0; } if (qptr != NULL) { /* value contains quote - only terminate with quote */ if ((*e == '\'') || (*e == '\"')) break; } else { if (*e == ',' && braces==0) break; } #ifdef TNOT if (isspace((int)*e)) { /* FAILURE */ return(1); } #endif /* TNOT */ e++; } /* END while (*e != '\0') */ } /* END if (*eq == '=') */ else { /* no attr=value pair found */ fprintf(stderr, "Cannot find an attr=value pair in comma separated value '%s'\n", r); exit(1); } /* This code in combination with the backend server code ends up with * the logic of last added element remains. All others are dropped off. * Instead of posponing all of this logic, it will now occur here. */ gpugres = !strncmp(r,"gpus",strlen("gpus")); if (gpugres) { len = 5; /* + 6 = 1 for null terminator and 5 for 'gpus:' */ vlen = (e - v) + 6; name = (char *)memmgr_calloc(mm, 1, len); if (v) value = (char *)memmgr_calloc(mm, 1, vlen); } else { len++; vlen = (e - v) + 1; name = (char *)memmgr_calloc(mm, 1, len); if (v) value = (char *)memmgr_calloc(mm, 1, vlen); } if ((name) && ((v) && (value))) { if (gpugres) snprintf(name, len, "gres"); else snprintf(name, len, "%s", r); if (v) { if (gpugres) { char *gpu_eq = strchr(r, '='); if(gpu_eq == NULL) { fprintf(stderr,"Error with resource strings.\n"); exit(1); } *gpu_eq = ':'; snprintf(value, vlen, "%s", r); *gpu_eq = '='; } else snprintf(value, vlen, "%s", v); hash_add_or_exit(mm, res_attr, name, value, p_type); } else hash_add_or_exit(mm, res_attr, name, (char *)"\0", p_type); } else { fprintf(stderr, "Error allocating memory for add_verify_resources\n"); exit(1); } /* Get ready for next resource/value pair */ if (qptr != NULL) { /* skip quotes looking for ',' */ while ((*e == '\'') || (*e == '\"')) e++; } if (v != NULL) r = e; else r = eq; if (*r == ',') { r++; if (*r == '\0') { return(1); } } } /* END while (*r != '\0') */ /* SUCCESS */ return(0); } /* END add_verify_resources() */