Пример #1
0
/**
 * @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);
}
Пример #2
0
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;
}
Пример #3
0
/**
 * @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);
}