void req_stat_resv(struct batch_request * preq) { char *name; struct batch_reply *preply; resc_resv *presv = NULL; int rc = 0; int type = 0; /* * first, validate the name sent in the request. * This is either the ID of a specific reservation * or a '\0' or "@..." for all reservations. */ name = preq->rq_ind.rq_status.rq_id; if ((*name == '\0') || (*name =='@')) type = 1; else { presv = find_resv(name); if (presv == NULL) { req_reject(PBSE_UNKRESVID, 0, preq); return; } } preply = &preq->rq_reply; preply->brp_choice = BATCH_REPLY_CHOICE_Status; CLEAR_HEAD(preply->brp_un.brp_status); if (type == 0) { /* get status of the specifically named reservation */ rc = status_resv(presv, preq, &preply->brp_un.brp_status); } else { /* get status of all the reservations */ presv = (resc_resv *)GET_NEXT(svr_allresvs); while (presv) { rc = status_resv(presv, preq, &preply->brp_un.brp_status); if (rc == PBSE_PERM) rc = 0; if (rc) break; presv = (resc_resv *)GET_NEXT(presv->ri_allresvs); } } if (rc == 0) (void)reply_send(preq); else req_reject(rc, bad, preq); }
resc_resv * chk_rescResv_request(char *resvID, struct batch_request *preq) { resc_resv *presv; if ((presv = find_resv(resvID)) == NULL) { log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_RESV, LOG_INFO, resvID, msg_unkresvID); req_reject(PBSE_UNKRESVID, 0, preq); return NULL; } if (svr_authorize_resvReq(preq, presv) == -1) { (void)sprintf(log_buffer, msg_permlog, preq->rq_type, "RESCRESV", presv->ri_qs.ri_resvID, preq->rq_user, preq->rq_host); log_event(PBSEVENT_SECURITY, PBS_EVENTCLASS_RESV, LOG_INFO, presv->ri_qs.ri_resvID, log_buffer); req_reject(PBSE_PERM, 0, preq); return NULL; } return (presv); }
/** * @brief Service the Modify Reservation Request from client such as pbs_ralter. * * This request atomically modifies one or more of a reservation's attributes. * An error is returned to the client if the user does not have permission * to perform the modification, the attribute is read-only, the reservation is * running and the attribute is only modifiable when the reservation is not * running or is empty. * * @param[in] preq - pointer to batch request from client */ void req_modifyReservation(struct batch_request *preq) { char *rid = NULL; svrattrl *psatl = NULL; attribute_def *pdef = NULL; int rc = 0; int bad = 0; char buf[PBS_MAXUSER + PBS_MAXHOSTNAME + 32] = {0}; int sock; int resc_access_perm_save = 0; int send_to_scheduler = 0; int log_len = 0; char *fmt = "%a %b %d %H:%M:%S %Y"; int is_standing = 0; int next_occr_start = 0; extern char *msg_stdg_resv_occr_conflict; resc_resv *presv; if (preq == NULL) return; sock = preq->rq_conn; presv = chk_rescResv_request(preq->rq_ind.rq_modify.rq_objname, preq); /* Note: on failure, chk_rescResv_request invokes req_reject * appropriate reply is sent and batch_request is freed. */ if (presv == NULL) return; rid = preq->rq_ind.rq_modify.rq_objname; if ((presv = find_resv(rid)) == NULL) { /* Not on "all_resvs" list try "new_resvs" list */ presv = (resc_resv *)GET_NEXT(svr_newresvs); while (presv) { if (!strcmp(presv->ri_qs.ri_resvID, rid)) break; presv = (resc_resv *)GET_NEXT(presv->ri_allresvs); } } if (presv == NULL) { req_reject(PBSE_UNKRESVID, 0, preq); return; } is_standing = presv->ri_wattr[RESV_ATR_resv_standing].at_val.at_long; if (is_standing) next_occr_start = get_occurrence(presv->ri_wattr[RESV_ATR_resv_rrule].at_val.at_str, presv->ri_wattr[RESV_ATR_start].at_val.at_long, presv->ri_wattr[RESV_ATR_resv_timezone].at_val.at_str, 2); resc_access_perm_save = resc_access_perm; psatl = (svrattrl *)GET_NEXT(preq->rq_ind.rq_modify.rq_attr); presv->ri_alter_flags = 0; while (psatl) { long temp = 0; char *end = NULL; int index; /* identify the attribute by name */ index = find_attr(resv_attr_def, psatl->al_name, RESV_ATR_LAST); if (index < 0) { /* didn`t recognize the name */ reply_badattr(PBSE_NOATTR, 1, psatl, preq); return; } pdef = &resv_attr_def[index]; /* Does attribute's definition flags indicate that * we have sufficient permission to write the attribute? */ resc_access_perm = resc_access_perm_save; /* reset */ if (psatl->al_flags & ATR_VFLAG_HOOK) { resc_access_perm = ATR_DFLAG_USWR | \ ATR_DFLAG_OPWR | \ ATR_DFLAG_MGWR | \ ATR_DFLAG_SvWR | \ ATR_DFLAG_Creat; } if ((pdef->at_flags & resc_access_perm) == 0) { reply_badattr(PBSE_ATTRRO, 1, psatl, preq); return; } switch (index) { case RESV_ATR_start: if ((presv->ri_wattr[RESV_ATR_state].at_val.at_long != RESV_RUNNING) || !(presv->ri_qp->qu_numjobs)) { temp = strtol(psatl->al_value, &end, 10); if ((temp > time(NULL)) && (temp != presv->ri_wattr[RESV_ATR_start].at_val.at_long)) { if (!is_standing || (temp < next_occr_start)) { send_to_scheduler = RESV_START_TIME_MODIFIED; presv->ri_alter_stime = presv->ri_wattr[RESV_ATR_start].at_val.at_long; presv->ri_alter_flags |= RESV_START_TIME_MODIFIED; } else { snprintf(log_buffer, sizeof(log_buffer), "%s", msg_stdg_resv_occr_conflict); log_event(PBSEVENT_RESV, PBS_EVENTCLASS_RESV, LOG_INFO, preq->rq_ind.rq_modify.rq_objname, log_buffer); req_reject(PBSE_STDG_RESV_OCCR_CONFLICT, 0, preq); return; } } else { req_reject(PBSE_BADTSPEC, 0, preq); return; } } else { if (presv->ri_qp->qu_numjobs) req_reject(PBSE_RESV_NOT_EMPTY, 0, preq); else req_reject(PBSE_BADTSPEC, 0, preq); return; } break; case RESV_ATR_end: temp = strtol(psatl->al_value, &end, 10); if (temp == presv->ri_wattr[RESV_ATR_end].at_val.at_long) { req_reject(PBSE_BADTSPEC, 0, preq); return; } if (!is_standing || temp < next_occr_start) { send_to_scheduler = RESV_END_TIME_MODIFIED; presv->ri_alter_etime = presv->ri_wattr[RESV_ATR_end].at_val.at_long; presv->ri_alter_flags |= RESV_END_TIME_MODIFIED; } else { snprintf(log_buffer, sizeof(log_buffer), "%s", msg_stdg_resv_occr_conflict); log_event(PBSEVENT_RESV, PBS_EVENTCLASS_RESV, LOG_INFO, preq->rq_ind.rq_modify.rq_objname, log_buffer); req_reject(PBSE_STDG_RESV_OCCR_CONFLICT, 0, preq); return; } break; default: break; } /* decode attribute */ rc = pdef->at_decode(&presv->ri_wattr[index], psatl->al_name, psatl->al_resc, psatl->al_value); if (rc != 0) { reply_badattr(rc, 1, psatl, preq); return; } psatl = (svrattrl *)GET_NEXT(psatl->al_link); } resc_access_perm = resc_access_perm_save; /* restore perm */ if (send_to_scheduler) { presv->ri_alter_state = presv->ri_wattr[RESV_ATR_state].at_val.at_long; resv_setResvState(presv, RESV_BEING_ALTERED, presv->ri_qs.ri_substate); /*"start", "end","duration", and "wall"; derive and check */ if (start_end_dur_wall(presv, RESC_RESV_OBJECT)) { req_reject(PBSE_BADTSPEC, 0, preq); resv_revert_alter_times(presv); return; } presv->ri_wattr[RESV_ATR_resource].at_flags |= ATR_VFLAG_SET | ATR_VFLAG_MODIFY | ATR_VFLAG_MODCACHE; } bad = 0; psatl = (svrattrl *)GET_NEXT(preq->rq_ind.rq_modify.rq_attr); if (psatl) rc = modify_resv_attr(presv, psatl, preq->rq_perm, &bad); if (send_to_scheduler) set_scheduler_flag(SCH_SCHEDULE_RESV_RECONFIRM, dflt_scheduler); (void)sprintf(log_buffer, "Attempting to modify reservation"); if (presv->ri_alter_flags & RESV_START_TIME_MODIFIED) { strftime(buf, sizeof(buf), fmt, localtime((time_t *) &presv->ri_wattr[RESV_ATR_start].at_val.at_long)); log_len = strlen(log_buffer); snprintf(log_buffer + log_len, sizeof(log_buffer) - log_len," start=%s", buf); } if (presv->ri_alter_flags & RESV_END_TIME_MODIFIED) { strftime(buf, sizeof(buf), fmt, localtime((time_t *) &presv->ri_wattr[RESV_ATR_end].at_val.at_long)); log_len = strlen(log_buffer); snprintf(log_buffer + log_len, sizeof(log_buffer) - log_len," end=%s", buf); } log_event(PBSEVENT_RESV, PBS_EVENTCLASS_RESV, LOG_INFO, preq->rq_ind.rq_modify.rq_objname, log_buffer); if ((presv->ri_wattr[RESV_ATR_interactive].at_flags & ATR_VFLAG_SET) == 0) { char buf1[PBS_MAXUSER + PBS_MAXHOSTNAME + 32] = {0}; /*Not "interactive" so don't wait on scheduler, reply now*/ sprintf(buf, "%s ALTER REQUESTED", presv->ri_qs.ri_resvID); sprintf(buf1, "requestor=%s@%s", preq->rq_user, preq->rq_host); if ((rc = reply_text(preq, PBSE_NONE, buf))) { /* reply failed, close connection; DON'T purge resv */ close_client(sock); return; } } else { /*Don't reply back until scheduler decides*/ long dt; presv->ri_brp = preq; dt = presv->ri_wattr[RESV_ATR_interactive].at_val.at_long; /*reply with id and state no decision in +dt secs*/ (void)gen_future_reply(presv, dt); (void)snprintf(buf, sizeof(buf), "requestor=%s@%s Interactive=%ld", preq->rq_user, preq->rq_host, dt); } }
void req_confirmresv(struct batch_request *preq) { char buf[PBS_MAXQRESVNAME+PBS_MAXHOSTNAME+256] = {0}; /* FQDN resvID+text */ time_t newstart = 0; attribute *petime = NULL; resc_resv *presv = NULL; int rc = 0; int state = 0; int sub = 0; int resv_count = 0; int is_degraded = 0; long next_retry_time = 0; char *execvnodes = NULL; char *next_execvnode = NULL; char **short_xc = NULL; char **tofree = NULL; char *str_time = NULL; extern char server_host[]; int is_being_altered = 0; char *tmp_buf = NULL; size_t tmp_buf_size = 0; if ((preq->rq_perm & (ATR_DFLAG_MGWR | ATR_DFLAG_OPWR)) == 0) { req_reject(PBSE_PERM, 0, preq); return; } presv = find_resv(preq->rq_ind.rq_run.rq_jid); if (presv == NULL) { req_reject(PBSE_UNKRESVID, 0, preq); return; } is_degraded = presv->ri_qs.ri_substate == RESV_DEGRADED ? 1 : 0; is_being_altered = presv->ri_alter_flags; if (preq->rq_extend == NULL) { req_reject(PBSE_resvFail, 0, preq); return; } /* If the reservation was degraded and it could not be reconfirmed by the * scheduler, then the retry time for that reservation is reset to the half- * time between now and the time to reservation start or, if the retry time * is invalid, set it to some time after the soonest occurrence is to start */ if (strcmp(preq->rq_extend, PBS_RESV_CONFIRM_FAIL) == 0) { if (is_degraded && !is_being_altered) { long degraded_time = presv->ri_degraded_time; DBPRT(("degraded_time of %s is %s", presv->ri_qs.ri_resvID, ctime(°raded_time))); next_retry_time = time_now + ((degraded_time - time_now)/2); /* If reservation is still degraded, and time of degraded resv to start * is over cutoff from now, then set a time to try again. */ if (next_retry_time <= (degraded_time - reserve_retry_cutoff)) { set_resv_retry(presv, next_retry_time); str_time = ctime(&(presv->ri_wattr[RESV_ATR_retry].at_val.at_long)); if (str_time != NULL) { str_time[strlen(str_time)-1] = '\0'; (void)snprintf(log_buffer, sizeof(log_buffer), "Next attempt to reconfirm reservation will be made on %s", str_time); log_event(PBSEVENT_DEBUG2, PBS_EVENTCLASS_RESV, LOG_NOTICE, presv->ri_qs.ri_resvID, log_buffer); } } else { /* reached a retry attempt that falls within the cutoff * When processing an advance reservation, unset retry attribute */ if (presv->ri_wattr[RESV_ATR_resv_standing].at_val.at_long == 0) { unset_resv_retry(presv); } else { /* When processing a standing reservation, set a retry time * past the end time of the soonest occurrence. */ set_resv_retry(presv, presv->ri_wattr[RESV_ATR_end].at_val.at_long + RESV_RETRY_DELAY); } } } else { if (!is_being_altered) log_event(PBS_EVENTCLASS_RESV, PBS_EVENTCLASS_RESV, LOG_INFO, presv->ri_qs.ri_resvID, "Reservation denied"); /* Clients waiting on an interactive request must be * notified of the failure to confirm */ if ((presv->ri_brp != NULL) && (presv->ri_wattr[RESV_ATR_interactive].at_flags & ATR_VFLAG_SET)) { presv->ri_wattr[RESV_ATR_interactive].at_flags &= ~ATR_VFLAG_SET; snprintf(buf, sizeof(buf), "%s DENIED", presv->ri_qs.ri_resvID); (void)reply_text(presv->ri_brp, PBSE_NONE, buf); presv->ri_brp = NULL; } if (!is_being_altered) { (void)snprintf(log_buffer, sizeof(log_buffer), "requestor=%s@%s", msg_daemonname, server_host); account_recordResv(PBS_ACCT_DRss, presv, log_buffer); log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_RESV, LOG_NOTICE, presv->ri_qs.ri_resvID, "reservation deleted"); resv_purge(presv); } } if (presv->ri_qs.ri_state == RESV_BEING_ALTERED) { resv_revert_alter_times(presv); log_event(PBSEVENT_RESV, PBS_EVENTCLASS_RESV, LOG_INFO, presv->ri_qs.ri_resvID, "Reservation alter denied"); } reply_ack(preq); return; } #ifdef NAS /* localmod 122 */ /* If an advance reservation has already been confirmed there's no * work to be done. */ if (presv->ri_qs.ri_state == RESV_CONFIRMED && !presv->ri_wattr[RESV_ATR_resv_standing].at_val.at_long) { reply_ack(preq); return; } #endif /* localmod 122 */ /* Do not alter a reservation that started running when the reconfirmation * message was received. If a standing reservation, then set a retry time * past the end of this occurrence. */ if (presv->ri_qs.ri_state == RESV_RUNNING) { if (presv->ri_wattr[RESV_ATR_resv_standing].at_val.at_long) set_resv_retry(presv, presv->ri_wattr[RESV_ATR_end].at_val.at_long + 10); req_reject(PBSE_TOOLATE, 0, preq); return; } petime = &presv->ri_wattr[RESV_ATR_end]; /* if passed in the confirmation, set a new start time */ if ((newstart = (time_t)preq->rq_ind.rq_run.rq_resch) != 0) { presv->ri_qs.ri_stime = newstart; presv->ri_wattr[RESV_ATR_start].at_val.at_long = newstart; presv->ri_wattr[RESV_ATR_start].at_flags |= ATR_VFLAG_SET | ATR_VFLAG_MODIFY | ATR_VFLAG_MODCACHE; presv->ri_qs.ri_etime = newstart + presv->ri_qs.ri_duration; petime->at_val.at_long = presv->ri_qs.ri_etime; petime->at_flags |= ATR_VFLAG_SET | ATR_VFLAG_MODIFY | ATR_VFLAG_MODCACHE; } /* The main difference between an advance reservation and a standing * reservation is the format of the execvnodes returned by "rq_destin": * An advance reservation has a single execvnode while a standing reservation * has a sting with the particular format: * <num_resv>#<execvnode1>[<range>]<exevnode2>[... * describing the execvnodes associated to each occurrence. */ if (presv->ri_wattr[RESV_ATR_resv_standing].at_val.at_long) { /* The number of occurrences in the standing reservation and index are parsed * from the execvnode string which is of the form: * <num_occurrences>#<vnode1>[range1]<vnode2>[range2]... */ resv_count = get_execvnodes_count(preq->rq_ind.rq_run.rq_destin); if (resv_count == 0) { req_reject(PBSE_INTERNAL, 0, preq); return; } execvnodes = strdup(preq->rq_ind.rq_run.rq_destin); if (execvnodes == NULL) { req_reject(PBSE_SYSTEM, 0, preq); return; } DBPRT(("stdg_resv conf: execvnodes_seq is %s\n", execvnodes)); /* execvnodes is of the form: * <num_resv>#<(execvnode1)>[<range>]<(exevnode2)>[... * this "condensed" string is unrolled into a pointer array of * execvnodes per occurrence, e.g. short_xc[0] are the execvnodes * for 1st occurrence, short_xc[1] for the 2nd etc... * If something goes wrong during unrolling then NULL is returned. * which causes the confirmation message to be rejected */ short_xc = unroll_execvnode_seq(execvnodes, &tofree); if (short_xc == NULL) { free(execvnodes); req_reject(PBSE_SYSTEM, 0, preq); return; } /* The execvnode of the soonest (i.e., next) occurrence */ next_execvnode = strdup(short_xc[0]); if (next_execvnode == NULL) { free(short_xc); free_execvnode_seq(tofree); free(execvnodes); req_reject(PBSE_SYSTEM, 0, preq); return; } /* Release the now obsolete allocations used to manipulate the * unrolled string */ free(short_xc); free_execvnode_seq(tofree); free(execvnodes); /* When confirming for the first time, set the index and count */ if (!is_degraded) { /* Add first occurrence's end date on timed task list */ if (presv->ri_wattr[RESV_ATR_start].at_val.at_long != PBS_RESV_FUTURE_SCH) { if (gen_task_EndResvWindow(presv)) { free(next_execvnode); req_reject(PBSE_SYSTEM, 0, preq); return; } } if (!is_being_altered) { presv->ri_wattr[RESV_ATR_resv_count].at_val.at_long = resv_count; presv->ri_wattr[RESV_ATR_resv_count].at_flags |= ATR_VFLAG_SET | ATR_VFLAG_MODIFY | ATR_VFLAG_MODCACHE; } /* Set first occurrence to index 1 * (rather than 0 because it gets displayed in pbs_rstat -f) */ presv->ri_wattr[RESV_ATR_resv_idx].at_val.at_long = 1; presv->ri_wattr[RESV_ATR_resv_idx].at_flags |= ATR_VFLAG_SET | ATR_VFLAG_MODIFY | ATR_VFLAG_MODCACHE; } /* Skip setting the execvnodes sequence when reconfirming the last * occurrence or when altering a reservation. */ if (!is_being_altered) { if (presv->ri_wattr[RESV_ATR_resv_idx].at_val.at_long < presv->ri_wattr[RESV_ATR_resv_count].at_val.at_long) { /* now assign the execvnodes sequence attribute */ (void) resv_attr_def[(int)RESV_ATR_resv_execvnodes].at_free( &presv->ri_wattr[(int)RESV_ATR_resv_execvnodes]); (void) resv_attr_def[(int)RESV_ATR_resv_execvnodes].at_decode( &presv->ri_wattr[(int)RESV_ATR_resv_execvnodes], NULL, NULL, preq->rq_ind.rq_run.rq_destin); } } } else { /* Advance reservation */ next_execvnode = strdup(preq->rq_ind.rq_run.rq_destin); if (next_execvnode == NULL) { req_reject(PBSE_SYSTEM, 0, preq); return; } } /* Is reservation still a viable reservation? */ if ((rc = chk_resvReq_viable(presv)) != 0) { free(next_execvnode); req_reject(PBSE_BADTSPEC, 0, preq); return; } /* When reconfirming a degraded reservation, first free the nodes linked * to the reservation and unset all attributes relating to retry attempts */ if (is_degraded) { free_resvNodes(presv); /* Reset retry time */ unset_resv_retry(presv); /* reset vnodes_down counter to 0 */ presv->ri_vnodes_down = 0; } if (is_being_altered & RESV_END_TIME_MODIFIED) { if (gen_task_EndResvWindow(presv)) { free(next_execvnode); req_reject(PBSE_SYSTEM, 0, preq); return; } } /* * Assign the allocated resources to the reservation * and the reservation to the associated vnodes. */ if (is_being_altered) free_resvNodes(presv); rc = assign_resv_resc(presv, next_execvnode); if (rc != PBSE_NONE) { free(next_execvnode); req_reject(rc, 0, preq); return; } /* place "Time4resv" task on "task_list_timed" only if this is a * confirmation but not the reconfirmation of a degraded reservation as * in this case, the reservation had already been confirmed and added to * the task list before */ if (!is_degraded && (is_being_altered != RESV_END_TIME_MODIFIED) && (rc = gen_task_Time4resv(presv)) != 0) { free(next_execvnode); req_reject(rc, 0, preq); return; } /* * compute new values for state and substate * and update the resc_resv object with these * newly computed values */ eval_resvState(presv, RESVSTATE_gen_task_Time4resv, 0, &state, &sub); (void)resv_setResvState(presv, state, sub); cmp_resvStateRelated_attrs((void *)presv, presv->ri_qs.ri_type); Update_Resvstate_if_resv(presv->ri_jbp); if (presv->ri_modified) (void)job_or_resv_save((void *)presv, SAVERESV_FULL, RESC_RESV_OBJECT); log_buffer[0] = '\0'; /* * Notify all interested parties that the reservation * is moving from state UNCONFIRMED to CONFIRMED */ if (presv->ri_brp) { presv = find_resv(presv->ri_qs.ri_resvID); if (presv->ri_wattr[(int)RESV_ATR_convert].at_val.at_str != NULL) { rc = cnvrt_qmove(presv); if (rc != 0) { snprintf(buf, sizeof(buf), "%.240s FAILED", presv->ri_qs.ri_resvID); } else { snprintf(buf, sizeof(buf), "%.240s CONFIRMED", presv->ri_qs.ri_resvID); } } else { snprintf(buf, sizeof(buf), "%.240s CONFIRMED", presv->ri_qs.ri_resvID); } rc = reply_text(presv->ri_brp, PBSE_NONE, buf); presv->ri_brp = NULL; } svr_mailownerResv(presv, MAIL_CONFIRM, MAIL_NORMAL, log_buffer); presv->ri_wattr[RESV_ATR_interactive].at_flags &= ~ATR_VFLAG_SET; if (is_being_altered) { /* * If the reservation is currently running and its start time is being * altered after the current time, It is going back to the confirmed state. * We need to stop the reservation queue as it would have been started at * the original start time. * This will prevent any jobs - that are submitted after the * reservation's start time is changed - from running. * The reservation went to CO from RN while being altered, that means the reservation * had resources assigned. We should decrement their usages until it starts running * again, where the resources will be accounted again. */ if (presv->ri_qs.ri_state == RESV_CONFIRMED && presv->ri_alter_state == RESV_RUNNING) { change_enableORstart(presv, Q_CHNG_START, "FALSE"); if (presv->ri_giveback) { set_resc_assigned((void *)presv, 1, DECR); presv->ri_giveback = 0; } } /* * Reset only the flags and end time backup here, as we will need * the start time backup in Time4occurrenceFinish for a standing * reservation. Reset it for an advanced reservation. */ if (!(presv->ri_wattr[RESV_ATR_resv_standing].at_val.at_long)) { presv->ri_alter_stime = 0; } presv->ri_alter_etime = 0; presv->ri_alter_flags = 0; log_event(PBSEVENT_RESV, PBS_EVENTCLASS_RESV, LOG_INFO, presv->ri_qs.ri_resvID, "Reservation alter confirmed"); } else { log_event(PBSEVENT_RESV, PBS_EVENTCLASS_RESV, LOG_INFO, presv->ri_qs.ri_resvID, "Reservation confirmed"); } if (!is_degraded) { /* 100 extra bytes for field names, times, and count */ tmp_buf_size = 100 + strlen(preq->rq_user) + strlen(preq->rq_host) + strlen(next_execvnode); if (tmp_buf_size > sizeof(buf)) { tmp_buf = malloc(tmp_buf_size); if (tmp_buf == NULL) { snprintf(log_buffer, LOG_BUF_SIZE-1, "malloc failure (errno %d)", errno); log_err(PBSE_SYSTEM, __func__, log_buffer); free(next_execvnode); reply_ack(preq); return; } } else { tmp_buf = buf; tmp_buf_size = sizeof(buf); } if (presv->ri_wattr[RESV_ATR_resv_standing].at_val.at_long) { (void)snprintf(tmp_buf, tmp_buf_size, "requestor=%s@%s start=%ld end=%ld nodes=%s count=%ld", preq->rq_user, preq->rq_host, presv->ri_qs.ri_stime, presv->ri_qs.ri_etime, next_execvnode, presv->ri_wattr[RESV_ATR_resv_count].at_val.at_long); } else { (void)snprintf(tmp_buf, tmp_buf_size, "requestor=%s@%s start=%ld end=%ld nodes=%s", preq->rq_user, preq->rq_host, presv->ri_qs.ri_stime, presv->ri_qs.ri_etime, next_execvnode); } account_recordResv(PBS_ACCT_CR, presv, tmp_buf); if (tmp_buf != buf) { free(tmp_buf); tmp_buf_size = 0; } } free(next_execvnode); reply_ack(preq); return; }