/** * @brief * Displays the occurrences in a two-column format: * the first column corresponds to the occurrence date and time * the second column corresponds to the reserved execvnode * * @par NOTE: This is currently only used by pbs_rstat and only * for testing purpose, it is not used in production environment. * * @param[in] rrule - The recurrence rule considered * @param[in] dtstart - The date start of the recurrence * @param[in] seq_execvnodes - The condensed form of execvnodes/occurrence * @param[in] tz - The timezone associated to the recurrence rule * @param[in] ridx - The index of the occurrence from which to start displaying information * @param[in] count - The total number of occurrences considered * */ void display_occurrences(char *rrule, time_t dtstart, char *seq_execvnodes, char *tz, int ridx, int count) { #ifdef LIBICAL char **short_xc; char **tofree; char *tt_str; time_t next = 0; int i = 1; if (tz == NULL || rrule == NULL) return; if (get_num_occurrences(rrule, dtstart, tz) == 0) return; short_xc = (char **) unroll_execvnode_seq(seq_execvnodes, &tofree); printf("Occurrence Dates\t Occurrence Execvnode:\n"); for (; ridx <= count && next != -1; ridx++) { next = get_occurrence(rrule, dtstart, tz, i); i++; tt_str = ctime(&next); /* ctime adds a carriage return at the end, strip it */ tt_str[strlen(tt_str)-1] = '\0'; printf("%2s %2s\n", tt_str, short_xc[ridx-1]); } free_execvnode_seq(tofree); free(short_xc); #endif }
/** * @brief * display the number of occurences and occurences. * * @param[in] rrule - The recurrence rule considered * @param[in] dtstart - The date start of the recurrence * @param[in] tz - The timezone associated to the recurrence rule * */ void test_it(char *rrule, time_t dtstart, char *tz) { int no; time_t next; int i; no = get_num_occurrences(rrule, dtstart, tz); printf("Number of occurrences = %d\n", no); next = dtstart; for (i=0; i < no; i++) { next = get_occurrence(rrule, dtstart, tz, i+1); printf("Next occurrence on %s", ctime(&next)); } return; }
/** * @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); } }
/** * @brief * update_resresv_on_end - update a resource_resv structure when * it ends * * @param[out] resresv - the resresv to update * @param[in] job_state - the new state if resresv is a job * * @return nothing * */ void update_resresv_on_end(resource_resv *resresv, char *job_state) { queue_info *resv_queue; resource_resv *next_occr = NULL; time_t next_occr_time; char logbuf[MAX_LOG_SIZE]; int ret; int i; if (resresv == NULL) return; /* now that it isn't running, it might be runnable again */ resresv->can_not_run = 0; /* unless of course it's a job and its queue is in an ineligible state */ if (resresv->is_job && resresv->job != NULL && !resresv->job->queue->is_ok_to_run) resresv->can_not_run = 1; /* no longer running... clear start and end times */ resresv->start = UNSPECIFIED; resresv->end = UNSPECIFIED; if (resresv->is_job && resresv->job != NULL) { set_job_state(job_state, resresv->job); if (resresv->job->is_suspended) { #ifndef NAS /* localmod 005 */ int i; #endif /* localmod 005 */ nspec **ns = resresv->nspec_arr; resresv->job->is_susp_sched = 1; for (i = 0; ns[i] != NULL; i++) ns[i]->ninfo->num_susp_jobs++; } resresv->job->is_provisioning = 0; /* free resources allocated to job since it's now been requeued */ if (resresv->job->is_queued && !resresv->job->is_checkpointed) { free(resresv->ninfo_arr); resresv->ninfo_arr = NULL; free_nspecs(resresv->nspec_arr); resresv->nspec_arr = NULL; free_resource_req_list(resresv->job->resused); resresv->job->resused = NULL; if (resresv->nodepart_name != NULL) { free(resresv->nodepart_name); resresv->nodepart_name = NULL; } free_selspec(resresv->execselect); resresv->execselect = NULL; } } else if (resresv->is_resv && resresv->resv !=NULL) { resresv->resv->resv_state = RESV_DELETED; resv_queue = find_queue_info(resresv->server->queues, resresv->resv->queuename); if (resv_queue != NULL) { resv_queue->is_started = 0; ret = is_ok_to_run_queue(resresv->server->policy, resv_queue); if (ret == SUCCESS) resv_queue->is_ok_to_run = 1; else resv_queue->is_ok_to_run = 0; if (resresv->resv->is_standing) { /* This occurrence is over, move resv pointers of all jobs that are * left to next occurrence if one exists */ if (resresv->resv->resv_idx < resresv->resv->count) { next_occr_time = get_occurrence(resresv->resv->rrule, resresv->resv->req_start, resresv->resv->timezone, 2); if (next_occr_time >= 0) { next_occr = find_resource_resv_by_time(resresv->server->resvs, resresv->name, next_occr_time); if (next_occr != NULL) { if (resv_queue->jobs != NULL) { for (i = 0; resv_queue->jobs[i] != NULL; i++) { if (in_runnable_state(resv_queue->jobs[i])) resv_queue->jobs[i]->job->resv = next_occr; } } } else { snprintf(logbuf, MAX_LOG_SIZE, "Can't find occurrence of standing reservation at time %ld", next_occr_time); schdlog(PBSEVENT_DEBUG, PBS_EVENTCLASS_SERVER, LOG_DEBUG, resresv->name, logbuf); } } } } } } }