/*___INFO__MARK_BEGIN__*/ /************************************************************************* * * The Contents of this file are made available subject to the terms of * the Sun Industry Standards Source License Version 1.2 * * Sun Microsystems Inc., March, 2001 * * * Sun Industry Standards Source License Version 1.2 * ================================================= * The contents of this file are subject to the Sun Industry Standards * Source License Version 1.2 (the "License"); You may not use this file * except in compliance with the License. You may obtain a copy of the * License at http://gridengine.sunsource.net/Gridengine_SISSL_license.html * * Software provided under this License is provided on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. * See the License for the specific provisions governing your rights and * obligations concerning the Software. * * The Initial Developer of the Original Code is: Sun Microsystems, Inc. * * Copyright: 2001 by Sun Microsystems, Inc. * * All Rights Reserved. * ************************************************************************/ /*___INFO__MARK_END__*/ #include #include #include #include "Job.h" /****** C_Job::C_Job() ********************************************************* * NAME * C_Job::C_Job() -- constructor of the job object * * SYNOPSIS * C_Job::C_Job() * * FUNCTION * Initializes an empty job object. * * NOTES *******************************************************************************/ C_Job::C_Job() { m_JobStatus = js_Invalid; m_job_id = 0; m_ja_task_id = 0; m_pe_task_id = NULL; m_comm_sock = 0; m_hProcess = INVALID_HANDLE_VALUE; m_hJobObject = NULL; m_ForwardedSignal = 0; // data members to start the job jobname = NULL; nargs = 0; args = NULL; nconf = 0; conf = NULL; nenv = 0; env = NULL; user = NULL; pass = NULL; domain = NULL; // data members that hold results and usage mem = 0; cpu = 0; vmem = 0; dwExitCode = 0; // Exit code of job, if it ran szError = NULL; // Error message, in case of error lUserSec = 0; // User part of job run time lUserUSec = 0; // User part of job run time usec lKernelSec = 0; // Kernel part of job run time lKernelUSec = 0; // Kernel part of job run time usec } /****** C_Job::C_Job() ********************************************************* * NAME * C_Job::C_Job() -- copy-constructor of the job object * * SYNOPSIS * C_Job::C_Job(const C_Job& otherJob) * * FUNCTION * Copies the content of otherJob to this job object. * * NOTES *******************************************************************************/ C_Job::C_Job(const C_Job& otherJob) { int i; m_JobStatus = otherJob.m_JobStatus; m_job_id = otherJob.m_job_id; m_ja_task_id = otherJob.m_ja_task_id; m_pe_task_id = otherJob.m_pe_task_id ? strdup(otherJob.m_pe_task_id) : NULL; m_comm_sock = otherJob.m_comm_sock; m_hProcess = otherJob.m_hProcess; m_hJobObject = otherJob.m_hJobObject; m_ForwardedSignal = otherJob.m_ForwardedSignal; // data members to start the job jobname = otherJob.jobname ? strdup(otherJob.jobname) : NULL; nargs = otherJob.nargs; args = new char*[nargs]; for(i=0; i"); strcat(pszBuffer, szTemp); sprintf(szTemp, "%d\n", m_comm_sock); strcat(pszBuffer, szTemp); sprintf(szTemp, "%p\n", m_hProcess); strcat(pszBuffer, szTemp); sprintf(szTemp, "%d\n", m_ForwardedSignal); strcat(pszBuffer, szTemp); sprintf(szTemp, "%s\n", jobname ? jobname : ""); strcat(pszBuffer, szTemp); sprintf(szTemp, "%d\n", nargs); strcat(pszBuffer, szTemp); for(i=0; i"); strcat(pszBuffer, szTemp); sprintf(szTemp, "%s\n", pass ? pass : ""); strcat(pszBuffer, szTemp); sprintf(szTemp, "%s\n", domain ? domain : ""); strcat(pszBuffer, szTemp); sprintf(szTemp, "%ld\n", mem); strcat(pszBuffer, szTemp); sprintf(szTemp, "%ld\n", cpu); strcat(pszBuffer, szTemp); sprintf(szTemp, "%ld\n", vmem); strcat(pszBuffer, szTemp); sprintf(szTemp, "%ld\n", dwExitCode); strcat(pszBuffer, szTemp); sprintf(szTemp, "%s\n", szError); strcat(pszBuffer, szTemp); sprintf(szTemp, "%ld\n", lUserSec); strcat(pszBuffer, szTemp); sprintf(szTemp, "%ld\n", lUserUSec); strcat(pszBuffer, szTemp); sprintf(szTemp, "%ld\n", lKernelSec); strcat(pszBuffer, szTemp); sprintf(szTemp, "%ld\n", lKernelUSec); strcat(pszBuffer, szTemp); dwBufLen = (DWORD)strlen(pszBuffer); bRet = WriteFile(hFile, pszBuffer, dwBufLen, &dwWritten, NULL); delete pszBuffer; return bRet ? dwWritten : -1; } /****** C_Job::Unserialize() *************************************************** * NAME * C_Job::Unserialize() -- Reads this C_Job object from a file * * SYNOPSIS * int C_Job::Unserialize(HANDLE hFile) * * FUNCTION * Reads this C_Job object from a file. * * INPUTS * HANDLE hFile - Handle of the file opened for reading. * * RESULT * int - Number of Bytes read from the file if reading succeeded, * -1 if reading failed. *******************************************************************************/ int C_Job::Unserialize(HANDLE hFile) { BOOL bRet; int i; char *pszBuffer; char *pszTemp; DWORD dwRead = 0; DWORD dwBufLen = 100000; pszBuffer = new char[dwBufLen]; ZeroMemory(pszBuffer, dwBufLen); FreeAllocatedMembers(); bRet = ReadFile(hFile, pszBuffer, dwBufLen, &dwRead, NULL); if(bRet) { pszTemp = strtok(pszBuffer, "\n"); sscanf(pszTemp, "%d\n", &m_JobStatus); pszTemp = strtok(NULL, "\n"); sscanf(pszTemp, "%ld\n", &m_job_id); pszTemp = strtok(NULL, "\n"); sscanf(pszTemp, "%ld\n", &m_ja_task_id); pszTemp = strtok(NULL, "\n"); if(strcmp(pszTemp, "")!=0) { m_pe_task_id = strdup(pszTemp); } pszTemp = strtok(NULL, "\n"); sscanf(pszTemp, "%d\n", &m_comm_sock); pszTemp = strtok(NULL, "\n"); sscanf(pszTemp, "%p\n", &m_hProcess); pszTemp = strtok(NULL, "\n"); sscanf(pszTemp, "%d\n", &m_ForwardedSignal); pszTemp = strtok(NULL, "\n"); if(strcmp(pszTemp, "")!=0) { jobname = strdup(pszTemp); } pszTemp = strtok(NULL, "\n"); sscanf(pszTemp, "%d\n", &nargs); pszTemp = strtok(NULL, "\n"); args = new char*[nargs]; for(i=0; i")!=0) { user = strdup(pszTemp); } pszTemp = strtok(NULL, "\n"); if(strcmp(pszTemp, "")!=0) { pass = strdup(pszTemp); } pszTemp = strtok(NULL, "\n"); if(strcmp(pszTemp, "")!=0) { domain = strdup(pszTemp); } pszTemp = strtok(NULL, "\n"); sscanf(pszTemp, "%ld\n", &mem); pszTemp = strtok(NULL, "\n"); sscanf(pszTemp, "%ld\n", &cpu); pszTemp = strtok(NULL, "\n"); sscanf(pszTemp, "%ld\n", &vmem); pszTemp = strtok(NULL, "\n"); sscanf(pszTemp, "%ld\n", &dwExitCode); pszTemp = strtok(NULL, "\n"); if(strcmp(pszTemp, "")!=0) { szError = strdup(pszTemp); } pszTemp = strtok(NULL, "\n"); sscanf(pszTemp, "%ld\n", &lUserSec); pszTemp = strtok(NULL, "\n"); sscanf(pszTemp, "%ld\n", &lUserUSec); pszTemp = strtok(NULL, "\n"); sscanf(pszTemp, "%ld\n", &lKernelSec); pszTemp = strtok(NULL, "\n"); sscanf(pszTemp, "%ld\n", &lKernelUSec); } delete pszBuffer; return bRet ? dwRead : -1; } /****** C_Job::FreeAllocatedMembers() ****************************************** * NAME * C_Job::FreeAllocatedMembers() -- Frees all dynamically allocated buffers * * SYNOPSIS * void C_Job::FreeAllocatedMembers() * * FUNCTION * Frees all dynamically allocated buffers of the object. * * RESULT * void - none *******************************************************************************/ void C_Job::FreeAllocatedMembers() { int i; free(jobname); jobname = NULL; for(i=0; i=0) { return ":"; } else { return ";"; } } /****** C_Job::MergeSysEnvTableWithJobEnvTable() const ************************* * NAME * C_Job::MergeSysEnvTableWithJobEnvTable() const -- * Merges the two environment tables * * SYNOPSIS * void C_Job::MergeSysEnvTableWithJobEnvTable(CMapStringToString &mapSysEnv, * CMapStringToString &mapMergedEnv) const * * FUNCTION * Merges the two environments from the system and this job object. * * INPUTS * CMapStringToString &mapSysEnv - Copy of the system environment * * OUTPUTS * CMapStringToString &mapSysEnv - Modified copy of the system environemnt. * All variables that were merged to the * merged env were removed from the copy of * the system environment. * CMapStringToString &mapMergedEnv - The merged environment. * * RESULT * void - none *******************************************************************************/ void C_Job::MergeSysEnvTableWithJobEnvTable(CMapStringToString &mapSysEnv, CMapStringToString &mapMergedEnv) const { CString strKey; CString strMergedValue; CString strSysValue; POSITION Pos; // Copy whole job env into merged env BuildTableFromJobEnv(mapMergedEnv); // TODO: Take care of case of the keys (=variables)! // Search for all duplicates in the maps, // remove duplicate ordinary variables from system env, merge pathes Pos = mapMergedEnv.GetStartPosition(); while(Pos) { mapMergedEnv.GetNextAssoc(Pos, strKey, strMergedValue); if(mapSysEnv.Lookup(strKey, strSysValue)) { if(IsEnvAPath(strKey)) { strMergedValue.Append(PathDelimiter(strMergedValue)); strMergedValue.Append(strSysValue); mapMergedEnv.SetAt(strKey, strMergedValue); } mapSysEnv.RemoveKey(strKey); } } // Append remainder of system env to merged env Pos = mapSysEnv.GetStartPosition(); while(Pos) { mapSysEnv.GetNextAssoc(Pos, strKey, strSysValue); mapMergedEnv.SetAt(strKey, strSysValue); } } /****** C_Job::BuildSysEnvTable() const **************************************** * NAME * C_Job::BuildSysEnvTable() const -- Copies the system environment to a * StringToString map * * SYNOPSIS * void C_Job::BuildSysEnvTable(CMapStringToString &mapSysEnv) const * * FUNCTION * Copies the systen environment to a CMapStringToString map object. * * OUTPUT * CMapStringToString &mapSysEnv - Reference to the map object * * RESULT * void - none *******************************************************************************/ void C_Job::BuildSysEnvTable(CMapStringToString &mapSysEnv) const { char *pszEnv; char *pLine; char *pToken; char *pKey; pszEnv = GetEnvironmentStrings(); pLine = pszEnv; while(*pLine != '\0') { pKey = strtok(pLine, "="); pToken = pKey+strlen(pKey)+1; mapSysEnv.SetAt(strupr(pKey), pToken); pLine = pToken+strlen(pToken)+1; } FreeEnvironmentStrings(pszEnv); } /****** C_Job::BuildEnvironmentFromTable() ************************************* * NAME * void C_Job::BuildEnvironmentFromTable() const - Creates the job environment * from a StringToString map. * * SYNOPSIS * void C_Job::BuildEnvironmentFromTable(const CMapStringToString &mapMergedEnv, * char *&pszEnv) const * * FUNCTION * Builds the job environment from a CMapStringToString map object. * * INPUTS * CMapStringToString &mapMergedEnv - Reference to the map object containing * the merged environment (merged of * system and job environment) * * OUTPUTS * char *&pszEnv - Reference to a pointer pointing to the environment buffer * that gets allocated in this function. After usage, free * it with free(). * * RESULT * void - none *******************************************************************************/ void C_Job::BuildEnvironmentFromTable(const CMapStringToString &mapMergedEnv, char *&pszEnv) const { char *ptr; POSITION Pos; CString strKey, strValue; size_t nEnvSize = 0; Pos = mapMergedEnv.GetStartPosition(); while(Pos) { mapMergedEnv.GetNextAssoc(Pos, strKey, strValue); nEnvSize += strKey.GetLength() + strlen("=") + strValue.GetLength() + 1; } nEnvSize++; // Allocate environment buffer, copy system and job environment // to buffer pszEnv = (char*)malloc(nEnvSize); ptr = pszEnv; Pos = mapMergedEnv.GetStartPosition(); while(Pos) { mapMergedEnv.GetNextAssoc(Pos, strKey, strValue); sprintf(ptr, "%s=%s", strKey.GetString(), strValue.GetString()); ptr += strlen(ptr)+1; } *ptr = '\0'; } /****** C_Job::Terminate() ***************************************************** * NAME * C_Job::Terminate() -- terminates all processes in the Windows job object * associated to this C_Job object. * * SYNOPSIS * int C_Job::Terminate() * * FUNCTION * Terminates all processes in the Windows job object associated to this * C_Job object. This avoids getting zombies and orphans of this job. * * RESULT * int * 0: All processes where terminated successfully. * >0: value of GetLastError() * * NOTES *******************************************************************************/ int C_Job:: Terminate() { if (TerminateJobObject(m_hJobObject, 999) == FALSE) { return GetLastError(); } return 0; } /****** C_Job::StoreUsage() **************************************************** * NAME * C_Job::StoreUsage() -- retrieves job usage from the system and stores it * in the C_Job object. * * SYNOPSIS * int C_Job::StoreUsage() * * FUNCTION * retrieves job usage from the system and stores it in the C_Job object. * * RESULT * DWORD * 0: the usage was retrieved successfully * 1: can't get the exit code of the job * 2: can't get the usage of the job * * NOTES * Call this function only when the main process of the job has terminated. *******************************************************************************/ int C_Job::StoreUsage() { JOBOBJECT_BASIC_AND_IO_ACCOUNTING_INFORMATION JobInfo; DWORD dwReturnLength = 0; int ret = 0; try { if(GetExitCodeProcess(m_hProcess, &dwExitCode) == FALSE) { throw 1; } ZeroMemory(&JobInfo, sizeof(JobInfo)); if (QueryInformationJobObject(m_hJobObject, JobObjectBasicAndIoAccountingInformation, &JobInfo, sizeof(JobInfo), &dwReturnLength) == FALSE) { throw 2; } lUserSec = (long)((_int64)JobInfo.BasicInfo.TotalUserTime.QuadPart/10000000); lUserUSec = (long)((_int64)JobInfo.BasicInfo.TotalUserTime.QuadPart%10000000) / 10; lKernelSec = (long)((_int64)JobInfo.BasicInfo.TotalKernelTime.QuadPart/1000000); lKernelUSec = (long)((_int64)JobInfo.BasicInfo.TotalKernelTime.QuadPart%1000000) / 10; } catch (int retval) { ret = retval; } return ret; }