int poke_scheduler(attribute *pattr, void *pobj, int actmode) { if (pobj == &server || pobj == dflt_scheduler) { if (pobj == &server) { /* set this attribute on main scheduler */ if (dflt_scheduler) { sched_attr_def[(int) SCHED_ATR_scheduling].at_set(&dflt_scheduler->sch_attr[(int) SCHED_ATR_scheduling], pattr, SET); (void)sched_save_db(dflt_scheduler, SVR_SAVE_FULL); } } else { svr_attr_def[(int) SRV_ATR_scheduling].at_set(&server.sv_attr[SRV_ATR_scheduling], pattr, SET); svr_save_db(&server, SVR_SAVE_QUICK); } if (actmode == ATR_ACTION_ALTER) { if (pattr->at_val.at_long) set_scheduler_flag(SCH_SCHEDULE_CMD, dflt_scheduler); } } else { if (actmode == ATR_ACTION_ALTER) { if (pattr->at_val.at_long) set_scheduler_flag(SCH_SCHEDULE_CMD, (pbs_sched *)pobj); } } return PBSE_NONE; }
/** * @brief * queuestart_action - when queue is stopped or started, * for all jobs in queue and determine their accrue type * action function for QA_ATR_started. * * @param[in] pattr - pointer to special attributes of an Array Job * @param[in] pobject - queue which is stopped or started * @param[in] actmode - not used. * * @return int * @retval 0 - success */ int queuestart_action(attribute *pattr, void *pobject, int actmode) { job *pj; /* pointer to job */ long oldtype; long newaccruetype = -1; /* if determining accrue type */ pbs_queue *pque = (pbs_queue *) pobject; if ((pque != NULL) && (server.sv_attr[SRV_ATR_EligibleTimeEnable].at_val.at_long == 1)) { if (pattr->at_val.at_long == 0) { /* started = OFF */ /* queue stopped, start accruing eligible time */ /* running jobs and jobs accruing ineligible time are exempted */ /* jobs accruing eligible time are also exempted */ pj = (job*)GET_NEXT(pque->qu_jobs); while (pj != (job*)0) { oldtype = pj->ji_wattr[(int)JOB_ATR_accrue_type].at_val.at_long; if (oldtype != JOB_RUNNING && oldtype != JOB_INELIGIBLE && oldtype != JOB_ELIGIBLE) { /* determination of accruetype not required here */ (void)update_eligible_time(JOB_ELIGIBLE, pj); } pj = (job*)GET_NEXT(pj->ji_jobque); } } else { /* started = ON */ /* determine accrue type and accrue time */ pj = (job*)GET_NEXT(pque->qu_jobs); while (pj != (job*)0) { oldtype = pj->ji_wattr[(int)JOB_ATR_accrue_type].at_val.at_long; if (oldtype != JOB_RUNNING && oldtype != JOB_INELIGIBLE && oldtype != JOB_ELIGIBLE) { newaccruetype = determine_accruetype(pj); (void)update_eligible_time(newaccruetype, pj); } pj = (job*)GET_NEXT(pj->ji_jobque); } /* if scheduling = True, notify scheduler to start */ if (server.sv_attr[SRV_ATR_scheduling].at_val.at_long) set_scheduler_flag(SCH_SCHEDULE_STARTQ); } } return 0; }
/** * @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 * Sets default scheduler attributes * * @param[in] psched - Scheduler * @parma[in] unset_flag - flag to indicate if this function is called after unset of any sched attributes. * @parma[in] from_scheduler - flag to indicate if this function is called on a request from scheduler. * * */ void set_sched_default(pbs_sched *psched, int unset_flag, int from_scheduler) { char *temp; char dir_path[MAXPATHLEN +1] = {0}; int flag = 0; if (!psched) return; if ((psched->sch_attr[(int) SCHED_ATR_sched_cycle_len].at_flags & ATR_VFLAG_SET) == 0) { set_attr_svr(&(psched->sch_attr[(int) SCHED_ATR_sched_cycle_len]), &sched_attr_def[(int) SCHED_ATR_sched_cycle_len], TOSTR(PBS_SCHED_CYCLE_LEN_DEFAULT)); } if (!unset_flag && (psched->sch_attr[(int) SCHED_ATR_schediteration].at_flags & ATR_VFLAG_SET) == 0) { set_attr_svr(&(psched->sch_attr[(int) SCHED_ATR_schediteration]), &sched_attr_def[(int) SCHED_ATR_schediteration], TOSTR(PBS_SCHEDULE_CYCLE)); } if ((psched->sch_attr[(int) SCHED_ATR_scheduling].at_flags & ATR_VFLAG_SET) == 0) { if (psched != dflt_scheduler) temp = "0"; else temp = "1"; set_attr_svr(&(psched->sch_attr[(int) SCHED_ATR_scheduling]), &sched_attr_def[(int) SCHED_ATR_scheduling], temp); } if ((psched->sch_attr[(int) SCHED_ATR_sched_state].at_flags & ATR_VFLAG_SET) == 0) { if (psched != dflt_scheduler) temp = SC_DOWN; else temp = SC_IDLE; set_attr_svr(&(psched->sch_attr[(int) SCHED_ATR_sched_state]), &sched_attr_def[(int) SCHED_ATR_sched_state], temp); } if ((psched->sch_attr[(int) SCHED_ATR_sched_priv].at_flags & ATR_VFLAG_SET) == 0) { if (psched != dflt_scheduler) (void) snprintf(dir_path, MAXPATHLEN, "%s/sched_priv_%s", pbs_conf.pbs_home_path, psched->sc_name); else (void) snprintf(dir_path, MAXPATHLEN, "%s/sched_priv", pbs_conf.pbs_home_path); set_attr_svr(&(psched->sch_attr[(int) SCHED_ATR_sched_priv]), &sched_attr_def[(int) SCHED_ATR_sched_priv], dir_path); } if ((psched->sch_attr[(int) SCHED_ATR_sched_log].at_flags & ATR_VFLAG_SET) == 0) { if (psched != dflt_scheduler) (void) snprintf(dir_path, MAXPATHLEN, "%s/sched_logs_%s", pbs_conf.pbs_home_path, psched->sc_name); else (void) snprintf(dir_path, MAXPATHLEN, "%s/sched_logs", pbs_conf.pbs_home_path); set_attr_svr(&(psched->sch_attr[(int) SCHED_ATR_sched_log]), &sched_attr_def[(int) SCHED_ATR_sched_log], dir_path); } if (!(psched->sch_attr[SCHED_ATR_preempt_queue_prio].at_flags & ATR_VFLAG_SET)) { psched->sch_attr[SCHED_ATR_preempt_queue_prio].at_val.at_long = PBS_PREEMPT_QUEUE_PRIO_DEFAULT; psched->sch_attr[SCHED_ATR_preempt_queue_prio].at_flags |= ATR_VFLAG_SET | ATR_VFLAG_MODCACHE | ATR_VFLAG_DEFLT; flag = 1; } if (!(psched->sch_attr[SCHED_ATR_preempt_prio].at_flags & ATR_VFLAG_SET)) { psched->sch_attr[SCHED_ATR_preempt_prio].at_val.at_str = strdup(PBS_PREEMPT_PRIO_DEFAULT); psched->sch_attr[SCHED_ATR_preempt_prio].at_flags |= ATR_VFLAG_SET | ATR_VFLAG_MODCACHE | ATR_VFLAG_DEFLT; flag = 1; } if (!(psched->sch_attr[SCHED_ATR_preempt_order].at_flags & ATR_VFLAG_SET)) { psched->sch_attr[SCHED_ATR_preempt_order].at_val.at_str = strdup(PBS_PREEMPT_ORDER_DEFAULT); action_sched_preempt_order(&psched->sch_attr[SCHED_ATR_preempt_order], psched, ATR_ACTION_ALTER); psched->sch_attr[SCHED_ATR_preempt_order].at_flags |= ATR_VFLAG_SET | ATR_VFLAG_MODCACHE | ATR_VFLAG_DEFLT; flag = 1; } if (!unset_flag && !from_scheduler && !(psched->sch_attr[SCHED_ATR_preempt_sort].at_flags & ATR_VFLAG_SET)) { psched->sch_attr[SCHED_ATR_preempt_sort].at_val.at_str = strdup(PBS_PREEMPT_SORT_DEFAULT); psched->sch_attr[SCHED_ATR_preempt_sort].at_flags |= ATR_VFLAG_SET | ATR_VFLAG_MODCACHE | ATR_VFLAG_DEFLT; flag = 1; } if (flag) set_scheduler_flag(SCH_ATTRS_CONFIGURE, psched); }