/** * SSH job: Popen * If command is NULL, "/bin/sh" used as command. */ static pid_t ngislSSHjobSSHpopen( ngisSSHjob_t *job, char *command, ngisStandardIO_t* sio) { char *sshCommand = NULL; pid_t ret = -1; ngisLog_t *log; static const char fName[] = "ngislSSHjobSSHpopen"; NGIS_ASSERT(job != NULL); NGIS_ASSERT(sio != NULL); log = job->ngsj_log; sshCommand = ngisSSHjobCreateSSHcommand(job, command); if (sshCommand == NULL) { ngisErrorPrint(log, fName, "Can't create SSH command.\n"); goto finalize; } ret = ngisPopen(sio, sshCommand); if (ret < 0) { ngisErrorPrint(log, fName, "Can't execute SSH command.\n"); goto finalize; } finalize: NGIS_NULL_CHECK_AND_FREE(sshCommand); return ret; }
static int ngislSSHjobDisable( ngisSSHjob_t *job) { int result; int ret = 1; ngisLog_t *log; static const char fName[] = "ngislSSHjobDisable"; NGIS_ASSERT(job != NULL); log = ((ngisJob_t *)job)->ngj_log; /* Stop file transfer */ if (job->ngsj_fileTransfer != NULL) { result = ngisSSHjobFileTransferDestroy(job->ngsj_fileTransfer); if (result == 0) { ngisErrorPrint(log, fName, "Can't destroy file transfer.\n"); ret = 0; } } NGIS_NULL_CHECK_AND_DESTROY(job->ngsj_timerCallback, ngisCallbackCancel); NGIS_NULL_CHECK_AND_DESTROY(job->ngsj_stdinCallback, ngisCallbackCancel); NGIS_NULL_CHECK_AND_FREE(job->ngsj_command); NGIS_NULL_CHECK_AND_DESTROY(job->ngsj_lBufStdout, ngisLineBufferDestroy); NGIS_NULL_CHECK_AND_DESTROY(job->ngsj_lBufStderr, ngisLineBufferDestroy); result = ngisStandardIOclose(&job->ngsj_stdio); if (result == 0) { ngisErrorPrint(log, fName, "Can't close the STDIO\n"); ret = 0; } /* Remove Script File */ #define NGISL_SSH_JOB_FILE_DESTROY(filename) do { \ char *scriptName = (filename); \ if (scriptName != NULL) { \ ngisDebugPrint(log, fName, "Unlink %s.\n", scriptName); \ result = unlink(scriptName); \ if (result < 0) { \ ngisErrorPrint(log, fName, \ "unlink(%s): %s", scriptName, strerror(errno)); \ ret = 0; \ } \ } \ NGIS_NULL_CHECK_AND_FREE(filename); \ }while (0) NGISL_SSH_JOB_FILE_DESTROY(job->ngsj_localScriptNameForArrayJob); NGISL_SSH_JOB_FILE_DESTROY(job->ngsj_localScriptName); #undef NGISL_SSH_JOB_FILE_DESTROY return ret; }
/** * SSH Job: Finalize */ static int ngislSSHjobFinalize( ngisJob_t *job) { int result; int ret = 1; ngisLog_t *log; ngisSSHjob_t *sshJob = (ngisSSHjob_t *)job; static const char fName[] = "ngislSSHjobFinalize"; NGIS_ASSERT(sshJob != NULL); log = job->ngj_log; result = ngislSSHjobDisable(sshJob); if (result == 0) { ngisErrorPrint(log, fName, "Can't disable the SSH job."); } /* Destroy Executables */ if (sshJob->ngsj_executables != NULL) { ngislExecutableDestroy( sshJob->ngsj_executables, sshJob->ngsj_nExecutables); sshJob->ngsj_executables = NULL; } NGIS_NULL_CHECK_AND_DESTROY( sshJob->ngsj_attributes, ngisSSHjobAttributesDestroy); NGIS_NULL_CHECK_AND_FREE(sshJob->ngsj_remoteExecutablePath); NGIS_NULL_CHECK_AND_FREE(sshJob->ngsj_remoteTempdir); NGIS_NULL_CHECK_AND_FREE(sshJob->ngsj_remoteTempdirBase); NGIS_NULL_CHECK_AND_FREE(sshJob->ngsj_pidRemoteSh); if (!NGIS_LIST_IS_INVALID_VALUE(&sshJob->ngsj_funcQueue)) { NGIS_LIST_FINALIZE(ngisSSHjobFunc_t, &sshJob->ngsj_funcQueue); } ngislSSHjobInitializeMember(sshJob); return ret; }
int ngisSSHjobPBSdoCancel( ngisSSHjob_t *job) { ngisStringBuffer_t sBuf; int sBufInitialized = 0; char *command = NULL; int i; int ret = 1; int nExe = 0; int result; ngisCallback_t callback; ngisLog_t *log; static const char fName[] = "ngisSSHjobPBSdoCancel"; NGIS_ASSERT(job != NULL); log = job->ngsj_log; nExe = ngisSSHjobGetNexecutable(job, NGIS_EXECUTABLE_STATUS_PENDING); nExe += ngisSSHjobGetNexecutable(job, NGIS_EXECUTABLE_STATUS_ACTIVE); if (nExe == 0) { /* There is no executable. */ goto finalize; } result = ngisStringBufferInitialize(&sBuf); if (result == 0) { ngisErrorPrint(log, fName, "Can't initialize the string buffer.\n"); ret = 0; goto finalize; } sBufInitialized = 1; result = ngisStringBufferAppend(&sBuf, job->ngsj_attributes->ngsja_sshDeleteCommand); if (result == 0) { ngisErrorPrint(log, fName, "Can't append string to the string buffer.\n"); ret = 0; goto finalize; } for (i = 0;i < job->ngsj_nExecutables;++i) { switch (job->ngsj_executables[i].nge_status) { case NGIS_EXECUTABLE_STATUS_PENDING: case NGIS_EXECUTABLE_STATUS_ACTIVE: result = ngisStringBufferFormat(&sBuf, " %s", job->ngsj_executables[i].nge_identifier); if (result == 0) { ngisErrorPrint(log, fName, "Can't append string to the string buffer.\n"); ret = 0; goto finalize; } break; default: break; } } result = ngisStringBufferAppend(&sBuf, "\n"); if (result == 0) { ngisErrorPrint(log, fName, "Can't append string to the string buffer.\n"); ret = 0; goto finalize; } command = ngisStringBufferRelease(&sBuf); if (command == NULL) { ngisErrorPrint(log, fName, "Can't release string from string buffer.\n"); ret = 0; goto finalize; } callback = ngisCallbackWriteFormat( job->ngsj_stdio.ngsio_in, ngisSSHjobCancelWriteCallback, job, "%s", command); if (!ngisCallbackIsValid(callback)) { ngisErrorPrint(log, fName, "Can't send command string.\n"); ret = 0; goto finalize; } job->ngsj_stdinCallback = callback; finalize: NGIS_NULL_CHECK_AND_FREE(command); if (sBufInitialized != 0) { ngisStringBufferFinalize(&sBuf); sBufInitialized = 0; } return ret; }
static void ngislSSHjobPBSqueryStatusReadCallback( void *arg, ngisLineBuffer_t *lBuf, char *line, ngisCallbackResult_t cResult) { ngisSSHjob_t *job = arg; int result; int i; ngisTokenAnalyzer_t tokenAnalyzer; int tokenAnalyzerInitialized = 0; char *status = NULL; ngisLog_t *log; static const char fName[] = "ngislSSHjobPBSqueryStatusReadCallback"; NGIS_ASSERT(job != NULL); NGIS_ASSERT(lBuf != NULL); log = job->ngsj_log; switch (cResult) { case NGIS_CALLBACK_RESULT_EOF: ngisErrorPrint(log, fName, "Unexcept EOF.\n"); goto error; case NGIS_CALLBACK_RESULT_CANCEL: ngisDebugPrint(log, fName, "Callback is canceled.\n"); return; case NGIS_CALLBACK_RESULT_FAILED: ngisErrorPrint(log, fName, "Can't read the reply.\n"); goto error; case NGIS_CALLBACK_RESULT_SUCCESS: break; default: NGIS_ASSERT_NOTREACHED(); } /* Failed? */ if (strcmp(line, "dummy") == 0) { /* Done */ job->ngsj_executables[0].nge_exitCode = 0;/* Success */ result = ngisSSHjobExecutableSetStatus( job, &job->ngsj_executables[0], NGIS_EXECUTABLE_STATUS_EXIT); if (result == 0) { ngisErrorPrint(log, fName, "Can't set status.\n"); goto error; } result = ngisSSHjobProcessAfterExit(job); if (result == 0) { ngisErrorPrint(log, fName, "Can't process after exit.\n"); goto error; } return; } ngisTokenAnalyzerInitialize(&tokenAnalyzer, line); tokenAnalyzerInitialized = 0; /* job_state = [STATUS] */ for (i = 0;i < 2;++i) { result = ngisTokenAnalyzerNext(&tokenAnalyzer); if (result == 0) { ngisErrorPrint(log, fName, "Can't get status.\n."); goto error; } } /* Get Status */ status = ngisTokenAnalyzerGetString(&tokenAnalyzer); if (status == NULL) { ngisErrorPrint(log, fName, "Can't get status.\n"); goto error; } ngisDebugPrint(log, fName, "Status string is \"%s\".\n", status); /* Check Status */ switch (*status) { case 'Q': case 'W': case 'T': break; case 'B': case 'E': case 'R': case 'X': /* t(ransfering), r(unning) */ job->ngsj_executables[0].nge_status = NGIS_EXECUTABLE_STATUS_ACTIVE; break; case 'H': /* Do nothing */ break; case 'S': break; case 'U': default: /* DONOTHING */; } free(status); status = NULL; ngisTokenAnalyzerFinalize(&tokenAnalyzer); tokenAnalyzerInitialized = 0; result = ngisLineBufferReadLine(job->ngsj_lBufStdout, ngisSSHjobQueryStatusReadDummyCallback, job); if (result == 0) { ngisErrorPrint(log, fName, "Can't register the function for reading the line.\n"); goto error; } return; error: NGIS_NULL_CHECK_AND_FREE(status); if (tokenAnalyzerInitialized != 0) { ngisTokenAnalyzerFinalize(&tokenAnalyzer); tokenAnalyzerInitialized = 0; } result = ngisSSHjobProcessAfterExit(job); if (result == 0) { ngisErrorPrint(NULL, fName, "The job isn't able to be done.\n"); } return; }
static void ngislSSHjobPBSsubmitReadCallback( void *arg, ngisLineBuffer_t *lBuf, char *line, ngisCallbackResult_t cResult) { ngisSSHjob_t *job = arg; int result; char *jobID = NULL; int nActive; ngisLog_t *log; static const char fName[] = "ngislSSHjobPBSsubmitReadCallback"; NGIS_ASSERT(job != NULL); NGIS_ASSERT(lBuf != NULL); log = job->ngsj_log; switch (cResult) { case NGIS_CALLBACK_RESULT_CANCEL: ngisDebugPrint(log, fName, "Callback is canceled.\n"); return; case NGIS_CALLBACK_RESULT_EOF: ngisErrorPrint(log, fName, "Unexcept EOF.\n"); goto error; case NGIS_CALLBACK_RESULT_FAILED: ngisErrorPrint(log, fName, "Can't read the reply.\n"); goto error; case NGIS_CALLBACK_RESULT_SUCCESS: break; default: NGIS_ASSERT_NOTREACHED(); } /* Failed? */ if (strcmp(line, NGIS_SSH_JOB_COMMAND_FAILED) == 0) { ngisErrorPrint(log, fName, "Can't submit the job.\n"); goto next; } ngisDebugPrint(log, fName, "Job ID = %s.\n", line); jobID = strdup(line); if (jobID == NULL) { ngisErrorPrint(log, fName, "Can't copy the job ID.\n"); goto next; } next: if (jobID != NULL) { job->ngsj_executables[job->ngsj_iExecutables].nge_identifier = jobID; jobID = NULL; result = ngisSSHjobExecutableSetStatus( job, &job->ngsj_executables[job->ngsj_iExecutables], NGIS_EXECUTABLE_STATUS_PENDING); if (result == 0) { ngisErrorPrint(log, fName, "Can't set status.\n"); goto next; } } else { result = ngisSSHjobExecutableSetStatus( job, &job->ngsj_executables[job->ngsj_iExecutables], NGIS_EXECUTABLE_STATUS_FAILED); if (result == 0) { ngisErrorPrint(log, fName, "Can't set status.\n"); } } job->ngsj_iExecutables++; if (job->ngsj_iExecutables < job->ngsj_nExecutables) { result = ngislSSHjobPBSsubmit(job); if (result == 0) { ngisErrorPrint(log, fName, "Can't submit next job.\n"); goto error; } } else { nActive = ngisSSHjobGetNexecutable(job, NGIS_EXECUTABLE_STATUS_PENDING); if (nActive == 0) { ngisErrorPrint(log, fName, "Can't execute all executables.\n"); goto error; } /* Polling Start */ result = ngisSSHjobPollingStart(job); if (result == 0) { ngisErrorPrint(log, fName, "Can't start status polling.\n"); goto error; } } return; error: NGIS_NULL_CHECK_AND_FREE(jobID); result = ngisSSHjobProcessAfterExit(job); if (result == 0) { ngisErrorPrint(NULL, fName, "The job isn't able to be done.\n"); } return; }
static int ngislSSHjobDoCancel( ngisSSHjob_t* job) { ngisStringBuffer_t sBuf; int sBufInitialized = 0; char *command = NULL; int i; int ret = 1; int nActive = 0; int result; ngisCallback_t callback; ngisLog_t *log; ngisExecutable_t *exe; static const char fName[] = "ngislSSHjobDoCancel"; NGIS_ASSERT(job != NULL); log = job->ngsj_log; nActive = ngisSSHjobGetNexecutable(job, NGIS_EXECUTABLE_STATUS_ACTIVE); if (nActive == 0) { /* There is no executable. */ goto finalize; } result = ngisStringBufferInitialize(&sBuf); if (result == 0) { ngisErrorPrint(log, fName, "Can't initialize the string buffer.\n"); ret = 0; goto finalize; } sBufInitialized = 1; result = ngisStringBufferAppend(&sBuf, NGIS_KILL_COMMAND); if (result == 0) { ngisErrorPrint(log, fName, "Can't append string to the string buffer.\n"); ret = 0; goto finalize; } for (i = 0;i < job->ngsj_nExecutables;++i) { exe = &job->ngsj_executables[i]; if (exe->nge_status == NGIS_EXECUTABLE_STATUS_ACTIVE) { result = ngisStringBufferFormat(&sBuf, " %s", exe->nge_identifier); if (result == 0) { ngisErrorPrint(log, fName, "Can't append string to the string buffer.\n"); ret = 0; goto finalize; } } } result = ngisStringBufferAppend(&sBuf, "\n"); if (result == 0) { ngisErrorPrint(log, fName, "Can't append string to the string buffer.\n"); ret = 0; goto finalize; } command = ngisStringBufferRelease(&sBuf); if (command == NULL) { ngisErrorPrint(log, fName, "Can't append string to the string buffer.\n"); ret = 0; goto finalize; } callback = ngisCallbackWriteFormat(job->ngsj_stdio.ngsio_in, ngisSSHjobCancelWriteCallback, job, "%s", command); if (!ngisCallbackIsValid(callback)) { ngisErrorPrint(log, fName, "Can't register function for sending command string.\n"); ret = 0; goto finalize; } job->ngsj_stdinCallback = callback; finalize: NGIS_NULL_CHECK_AND_FREE(command); if (sBufInitialized != 0) { ngisStringBufferFinalize(&sBuf); sBufInitialized = 0; } return ret; }
/** * SSH Job: Initialize */ static int ngislSSHjobInitialize( ngisJob_t *job, ngisOptionContainer_t *opts) { ngisSSHjob_t *sshJob = (ngisSSHjob_t *)job; ngisSSHjobAttributes_t *attr = NULL; char *jobID = NULL; int result; pid_t pid = -1; ngisLog_t *log = NULL; static const char fName[] = "ngislSSHjobInitialize"; NGIS_ASSERT(sshJob != NULL); NGIS_ASSERT(opts != NULL); log = job->ngj_log; ngislSSHjobInitializeMember(sshJob); /* Function Queue */ NGIS_LIST_INITIALIZE(ngisSSHjobFunc_t, &sshJob->ngsj_funcQueue); /* Create SSH Job Attribute from Invoke Server Options */ attr = ngisSSHjobAttributesCreate(opts); if (attr == NULL) { ngisErrorPrint(log, fName, "Can't create SSH job attributes.\n"); goto error; } sshJob->ngsj_attributes = attr; ngislSSHjobWarnIgnoredOptions(sshJob, opts); /* Set JobManager*/ if ((attr->ngsja_jobManager == NULL) || (strcmp(attr->ngsja_jobManager, "jobmanager-fork") == 0)) { sshJob->ngsj_jobManagerType = NGIS_SSH_JOB_MANAGER_NORMAL; } else if (strcmp(attr->ngsja_jobManager, "jobmanager-sge") == 0) { sshJob->ngsj_jobManagerType = NGIS_SSH_JOB_MANAGER_SGE; } else if (strcmp(attr->ngsja_jobManager, "jobmanager-pbs") == 0) { sshJob->ngsj_jobManagerType = NGIS_SSH_JOB_MANAGER_PBS; } else { ngisErrorPrint(log, fName, "Invalid job manager.\n"); goto error; } /* Number of the job of queuing system */ switch (attr->ngsja_jobBackend) { case NGIS_BACKEND_NORMAL: switch(sshJob->ngsj_jobManagerType) { case NGIS_SSH_JOB_MANAGER_PBS: case NGIS_SSH_JOB_MANAGER_SGE: sshJob->ngsj_nExecutables = 1; break; case NGIS_SSH_JOB_MANAGER_NORMAL: sshJob->ngsj_nExecutables = attr->ngsja_count; break; } break; case NGIS_BACKEND_MPI: case NGIS_BACKEND_BLACS: sshJob->ngsj_nExecutables = 1; break; default: NGIS_ASSERT_NOTREACHED(); } /* Create Executable Handle */ sshJob->ngsj_executables = ngislExecutableCreate(sshJob->ngsj_nExecutables, log); if (sshJob->ngsj_executables == NULL) { ngisErrorPrint(log, fName, "Can't create the executables.\n"); goto error; } /* Execute SSH */ pid = ngislSSHjobExecuteSSH(sshJob); if (pid < 0) { ngisErrorPrint(log, fName, "Can't execute SSH.\n"); goto error; } /* Create Line Buffer */ sshJob->ngsj_lBufStdout = ngisLineBufferCreate(sshJob->ngsj_stdio.ngsio_out, "\n"); if (sshJob->ngsj_lBufStdout == NULL) { ngisErrorPrint(log, fName, "Can't create line buffer for the STDOUT.\n"); goto error; } sshJob->ngsj_lBufStderr = ngisLineBufferCreate(sshJob->ngsj_stdio.ngsio_error, "\n"); if (sshJob->ngsj_lBufStderr == NULL) { ngisErrorPrint(log, fName, "Can't create line buffer for the STDERR.\n"); goto error; } /* Register function for reading STDERR */ result = ngisLineBufferReadLine( sshJob->ngsj_lBufStderr, ngisSSHjobErrorCallback, sshJob); if (result == 0) { ngisErrorPrint(log, fName, "Can't register callback for reading STDERR.\n"); goto error; } /* Prepare submitting the job */ switch (sshJob->ngsj_jobManagerType) { case NGIS_SSH_JOB_MANAGER_NORMAL: result = ngisSSHjobPrepare(sshJob); break; case NGIS_SSH_JOB_MANAGER_SGE: result = ngisSSHjobSGEprepare(sshJob); break; case NGIS_SSH_JOB_MANAGER_PBS: result = ngisSSHjobPBSprepare(sshJob); break; default: NGIS_ASSERT_NOTREACHED(); } if (result == 0) { ngisErrorPrint(log, fName, "Can't prepare.\n"); goto error; } /* Job ID is process ID of SSH */ jobID = ngisStrdupPrintf("%ld", (long)pid); if (jobID == NULL) { ngisErrorPrint(log, fName, "Can't create Job ID.\n"); goto error; } result = ngisJobRegisterID(job, jobID); if (result == 0) { ngisErrorPrint(log, fName, "Can't register Job ID to protocol.\n"); goto error; } result = ngisSSHjobFunctionPop(sshJob); if (result == 0) { ngisErrorPrint(log, fName, "Can't execute the next process.\n"); goto error; } NGIS_NULL_CHECK_AND_FREE(jobID); return 1; /* Error occurred */ error: NGIS_NULL_CHECK_AND_FREE(jobID); result = ngislSSHjobFinalize(job); if (result == 0) { ngisErrorPrint(log, fName, "Can't finalize the ssh job.\n"); } return 0; }
static int ngislSSHjobTransferStdouterr( ngisSSHjob_t *job, ngisSSHjobTransferTarget_t targetType) { ngisSSHjobFileTransfer_t *fileTransfer = NULL; int ret = 1; int result; char *remoteFileName = NULL; char *localFileName = NULL; char *remoteFileNameFormat = NULL; ngisLog_t *log; static const char fName[] = "ngislSSHjobTransferStdouterr"; NGIS_ASSERT(job != NULL); log = job->ngsj_log; switch (targetType) { case NGIS_SSH_JOB_TRANSFER_STDOUT: remoteFileNameFormat = "%s/stdout.*"; localFileName = job->ngsj_attributes->ngsja_stdoutFile; break; case NGIS_SSH_JOB_TRANSFER_STDERR: remoteFileNameFormat = "%s/stderr.*"; localFileName = job->ngsj_attributes->ngsja_stderrFile; break; default: NGIS_ASSERT_NOTREACHED(); } remoteFileName = ngisStrdupPrintf( remoteFileNameFormat, job->ngsj_remoteTempdir); if (remoteFileName == NULL) { ngisErrorPrint(log, fName, "Can't copy string of temporary filename.\n"); ret = 0; goto finalize; } fileTransfer = ngisSSHjobFileTransferCreate( job, localFileName, remoteFileName, NGIS_SSH_JOB_FILE_TRANSFER_REMOTE_TO_LOCAL); if (fileTransfer == NULL) { ngisErrorPrint(log, fName, "Can't create file transfer.\n"); ret = 0; goto finalize; } result = ngisSSHjobFileTransferStart(fileTransfer); if (result == 0) { ngisErrorPrint(log, fName, "Can't start file transfer.\n"); ret = 0; goto finalize; } finalize: NGIS_NULL_CHECK_AND_FREE(remoteFileName); if ((ret == 0) && (fileTransfer != NULL)) { result = ngisSSHjobFileTransferDestroy(fileTransfer); if (result == 0) { ngisErrorPrint(log, fName, "Can't destroy file transfer.\n"); } } return ret; }