END_TEST START_TEST(svr_enquejob_test) { struct job test_job; int result = PBSE_NONE; /*initialize_globals*/ server.sv_qs_mutex = (pthread_mutex_t *)calloc(1, sizeof(pthread_mutex_t)); server.sv_attr_mutex = (pthread_mutex_t *)calloc(1, sizeof(pthread_mutex_t)); server.sv_jobstates_mutex = (pthread_mutex_t *)calloc(1, sizeof(pthread_mutex_t)); pthread_mutex_init(server.sv_qs_mutex,NULL); pthread_mutex_init(server.sv_attr_mutex,NULL); pthread_mutex_init(server.sv_jobstates_mutex,NULL); memset(&test_job, 0, sizeof(test_job)); result = svr_enquejob(NULL, 0, 0, false); fail_unless(result != PBSE_NONE, "NULL input pointer fail"); result = svr_enquejob(&test_job, 0, 0, false); /*Need more complicated mocking in order to have other result than PBSE_JOBNOTFOUND*/ fail_unless(result == PBSE_JOBNOTFOUND, "svr_enquejob fail: %d", result); }
static void close_quejob( int sfds) { job *pjob; job *npjob; pjob = (job *)GET_NEXT(svr_newjobs); while (pjob != NULL) { npjob = GET_NEXT(pjob->ji_alljobs); if (pjob->ji_qs.ji_un.ji_newt.ji_fromsock == sfds) { if (pjob->ji_qs.ji_substate == JOB_SUBSTATE_TRANSICM) { #ifndef PBS_MOM if (pjob->ji_qs.ji_svrflags & JOB_SVFLG_HERE) { /* * the job was being created here for the first time * go ahead and enqueue it as QUEUED; otherwise, hold * it here as TRANSICM until we hear from the sending * server again to commit. */ delete_link(&pjob->ji_alljobs); pjob->ji_qs.ji_state = JOB_STATE_QUEUED; pjob->ji_qs.ji_substate = JOB_SUBSTATE_QUEUED; if (svr_enquejob(pjob)) job_abt(&pjob, msg_err_noqueue); } #endif /* PBS_MOM */ } else { /* else delete the job */ delete_link(&pjob->ji_alljobs); job_purge(pjob); } break; } /* END if (..) */ pjob = npjob; } return; } /* END close_quejob() */
int close_quejob_by_jobid( char *job_id) { int rc = PBSE_NONE; job *pjob = NULL; if (LOGLEVEL >= 10) { LOG_EVENT(PBSEVENT_JOB, PBS_EVENTCLASS_JOB, __func__, job_id); } if ((pjob = svr_find_job(job_id, FALSE)) == NULL) { rc = PBSE_JOBNOTFOUND; return(rc); } mutex_mgr pjob_mutex = mutex_mgr(pjob->ji_mutex, true); if (pjob->ji_qs.ji_substate != JOB_SUBSTATE_TRANSICM) { remove_job(&newjobs,pjob); svr_job_purge(pjob); pjob = NULL; } else if (pjob->ji_qs.ji_svrflags & JOB_SVFLG_HERE) { remove_job(&newjobs,pjob); pjob->ji_qs.ji_state = JOB_STATE_QUEUED; pjob->ji_qs.ji_substate = JOB_SUBSTATE_QUEUED; rc = svr_enquejob(pjob, FALSE, -1, false); if ((rc == PBSE_JOBNOTFOUND) || (rc == PBSE_JOB_RECYCLED)) { pjob = NULL; } else if (rc != PBSE_NONE) { job_abt(&pjob, msg_err_noqueue); pjob = NULL; } } if (pjob == NULL) pjob_mutex.set_lock_on_exit(false); return(rc); } /* close_quejob_by_jobid() */
int req_orderjob( struct batch_request *vp) /* I */ { job *pjob; job *pjob1; job *pjob2; int rank; int rc = 0; char tmpqn[PBS_MAXQUEUENAME+1]; struct batch_request *req = (struct batch_request *)vp; char log_buf[LOCAL_LOG_BUF_SIZE]; pbs_queue *pque1; pbs_queue *pque2; if ((pjob1 = chk_job_request(req->rq_ind.rq_move.rq_jid, req)) == NULL) { return(PBSE_NONE); } mutex_mgr job1_mutex(pjob1->ji_mutex, true); if ((pjob2 = chk_job_request(req->rq_ind.rq_move.rq_destin, req)) == NULL) { return(PBSE_NONE); } mutex_mgr job2_mutex(pjob2->ji_mutex, true); if (((pjob = pjob1)->ji_qs.ji_state == JOB_STATE_RUNNING) || ((pjob = pjob2)->ji_qs.ji_state == JOB_STATE_RUNNING)) { #ifndef NDEBUG sprintf(log_buf, "%s %d", pbse_to_txt(PBSE_BADSTATE), pjob->ji_qs.ji_state); strcat(log_buf, __func__); log_event( PBSEVENT_DEBUG, PBS_EVENTCLASS_JOB, pjob->ji_qs.ji_jobid, log_buf); #endif /* NDEBUG */ req_reject(PBSE_BADSTATE, 0, req, NULL, NULL); return(PBSE_NONE); } else if ((pjob1->ji_qhdr == NULL) || (pjob2->ji_qhdr == NULL)) { req_reject(PBSE_BADSTATE, 0, req, NULL, "One of the jobs does not have a queue"); return(PBSE_NONE); } else if (pjob1->ji_qhdr != pjob2->ji_qhdr) { /* jobs are in different queues */ int ok = FALSE; if ((pque2 = get_jobs_queue(&pjob2)) == NULL) { rc = PBSE_BADSTATE; job2_mutex.set_lock_on_exit(false); } else { mutex_mgr pque2_mutex = mutex_mgr(pque2->qu_mutex, true); if ((rc = svr_chkque(pjob1, pque2, get_variable(pjob1, pbs_o_host), MOVE_TYPE_Order, NULL)) == PBSE_NONE) { pque2_mutex.unlock(); if ((pque1 = get_jobs_queue(&pjob1)) == NULL) { rc = PBSE_BADSTATE; job1_mutex.set_lock_on_exit(false); } else if (pjob1 != NULL) { mutex_mgr pque1_mutex = mutex_mgr(pque1->qu_mutex, true); if ((rc = svr_chkque(pjob2, pque1, get_variable(pjob2, pbs_o_host), MOVE_TYPE_Order, NULL)) == PBSE_NONE) { ok = TRUE; } } } } if (ok == FALSE) { req_reject(rc, 0, req, NULL, NULL); return(PBSE_NONE); } } /* now swap the order of the two jobs in the queue lists */ rank = pjob1->ji_wattr[JOB_ATR_qrank].at_val.at_long; pjob1->ji_wattr[JOB_ATR_qrank].at_val.at_long = pjob2->ji_wattr[JOB_ATR_qrank].at_val.at_long; pjob2->ji_wattr[JOB_ATR_qrank].at_val.at_long = rank; if (pjob1->ji_qhdr != pjob2->ji_qhdr) { strcpy(tmpqn, pjob1->ji_qs.ji_queue); strcpy(pjob1->ji_qs.ji_queue, pjob2->ji_qs.ji_queue); strcpy(pjob2->ji_qs.ji_queue, tmpqn); svr_dequejob(pjob1, FALSE); svr_dequejob(pjob2, FALSE); if (svr_enquejob(pjob1, FALSE, -1) == PBSE_JOB_RECYCLED) { pjob1 = NULL; job1_mutex.set_lock_on_exit(false); } if (svr_enquejob(pjob2, FALSE, -1) == PBSE_JOB_RECYCLED) { pjob2 = NULL; job2_mutex.set_lock_on_exit(false); } } else { if ((pque1 = get_jobs_queue(&pjob1)) != NULL) { mutex_mgr pque1_mutex = mutex_mgr(pque1->qu_mutex, true); swap_jobs(pque1->qu_jobs,pjob1,pjob2); swap_jobs(NULL,pjob1,pjob2); } } /* need to update disk copy of both jobs to save new order */ if (pjob1 != NULL) { job_save(pjob1, SAVEJOB_FULL, 0); } if (pjob2 != NULL) { job_save(pjob2, SAVEJOB_FULL, 0); } /* SUCCESS */ reply_ack(req); return(PBSE_NONE); } /* END req_orderjob() */
static int local_move( job *jobp, struct batch_request *req) { char *id = "local_move"; pbs_queue *qp; char *destination = jobp->ji_qs.ji_destin; int mtype; /* search for destination queue */ if ((qp = find_queuebyname(destination)) == NULL) { sprintf(log_buffer, "queue %s does not exist\n", destination); log_err(-1, id, log_buffer); pbs_errno = PBSE_UNKQUE; return(ROUTE_PERM_FAILURE); } /* * if being moved at specific request of administrator, then * checks on queue availability, etc. are skipped; * otherwise all checks are enforced. */ if (req == 0) { mtype = MOVE_TYPE_Route; /* route */ } else if (req->rq_perm & (ATR_DFLAG_MGRD | ATR_DFLAG_MGWR)) { mtype = MOVE_TYPE_MgrMv; /* privileged move */ } else { mtype = MOVE_TYPE_Move; /* non-privileged move */ } if ((pbs_errno = svr_chkque( jobp, qp, get_variable(jobp, pbs_o_host), mtype, NULL))) { /* should this queue be retried? */ return(should_retry_route(pbs_errno)); } /* dequeue job from present queue, update destination and */ /* queue_rank for new queue and enqueue into destination */ svr_dequejob(jobp); strcpy(jobp->ji_qs.ji_queue, destination); jobp->ji_wattr[JOB_ATR_qrank].at_val.at_long = ++queue_rank; pbs_errno = svr_enquejob(jobp); if (pbs_errno != 0) { return(ROUTE_PERM_FAILURE); /* should never ever get here */ } jobp->ji_lastdest = 0; /* reset in case of another route */ job_save(jobp, SAVEJOB_FULL); return(ROUTE_SUCCESS); } /* END local_move() */
void req_orderjob(struct batch_request *req) { int jt1, jt2; /* job type */ job *pjob; job *pjob1; job *pjob2; long rank; int rc; char tmpqn[PBS_MAXQUEUENAME+1]; if ((pjob1=chk_job_request(req->rq_ind.rq_move.rq_jid, req, &jt1)) == NULL) return; if ((pjob2=chk_job_request(req->rq_ind.rq_move.rq_destin, req, &jt2)) == NULL) return; if ((jt1 == IS_ARRAY_Single) || (jt2 == IS_ARRAY_Single) || (jt1 == IS_ARRAY_Range) || (jt2 == IS_ARRAY_Range)) { /* can only move regular or Array Job, not Subjobs */ req_reject(PBSE_IVALREQ, 0, req); return; } if (((pjob = pjob1)->ji_qs.ji_state == JOB_STATE_RUNNING) || ((pjob = pjob2)->ji_qs.ji_state == JOB_STATE_RUNNING) || ((pjob = pjob1)->ji_qs.ji_state == JOB_STATE_BEGUN) || ((pjob = pjob2)->ji_qs.ji_state == JOB_STATE_BEGUN)) { #ifndef NDEBUG (void)sprintf(log_buffer, "(%s) %s, state=%d", __func__, msg_badstate, pjob->ji_qs.ji_state); log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_JOB, LOG_DEBUG, pjob->ji_qs.ji_jobid, log_buffer); #endif /* NDEBUG */ req_reject(PBSE_BADSTATE, 0, req); return; } else if (pjob1->ji_qhdr != pjob2->ji_qhdr) { /* Jobs are in different queues */ if ((rc = svr_chkque(pjob1, pjob2->ji_qhdr, get_hostPart(pjob1->ji_wattr[(int)JOB_ATR_job_owner].at_val.at_str), MOVE_TYPE_Order)) || (rc = svr_chkque(pjob2, pjob1->ji_qhdr, get_hostPart(pjob2->ji_wattr[(int)JOB_ATR_job_owner].at_val.at_str), MOVE_TYPE_Order))) { req_reject(rc, 0, req); return; } } /* now swap the order of the two jobs in the queue lists */ rank = pjob1->ji_wattr[(int)JOB_ATR_qrank].at_val.at_long; pjob1->ji_wattr[(int)JOB_ATR_qrank].at_val.at_long = pjob2->ji_wattr[(int)JOB_ATR_qrank].at_val.at_long; pjob1->ji_wattr[(int)JOB_ATR_qrank].at_flags |= ATR_VFLAG_MODCACHE; pjob2->ji_wattr[(int)JOB_ATR_qrank].at_val.at_long = rank; pjob2->ji_wattr[(int)JOB_ATR_qrank].at_flags |= ATR_VFLAG_MODCACHE; if (pjob1->ji_qhdr != pjob2->ji_qhdr) { (void)strcpy(tmpqn, pjob1->ji_qs.ji_queue); (void)strcpy(pjob1->ji_qs.ji_queue, pjob2->ji_qs.ji_queue); (void)strcpy(pjob2->ji_qs.ji_queue, tmpqn); svr_dequejob(pjob1); svr_dequejob(pjob2); (void)svr_enquejob(pjob1); (void)svr_enquejob(pjob2); } else { swap_link(&pjob1->ji_jobque, &pjob2->ji_jobque); swap_link(&pjob1->ji_alljobs, &pjob2->ji_alljobs); } /* need to update disk copy of both jobs to save new order */ (void)job_save(pjob1, SAVEJOB_FULL); (void)job_save(pjob2, SAVEJOB_FULL); reply_ack(req); }
/** * @brief * create_subjob - create a Subjob from the parent Array Job * Certain attributes are changed or left out * @param[in] parent - pointer to parent Job * @param[in] newjid - new job id * @param[in] rc - return code * @return pointer to new job * @retval NULL - error */ job * create_subjob(job *parent, char *newjid, int *rc) { pbs_list_head attrl; int i; int j; int indx; char *index; attribute_def *pdef; attribute *ppar; attribute *psub; svrattrl *psatl; job *subj; long eligibletime; long time_msec; #ifdef WIN32 struct _timeb tval; #else struct timeval tval; #endif if ((parent->ji_qs.ji_svrflags & JOB_SVFLG_ArrayJob) == 0) { *rc = PBSE_IVALREQ; return NULL; /* parent not an array job */ } /* find and copy the index */ if ((index = get_index_from_jid(newjid)) == NULL) { *rc = PBSE_IVALREQ; return NULL; } if ((indx = subjob_index_to_offset(parent, index)) == -1) { *rc = PBSE_UNKJOBID; return NULL; } if (parent->ji_ajtrk->tkm_tbl[indx].trk_status != JOB_STATE_QUEUED) { *rc = PBSE_BADSTATE; return NULL; } /* * allocate and clear basic structure * cannot copy job attributes because cannot share strings and other * malloc-ed data, so copy ji_qs as a whole and then copy the * non-saved items before ji_qs. */ subj = job_alloc(); subj->ji_qs = parent->ji_qs; /* copy the fixed save area */ #ifdef PBS_CRED_GRIDPROXY subj->ji_gsscontext = parent->ji_gsscontext; #endif subj->ji_qhdr = parent->ji_qhdr; subj->ji_resvp = parent->ji_resvp; subj->ji_myResv = parent->ji_myResv; subj->ji_parentaj = parent; strcpy(subj->ji_qs.ji_jobid, newjid); /* replace job id */ *subj->ji_qs.ji_fileprefix = '\0'; subj->ji_subjindx = indx; /* * now that is all done, copy the required attributes by * encoding and then decoding into the new array. Then add the * subjob specific attributes. */ resc_access_perm = ATR_DFLAG_ACCESS; CLEAR_HEAD(attrl); for (i = 0; attrs_to_copy[i] != JOB_ATR_LAST; i++) { j = (int)attrs_to_copy[i]; ppar = &parent->ji_wattr[j]; psub = &subj->ji_wattr[j]; pdef = &job_attr_def[j]; if (pdef->at_encode(ppar, &attrl, pdef->at_name, NULL, ATR_ENCODE_MOM, &psatl) > 0) { for (psatl = (svrattrl *)GET_NEXT(attrl); psatl; psatl = ((svrattrl *)GET_NEXT(psatl->al_link))) { pdef->at_decode(psub, psatl->al_name, psatl->al_resc, psatl->al_value); } /* carry forward the default bit if set */ psub->at_flags |= (ppar->at_flags & ATR_VFLAG_DEFLT); free_attrlist(&attrl); } } psub = &subj->ji_wattr[(int)JOB_ATR_array_id]; job_attr_def[(int)JOB_ATR_array_id].at_decode(psub, NULL, NULL, parent->ji_qs.ji_jobid); psub = &subj->ji_wattr[(int)JOB_ATR_array_index]; job_attr_def[(int)JOB_ATR_array_index].at_decode(psub, NULL, NULL, index); /* Lastly, set or clear a few flags and link in the structure */ subj->ji_qs.ji_svrflags &= ~JOB_SVFLG_ArrayJob; subj->ji_qs.ji_svrflags |= JOB_SVFLG_SubJob; subj->ji_modified = 1; /* ** will likely take this out ** */ subj->ji_qs.ji_substate = JOB_SUBSTATE_TRANSICM; (void)svr_setjobstate(subj, JOB_STATE_QUEUED, JOB_SUBSTATE_QUEUED); subj->ji_wattr[(int)JOB_ATR_state].at_flags |= ATR_VFLAG_SET; subj->ji_wattr[(int)JOB_ATR_substate].at_flags |= ATR_VFLAG_SET; /* subjob needs to borrow eligible time from parent job array. * expecting only to accrue eligible_time and nothing else. */ if (server.sv_attr[(int)SRV_ATR_EligibleTimeEnable].at_val.at_long == 1) { eligibletime = parent->ji_wattr[(int)JOB_ATR_eligible_time].at_val.at_long; if (parent->ji_wattr[(int)JOB_ATR_accrue_type].at_val.at_long == JOB_ELIGIBLE) eligibletime += subj->ji_wattr[(int)JOB_ATR_sample_starttime].at_val.at_long - parent->ji_wattr[(int)JOB_ATR_sample_starttime].at_val.at_long; subj->ji_wattr[(int)JOB_ATR_eligible_time].at_val.at_long = eligibletime; subj->ji_wattr[(int)JOB_ATR_eligible_time].at_flags |= ATR_VFLAG_MODIFY | ATR_VFLAG_MODCACHE; } #ifdef WIN32 _ftime_s(&tval); time_msec = (tval.time * 1000L) + tval.millitm; #else gettimeofday(&tval, NULL); time_msec = (tval.tv_sec * 1000L) + (tval.tv_usec/1000L); #endif /* set the queue rank attribute */ subj->ji_wattr[(int)JOB_ATR_qrank].at_val.at_long = time_msec; subj->ji_wattr[(int)JOB_ATR_qrank].at_flags |= ATR_VFLAG_SET|ATR_VFLAG_MODCACHE; if (svr_enquejob(subj) != 0) { job_purge(subj); *rc = PBSE_IVALREQ; return NULL; } *rc = PBSE_NONE; return subj; }
void req_orderjob( struct batch_request *req) /* I */ { #ifndef NDEBUG char *id = "req_orderjob"; #endif job *pjob; job *pjob1; job *pjob2; int rank; int rc; char tmpqn[PBS_MAXQUEUENAME+1]; if ((pjob1 = chk_job_request(req->rq_ind.rq_move.rq_jid, req)) == NULL) { return; } if ((pjob2 = chk_job_request(req->rq_ind.rq_move.rq_destin, req)) == NULL) { return; } if (((pjob = pjob1)->ji_qs.ji_state == JOB_STATE_RUNNING) || ((pjob = pjob2)->ji_qs.ji_state == JOB_STATE_RUNNING)) { #ifndef NDEBUG sprintf(log_buffer, "%s %d", pbse_to_txt(PBSE_BADSTATE), pjob->ji_qs.ji_state); strcat(log_buffer, id); log_event( PBSEVENT_DEBUG, PBS_EVENTCLASS_JOB, pjob->ji_qs.ji_jobid, log_buffer); #endif /* NDEBUG */ req_reject(PBSE_BADSTATE, 0, req, NULL, NULL); return; } else if (pjob1->ji_qhdr != pjob2->ji_qhdr) { /* jobs are in different queues */ if ((rc = svr_chkque( pjob1, pjob2->ji_qhdr, get_variable(pjob1, pbs_o_host), MOVE_TYPE_Order, NULL)) || (rc = svr_chkque( pjob2, pjob1->ji_qhdr, get_variable(pjob2, pbs_o_host), MOVE_TYPE_Order, NULL))) { req_reject(rc, 0, req, NULL, NULL); return; } } /* now swap the order of the two jobs in the queue lists */ rank = pjob1->ji_wattr[(int)JOB_ATR_qrank].at_val.at_long; pjob1->ji_wattr[(int)JOB_ATR_qrank].at_val.at_long = pjob2->ji_wattr[(int)JOB_ATR_qrank].at_val.at_long; pjob2->ji_wattr[(int)JOB_ATR_qrank].at_val.at_long = rank; if (pjob1->ji_qhdr != pjob2->ji_qhdr) { (void)strcpy(tmpqn, pjob1->ji_qs.ji_queue); (void)strcpy(pjob1->ji_qs.ji_queue, pjob2->ji_qs.ji_queue); (void)strcpy(pjob2->ji_qs.ji_queue, tmpqn); svr_dequejob(pjob1); svr_dequejob(pjob2); (void)svr_enquejob(pjob1); (void)svr_enquejob(pjob2); } else { swap_link(&pjob1->ji_jobque, &pjob2->ji_jobque); swap_link(&pjob1->ji_alljobs, &pjob2->ji_alljobs); } /* need to update disk copy of both jobs to save new order */ job_save(pjob1, SAVEJOB_FULL); job_save(pjob2, SAVEJOB_FULL); reply_ack(req); /* SUCCESS */ return; } /* END req_orderjob() */
int local_move( job *pjob, int *my_err, struct batch_request *req) { pbs_queue *dest_que = NULL; char *destination = pjob->ji_qs.ji_destin; int mtype; char log_buf[LOCAL_LOG_BUF_SIZE]; char job_id[PBS_MAXSVRJOBID+1]; int rc; bool reservation = false; /* Sometimes multiple threads are trying to route the same job. Protect against this * by making sure that the destionation queue and the current queue are different. * If they are the same then consider it done correctly */ if (!strcmp(pjob->ji_qs.ji_queue, pjob->ji_qs.ji_destin)) return(PBSE_NONE); if (LOGLEVEL >= 8) { sprintf(log_buf, "%s", pjob->ji_qs.ji_jobid); log_event(PBSEVENT_JOB, PBS_EVENTCLASS_JOB, __func__, log_buf); } /* * if being moved at specific request of administrator, then * checks on queue availability, etc. are skipped; * otherwise all checks are enforced. */ if (req == 0) { mtype = MOVE_TYPE_Route; /* route */ } else if (req->rq_perm & (ATR_DFLAG_MGRD | ATR_DFLAG_MGWR)) { mtype = MOVE_TYPE_MgrMv; /* privileged move */ } else { mtype = MOVE_TYPE_Move; /* non-privileged move */ } strcpy(job_id, pjob->ji_qs.ji_jobid); unlock_ji_mutex(pjob, __func__, NULL, LOGLEVEL); dest_que = find_queuebyname(destination); if (dest_que == NULL) { /* this should never happen */ sprintf(log_buf, "queue %s does not exist\n", pjob->ji_qs.ji_queue); log_err(-1, __func__, log_buf); *my_err = PBSE_UNKQUE; return(-1); } mutex_mgr dest_que_mutex = mutex_mgr(dest_que->qu_mutex, true); if ((pjob = svr_find_job(job_id, TRUE)) == NULL) { /* job disappeared while locking queue */ return(PBSE_JOB_RECYCLED); } /* check the destination */ if ((*my_err = svr_chkque(pjob, dest_que, get_variable(pjob, pbs_o_host), mtype, NULL))) { /* should this queue be retried? */ return(should_retry_route(*my_err)); } reservation = have_reservation(pjob, dest_que); /* dequeue job from present queue, update destination and */ /* queue_rank for new queue and enqueue into destination */ dest_que_mutex.unlock(); rc = svr_dequejob(pjob, FALSE); if (rc) return(rc); snprintf(pjob->ji_qs.ji_queue, sizeof(pjob->ji_qs.ji_queue), "%s", destination); pjob->ji_wattr[JOB_ATR_qrank].at_val.at_long = ++queue_rank; if ((*my_err = svr_enquejob(pjob, FALSE, NULL, reservation, false)) == PBSE_JOB_RECYCLED) return(-1); if (*my_err != PBSE_NONE) { return(-1); /* should never ever get here */ } if (pjob != NULL) { pjob->ji_lastdest = 0; /* reset in case of another route */ job_save(pjob, SAVEJOB_FULL, 0); } return(PBSE_NONE); } /* END local_move() */
/** * @brief * Move a job to another queue in this Server. * * @par * Check the destination to see if it can accept the job. * If the job can enter the new queue, dequeue from the existing queue and * enqueue into the new queue * * @par * Note - the destination is specified by the queue's name in the * ji_qs.ji_destin element of the job structure. * * param[in] jobp - pointer to job to move * param[in] req - client request from a qmove client, null if a route * * @return int * @retval 0 : success * @retval -1 : permanent failure or rejection, see pbs_errno * @retval 1 : failed but try again later */ int local_move(job *jobp, struct batch_request *req) { pbs_queue *qp; char *destination = jobp->ji_qs.ji_destin; int mtype; attribute *pattr; long newtype = -1; /* search for destination queue */ if ((qp = find_queuebyname(destination)) == NULL) { sprintf(log_buffer, "queue %s does not exist", destination); log_err(-1, __func__, log_buffer); pbs_errno = PBSE_UNKQUE; return -1; } /* * if being moved at specific request of administrator, then * checks on queue availability, etc. are skipped; * otherwise all checks are enforced. */ if (req == NULL) { mtype = MOVE_TYPE_Route; /* route */ } else if (req->rq_perm & (ATR_DFLAG_MGRD | ATR_DFLAG_MGWR)) { mtype = MOVE_TYPE_MgrMv; /* privileged move */ } else { mtype = MOVE_TYPE_Move; /* non-privileged move */ } pbs_errno = svr_chkque(jobp, qp, get_hostPart(jobp->ji_wattr[(int)JOB_ATR_job_owner].at_val.at_str), mtype); if (pbs_errno) { /* should this queue be retried? */ return (should_retry_route(pbs_errno)); } /* dequeue job from present queue, update destination and */ /* queue_rank for new queue and enqueue into destination */ svr_dequejob(jobp); jobp->ji_myResv = NULL; strncpy(jobp->ji_qs.ji_queue, qp->qu_qs.qu_name, PBS_MAXQUEUENAME); jobp->ji_qs.ji_queue[PBS_MAXQUEUENAME] = '\0'; jobp->ji_wattr[(int)JOB_ATR_qrank].at_val.at_long = ++queue_rank; jobp->ji_wattr[(int)JOB_ATR_qrank].at_flags |= ATR_VFLAG_MODCACHE; pattr = &jobp->ji_wattr[(int)JOB_ATR_reserve_ID]; if (qp->qu_resvp) { job_attr_def[(int)JOB_ATR_reserve_ID].at_decode(pattr, (char *)0, (char *)0, qp->qu_resvp->ri_qs.ri_resvID); jobp->ji_myResv = qp->qu_resvp; } else { job_attr_def[(int)JOB_ATR_reserve_ID].at_decode(pattr, (char *)0, (char *)0, (char*)0); } if (server.sv_attr[(int)SRV_ATR_EligibleTimeEnable].at_val.at_long == 1) { newtype = determine_accruetype(jobp); if (newtype == -1) /* unable to determine accruetype, set it to NEW */ (void)update_eligible_time(JOB_INITIAL, jobp); else /* found suiting accruetype, update to this */ (void)update_eligible_time(newtype, jobp); } if ((pbs_errno = svr_enquejob(jobp)) != 0) return -1; /* should never ever get here */ jobp->ji_lastdest = 0; /* reset in case of another route */ (void)job_save(jobp, SAVEJOB_FULL); /* If a scheduling cycle is in progress, then this moved job may have * had changes resulting from the move that would impact scheduling or * placement, add job to list of jobs which cannot be run in this cycle. */ if ((req == NULL || (req->rq_conn != scheduler_sock)) && (scheduler_jobs_stat)) am_jobs_add(jobp); return 0; }