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() */
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; bool reservation1 = false; bool reservation2 = false; 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; if (pjob2 == NULL) job2_mutex.set_unlock_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) { reservation1 = have_reservation(pjob1, pque2); pque2_mutex.unlock(); if ((pque1 = get_jobs_queue(&pjob1)) == NULL) { rc = PBSE_BADSTATE; if (pjob1 == NULL) job1_mutex.set_unlock_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) { reservation2 = have_reservation(pjob2, pque1); 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, reservation1) == PBSE_JOB_RECYCLED) { pjob1 = NULL; job1_mutex.set_unlock_on_exit(false); } if (svr_enquejob(pjob2, FALSE, -1, reservation2) == PBSE_JOB_RECYCLED) { pjob2 = NULL; job2_mutex.set_unlock_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() */