job * chk_job_request(char *jobid, struct batch_request *preq, int *rc) { int t; int histerr = 0; job *pjob; int deletehist = 0; char *p1; char *p2; if (preq->rq_extend && strstr(preq->rq_extend, DELETEHISTORY)) deletehist = 1; t = is_job_array(jobid); if ((t == IS_ARRAY_NO) || (t == IS_ARRAY_ArrayJob)) pjob = find_job(jobid); /* regular or ArrayJob itself */ else pjob = find_arrayparent(jobid); /* subjob(s) */ *rc = t; if (pjob == NULL) { log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_JOB, LOG_INFO, jobid, msg_unkjobid); req_reject(PBSE_UNKJOBID, 0, preq); return NULL; } else { histerr = svr_chk_histjob(pjob); if (histerr && deletehist == 0) { req_reject(histerr, 0, preq); return NULL; } if (deletehist ==1&& pjob->ji_qs.ji_state == JOB_STATE_MOVED && pjob->ji_qs.ji_substate != JOB_SUBSTATE_FINISHED) { job_purge(pjob); req_reject(PBSE_UNKJOBID, 0, preq); return NULL; } } /* * The job was found using the job ID in the request, but it may not * match exactly (i.e. FQDN vs. unqualified hostname). Overwrite the * host portion of the job ID in the request with the host portion of * the one from the server job structure. Do not modify anything * before the first dot in the job ID because it may be an array job. * This will allow find_job() to look for an exact match when the * request is serviced by MoM. */ p1 = strchr(pjob->ji_qs.ji_jobid, '.'); if (p1) { p2 = strchr(jobid, '.'); if (p2) *p2 = '\0'; strncat(jobid, p1, PBS_MAXSVRJOBID-1); } if (svr_authorize_jobreq(preq, pjob) == -1) { (void)sprintf(log_buffer, msg_permlog, preq->rq_type, "Job", pjob->ji_qs.ji_jobid, preq->rq_user, preq->rq_host); log_event(PBSEVENT_SECURITY, PBS_EVENTCLASS_JOB, LOG_INFO, pjob->ji_qs.ji_jobid, log_buffer); req_reject(PBSE_PERM, 0, preq); return NULL; } if ((t == IS_ARRAY_NO) && (pjob->ji_qs.ji_state == JOB_STATE_EXITING)) { /* special case Deletejob with "force" */ if ((preq->rq_type == PBS_BATCH_DeleteJob) && (preq->rq_extend != NULL) && (strcmp(preq->rq_extend, "force") == 0)) { return (pjob); } (void)sprintf(log_buffer, "%s, state=%d", msg_badstate, pjob->ji_qs.ji_state); log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_JOB, LOG_INFO, pjob->ji_qs.ji_jobid, log_buffer); req_reject(PBSE_BADSTATE, 0, preq); return NULL; } return (pjob); }
/** * @brief * setup_arrayjob_attrs - set up the special attributes of an Array Job * Called as "action" routine for the attribute array_indices_submitted * * @param[in] pattr - pointer to special attributes of an Array Job * @param[in] pobj - pointer to job structure * @param[in] mode - actmode * * @return PBS error * @retval 0 - success */ int setup_arrayjob_attrs(attribute *pattr, void *pobj, int mode) { int i; job *pjob = pobj; if (mode == ATR_ACTION_NEW) { /* validate max array size */ int l, x, y, z, ct; char *ep; if (server.sv_attr[(int)SVR_ATR_maxarraysize].at_flags & ATR_VFLAG_SET) l = server.sv_attr[(int)SVR_ATR_maxarraysize].at_val.at_long; else l = PBS_MAX_ARRAY_JOB_DFL; /* default limit 10000 */ if (parse_subjob_index(pattr->at_val.at_str, &ep, &x, &y, &z, &ct) != 0) return PBSE_BADATVAL; if (ct > l) return PBSE_MaxArraySize; } /* set attribute "array" True and clear "array_state_count" */ pjob->ji_wattr[(int)JOB_ATR_array].at_val.at_long = 1; pjob->ji_wattr[(int)JOB_ATR_array].at_flags = ATR_VFLAG_SET | ATR_VFLAG_MODCACHE; job_attr_def[(int)JOB_ATR_array_state_count].at_free(&pjob->ji_wattr[(int)JOB_ATR_array_state_count]); if (mode == ATR_ACTION_RECOV) { int x, y, z, ct; char *ep; /* on recovery ... */ /* parse the various components again, since we dont store them */ if (parse_subjob_index(pattr->at_val.at_str, &ep, &x, &y, &z, &ct) != 0) return PBSE_BADATVAL; pjob->ji_ajtrk->tkm_ct = ct; pjob->ji_ajtrk->tkm_step = z; pjob->ji_ajtrk->tkm_flags = 0; /* reset counts and any running/exiting subjob to queued */ for (i=0; i < PBS_NUMJOBSTATE; ++i) pjob->ji_ajtrk->tkm_subjsct[i] = 0; for (i=0; i < pjob->ji_ajtrk->tkm_ct; ++i) { if ((pjob->ji_ajtrk->tkm_tbl[i].trk_status == JOB_STATE_RUNNING) || (pjob->ji_ajtrk->tkm_tbl[i].trk_status == JOB_STATE_EXITING)) pjob->ji_ajtrk->tkm_tbl[i].trk_status =JOB_STATE_QUEUED; pjob->ji_ajtrk->tkm_subjsct[pjob->ji_ajtrk->tkm_tbl[i].trk_status]++; } /* clear and reset array_indices_remaining to new value */ job_attr_def[(int)JOB_ATR_array_indices_remaining].at_free(&pjob->ji_wattr[(int)JOB_ATR_array_indices_remaining]); job_attr_def[(int)JOB_ATR_array_indices_remaining].at_decode(&pjob->ji_wattr[(int)JOB_ATR_array_indices_remaining], NULL, NULL, cvt_range(pjob->ji_ajtrk, JOB_STATE_QUEUED)); return (PBSE_NONE); } if ((mode != ATR_ACTION_ALTER) && (mode != ATR_ACTION_NEW)) return PBSE_BADATVAL; if (is_job_array(pjob->ji_qs.ji_jobid) != IS_ARRAY_ArrayJob) return PBSE_BADATVAL; /* not an Array Job */ if (mode == ATR_ACTION_ALTER) { if (pjob->ji_qs.ji_state != JOB_STATE_QUEUED) return PBSE_MODATRRUN; /* cannot modify once begun */ /* clear "array_indices_remaining" so can be reset */ job_attr_def[(int)JOB_ATR_array_indices_remaining].at_free(&pjob->ji_wattr[(int)JOB_ATR_array_indices_remaining]); } /* set "array_indices_remaining" if not already set */ if ((pjob->ji_wattr[(int)JOB_ATR_array_indices_remaining].at_flags & ATR_VFLAG_SET) == 0) job_attr_def[(int)JOB_ATR_array_indices_remaining].at_decode(&pjob->ji_wattr[(int)JOB_ATR_array_indices_remaining], NULL, NULL, pattr->at_val.at_str); /* set other Array related fields in the job structure */ pjob->ji_qs.ji_svrflags |= JOB_SVFLG_ArrayJob; if (mode == ATR_ACTION_NEW) { if (pjob->ji_ajtrk) free(pjob->ji_ajtrk); if ((pjob->ji_ajtrk = mk_subjob_index_tbl(pjob->ji_wattr[(int)JOB_ATR_array_indices_submitted].at_val.at_str, JOB_STATE_QUEUED)) == NULL) return PBSE_BADATVAL; } return (PBSE_NONE); }
/** * @brief * Support function for req_stat_job(). * Builds status reply for a single job id, which may be: a normal job, * an Array job, a single subjob or a range of subjobs. * Finds the job structure for the job id and calls either do_stat_of_a_job() * or status_subjob() to build that actual status reply. * * @param[in,out] preq - pointer to the stat job batch request, reply updated * @param[in] name - job id to be statused * @param[in] dohistjobs - flag to include job if it is a history job * @param[in] dosubjobs - flag to expand a Array job to include all subjobs * * @return int * @retval PBSE_NONE (0) : no error * @retval non-zero : PBS error code to return to client */ static int stat_a_jobidname(struct batch_request *preq, char *name, int dohistjobs, int dosubjobs) { int i, indx, x, y, z; char *pc; char *range; int rc; job *pjob; struct batch_reply *preply = &preq->rq_reply; svrattrl *pal; if ((i = is_job_array(name)) == IS_ARRAY_Single) { pjob = find_arrayparent(name); if (pjob == NULL) { return (PBSE_UNKJOBID); } else if ((!dohistjobs) && (rc = svr_chk_histjob(pjob))) { return (rc); } indx = subjob_index_to_offset(pjob, get_index_from_jid(name)); if (indx != -1) { pal = (svrattrl *)GET_NEXT(preq->rq_ind.rq_status.rq_attr); rc = status_subjob(pjob, preq, pal, indx, &preply->brp_un.brp_status, &bad); } else { rc = PBSE_UNKJOBID; } return (rc); /* no job still needs to be stat-ed */ } else if ((i == IS_ARRAY_NO) || (i == IS_ARRAY_ArrayJob)) { pjob = find_job(name); if (pjob == NULL) { return (PBSE_UNKJOBID); } else if ((!dohistjobs) && (rc = svr_chk_histjob(pjob))) { return (rc); } return (do_stat_of_a_job(preq, pjob, dohistjobs, dosubjobs)); } else { /* range of sub jobs */ range = get_index_from_jid(name); if (range == NULL) { return (PBSE_IVALREQ); } pjob = find_arrayparent(name); if (pjob == NULL) { return (PBSE_UNKJOBID); } else if ((!dohistjobs) && (rc = svr_chk_histjob(pjob))) { return (rc); } pal = (svrattrl *)GET_NEXT(preq->rq_ind.rq_status.rq_attr); while (1) { if ((i=parse_subjob_index(range,&pc,&x,&y,&z,&i)) == -1) { return (PBSE_IVALREQ); } else if (i == 1) break; while (x <= y) { indx = numindex_to_offset(pjob, x); if (indx < 0) { x += z; continue; } rc = status_subjob(pjob, preq, pal, indx, &preply->brp_un.brp_status, &bad); if (rc && (rc != PBSE_PERM)) { return (rc); } x += z; } range = pc; } /* stat-ed the range, no more to stat for this id */ return (PBSE_NONE); } }