/** * @brief * issue a batch request to another server or to a MOM * or even to ourself! * * If the request is meant for this every server, then * Set up work-task of type WORK_Deferred_Local with a dummy * connection handle (PBS_LOCAL_CONNECTION). * * Dispatch the request to be processed. [reply_send() will * dispatch the reply via the work task entry.] * * If the request is to another server/MOM, then * Set up work-task of type WORK_Deferred_Reply with the * connection handle as the event. * * Encode and send the request. * * When the reply is ready, process_reply() will decode it and * dispatch the work task. * * @note * IT IS UP TO THE FUNCTION DISPATCHED BY THE WORK TASK TO CLOSE THE * CONNECTION (connection handle not socket) and FREE THE REQUEST * STRUCTURE. The connection (non-negative if open) is in wt_event * and the pointer to the request structure is in wt_parm1. * * @param[in] conn - connection index * @param[in] request - batch request to send * @param[in] func - The callback function to invoke to handle the batch reply * @param[out] ppwt - Return work task to be maintained by server to handle * deferred replies * @param[in] rpp - conn is over tcp or rpp? * * @return Error code * @retval 0 - Success * @retval -1 - Failure * */ int issue_Drequest(int conn, struct batch_request *request, void (*func)(), struct work_task **ppwt, int rpp) { struct attropl *patrl; struct work_task *ptask; struct svrattrl *psvratl; int rc; int sock = -1; enum work_type wt; char *msgid = NULL; request->rppcmd_msgid = NULL; if (conn == PBS_LOCAL_CONNECTION) { wt = WORK_Deferred_Local; request->rq_conn = PBS_LOCAL_CONNECTION; } else if (rpp) { sock = conn; request->rq_conn = conn; wt = WORK_Deferred_Reply; } else { sock = connection[conn].ch_socket; request->rq_conn = sock; wt = WORK_Deferred_Reply; DIS_tcp_setup(sock); } ptask = set_task(wt, (long) conn, func, (void *) request); if (ptask == NULL) { log_err(errno, __func__, "could not set_task"); if (ppwt != 0) *ppwt = 0; return (-1); } if (conn == PBS_LOCAL_CONNECTION) { /* the request should be issued to ourself */ dispatch_request(PBS_LOCAL_CONNECTION, request); if (ppwt != 0) *ppwt = ptask; return (0); } /* the request is bound to another server, encode/send the request */ switch (request->rq_type) { #ifndef PBS_MOM case PBS_BATCH_DeleteJob: rc = PBSD_mgr_put(conn, PBS_BATCH_DeleteJob, MGR_CMD_DELETE, MGR_OBJ_JOB, request->rq_ind.rq_delete.rq_objname, NULL, request->rq_extend, rpp, &msgid); break; case PBS_BATCH_HoldJob: attrl_fixlink(&request->rq_ind.rq_hold.rq_orig.rq_attr); psvratl = (struct svrattrl *)GET_NEXT( request->rq_ind.rq_hold.rq_orig.rq_attr); patrl = &psvratl->al_atopl; rc = PBSD_mgr_put(conn, PBS_BATCH_HoldJob, MGR_CMD_SET, MGR_OBJ_JOB, request->rq_ind.rq_hold.rq_orig.rq_objname, patrl, NULL, rpp, &msgid); break; case PBS_BATCH_MessJob: rc = PBSD_msg_put(conn, request->rq_ind.rq_message.rq_jid, request->rq_ind.rq_message.rq_file, request->rq_ind.rq_message.rq_text, NULL, rpp, &msgid); break; case PBS_BATCH_RelnodesJob: rc = PBSD_relnodes_put(conn, request->rq_ind.rq_relnodes.rq_jid, request->rq_ind.rq_relnodes.rq_node_list, NULL, rpp, &msgid); break; case PBS_BATCH_PySpawn: rc = PBSD_py_spawn_put(conn, request->rq_ind.rq_py_spawn.rq_jid, request->rq_ind.rq_py_spawn.rq_argv, request->rq_ind.rq_py_spawn.rq_envp, rpp, &msgid); break; case PBS_BATCH_ModifyJob: attrl_fixlink(&request->rq_ind.rq_modify.rq_attr); patrl = (struct attropl *)&((struct svrattrl *)GET_NEXT( request->rq_ind.rq_modify.rq_attr))->al_atopl; rc = PBSD_mgr_put(conn, PBS_BATCH_ModifyJob, MGR_CMD_SET, MGR_OBJ_JOB, request->rq_ind.rq_modify.rq_objname, patrl, NULL, rpp, &msgid); break; case PBS_BATCH_Rerun: if (rpp) { rc = is_compose_cmd(sock, IS_CMD, &msgid); if (rc != 0) break; } rc=encode_DIS_ReqHdr(sock, PBS_BATCH_Rerun, pbs_current_user); if (rc != 0) break; rc=encode_DIS_JobId(sock, request->rq_ind.rq_rerun); if (rc != 0) break; rc=encode_DIS_ReqExtend(sock, 0); if (rc != 0) break; rc = DIS_wflush(sock, rpp); break; case PBS_BATCH_RegistDep: if (rpp) { rc = is_compose_cmd(sock, IS_CMD, &msgid); if (rc != 0) break; } rc=encode_DIS_ReqHdr(sock, PBS_BATCH_RegistDep, pbs_current_user); if (rc != 0) break; rc=encode_DIS_Register(sock, request); if (rc != 0) break; rc=encode_DIS_ReqExtend(sock, 0); if (rc != 0) break; rc = DIS_wflush(sock, rpp); break; case PBS_BATCH_SignalJob: rc = PBSD_sig_put(conn, request->rq_ind.rq_signal.rq_jid, request->rq_ind.rq_signal.rq_signame, NULL, rpp, &msgid); break; case PBS_BATCH_StatusJob: rc = PBSD_status_put(conn, PBS_BATCH_StatusJob, request->rq_ind.rq_status.rq_id, NULL, NULL, rpp, &msgid); break; case PBS_BATCH_TrackJob: if (rpp) { rc = is_compose_cmd(sock, IS_CMD, &msgid); if (rc != 0) break; } rc=encode_DIS_ReqHdr(sock, PBS_BATCH_TrackJob, pbs_current_user); if (rc != 0) break; rc=encode_DIS_TrackJob(sock, request); if (rc != 0) break; rc=encode_DIS_ReqExtend(sock, request->rq_extend); if (rc != 0) break; rc = DIS_wflush(sock, rpp); break; case PBS_BATCH_CopyFiles: if (rpp) { rc = is_compose_cmd(sock, IS_CMD, &msgid); if (rc != 0) break; } rc=encode_DIS_ReqHdr(sock, PBS_BATCH_CopyFiles, pbs_current_user); if (rc != 0) break; rc=encode_DIS_CopyFiles(sock, request); if (rc != 0) break; rc=encode_DIS_ReqExtend(sock, 0); if (rc != 0) break; rc = DIS_wflush(sock, rpp); break; case PBS_BATCH_CopyFiles_Cred: if (rpp) { rc = is_compose_cmd(sock, IS_CMD, &msgid); if (rc != 0) break; } rc=encode_DIS_ReqHdr(sock, PBS_BATCH_CopyFiles_Cred, pbs_current_user); if (rc != 0) break; rc=encode_DIS_CopyFiles_Cred(sock, request); if (rc != 0) break; rc=encode_DIS_ReqExtend(sock, 0); if (rc != 0) break; rc = DIS_wflush(sock, rpp); break; case PBS_BATCH_DelFiles: if (rpp) { rc = is_compose_cmd(sock, IS_CMD, &msgid); if (rc != 0) break; } rc=encode_DIS_ReqHdr(sock, PBS_BATCH_DelFiles, pbs_current_user); if (rc != 0) break; rc=encode_DIS_CopyFiles(sock, request); if (rc != 0) break; rc=encode_DIS_ReqExtend(sock, 0); if (rc != 0) break; rc = DIS_wflush(sock, rpp); break; case PBS_BATCH_DelFiles_Cred: if (rpp) { rc = is_compose_cmd(sock, IS_CMD, &msgid); if (rc != 0) break; } rc=encode_DIS_ReqHdr(sock, PBS_BATCH_DelFiles_Cred, pbs_current_user); if (rc != 0) break; rc=encode_DIS_CopyFiles_Cred(sock, request); if (rc != 0) break; rc=encode_DIS_ReqExtend(sock, 0); if (rc != 0) break; rc = DIS_wflush(sock, rpp); break; case PBS_BATCH_FailOver: rc = put_failover(sock, request); /* we should never do rpp for this one */ break; #else /* PBS_MOM */ case PBS_BATCH_JobObit: rc=encode_DIS_ReqHdr(sock, PBS_BATCH_JobObit, pbs_current_user); if (rc != 0) break; rc=encode_DIS_JobObit(sock, request); if (rc != 0) break; rc=encode_DIS_ReqExtend(sock, 0); if (rc != 0) break; rc = DIS_wflush(sock, rpp); break; #endif /* PBS_MOM */ default: (void)sprintf(log_buffer, msg_issuebad, request->rq_type); log_err(-1, __func__, log_buffer); delete_task(ptask); rc = -1; break; } if (rc) { sprintf(log_buffer, "issue_Drequest failed, error=%d on request %d", rc, request->rq_type); log_err(-1, __func__, log_buffer); if (msgid) free(msgid); delete_task(ptask); } else if (ppwt != 0) { if (rpp) { rpp_add_close_func(sock, process_DreplyRPP); /* register a close handler */ ptask->wt_event2 = msgid; /* * since its an rpp delayed task, remove it from the task_event list * caller will add to moms deferred cmd list */ delete_link(&ptask->wt_linkall); } ptask->wt_aux2 = rpp; /* 0 in case of non-TPP */ *ppwt = ptask; } return (rc); }
void dispatch_request(int sfds, struct batch_request *request) { conn_t *conn = NULL; int rpp = request->isrpp; if (!rpp) { if (sfds != PBS_LOCAL_CONNECTION) { conn = get_conn(sfds); if (!conn) { log_event(PBSEVENT_SYSTEM, PBS_EVENTCLASS_REQUEST, LOG_ERR, "dispatch_request", "did not find socket in connection table"); req_reject(PBSE_SYSTEM, 0, request); close_client(sfds); return; } } } switch (request->rq_type) { case PBS_BATCH_QueueJob: if (rpp) { request->rpp_ack = 0; rpp_add_close_func(sfds, close_quejob); } else net_add_close_func(sfds, close_quejob); req_quejob(request); break; case PBS_BATCH_JobCred: #ifndef PBS_MOM /* Reject if a user client (qsub -Wpwd) and not a */ /* server (qmove) enqueued a job with JobCredential */ if ( !request->rq_fromsvr && \ (server.sv_attr[SRV_ATR_ssignon_enable].at_flags \ & ATR_VFLAG_SET) && \ (server.sv_attr[SRV_ATR_ssignon_enable].at_val.at_long == 1) ) { req_reject(PBSE_SSIGNON_SET_REJECT, 0, request); close_client(sfds); break; } #endif if (rpp) request->rpp_ack = 0; req_jobcredential(request); break; case PBS_BATCH_UserCred: #ifdef PBS_MOM #ifdef WIN32 req_reject(PBSE_NOSUP, 0, request); #else req_reject(PBSE_UNKREQ, 0, request); #endif close_client(sfds); #else req_usercredential(request); #endif break; case PBS_BATCH_UserMigrate: #ifdef PBS_MOM #ifdef WIN32 req_reject(PBSE_NOSUP, 0, request); #else req_reject(PBSE_UNKREQ, 0, request); #endif /* WIN32 */ close_client(sfds); #else req_user_migrate(request); #endif /* PBS_MOM */ break; case PBS_BATCH_GSS_Context: req_gsscontext(request); break; case PBS_BATCH_jobscript: if (rpp) request->rpp_ack = 0; req_jobscript(request); break; /* * The PBS_BATCH_Rdytocommit message is deprecated. * The server does not do anything with it anymore, but * simply acks the request (in case some client makes this call) */ case PBS_BATCH_RdytoCommit: if (request->isrpp) request->rpp_ack = 0; reply_ack(request); break; case PBS_BATCH_Commit: if (rpp) request->rpp_ack = 0; req_commit(request); if (rpp) rpp_add_close_func(sfds, (void (*)(int))0); else net_add_close_func(sfds, (void (*)(int))0); break; case PBS_BATCH_DeleteJob: log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_JOB, LOG_INFO, request->rq_ind.rq_delete.rq_objname, "delete job request received"); req_deletejob(request); break; #ifndef PBS_MOM case PBS_BATCH_SubmitResv: req_resvSub(request); break; case PBS_BATCH_DeleteResv: req_deleteReservation(request); break; case PBS_BATCH_ModifyResv: req_modifyReservation(request); break; case PBS_BATCH_ResvOccurEnd: req_reservationOccurrenceEnd(request); break; #endif case PBS_BATCH_HoldJob: if (sfds != PBS_LOCAL_CONNECTION && !rpp) conn->cn_authen |= PBS_NET_CONN_NOTIMEOUT; req_holdjob(request); break; #ifndef PBS_MOM case PBS_BATCH_LocateJob: req_locatejob(request); break; case PBS_BATCH_Manager: req_manager(request); break; case PBS_BATCH_RelnodesJob: req_relnodesjob(request); break; #endif case PBS_BATCH_MessJob: req_messagejob(request); break; case PBS_BATCH_PySpawn: if (sfds != PBS_LOCAL_CONNECTION && !rpp) conn->cn_authen |= PBS_NET_CONN_NOTIMEOUT; req_py_spawn(request); break; case PBS_BATCH_ModifyJob: req_modifyjob(request); break; case PBS_BATCH_Rerun: req_rerunjob(request); break; #ifndef PBS_MOM case PBS_BATCH_MoveJob: req_movejob(request); break; case PBS_BATCH_OrderJob: req_orderjob(request); break; case PBS_BATCH_Rescq: req_reject(PBSE_NOSUP, 0, request); break; case PBS_BATCH_ReserveResc: req_reject(PBSE_NOSUP, 0, request); break; case PBS_BATCH_ReleaseResc: req_reject(PBSE_NOSUP, 0, request); break; case PBS_BATCH_ReleaseJob: if (sfds != PBS_LOCAL_CONNECTION && !rpp) conn->cn_authen |= PBS_NET_CONN_NOTIMEOUT; req_releasejob(request); break; case PBS_BATCH_RunJob: case PBS_BATCH_AsyrunJob: req_runjob(request); break; case PBS_BATCH_DefSchReply: req_defschedreply(request); break; case PBS_BATCH_ConfirmResv: req_confirmresv(request); break; case PBS_BATCH_SelectJobs: case PBS_BATCH_SelStat: req_selectjobs(request); break; #endif /* !PBS_MOM */ case PBS_BATCH_Shutdown: req_shutdown(request); break; case PBS_BATCH_SignalJob: log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_JOB, LOG_INFO, request->rq_ind.rq_signal.rq_jid, "signal job request received"); req_signaljob(request); break; case PBS_BATCH_MvJobFile: req_mvjobfile(request); break; #ifndef PBS_MOM /* Server Only Functions */ case PBS_BATCH_StatusJob: if (set_to_non_blocking(conn) == -1) { req_reject(PBSE_SYSTEM, 0, request); close_client(sfds); return; } req_stat_job(request); clear_non_blocking(conn); break; case PBS_BATCH_StatusQue: if (set_to_non_blocking(conn) == -1) { req_reject(PBSE_SYSTEM, 0, request); close_client(sfds); return; } req_stat_que(request); clear_non_blocking(conn); break; case PBS_BATCH_StatusNode: if (set_to_non_blocking(conn) == -1) { req_reject(PBSE_SYSTEM, 0, request); close_client(sfds); return; } req_stat_node(request); clear_non_blocking(conn); break; case PBS_BATCH_StatusResv: if (set_to_non_blocking(conn) == -1) { req_reject(PBSE_SYSTEM, 0, request); close_client(sfds); return; } req_stat_resv(request); clear_non_blocking(conn); break; case PBS_BATCH_StatusSvr: req_stat_svr(request); break; case PBS_BATCH_StatusSched: req_stat_sched(request); break; case PBS_BATCH_StatusHook: if (!is_local_root(request->rq_user, request->rq_host)) { sprintf(log_buffer, "%s@%s is unauthorized to " "access hooks data from server %s", request->rq_user, request->rq_host, server_host); reply_text(request, PBSE_HOOKERROR, log_buffer); log_event(PBSEVENT_ADMIN, PBS_EVENTCLASS_HOOK, LOG_INFO, "", log_buffer); /* don't call close_client() to allow other */ /* non-hook related requests to continue */ break; } if (set_to_non_blocking(conn) == -1) { req_reject(PBSE_SYSTEM, 0, request); close_client(sfds); return; } req_stat_hook(request); clear_non_blocking(conn); break; case PBS_BATCH_TrackJob: req_track(request); break; case PBS_BATCH_RegistDep: req_register(request); break; case PBS_BATCH_AuthenResvPort: if (pbs_conf.auth_method == AUTH_MUNGE) { req_reject(PBSE_BADCRED, 0, request); close_client(sfds); return; } req_authenResvPort(request); break; case PBS_BATCH_StageIn: req_stagein(request); break; case PBS_BATCH_FailOver: req_failover(request); break; case PBS_BATCH_StatusRsc: req_stat_resc(request); break; case PBS_BATCH_MomRestart: log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_NODE, LOG_INFO, request->rq_ind.rq_momrestart.rq_momhost, "Mom restarted on host"); req_momrestart(request); break; #else /* MOM only functions */ case PBS_BATCH_CopyFiles: log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_JOB, LOG_INFO, request->rq_ind.rq_cpyfile.rq_jobid, "copy file request received"); /* don't time-out as copy may take long time */ if (sfds != PBS_LOCAL_CONNECTION && !rpp) conn->cn_authen |= PBS_NET_CONN_NOTIMEOUT; req_cpyfile(request); break; case PBS_BATCH_CopyFiles_Cred: log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_JOB, LOG_INFO, request->rq_ind.rq_cpyfile_cred.rq_copyfile.rq_jobid, "copy file cred request received"); /* don't time-out as copy may take long time */ if (sfds != PBS_LOCAL_CONNECTION && !rpp) conn->cn_authen |= PBS_NET_CONN_NOTIMEOUT; req_cpyfile(request); break; case PBS_BATCH_DelFiles: log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_JOB, LOG_INFO, request->rq_ind.rq_cpyfile.rq_jobid, "delete file request received"); req_delfile(request); break; case PBS_BATCH_DelFiles_Cred: log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_JOB, LOG_INFO, request->rq_ind.rq_cpyfile_cred.rq_copyfile.rq_jobid, "delete file cred request received"); req_delfile(request); break; case PBS_BATCH_CopyHookFile: log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_HOOK, LOG_INFO, request->rq_ind.rq_hookfile.rq_filename, "copy hook-related file request received"); req_copy_hookfile(request); break; case PBS_BATCH_DelHookFile: log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_HOOK, LOG_INFO, request->rq_ind.rq_hookfile.rq_filename, "delete hook-related file request received"); req_del_hookfile(request); break; #endif default: req_reject(PBSE_UNKREQ, 0, request); close_client(sfds); break; } return; }
/** * @brief * Send execution job on connected rpp stream. * * @param[in] jobp - pointer to the job being sent * @param[in] hostaddr - the address of host to send job to, host byte order * @param[in] port - the destination port, host byte order * @param[in] request - The batch request associated with this send job call * * @return int * @retval 2 : success * @retval -1 : failure (pbs_errno set to error number) * */ int send_job_exec(job *jobp, pbs_net_t hostaddr, int port, struct batch_request *request) { pbs_list_head attrl; attribute *pattr; mominfo_t *pmom = NULL; int stream = -1; int encode_type; char *destin = jobp->ji_qs.ji_destin; int i; size_t credlen = 0; char *credbuf = NULL; char job_id[PBS_MAXSVRJOBID + 1]; struct attropl *pqjatr; /* list (single) of attropl for quejob */ int rc; int rpp = 1; char *jobid = NULL; char *script = NULL; char *msgid = NULL; char *dup_msgid = NULL; struct work_task *ptask = NULL; /* if job has a script read it from database */ if (jobp->ji_qs.ji_svrflags & JOB_SVFLG_SCRIPT) { /* * copy the job script from database to a temp file * PBSD_jscript works with a file * delete it at the end of the send */ if ((script = svr_load_jobscript(jobp)) == NULL) { pbs_errno = PBSE_SYSTEM; snprintf(log_buffer, sizeof(log_buffer), "Failed to load job script for job %s", jobp->ji_qs.ji_jobid); log_err(pbs_errno, "send_job", log_buffer); goto send_err; } } stream = svr_connect(hostaddr, port, NULL, ToServerDIS, rpp); if (stream < 0) { log_event(PBSEVENT_ERROR, PBS_EVENTCLASS_REQUEST, LOG_WARNING, "", "Could not connect to Mom"); goto send_err; } pmom = tfind2((unsigned long) jobp->ji_qs.ji_un.ji_exect.ji_momaddr, jobp->ji_qs.ji_un.ji_exect.ji_momport, &ipaddrs); if (!pmom || (((mom_svrinfo_t *)(pmom->mi_data))->msr_state & INUSE_DOWN)) goto send_err; CLEAR_HEAD(attrl); resc_access_perm = ATR_DFLAG_MOM; encode_type = ATR_ENCODE_MOM; pattr = jobp->ji_wattr; for (i = 0; i < (int) JOB_ATR_LAST; i++) { if ((job_attr_def + i)->at_flags & resc_access_perm) { (void)(job_attr_def + i)->at_encode(pattr + i, &attrl, (job_attr_def + i)->at_name, (char *) 0, encode_type, NULL); } } attrl_fixlink(&attrl); /* save the job id for when after we purge the job */ /* read any credential file */ (void)get_credential(pmom->mi_host, jobp, PBS_GC_BATREQ, &credbuf, &credlen); (void) strcpy(job_id, jobp->ji_qs.ji_jobid); pbs_errno = 0; pqjatr = &((svrattrl *) GET_NEXT(attrl))->al_atopl; jobid = PBSD_queuejob(stream, jobp->ji_qs.ji_jobid, destin, pqjatr, (char *) 0, rpp, &msgid); free_attrlist(&attrl); if (jobid == NULL) goto send_err; rpp_add_close_func(stream, process_DreplyRPP); /* register a close handler */ /* adding msgid to deferred list, dont free msgid */ if ((ptask = add_mom_deferred_list(stream, pmom, post_sendmom, msgid, request, jobp)) == NULL) goto send_err; /* add to pjob->svrtask list so its automatically cleared when job is purged */ append_link(&jobp->ji_svrtask, &ptask->wt_linkobj, ptask); /* we cannot use the same msgid, since it is not part of the preq, * make a dup of it, and we can freely free it */ if ((dup_msgid = strdup(msgid)) == NULL) goto send_err; /* * henceforth use the same msgid, since we mean to say all this is * part of a single logical request to the mom * and we will be hanging off one request to be answered to finally */ if (jobp->ji_qs.ji_svrflags & JOB_SVFLG_SCRIPT) { if (PBSD_jscript_direct(stream, script, rpp, &dup_msgid) != 0) goto send_err; } free(script); script = NULL; if (credlen > 0) { rc = PBSD_jcred(stream, jobp->ji_extended.ji_ext.ji_credtype, credbuf, credlen, rpp, &dup_msgid); if (credbuf) free(credbuf); if (rc != 0) goto send_err; } if ((jobp->ji_qs.ji_svrflags & JOB_SVFLG_HASRUN) && (hostaddr != pbs_server_addr)) { if ((move_job_file(stream, jobp, StdOut, rpp, &dup_msgid) != 0) || (move_job_file(stream, jobp, StdErr, rpp, &dup_msgid) != 0) || (move_job_file(stream, jobp, Chkpt, rpp, &dup_msgid) != 0)) goto send_err; } if (PBSD_commit(stream, job_id, rpp, &dup_msgid) != 0) goto send_err; free(dup_msgid); /* free this as it is not part of any work task */ return 2; send_err: if (dup_msgid) free(dup_msgid); if (script) free(script); if (ptask) { if (ptask->wt_event2) free(ptask->wt_event2); delete_task(ptask); } sprintf(log_buffer, "send of job to %s failed error = %d", destin, pbs_errno); log_event(PBSEVENT_JOB, PBS_EVENTCLASS_JOB, LOG_INFO, jobp->ji_qs.ji_jobid, log_buffer); return (-1); }