/** * @brief * free_resource_resv - free a resource resv strcture an all of it's ptrs * * @param[in] resresv - resource_resv to free * * @return nothing * */ void free_resource_resv(resource_resv *resresv) { if (resresv == NULL) return; if (resresv->name != NULL) free(resresv->name); if (resresv->user != NULL) free(resresv->user); if (resresv->group != NULL) free(resresv->group); if (resresv->project != NULL) free(resresv->project); if (resresv->nodepart_name != NULL) free(resresv->nodepart_name); if (resresv->select != NULL) free_selspec(resresv->select); if (resresv->execselect != NULL) free_selspec(resresv->execselect); if (resresv->place_spec != NULL) free_place(resresv->place_spec); if (resresv->resreq != NULL) free_resource_req_list(resresv->resreq); if (resresv->ninfo_arr != NULL) free(resresv->ninfo_arr); if (resresv->nspec_arr != NULL) free_nspecs(resresv->nspec_arr); if (resresv->job != NULL) free_job_info(resresv->job); if (resresv->resv != NULL) free_resv_info(resresv->resv); if (resresv->aoename != NULL) free(resresv->aoename); if (resresv->eoename != NULL) free(resresv->eoename); if (resresv->node_set_str != NULL) free_string_array(resresv->node_set_str); if (resresv->node_set != NULL) free(resresv->node_set); free(resresv); }
/** * @brief * calculate the run time of a resresv through simulation of * future calendar events * * @param[in] name - the name of the resresv to find the start time of * @param[in] sinfo - the pbs environment * NOTE: sinfo will be modified, it should be a copy * @param[in] flags - some flags to control the function * SIM_RUN_JOB - simulate running the resresv * * @return int * @retval time_t of when the job will run * @retval 0 : can not determine when job will run * @retval 1 : on error * */ time_t calc_run_time(char *name, server_info *sinfo, int flags) { time_t event_time = (time_t) 0; /* time of the simulated event */ event_list *calendar; /* calendar we are simulating in */ resource_resv *resresv; /* the resource resv to find star time for */ /* the value returned from simulate_events(). Init to TIMED_END_EVENT to * force the initial check to see if the job can run */ unsigned int ret = TIMED_END_EVENT; schd_error *err = NULL; timed_event *te_start; timed_event *te_end; int desc; nspec **ns = NULL; if (name == NULL || sinfo == NULL) return (time_t) -1; event_time = sinfo->server_time; calendar = sinfo->calendar; resresv = find_resource_resv(sinfo->all_resresv, name); if (!is_resource_resv_valid(resresv, NULL)) return (time_t) -1; err = new_schd_error(); if(err == NULL) return (time_t) 0; do { /* policy is used from sinfo instead of being passed into calc_run_time() * because it's being simulated/updated in simulate_events() */ desc = describe_simret(ret); if (desc > 0 || (desc == 0 && policy_change_info(sinfo, resresv))) { clear_schd_error(err); if (resresv->is_job) ns = is_ok_to_run(sinfo->policy, -1, sinfo, resresv->job->queue, resresv, IGNORE_EQUIV_CLASS, err); else ns = is_ok_to_run(sinfo->policy, -1, sinfo, NULL, resresv, IGNORE_EQUIV_CLASS, err); } if (ns == NULL) /* event can not run */ ret = simulate_events(sinfo->policy, sinfo, SIM_NEXT_EVENT, &(sinfo->opt_backfill_fuzzy_time), &event_time); #ifdef NAS /* localmod 030 */ if (check_for_cycle_interrupt(0)) { break; } #endif /* localmod 030 */ } while (ns == NULL && !(ret & (TIMED_NOEVENT|TIMED_ERROR))); #ifdef NAS /* localmod 030 */ if (check_for_cycle_interrupt(0) || (ret & TIMED_ERROR)) { #else if ((ret & TIMED_ERROR)) { #endif /* localmod 030 */ free_schd_error(err); if (ns != NULL) free_nspecs(ns); return -1; } /* we can't run the job, but there are no timed events left to process */ if (ns == NULL && (ret & TIMED_NOEVENT)) { schdlogerr(PBSEVENT_SCHED, PBS_EVENTCLASS_SCHED, LOG_WARNING, resresv->name, "Can't find start time estimate", err); free_schd_error(err); return 0; } /* err is no longer needed, we've reported it. */ free_schd_error(err); err = NULL; if (resresv->is_job) resresv->job->est_start_time = event_time; resresv->start = event_time; resresv->end = event_time + resresv->duration; te_start = create_event(TIMED_RUN_EVENT, resresv->start, (event_ptr_t *) resresv, NULL, NULL); if (te_start == NULL) { if (ns != NULL) free_nspecs(ns); return -1; } te_end = create_event(TIMED_END_EVENT, resresv->end, (event_ptr_t *) resresv, NULL, NULL); if (te_end == NULL) { if (ns != NULL) free_nspecs(ns); free_timed_event(te_start); return -1; } add_event(calendar, te_start); add_event(calendar, te_end); if (flags & SIM_RUN_JOB) sim_run_update_resresv(sinfo->policy, resresv, ns, RURR_NO_FLAGS); else free_nspecs(ns); return event_time; } /** * @brief * create an event_list from running jobs and confirmed resvs * * @param[in] sinfo - server universe to act upon * * @return event_list */ event_list * create_event_list(server_info *sinfo) { event_list *elist; elist = new_event_list(); if (elist == NULL) return NULL; elist->events = create_events(sinfo); elist->next_event = elist->events; elist->current_time = &sinfo->server_time; add_dedtime_events(elist, sinfo->policy); return elist; }
/** * @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); } } } } } } }