/** * @brief * vn_encode_DIS_V4 - encode version 4 vnode information, used by Mom. * * @par Functionality: * Used to encode vnode information. See vn_encode_DIS() above for a * description of the information. Supports version 4 only. * * @param[in] fd - socket descriptor to which to write the encode info. * @param[in] vnlp - structure to encode and send. * * @return int * @retval DIS_SUCCESS (0) on success * @retval DIS_* on error. * * @par Side Effects: None * * @par MT-safe: No, the structure pointed to by vnlp needs to be locked * */ static int vn_encode_DIS_V4(int fd, vnl_t *vnlp) { int rc; unsigned int i, j; if (((rc = diswui(fd, PS_DIS_V4)) != 0) || ((rc = diswsl(fd, (long) vnlp->vnl_modtime)) != 0) || ((rc = diswui(fd, vnlp->vnl_used)) != 0)) return (rc); for (i = 0; i < vnlp->vnl_used; i++) { vnal_t *curreslist = VNL_NODENUM(vnlp, i); if ((rc = diswst(fd, curreslist->vnal_id)) != 0) return (rc); if ((rc = diswui(fd, curreslist->vnal_used)) != 0) return (rc); for (j = 0; j < curreslist->vnal_used; j++) { vna_t *curres = VNAL_NODENUM(curreslist, j); if ((rc = diswst(fd, curres->vna_name)) != 0) return (rc); if ((rc = diswst(fd, curres->vna_val)) != 0) return (rc); if ((rc = diswsi(fd, curres->vna_type)) != 0) return (rc); if ((rc = diswsi(fd, curres->vna_flag)) != 0) return (rc); } } return (DIS_SUCCESS); }
/** * @brief * free_and_return - free a vnl_t data structure. * * @par Functionality: * Note that this function is nearly identical to vnl_free() (q.v.), * with the exception of using the *_cur values to free partially- * * @param[in] vnlp - pointer to structure to free * * @return vnl_t * * @retval NULL * * @par Side Effects: None * * @par MT-safe: No, vnlp needs to be locked. * */ static vnl_t * free_and_return(vnl_t *vnlp) { unsigned int i, j; /* N.B. <=, not < because we may have a partially-allocated ith one */ for (i = 0; i <= vnlp->vnl_cur; i++) { vnal_t *vnrlp = VNL_NODENUM(vnlp, i); /* N.B. <=, not < (as above) for partially-allocated jth one */ for (j = 0; j <= vnrlp->vnal_cur; j++) { vna_t *vnrp = VNAL_NODENUM(vnrlp, j); free(vnrp->vna_name); free(vnrp->vna_val); } free(vnrlp->vnal_list); free(vnrlp->vnal_id); } free(vnlp->vnl_list); free(vnlp); return ((vnl_t *) NULL); }
/** * @brief * Find the vnode with ID vnid and adjust (decrement, increment, or set) * the value of resource res by the amount adjval * * @param[in] vp - pointer to vnl_t structure * @param[in] vnid - vnode id * @param[in] res - resource name * @param[in] op - enum for resource option * * @return Void * */ static void resadj(vnl_t *vp, const char *vnid, const char *res, enum res_op op, unsigned int adjval) { int i, j; sprintf(log_buffer, "vnode %s, resource %s, res_op %u, adjval %u", vnid, res, (int) op, adjval); log_event(PBSEVENT_DEBUG3, 0, LOG_DEBUG, __func__, log_buffer); for (i = 0; i < vp->vnl_used; i++) { vnal_t *vnalp; vnalp = VNL_NODENUM(vp, i); if (strcmp(vnalp->vnal_id, vnid) != 0) continue; for (j = 0; j < vnalp->vnal_used; j++) { vna_t *vnap; unsigned int resval; char valbuf[BUFSIZ]; vnap = VNAL_NODENUM(vnalp, j); if (strcmp(vnap->vna_name, res) == 0) { resval = strtoul(vnap->vna_val, NULL, 0); switch ((int) op) { case RES_DECR: resval -= adjval; break; case RES_INCR: resval += adjval; break; case RES_SET: resval = adjval; break; default: sprintf(log_buffer, "unknown res_op %u", (int) op); log_event(PBSEVENT_ERROR, 0, LOG_ERR, __func__, log_buffer); return; } /* * Deal with two things that should never * happen: first, the result of adjusting * the resource value should never be * negative. Second, BUFSIZ should always * be sufficient to hold any unsigned * quantity PBS deals with. */ if (((int) resval) < 0) { log_event(PBSEVENT_ERROR, 0, LOG_ERR, __func__, "res underflow"); return; } if (snprintf(valbuf, sizeof(valbuf), "%u", resval) >= sizeof(valbuf)) { log_event(PBSEVENT_ERROR, 0, LOG_ERR, __func__, "res overflow"); return; } /* * We now replace the current value with * the adjusted one. This may involve * surgery on the vna_t. */ if (op == RES_DECR) { /* * Since the resource value is now * smaller than before, it ought to * fit in the space that holds the * current value. */ strcpy(vnap->vna_val, valbuf); } else { char *vna_newval = strdup(valbuf); if (vna_newval != NULL) { free(vnap->vna_val); vnap->vna_val = vna_newval; } else { log_event(PBSEVENT_ERROR, 0, LOG_ERR, __func__, "vna_newval strdup failed"); } } return; } } } sprintf(log_buffer, "vnode %s, resource %s not found", vnid, res); log_event(PBSEVENT_DEBUG, 0, LOG_DEBUG, __func__, log_buffer); }
/** * @brief * Log debugging information containing a description of the vnode list * in 'vnl'. * (a rather complicated structure described in "placementsets.h"). * * @param[in] vnl - vnode list we're interested in * @param[in] header - heading of the log message * * @return void * */ void mom_vnlp_report(vnl_t *vnl, char *header) { int i, j, k; char reportbuf[LOG_BUF_SIZE+1]; char *p = NULL; vnl_t *vp; char attrprefix[] = ", attrs[]: "; int bytes_left; if (vnl == NULL) return; vp = vnl; for (i = 0; i < vp->vnl_used; i++) { vnal_t *vnalp; vnalp = VNL_NODENUM(vp, i); bytes_left = LOG_BUF_SIZE; p = reportbuf; k = snprintf(p, bytes_left, "vnode %s: nelem %lu", vnalp->vnal_id, vnalp->vnal_used); if (k < 0) break; bytes_left -= k; if (bytes_left <= 0) break; p += k; if (vnalp->vnal_used > 0) { k = snprintf(p, bytes_left, attrprefix); if (k < 0) break; bytes_left -= k; if (bytes_left <= 0) break; p += k; } for (j = 0; j < vnalp->vnal_used; j++) { vna_t *vnap; vnap = VNAL_NODENUM(vnalp, j); if (j > 0) { snprintf(p, bytes_left, ", "); bytes_left -= 2; if (bytes_left <= 0) break; p += 2; } k = snprintf(p, bytes_left, "\"%s\" = \"%s\"", vnap->vna_name, vnap->vna_val); if (k < 0) break; bytes_left -= k; if (bytes_left <= 0) break; p += k; } log_event(PBSEVENT_DEBUG3, 0, LOG_DEBUG, header?header:__func__, reportbuf); p = NULL; } if (p != NULL) { /* log any remaining item */ log_event(PBSEVENT_DEBUG3, 0, LOG_DEBUG, header?header:__func__, reportbuf); } }
/** * @brief * vn_decode_DIS_V3 - decode version 3 vnode information from Mom * * @par Functionality: * See vn_decode_DIS() above, This is called from there to decode * V3 information. * * @param[in] fd - socket descriptor from which to read * @param[out] rcp - pointer to place to return error code if error. * * @return vnl_t * * @retval pointer to decoded vnode information which has been malloc-ed. * @retval NULL on error, see rcp value * * @par Side Effects: None * * @par MT-safe: yes * */ static vnl_t * vn_decode_DIS_V3(int fd, int *rcp) { unsigned int i, j; unsigned int size; time_t t; vnl_t *vnlp; if ((vnlp = malloc(sizeof(vnl_t))) == NULL) { *rcp = DIS_NOMALLOC; return ((vnl_t *) NULL); } t = (time_t) disrsl(fd, rcp); if (*rcp != DIS_SUCCESS) return ((vnl_t *) NULL); else vnlp->vnl_modtime = t; size = disrui(fd, rcp); if (*rcp != DIS_SUCCESS) return ((vnl_t *) NULL); else vnlp->vnl_nelem = vnlp->vnl_used = size; if ((vnlp->vnl_list = calloc(vnlp->vnl_nelem, sizeof(vnal_t))) == NULL) { free(vnlp); *rcp = DIS_NOMALLOC; return ((vnl_t *) NULL); } for (i = 0; i < vnlp->vnl_used; i++) { vnal_t *curreslist = VNL_NODENUM(vnlp, i); /* * In case an error occurs and we need to free * whatever's been allocated so far, we use the * vnal_cur entry to record the number of vnal_t * entries to free. */ vnlp->vnl_cur = i; curreslist->vnal_id = disrst(fd, rcp); if (*rcp != DIS_SUCCESS) return (free_and_return(vnlp)); size = disrui(fd, rcp); if (*rcp != DIS_SUCCESS) return (free_and_return(vnlp)); else curreslist->vnal_nelem = curreslist->vnal_used = size; if ((curreslist->vnal_list = calloc(curreslist->vnal_nelem, sizeof(vna_t))) == NULL) return (free_and_return(vnlp)); for (j = 0; j < size; j++) { vna_t *curres = VNAL_NODENUM(curreslist, j); /* * In case an error occurs and we need to free * whatever's been allocated so far, we use the * vnal_cur entry to record the number of vna_t * entries to free. */ curreslist->vnal_cur = j; curres->vna_name = disrst(fd, rcp); if (*rcp != DIS_SUCCESS) return (free_and_return(vnlp)); curres->vna_val = disrst(fd, rcp); if (*rcp != DIS_SUCCESS) return (free_and_return(vnlp)); } } *rcp = DIS_SUCCESS; return (vnlp); }