Logo Search packages:      
Sourcecode: slurm-llnl version File versions  Download package

job_info.c

/*****************************************************************************\
 *  job_info.c - get/print the job state information of slurm
 *  $Id: job_info.c 12627 2007-11-06 19:48:55Z jette $
 *****************************************************************************
 *  Copyright (C) 2002-2006 The Regents of the University of California.
 *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
 *  Written by Morris Jette <jette1@llnl.gov> et. al.
 *  UCRL-CODE-226842.
 *  
 *  This file is part of SLURM, a resource management program.
 *  For details, see <http://www.llnl.gov/linux/slurm/>.
 *  
 *  SLURM is free software; you can redistribute it and/or modify it under
 *  the terms of the GNU General Public License as published by the Free
 *  Software Foundation; either version 2 of the License, or (at your option)
 *  any later version.
 *
 *  In addition, as a special exception, the copyright holders give permission 
 *  to link the code of portions of this program with the OpenSSL library under
 *  certain conditions as described in each individual source file, and 
 *  distribute linked combinations including the two. You must obey the GNU 
 *  General Public License in all respects for all of the code used other than 
 *  OpenSSL. If you modify file(s) with this exception, you may extend this 
 *  exception to your version of the file(s), but you are not obligated to do 
 *  so. If you do not wish to do so, delete this exception statement from your
 *  version.  If you delete this exception statement from all source files in 
 *  the program, then also delete it here.
 *  
 *  SLURM is distributed in the hope that it will be useful, but WITHOUT ANY
 *  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 *  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 *  details. 
 *  
 *  You should have received a copy of the GNU General Public License along
 *  with SLURM; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA.
\*****************************************************************************/

#ifdef HAVE_CONFIG_H
#  include "config.h"
#endif

#include <errno.h>
#include <pwd.h>
#include <grp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>

#include <slurm/slurm.h>
#include <slurm/slurm_errno.h>

#include "src/api/job_info.h"
#include "src/common/node_select.h"
#include "src/common/parse_time.h"
#include "src/common/slurm_auth.h"
#include "src/common/slurm_protocol_api.h"
#include "src/common/uid.h"
#include "src/common/xstring.h"
#include "src/common/forward.h"

/*
 * slurm_print_job_info_msg - output information about all Slurm 
 *    jobs based upon message as loaded using slurm_load_jobs
 * IN out - file to write to
 * IN job_info_msg_ptr - job information message pointer
 * IN one_liner - print as a single line if true
 */
extern void 
slurm_print_job_info_msg ( FILE* out, job_info_msg_t *jinfo, int one_liner )
{
      int i;
      job_info_t *job_ptr = jinfo->job_array;
      char time_str[32];

      slurm_make_time_str ((time_t *)&jinfo->last_update, time_str, 
            sizeof(time_str));
      fprintf( out, "Job data as of %s, record count %d\n",
             time_str, jinfo->record_count);

      for (i = 0; i < jinfo->record_count; i++) 
            slurm_print_job_info(out, &job_ptr[i], one_liner);
}

static void _sprint_range(char *str, uint16_t lower, uint16_t upper)
{
      /* Note: We don't have the size of str here */
      convert_num_unit((float)lower, str, 16, UNIT_NONE);
      if (upper > 0) {
            char tmp[128];
            convert_num_unit((float)upper, tmp, sizeof(tmp), UNIT_NONE);
            strcat(str, "-");
            strcat(str, tmp);
      }
}

/*
 * slurm_print_job_info - output information about a specific Slurm 
 *    job based upon message as loaded using slurm_load_jobs
 * IN out - file to write to
 * IN job_ptr - an individual job information record pointer
 * IN one_liner - print as a single line if true
 */
extern void
slurm_print_job_info ( FILE* out, job_info_t * job_ptr, int one_liner )
{
      char *print_this = slurm_sprint_job_info(job_ptr, one_liner);
      fprintf ( out, "%s", print_this);
      xfree(print_this);
}

/*
 * slurm_sprint_job_info - output information about a specific Slurm 
 *    job based upon message as loaded using slurm_load_jobs
 * IN job_ptr - an individual job information record pointer
 * IN one_liner - print as a single line if true
 * RET out - char * containing formatted output (must be freed after call)
 *           NULL is returned on failure.
 */
extern char *
slurm_sprint_job_info ( job_info_t * job_ptr, int one_liner )
{
      int i, j;
      char time_str[32], select_buf[122];
      struct group *group_info = NULL;
      char tmp1[128], tmp2[128];
      char tmp_line[128];
      char *ionodes = NULL;
      uint16_t exit_status = 0, term_sig = 0;
      char *out = NULL;
      
#ifdef HAVE_BG
      char *nodelist = "BP_List";
      select_g_get_jobinfo(job_ptr->select_jobinfo, 
                       SELECT_DATA_IONODES, 
                       &ionodes);
#else
      char *nodelist = "NodeList";
#endif      

      /****** Line 1 ******/
      snprintf(tmp_line, sizeof(tmp_line), 
            "JobId=%u UserId=%s(%u) ", 
            job_ptr->job_id, 
            uid_to_string((uid_t) job_ptr->user_id), job_ptr->user_id);
      out = xstrdup(tmp_line);
      group_info = getgrgid((gid_t) job_ptr->group_id );
      if ( group_info && group_info->gr_name[ 0 ] ) {
            snprintf(tmp_line, sizeof(tmp_line), "GroupId=%s(%u)",
                   group_info->gr_name, job_ptr->group_id );
      } else {
            snprintf(tmp_line, sizeof(tmp_line), "GroupId=(%u)", 
                  job_ptr->group_id );
      }
      xstrcat(out, tmp_line);
      if (one_liner)
            xstrcat(out, " ");
      else
            xstrcat(out, "\n   ");

      /****** Line 2 ******/
      snprintf(tmp_line, sizeof(tmp_line), "Name=%s", job_ptr->name);
      xstrcat(out, tmp_line);
      if (one_liner)
            xstrcat(out, " ");
      else
            xstrcat(out, "\n   ");

      /****** Line 3 ******/
      snprintf(tmp_line, sizeof(tmp_line), 
            "Priority=%u Partition=%s BatchFlag=%u", 
            job_ptr->priority, job_ptr->partition, 
            job_ptr->batch_flag);
      xstrcat(out, tmp_line);
      if (one_liner)
            xstrcat(out, " ");
      else
            xstrcat(out, "\n   ");

      /****** Line 4 ******/
      snprintf(tmp_line, sizeof(tmp_line),
            "AllocNode:Sid=%s:%u TimeLimit=", 
            job_ptr->alloc_node, job_ptr->alloc_sid);
      xstrcat(out, tmp_line);
      if (job_ptr->time_limit == INFINITE)
            sprintf(tmp_line, "UNLIMITED ");
      else if (job_ptr->time_limit == NO_VAL)
            sprintf(tmp_line, "Partition_Limit ");
      else
            sprintf(tmp_line, "%u ", job_ptr->time_limit);
      xstrcat(out, tmp_line);
      if (WIFSIGNALED(job_ptr->exit_code))
            term_sig = WTERMSIG(job_ptr->exit_code);
      else
            exit_status = WEXITSTATUS(job_ptr->exit_code);
      snprintf(tmp_line, sizeof(tmp_line),
            "ExitCode=%u:%u", 
            exit_status, term_sig);
      xstrcat(out, tmp_line);
      if (one_liner)
            xstrcat(out, " ");
      else
            xstrcat(out, "\n   ");

      /****** Line 5 ******/
      slurm_make_time_str((time_t *)&job_ptr->start_time, time_str,
            sizeof(time_str));
      snprintf(tmp_line, sizeof(tmp_line),
            "JobState=%s StartTime=%s EndTime=",
            job_state_string(job_ptr->job_state), time_str);
      xstrcat(out, tmp_line);
      if ((job_ptr->time_limit == INFINITE) && 
          (job_ptr->end_time > time(NULL)))
            sprintf(tmp_line, "NONE");
      else {
            slurm_make_time_str ((time_t *)&job_ptr->end_time, time_str,
                  sizeof(time_str));
            sprintf(tmp_line, "%s", time_str);
      }
      xstrcat(out, tmp_line);
      if (one_liner)
            xstrcat(out, " ");
      else
            xstrcat(out, "\n   ");

      /****** Line 6 ******/
      xstrfmtcat(out, "%s=", nodelist);
      xstrcat(out, job_ptr->nodes);
      if(ionodes) {
            sprintf(tmp_line, "[%s]", ionodes);
            xstrcat(out, tmp_line);
            xfree(ionodes);
      } 
      
      sprintf(tmp_line, " %sIndices=", nodelist);
      xstrcat(out, tmp_line);
      for (j = 0;  (job_ptr->node_inx && (job_ptr->node_inx[j] != -1)); 
                  j+=2) {
            if (j > 0)
                   xstrcat(out, ",");
            sprintf(tmp_line, "%d-%d", job_ptr->node_inx[j], 
                  job_ptr->node_inx[j+1]);
            xstrcat(out, tmp_line);
      }
      if (one_liner)
            xstrcat(out, " ");
      else
            xstrcat(out, "\n   ");

      /****** Line 6a (optional) ******/
#if 0
      /* mainly for debugging */ 
      convert_num_unit((float)job_ptr->num_cpu_groups, tmp1, sizeof(tmp1),
                   UNIT_NONE);
      snprintf(tmp_line, sizeof(tmp_line),
            "NumCPUGroups=%s ",
             tmp1);
      xstrcat(out, tmp_line);
#endif

      if ((job_ptr->num_cpu_groups > 0) && 
          (job_ptr->cpus_per_node) &&
          (job_ptr->cpu_count_reps)) {
            int length = 0;
            xstrcat(out, "AllocCPUs=");
            length += 10;
            for (i = 0; i < job_ptr->num_cpu_groups; i++) {
                  if (length > 70) {
                        /* skip to last CPU group entry */
                        if (i < job_ptr->num_cpu_groups - 1) {
                              continue;
                        }
                        /* add elipsis before last entry */
                        xstrcat(out, "...,");
                        length += 4;
                  }

                  snprintf(tmp_line, sizeof(tmp_line),
                        "%d",
                         job_ptr->cpus_per_node[i]);
                  xstrcat(out, tmp_line);
                  length += strlen(tmp_line);
                  if (job_ptr->cpu_count_reps[i] > 1) {
                        snprintf(tmp_line, sizeof(tmp_line),
                              "*%d",
                               job_ptr->cpu_count_reps[i]);
                        xstrcat(out, tmp_line);
                        length += strlen(tmp_line);
                  }
                  if (i < job_ptr->num_cpu_groups - 1) {
                        xstrcat(out, ",");
                        length++;
                  }
            }
            if (one_liner)
                  xstrcat(out, " ");
            else
                  xstrcat(out, "\n   ");
      }

      /****** Line 7 ******/
      convert_num_unit((float)job_ptr->num_procs, tmp1, sizeof(tmp1), 
                   UNIT_NONE);
#ifdef HAVE_BG
      convert_num_unit((float)job_ptr->num_nodes, tmp2, sizeof(tmp2),
                   UNIT_NONE);
      sprintf(tmp_line, "ReqProcs=%s MinBPs=%s ", tmp1, tmp2);
#else
      _sprint_range(tmp2, job_ptr->num_nodes, job_ptr->max_nodes);
      sprintf(tmp_line, "ReqProcs=%s ReqNodes=%s ", tmp1, tmp2);
#endif
      xstrcat(out, tmp_line);

      _sprint_range(tmp1, job_ptr->min_sockets, job_ptr->max_sockets);
      if (job_ptr->min_cores > 0) {
            _sprint_range(tmp2, job_ptr->min_cores, job_ptr->max_cores);
            strcat(tmp1, ":");
            strcat(tmp1, tmp2);
            if (job_ptr->min_threads > 0) {
                  _sprint_range(tmp2, job_ptr->min_threads,
                              job_ptr->max_threads);
                  strcat(tmp1, ":");
                  strcat(tmp1, tmp2);
            }
      }
      snprintf(tmp_line, sizeof(tmp_line), 
            "ReqS:C:T=%s",
            tmp1);
      xstrcat(out, tmp_line);
      if (one_liner)
            xstrcat(out, " ");
      else
            xstrcat(out, "\n   ");

      /****** Line 8 ******/
      snprintf(tmp_line, sizeof(tmp_line),
            "Shared=%s Contiguous=%d CPUs/task=%u", 
             (job_ptr->shared == 0 ? "0" :
              job_ptr->shared == 1 ? "1" : "OK"),
             job_ptr->contiguous, job_ptr->cpus_per_task);
      xstrcat(out, tmp_line);

      if (one_liner)
            xstrcat(out, " ");
      else
            xstrcat(out, "\n   ");

      /****** Line 9 ******/
      snprintf(tmp_line, sizeof(tmp_line), 
            "MinProcs=%u MinSockets=%u MinCores=%u MinThreads=%u", 
            job_ptr->job_min_procs, job_ptr->job_min_sockets, 
            job_ptr->job_min_cores, job_ptr->job_min_threads);
      xstrcat(out, tmp_line);
      if (one_liner)
            xstrcat(out, " ");
      else
            xstrcat(out, "\n   ");

      /****** Line 10 ******/
      convert_num_unit((float)job_ptr->job_min_memory, tmp1, sizeof(tmp1),
                   UNIT_NONE);
      convert_num_unit((float)job_ptr->job_min_tmp_disk, tmp2, sizeof(tmp2),
                   UNIT_NONE);
      snprintf(tmp_line, sizeof(tmp_line), 
            "MinMemory=%s MinTmpDisk=%s Features=%s",
            tmp1, tmp2, job_ptr->features);
      xstrcat(out, tmp_line);
      if (one_liner)
            xstrcat(out, " ");
      else
            xstrcat(out, "\n   ");

      /****** Line 11 ******/
      snprintf(tmp_line, sizeof(tmp_line), 
            "Dependency=%u Account=%s Reason=%s Network=%s",
            job_ptr->dependency, job_ptr->account,
            job_reason_string(job_ptr->state_reason), 
            job_ptr->network);
      xstrcat(out, tmp_line);
      if (one_liner)
            xstrcat(out, " ");
      else
            xstrcat(out, "\n   ");

      /****** Line 12 ******/
      snprintf(tmp_line, sizeof(tmp_line), "Req%s=%s Req%sIndices=", 
            nodelist, job_ptr->req_nodes, nodelist);
      xstrcat(out, tmp_line);
      for (j = 0; (job_ptr->req_node_inx && (job_ptr->req_node_inx[j] != -1));
                  j+=2) {
            if (j > 0)
                  xstrcat(out, ",");
            sprintf(tmp_line, "%d-%d", job_ptr->req_node_inx[j],
                  job_ptr->req_node_inx[j+1]);
            xstrcat(out, tmp_line);
      }
      if (one_liner)
            xstrcat(out, " ");
      else
            xstrcat(out, "\n   ");

      /****** Line 13 ******/
      snprintf(tmp_line, sizeof(tmp_line), "Exc%s=%s Exc%sIndices=", 
            nodelist, job_ptr->exc_nodes, nodelist);
      xstrcat(out, tmp_line);
      for (j = 0; (job_ptr->exc_node_inx && (job_ptr->exc_node_inx[j] != -1)); 
                  j+=2) {
            if (j > 0)
                  xstrcat(out, ",");
            sprintf(tmp_line, "%d-%d", job_ptr->exc_node_inx[j],
                  job_ptr->exc_node_inx[j+1]);
            xstrcat(out, tmp_line);
      }
      if (one_liner)
            xstrcat(out, " ");
      else
            xstrcat(out, "\n   ");

      /****** Line 14 ******/
      slurm_make_time_str((time_t *)&job_ptr->submit_time, time_str, 
            sizeof(time_str));
      sprintf(tmp_line, "SubmitTime=%s ", time_str);
      xstrcat(out, tmp_line);
      if (job_ptr->suspend_time) {
            slurm_make_time_str ((time_t *)&job_ptr->suspend_time, 
                  time_str, sizeof(time_str));
      } else {
            strncpy(time_str, "None", sizeof(time_str));
      }
      sprintf(tmp_line, "SuspendTime=%s PreSusTime=%ld", 
              time_str, (long int)job_ptr->pre_sus_time);
      xstrcat(out, tmp_line);

      /****** Line 15 (optional) ******/
      if (job_ptr->comment) {
            if (one_liner)
                  xstrcat(out, " ");
            else
                  xstrcat(out, "\n   ");
            sprintf(tmp_line, "Comment=%s ", job_ptr->comment);
            xstrcat(out, tmp_line);
      }

      /****** Line 16 (optional) ******/
      select_g_sprint_jobinfo(job_ptr->select_jobinfo,
                        select_buf, sizeof(select_buf),
                        SELECT_PRINT_MIXED);
      if (select_buf[0] != '\0') {
            if (one_liner)
                  xstrcat(out, " ");
            else
                  xstrcat(out, "\n   ");
            xstrcat(out, select_buf);
      }
      /****** Line 17 (optional) ******/
      select_g_sprint_jobinfo(job_ptr->select_jobinfo,
                        select_buf, sizeof(select_buf),
                        SELECT_PRINT_BLRTS_IMAGE);
      if (select_buf[0] != '\0') {
            if (one_liner)
                  xstrcat(out, " ");
            else
                  xstrcat(out, "\n   ");
            snprintf(tmp_line, sizeof(tmp_line),
                   "BlrtsImage=%s", select_buf);
            xstrcat(out, tmp_line);
      }
      /****** Line 18 (optional) ******/
      select_g_sprint_jobinfo(job_ptr->select_jobinfo,
                        select_buf, sizeof(select_buf),
                        SELECT_PRINT_LINUX_IMAGE);
      if (select_buf[0] != '\0') {
            if (one_liner)
                  xstrcat(out, " ");
            else
                  xstrcat(out, "\n   ");
            snprintf(tmp_line, sizeof(tmp_line),
                   "LinuxImage=%s", select_buf);
            xstrcat(out, tmp_line);
      }
      /****** Line 19 (optional) ******/
      select_g_sprint_jobinfo(job_ptr->select_jobinfo,
                        select_buf, sizeof(select_buf),
                        SELECT_PRINT_MLOADER_IMAGE);
      if (select_buf[0] != '\0') {
            if (one_liner)
                  xstrcat(out, " ");
            else
                  xstrcat(out, "\n   ");
            snprintf(tmp_line, sizeof(tmp_line),
                   "MloaderImage=%s", select_buf);
            xstrcat(out, tmp_line);
      }
      /****** Line 20 (optional) ******/
      select_g_sprint_jobinfo(job_ptr->select_jobinfo,
                        select_buf, sizeof(select_buf),
                        SELECT_PRINT_RAMDISK_IMAGE);
      if (select_buf[0] != '\0') {
            if (one_liner)
                  xstrcat(out, " ");
            else
                  xstrcat(out, "\n   ");
            snprintf(tmp_line, sizeof(tmp_line),
                   "RamDiskImage=%s", select_buf);
            xstrcat(out, tmp_line);
      }
      xstrcat(out, "\n\n");

      return out;

}
/*
 * slurm_load_jobs - issue RPC to get slurm all job configuration  
 *    information if changed since update_time 
 * IN update_time - time of current configuration data
 * IN job_info_msg_pptr - place to store a job configuration pointer
 * IN show_flags -  job filtering options
 * RET 0 or -1 on error
 * NOTE: free the response using slurm_free_job_info_msg
 */
extern int
slurm_load_jobs (time_t update_time, job_info_msg_t **resp,
            uint16_t show_flags)
{
      int rc;
      slurm_msg_t resp_msg;
      slurm_msg_t req_msg;
      job_info_request_msg_t req;

      slurm_msg_t_init(&req_msg);
      slurm_msg_t_init(&resp_msg);

      req.last_update  = update_time;
      req.show_flags = show_flags;
      req_msg.msg_type = REQUEST_JOB_INFO;
      req_msg.data     = &req;

      if (slurm_send_recv_controller_msg(&req_msg, &resp_msg) < 0)
            return SLURM_ERROR;

      switch (resp_msg.msg_type) {
      case RESPONSE_JOB_INFO:
            *resp = (job_info_msg_t *)resp_msg.data;
            break;
      case RESPONSE_SLURM_RC:
            rc = ((return_code_msg_t *) resp_msg.data)->return_code;
            slurm_free_return_code_msg(resp_msg.data);      
            if (rc) 
                  slurm_seterrno_ret(rc);
            break;
      default:
            slurm_seterrno_ret(SLURM_UNEXPECTED_MSG_ERROR);
            break;
      }

      return SLURM_PROTOCOL_SUCCESS ;
}


/*
 * slurm_pid2jobid - issue RPC to get the slurm job_id given a process_id 
 *    on this machine
 * IN job_pid     - process_id of interest on this machine
 * OUT job_id_ptr - place to store a slurm job_id
 * RET 0 or -1 on error
 */
extern int
slurm_pid2jobid (pid_t job_pid, uint32_t *jobid)
{
      int rc;
      slurm_msg_t req_msg;
      slurm_msg_t resp_msg;
      job_id_request_msg_t req;
      
      slurm_msg_t_init(&req_msg);
      slurm_msg_t_init(&resp_msg);

      /*
       *  Set request message address to slurmd on localhost
       */
      slurm_set_addr(&req_msg.address, (uint16_t)slurm_get_slurmd_port(), 
                   "localhost");

      req.job_pid      = job_pid;
      req_msg.msg_type = REQUEST_JOB_ID;
      req_msg.data     = &req;
      
      rc = slurm_send_recv_node_msg(&req_msg, &resp_msg, 0);

      if(rc != 0 || !resp_msg.auth_cred) {
            error("slurm_pid2jobid: %m");
            if(resp_msg.auth_cred)
                  g_slurm_auth_destroy(resp_msg.auth_cred);
            return SLURM_ERROR;
      }
      if(resp_msg.auth_cred)
            g_slurm_auth_destroy(resp_msg.auth_cred); 
      switch (resp_msg.msg_type) {
      case RESPONSE_JOB_ID:
            *jobid = ((job_id_response_msg_t *) resp_msg.data)->job_id;
            slurm_free_job_id_response_msg(resp_msg.data);
            break;
      case RESPONSE_SLURM_RC:
              rc = ((return_code_msg_t *) resp_msg.data)->return_code;
            slurm_free_return_code_msg(resp_msg.data);      
            if (rc) 
                  slurm_seterrno_ret(rc);
            break;
      default:
            slurm_seterrno_ret(SLURM_UNEXPECTED_MSG_ERROR);
            break;
      }

      return SLURM_PROTOCOL_SUCCESS;
}

/*
 * slurm_get_rem_time - get the expected time remaining for a given job
 * IN jobid     - slurm job id
 * RET remaining time in seconds or -1 on error 
 */
extern long slurm_get_rem_time(uint32_t jobid)
{
      time_t now = time(NULL);
      time_t end_time;
      long rc;

      if (slurm_get_end_time(jobid, &end_time) != SLURM_SUCCESS)
            return -1L;

      rc = difftime(end_time, now);
      if (rc < 0)
            rc = 0L;
      return rc;
}

/* FORTRAN VERSIONS OF slurm_get_rem_time */
extern int32_t islurm_get_rem_time__(uint32_t *jobid)
{
      time_t now = time(NULL);
      time_t end_time;
      int32_t rc;

      if ((jobid == NULL)
      ||  (slurm_get_end_time(*jobid, &end_time) != SLURM_SUCCESS))
            return 0;

      rc = difftime(end_time, now);
      if (rc < 0)
            rc = 0;
      return rc;
}
extern int32_t islurm_get_rem_time2__()
{
      uint32_t jobid;
      char *slurm_jobid = getenv("SLURM_JOBID");

      if (slurm_jobid == NULL)
            return 0;
      jobid = atol(slurm_jobid);
      return islurm_get_rem_time__(&jobid);
}


/*
 * slurm_get_end_time - get the expected end time for a given slurm job
 * IN jobid     - slurm job id
 * end_time_ptr - location in which to store scheduled end time for job 
 * RET 0 or -1 on error
 */
extern int
slurm_get_end_time(uint32_t jobid, time_t *end_time_ptr)
{
      int rc;
      slurm_msg_t resp_msg;
      slurm_msg_t req_msg;
      job_alloc_info_msg_t job_msg;
      srun_timeout_msg_t *timeout_msg;
      time_t now = time(NULL);
      static uint32_t jobid_cache = 0;
      static uint32_t jobid_env = 0;
      static time_t endtime_cache = 0;
      static time_t last_test_time = 0;

      slurm_msg_t_init(&req_msg);
      slurm_msg_t_init(&resp_msg);

      if (!end_time_ptr)
            slurm_seterrno_ret(EINVAL);

      if (jobid == 0) {
            if (jobid_env) {
                  jobid = jobid_env;
            } else {
                  char *env = getenv("SLURM_JOBID");
                  if (env) {
                        jobid = (uint32_t) atol(env);
                        jobid_env = jobid;
                  }
            }
            if (jobid == 0) {
                  slurm_seterrno(ESLURM_INVALID_JOB_ID);
                  return SLURM_ERROR;
            }
      }

      /* Just use cached data if data less than 60 seconds old */
      if ((jobid == jobid_cache)
      &&  (difftime(now, last_test_time) < 60)) {
            *end_time_ptr  = endtime_cache;
            return SLURM_SUCCESS;
      }

      job_msg.job_id     = jobid;
      req_msg.msg_type   = REQUEST_JOB_END_TIME;
      req_msg.data       = &job_msg;

      if (slurm_send_recv_controller_msg(&req_msg, &resp_msg) < 0)
            return SLURM_ERROR;

      switch (resp_msg.msg_type) {
      case SRUN_TIMEOUT:
            timeout_msg = (srun_timeout_msg_t *) resp_msg.data;
            last_test_time = time(NULL);
            jobid_cache    = jobid;
            endtime_cache  = timeout_msg->timeout;
            *end_time_ptr  = endtime_cache;
            slurm_free_srun_timeout_msg(resp_msg.data);
            break;
      case RESPONSE_SLURM_RC:
            rc = ((return_code_msg_t *) resp_msg.data)->return_code;
            slurm_free_return_code_msg(resp_msg.data);
            if (endtime_cache)
                  *end_time_ptr  = endtime_cache;
            else if (rc)
                  slurm_seterrno_ret(rc);
            break;
      default:
            if (endtime_cache)
                  *end_time_ptr  = endtime_cache;
            else
                  slurm_seterrno_ret(SLURM_UNEXPECTED_MSG_ERROR);
            break;
      }

      return SLURM_SUCCESS;
}

/*
 * slurm_get_select_jobinfo - get data from a select job credential
 * IN jobinfo  - updated select job credential
 * IN data_type - type of data to enter into job credential
 * IN/OUT data - the data to enter into job credential
 * RET 0 or -1 on error
 */
extern int slurm_get_select_jobinfo (select_jobinfo_t jobinfo,
            enum select_data_type data_type, void *data)
{
      return select_g_get_jobinfo (jobinfo, data_type, data);
}

/*
 * slurm_job_node_ready - report if nodes are ready for job to execute now
 * IN job_id - slurm job id
 * RET: READY_* values as defined in api/job_info.h
 */
extern int slurm_job_node_ready(uint32_t job_id)
{
      slurm_msg_t req, resp;
      job_id_msg_t msg;
      int rc;

      slurm_msg_t_init(&req);
      slurm_msg_t_init(&resp);

      req.msg_type = REQUEST_JOB_READY;
      req.data     = &msg;
      msg.job_id   = job_id;

      if (slurm_send_recv_controller_msg(&req, &resp) < 0)
            return -1;

      if (resp.msg_type == RESPONSE_JOB_READY) {
            rc = ((return_code_msg_t *) resp.data)->return_code;
            slurm_free_return_code_msg(resp.data);
      } else if (resp.msg_type == RESPONSE_SLURM_RC) {
            int job_rc = ((return_code_msg_t *) resp.data) -> 
                        return_code;
            if ((job_rc == ESLURM_INVALID_PARTITION_NAME)
            ||  (job_rc == ESLURM_INVALID_JOB_ID))
                  rc = READY_JOB_FATAL;
            else  /* EAGAIN */
                  rc = READY_JOB_ERROR;
            slurm_free_return_code_msg(resp.data);
      } else
            rc = READY_JOB_ERROR;

      return rc;
}


Generated by  Doxygen 1.6.0   Back to index