root/opal/mca/pmix/pmix4x/pmix/src/tools/pps/pps.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cbfunc
  2. notification_fn
  3. evhandler_reg_callbk
  4. main
  5. pretty_print
  6. pretty_print_nodes
  7. pretty_print_jobs
  8. pretty_print_vpids
  9. pretty_print_dashed_line
  10. gather_information
  11. gather_active_jobs
  12. gather_nodes
  13. gather_vpid_info
  14. pretty_node_state
  15. parseable_print

   1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
   2 /*
   3  * Copyright (c) 2004-2010 The Trustees of Indiana University and Indiana
   4  *                         University Research and Technology
   5  *                         Corporation.  All rights reserved.
   6  * Copyright (c) 2004-2011 The University of Tennessee and The University
   7  *                         of Tennessee Research Foundation.  All rights
   8  *                         reserved.
   9  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
  10  *                         University of Stuttgart.  All rights reserved.
  11  * Copyright (c) 2004-2005 The Regents of the University of California.
  12  *                         All rights reserved.
  13  * Copyright (c) 2006-2013 Cisco Systems, Inc.  All rights reserved.
  14  * Copyright (c) 2007      Sun Microsystems, Inc.  All rights reserved.
  15  * Copyright (c) 2007-2016 Los Alamos National Security, LLC.  All rights
  16  *                         reserved.
  17  * Copyright (c) 2010      Oracle and/or its affiliates.  All rights reserved.
  18  * Copyright (c) 2014-2017 Intel, Inc. All rights reserved.
  19  * Copyright (c) 2015      Research Organization for Information Science
  20  *                         and Technology (RIST). All rights reserved.
  21  * $COPYRIGHT$
  22  *
  23  * Additional copyrights may follow
  24  *
  25  * $HEADER$
  26  */
  27 
  28 /**
  29  * @fie
  30  * PMIX PS command
  31  *
  32  */
  33 
  34 #include "pmix_config.h"
  35 #include "pmix_common.h"
  36 
  37 #include <stdio.h>
  38 #include <errno.h>
  39 #ifdef HAVE_UNISTD_H
  40 #include <unistd.h>
  41 #endif  /* HAVE_UNISTD_H */
  42 #include <stdlib.h>
  43 #ifdef HAVE_SYS_STAT_H
  44 #include <sys/stat.h>
  45 #endif  /* HAVE_SYS_STAT_H */
  46 #ifdef HAVE_SYS_TYPES_H
  47 #include <sys/types.h>
  48 #endif  /* HAVE_SYS_TYPES_H */
  49 #ifdef HAVE_SYS_WAIT_H
  50 #include <sys/wait.h>
  51 #endif  /* HAVE_SYS_WAIT_H */
  52 #include <string.h>
  53 #ifdef HAVE_DIRENT_H
  54 #include <dirent.h>
  55 #endif  /* HAVE_DIRENT_H */
  56 
  57 #include "src/threads/threads.h"
  58 #include "src/util/basename.h"
  59 #include "src/util/cmd_line.h"
  60 #include "src/util/keyval_parse.h"
  61 #include "src/util/output.h"
  62 #include "src/util/pmix_environ.h"
  63 #include "src/util/show_help.h"
  64 #include "src/mca/base/base.h"
  65 #include "src/mca/pinstalldirs/base/base.h"
  66 #include "src/runtime/pmix_rte.h"
  67 
  68 #include "src/include/pmix_globals.h"
  69 #include <pmix_tool.h>
  70 #include <pmix.h>
  71 
  72 typedef struct {
  73     pmix_lock_t lock;
  74     pmix_status_t status;
  75 } mylock_t;
  76 
  77 /* define a structure for collecting returned
  78  * info from a query */
  79 typedef struct {
  80     mylock_t lock;
  81     pmix_info_t *info;
  82     size_t ninfo;
  83 } myquery_data_t;
  84 
  85 static pmix_proc_t myproc;
  86 
  87 /******************
  88  * Local Functions
  89  ******************/
  90 #if 0
  91 static int gather_information(pmix_ps_mpirun_info_t *hnpinfo);
  92 static int gather_active_jobs(pmix_ps_mpirun_info_t *hnpinfo);
  93 static int gather_nodes(pmix_ps_mpirun_info_t *hnpinfo);
  94 static int gather_vpid_info(pmix_ps_mpirun_info_t *hnpinfo);
  95 
  96 static int pretty_print(pmix_ps_mpirun_info_t *hnpinfo);
  97 static int pretty_print_nodes(pmix_node_t **nodes, pmix_std_cntr_t num_nodes);
  98 static int pretty_print_jobs(pmix_job_t **jobs, pmix_std_cntr_t num_jobs);
  99 static int pretty_print_vpids(pmix_job_t *job);
 100 static void pretty_print_dashed_line(int len);
 101 
 102 static char *pretty_node_state(pmix_node_state_t state);
 103 
 104 static int parseable_print(pmix_ps_mpirun_info_t *hnpinfo);
 105 #endif
 106 
 107 /*****************************************
 108  * Global Vars for Command line Arguments
 109  *****************************************/
 110 typedef struct {
 111     bool help;
 112     bool parseable;
 113     bool nodes;
 114     char *nspace;
 115     pid_t pid;
 116 } pmix_ps_globals_t;
 117 
 118 pmix_ps_globals_t pmix_ps_globals = {0};
 119 
 120 pmix_cmd_line_init_t cmd_line_opts[] = {
 121     { NULL,
 122       'h', NULL, "help",
 123       0,
 124       &pmix_ps_globals.help, PMIX_CMD_LINE_TYPE_BOOL,
 125       "This help message" },
 126 
 127     { NULL,
 128       '\0', NULL, "parseable",
 129       0,
 130       &pmix_ps_globals.parseable, PMIX_CMD_LINE_TYPE_BOOL,
 131       "Provide parseable output" },
 132 
 133     { NULL,
 134       '\0', NULL, "nspace",
 135       0,
 136      &pmix_ps_globals.nspace, PMIX_CMD_LINE_TYPE_STRING,
 137       "Nspace of job whose status is being requested" },
 138 
 139     { NULL,
 140       'p', NULL, "pid",
 141       1,
 142       &pmix_ps_globals.pid, PMIX_CMD_LINE_TYPE_INT,
 143       "Specify pid of starter to be contacted (default is to system server" },
 144 
 145     { NULL,
 146       'n', NULL, "nodes",
 147       0,
 148       &pmix_ps_globals.nodes, PMIX_CMD_LINE_TYPE_BOOL,
 149       "Display Node Information" },
 150 
 151     /* End of list */
 152     { NULL,
 153       '\0', NULL, NULL,
 154       0,
 155       NULL, PMIX_CMD_LINE_TYPE_NULL,
 156       NULL }
 157 };
 158 
 159 /* this is a callback function for the PMIx_Query
 160  * API. The query will callback with a status indicating
 161  * if the request could be fully satisfied, partially
 162  * satisfied, or completely failed. The info parameter
 163  * contains an array of the returned data, with the
 164  * info->key field being the key that was provided in
 165  * the query call. Thus, you can correlate the returned
 166  * data in the info->value field to the requested key.
 167  *
 168  * Once we have dealt with the returned data, we must
 169  * call the release_fn so that the PMIx library can
 170  * cleanup */
 171 static void cbfunc(pmix_status_t status,
 172                    pmix_info_t *info, size_t ninfo,
 173                    void *cbdata,
 174                    pmix_release_cbfunc_t release_fn,
 175                    void *release_cbdata)
 176 {
 177     myquery_data_t *mq = (myquery_data_t*)cbdata;
 178     size_t n;
 179 
 180     /* save the returned info - the PMIx library "owns" it
 181      * and will release it and perform other cleanup actions
 182      * when release_fn is called */
 183     if (0 < ninfo) {
 184         PMIX_INFO_CREATE(mq->info, ninfo);
 185         mq->ninfo = ninfo;
 186         for (n=0; n < ninfo; n++) {
 187             fprintf(stderr, "Transferring %s\n", info[n].key);
 188             PMIX_INFO_XFER(&mq->info[n], &info[n]);
 189         }
 190     }
 191 
 192     /* let the library release the data and cleanup from
 193      * the operation */
 194     if (NULL != release_fn) {
 195         release_fn(release_cbdata);
 196     }
 197 
 198     /* release the block */
 199     PMIX_WAKEUP_THREAD(&mq->lock.lock);
 200 }
 201 
 202 /* this is the event notification function we pass down below
 203  * when registering for general events - i.e.,, the default
 204  * handler. */
 205 static void notification_fn(size_t evhdlr_registration_id,
 206                             pmix_status_t status,
 207                             const pmix_proc_t *source,
 208                             pmix_info_t info[], size_t ninfo,
 209                             pmix_info_t results[], size_t nresults,
 210                             pmix_event_notification_cbfunc_fn_t cbfunc,
 211                             void *cbdata)
 212 {
 213     /* this example doesn't do anything with default events */
 214     if (NULL != cbfunc) {
 215         cbfunc(PMIX_EVENT_ACTION_COMPLETE, NULL, 0, NULL, NULL, cbdata);
 216     }
 217 }
 218 
 219 /* event handler registration is done asynchronously because it
 220  * may involve the PMIx server registering with the host RM for
 221  * external events. So we provide a callback function that returns
 222  * the status of the request (success or an error), plus a numerical index
 223  * to the registered event. The index is used later on to deregister
 224  * an event handler - if we don't explicitly deregister it, then the
 225  * PMIx server will do so when it see us exit */
 226 static void evhandler_reg_callbk(pmix_status_t status,
 227                                  size_t evhandler_ref,
 228                                  void *cbdata)
 229 {
 230     mylock_t *lock = (mylock_t*)cbdata;
 231 
 232     if (PMIX_SUCCESS != status) {
 233         fprintf(stderr, "Client %s:%d EVENT HANDLER REGISTRATION FAILED WITH STATUS %d, ref=%lu\n",
 234                    myproc.nspace, myproc.rank, status, (unsigned long)evhandler_ref);
 235     }
 236     lock->status = status;
 237     PMIX_WAKEUP_THREAD(&lock->lock);
 238 }
 239 
 240 int
 241 main(int argc, char *argv[])
 242 {
 243     pmix_status_t rc = PMIX_SUCCESS;
 244     pmix_info_t *info;
 245     pmix_query_t *query;
 246     size_t nq;
 247     myquery_data_t myquery_data;
 248     mylock_t mylock;
 249     pmix_cmd_line_t cmd_line;
 250 
 251     /* protect against problems if someone passes us thru a pipe
 252      * and then abnormally terminates the pipe early */
 253     signal(SIGPIPE, SIG_IGN);
 254 
 255     /* initialize the output system */
 256     if (!pmix_output_init()) {
 257         return PMIX_ERROR;
 258     }
 259 
 260     /* initialize install dirs code */
 261     if (PMIX_SUCCESS != (rc = pmix_mca_base_framework_open(&pmix_pinstalldirs_base_framework, 0))) {
 262         fprintf(stderr, "pmix_pinstalldirs_base_open() failed -- process will likely abort (%s:%d, returned %d instead of PMIX_SUCCESS)\n",
 263                 __FILE__, __LINE__, rc);
 264         return rc;
 265     }
 266 
 267     /* initialize the help system */
 268     pmix_show_help_init();
 269 
 270     /* keyval lex-based parser */
 271     if (PMIX_SUCCESS != (rc = pmix_util_keyval_parse_init())) {
 272         fprintf(stderr, "pmix_util_keyval_parse_init failed with %d\n", rc);
 273         return PMIX_ERROR;
 274     }
 275 
 276     /* Setup the parameter system */
 277     if (PMIX_SUCCESS != (rc = pmix_mca_base_var_init())) {
 278         fprintf(stderr, "pmix_mca_base_var_init failed with %d\n", rc);
 279         return PMIX_ERROR;
 280     }
 281 
 282     /* register params for pmix */
 283     if (PMIX_SUCCESS != (rc = pmix_register_params())) {
 284         fprintf(stderr, "pmix_register_params failed with %d\n", rc);
 285         return PMIX_ERROR;
 286     }
 287 
 288     /* Parse the command line options */
 289     pmix_cmd_line_create(&cmd_line, cmd_line_opts);
 290 
 291     pmix_mca_base_open();
 292     pmix_mca_base_cmd_line_setup(&cmd_line);
 293     rc = pmix_cmd_line_parse(&cmd_line, false, false, argc, argv);
 294 
 295     if (PMIX_SUCCESS != rc) {
 296         if (PMIX_ERR_SILENT != rc) {
 297             fprintf(stderr, "%s: command line error (%s)\n", argv[0],
 298                     PMIx_Error_string(rc));
 299         }
 300         return rc;
 301     }
 302 
 303     if (pmix_ps_globals.help) {
 304         char *str, *args = NULL;
 305         args = pmix_cmd_line_get_usage_msg(&cmd_line);
 306         str = pmix_show_help_string("help-pps.txt", "usage", true,
 307                                     args);
 308         if (NULL != str) {
 309             printf("%s", str);
 310             free(str);
 311         }
 312         free(args);
 313         /* If we show the help message, that should be all we do */
 314         exit(0);
 315     }
 316 
 317     /* if we were given the pid of a starter, then direct that
 318      * we connect to it */
 319 
 320     /* otherwise, use the system connection first, if available */
 321     PMIX_INFO_CREATE(info, 1);
 322     PMIX_INFO_LOAD(&info[0], PMIX_CONNECT_SYSTEM_FIRST, NULL, PMIX_BOOL);
 323     /* init as a tool */
 324     if (PMIX_SUCCESS != (rc = PMIx_tool_init(&myproc, info, 1))) {
 325         fprintf(stderr, "PMIx_tool_init failed: %d\n", rc);
 326         exit(rc);
 327     }
 328     PMIX_INFO_FREE(info, 1);
 329 
 330     /* register a default event handler */
 331     PMIX_CONSTRUCT_LOCK(&mylock.lock);
 332     PMIx_Register_event_handler(NULL, 0, NULL, 0,
 333                                 notification_fn, evhandler_reg_callbk, (void*)&mylock);
 334     PMIX_WAIT_THREAD(&mylock.lock);
 335     PMIX_DESTRUCT_LOCK(&mylock.lock);
 336 
 337     /* if we were given a specific nspace to ask about, then do so */
 338 
 339     /* if we were asked to provide the status of the nodes, then do that */
 340 
 341     /* otherwise, query the active nspaces */
 342     nq = 1;
 343     PMIX_QUERY_CREATE(query, nq);
 344     PMIX_ARGV_APPEND(rc, query[0].keys, PMIX_QUERY_NAMESPACES);
 345     /* setup the caddy to retrieve the data */
 346     PMIX_CONSTRUCT_LOCK(&myquery_data.lock.lock);
 347     myquery_data.info = NULL;
 348     myquery_data.ninfo = 0;
 349     /* execute the query */
 350     fprintf(stderr, "pps: querying nspaces\n");
 351     if (PMIX_SUCCESS != (rc = PMIx_Query_info_nb(query, nq, cbfunc, (void*)&myquery_data))) {
 352         fprintf(stderr, "PMIx_Query_info failed: %d\n", rc);
 353         goto done;
 354     }
 355     PMIX_WAIT_THREAD(&myquery_data.lock.lock);
 356     PMIX_DESTRUCT_LOCK(&myquery_data.lock.lock);
 357 
 358     /* we should have received back one info struct containing
 359      * a comma-delimited list of nspaces */
 360     if (1 != myquery_data.ninfo) {
 361         /* this is an error */
 362         fprintf(stderr, "PMIx Query returned an incorrect number of results: %lu\n", myquery_data.ninfo);
 363         PMIX_INFO_FREE(myquery_data.info, myquery_data.ninfo);
 364         goto done;
 365     }
 366 
 367     fprintf(stderr, "Active nspaces: %s\n", myquery_data.info[0].value.data.string);
 368 
 369     /***************
 370      * Cleanup
 371      ***************/
 372   done:
 373     PMIx_tool_finalize();
 374 
 375     return rc;
 376 }
 377 
 378 #if 0
 379 static int pretty_print(pmix_ps_mpirun_info_t *hnpinfo) {
 380     char *header;
 381     int len_hdr;
 382 
 383     /*
 384      * Print header and remember header length
 385      */
 386     len_hdr = asprintf(&header, "Information from mpirun %s", PMIX_JOBID_PRINT(hnpinfo->hnp->name.jobid));
 387 
 388     printf("\n\n%s\n", header);
 389     free(header);
 390     pretty_print_dashed_line(len_hdr);
 391 
 392     /*
 393      * Print Node Information
 394      */
 395     if( pmix_ps_globals.nodes )
 396         pretty_print_nodes(hnpinfo->nodes, hnpinfo->num_nodes);
 397 
 398     /*
 399      * Print Job Information
 400      */
 401     pretty_print_jobs(hnpinfo->jobs, hnpinfo->num_jobs);
 402 
 403     return PMIX_SUCCESS;
 404 }
 405 
 406 static int pretty_print_nodes(pmix_node_t **nodes, pmix_std_cntr_t num_nodes) {
 407     int line_len;
 408     int len_name    = 0,
 409         len_state   = 0,
 410         len_slots   = 0,
 411         len_slots_i = 0,
 412         len_slots_m = 0;
 413     pmix_node_t *node;
 414     pmix_std_cntr_t i;
 415 
 416     /*
 417      * Caculate segment lengths
 418      */
 419     len_name    = (int) strlen("Node Name");
 420     len_state   = (int) strlen("State");
 421     len_slots   = (int) strlen("Slots");
 422     len_slots_i = (int) strlen("Slots In Use");
 423     len_slots_m = (int) strlen("Slots Max");
 424 
 425     for(i=0; i < num_nodes; i++) {
 426         node = nodes[i];
 427 
 428         if( NULL != node->name &&
 429             (int)strlen(node->name) > len_name)
 430             len_name = (int) strlen(node->name);
 431 
 432         if( (int)strlen(pretty_node_state(node->state)) > len_state )
 433             len_state = (int)strlen(pretty_node_state(node->state));
 434     }
 435 
 436     line_len = (len_name    + 3 +
 437                 len_state   + 3 +
 438                 len_slots   + 3 +
 439                 len_slots_i + 3 +
 440                 len_slots_m) + 2;
 441 
 442     /*
 443      * Print the header
 444      */
 445     printf("%*s | ", len_name,    "Node Name");
 446     printf("%*s | ", len_state,   "State");
 447     printf("%*s | ", len_slots,   "Slots");
 448     printf("%*s | ", len_slots_m, "Slots Max");
 449     printf("%*s | ", len_slots_i, "Slots In Use");
 450     printf("\n");
 451 
 452     pretty_print_dashed_line(line_len);
 453 
 454     /*
 455      * Print Info
 456      */
 457     for(i=0; i < num_nodes; i++) {
 458         node = nodes[i];
 459 
 460         printf("%*s | ", len_name,    node->name);
 461         printf("%*s | ", len_state,   pretty_node_state(node->state));
 462         printf("%*d | ", len_slots,   (uint)node->slots);
 463         printf("%*d | ", len_slots_m, (uint)node->slots_max);
 464         printf("%*d | ", len_slots_i, (uint)node->slots_inuse);
 465         printf("\n");
 466 
 467     }
 468 
 469     return PMIX_SUCCESS;
 470 }
 471 
 472 static int pretty_print_jobs(pmix_job_t **jobs, pmix_std_cntr_t num_jobs) {
 473     int len_jobid = 0,
 474         len_state = 0,
 475         len_slots = 0,
 476         len_vpid_r = 0,
 477         len_ckpt_s = 0,
 478         len_ckpt_r = 0,
 479         len_ckpt_l = 0;
 480     int line_len;
 481     pmix_job_t *job;
 482     pmix_std_cntr_t i;
 483     char *jobstr;
 484     pmix_jobid_t mask=0x0000ffff;
 485 
 486     for(i=0; i < num_jobs; i++) {
 487         job = jobs[i];
 488 
 489         /* check the jobid to see if this is the daemons' job */
 490         if ((0 == (mask & job->jobid)) && !pmix_ps_globals.daemons) {
 491             continue;
 492         }
 493 
 494         /* setup the printed name - do -not- free this! */
 495         jobstr = PMIX_JOBID_PRINT(job->jobid);
 496 
 497         /*
 498          * Caculate segment lengths
 499          */
 500         len_jobid  = strlen(jobstr);;
 501         len_state  = (int) (strlen(pmix_job_state_to_str(job->state)) < strlen("State") ?
 502                             strlen("State") :
 503                             strlen(pmix_job_state_to_str(job->state)));
 504         len_slots  = 6;
 505         len_vpid_r = (int) strlen("Num Procs");
 506         len_ckpt_s = -3;
 507         len_ckpt_r = -3;
 508         len_ckpt_l = -3;
 509 
 510         line_len = (len_jobid  + 3 +
 511                     len_state  + 3 +
 512                     len_slots  + 3 +
 513                     len_vpid_r + 3 +
 514                     len_ckpt_s + 3 +
 515                     len_ckpt_r + 3 +
 516                     len_ckpt_l)
 517                     + 2;
 518 
 519         /*
 520          * Print Header
 521          */
 522         printf("\n");
 523         printf("%*s | ", len_jobid  , "JobID");
 524         printf("%*s | ", len_state  , "State");
 525         printf("%*s | ", len_slots  , "Slots");
 526         printf("%*s | ", len_vpid_r , "Num Procs");
 527         printf("\n");
 528 
 529         pretty_print_dashed_line(line_len);
 530 
 531         /*
 532          * Print Info
 533          */
 534         printf("%*s | ",  len_jobid ,  PMIX_JOBID_PRINT(job->jobid));
 535         printf("%*s | ",  len_state ,  pmix_job_state_to_str(job->state));
 536         printf("%*d | ",  len_slots ,  (uint)job->total_slots_alloc);
 537         printf("%*d | ",  len_vpid_r,  job->num_procs);
 538         printf("\n");
 539 
 540 
 541         pretty_print_vpids(job);
 542         printf("\n\n"); /* give a little room between job outputs */
 543     }
 544 
 545     return PMIX_SUCCESS;
 546 }
 547 
 548 static int pretty_print_vpids(pmix_job_t *job) {
 549     int len_o_proc_name = 0,
 550         len_proc_name   = 0,
 551         len_rank        = 0,
 552         len_pid         = 0,
 553         len_state       = 0,
 554         len_node        = 0,
 555         len_ckpt_s      = 0,
 556         len_ckpt_r      = 0,
 557         len_ckpt_l      = 0;
 558     int i, line_len;
 559     pmix_vpid_t v;
 560     pmix_proc_t *vpid;
 561     pmix_app_context_t *app;
 562     char *o_proc_name;
 563     char **nodename = NULL;
 564 
 565     if (0 == job->num_procs) {
 566         return PMIX_SUCCESS;
 567     }
 568 
 569     /*
 570      * Caculate segment lengths
 571      */
 572     len_o_proc_name = (int)strlen("PMIX Name");
 573     len_proc_name   = (int)strlen("Process Name");
 574     len_rank        = (int)strlen("Local Rank");
 575     len_pid         = 6;
 576     len_state       = 0;
 577     len_node        = 0;
 578     len_ckpt_s      = -3;
 579     len_ckpt_r      = -3;
 580     len_ckpt_l      = -3;
 581 
 582     nodename = (char **) malloc(job->num_procs * sizeof(char *));
 583     for(v=0; v < job->num_procs; v++) {
 584         char *rankstr;
 585         vpid = (pmix_proc_t*)job->procs->addr[v];
 586 
 587         /*
 588          * Find my app context
 589          */
 590         if( 0 >= (int)job->num_apps ) {
 591             if( 0 == vpid->name.vpid ) {
 592                 if( (int)strlen("pmixrun") > len_proc_name)
 593                     len_proc_name = strlen("pmixrun");
 594             }
 595             else {
 596                 if( (int)strlen("pmixd") > len_proc_name)
 597                     len_proc_name = strlen("pmixd");
 598             }
 599         }
 600         for( i = 0; i < (int)job->num_apps; ++i) {
 601             app = (pmix_app_context_t*)job->apps->addr[i];
 602             if( app->idx == vpid->app_idx ) {
 603                 if( (int)strlen(app->app) > len_proc_name)
 604                     len_proc_name = strlen(app->app);
 605                 break;
 606             }
 607         }
 608 
 609         o_proc_name = pmix_util_print_name_args(&vpid->name);
 610         if ((int)strlen(o_proc_name) > len_o_proc_name)
 611             len_o_proc_name = strlen(o_proc_name);
 612 
 613         asprintf(&rankstr, "%u", (uint)vpid->local_rank);
 614         if ((int)strlen(rankstr) > len_rank)
 615             len_rank = strlen(rankstr);
 616         free(rankstr);
 617 
 618         nodename[v] = NULL;
 619         if( pmix_get_attribute(&vpid->attributes, PMIX_PROC_NODENAME, (void**)&nodename[v], PMIX_STRING) &&
 620             (int)strlen(nodename[v]) > len_node) {
 621             len_node = strlen(nodename[v]);
 622         } else if ((int)strlen("Unknown") > len_node) {
 623             len_node = strlen("Unknown");
 624         }
 625 
 626         if( (int)strlen(pmix_proc_state_to_str(vpid->state)) > len_state)
 627             len_state = strlen(pmix_proc_state_to_str(vpid->state));
 628 
 629     }
 630 
 631     line_len = (len_o_proc_name + 3 +
 632                 len_proc_name   + 3 +
 633                 len_rank        + 3 +
 634                 len_pid         + 3 +
 635                 len_state       + 3 +
 636                 len_node        + 3 +
 637                 len_ckpt_s      + 3 +
 638                 len_ckpt_r      + 3 +
 639                 len_ckpt_l)
 640                 + 2;
 641 
 642     /*
 643      * Print Header
 644      */
 645     printf("\t");
 646     printf("%*s | ", len_proc_name   , "Process Name");
 647     printf("%*s | ", len_o_proc_name , "PMIX Name");
 648     printf("%*s | ", len_rank        , "Local Rank");
 649     printf("%*s | ", len_pid         , "PID");
 650     printf("%*s | ", len_node        , "Node");
 651     printf("%*s | ", len_state       , "State");
 652     printf("\n");
 653 
 654     printf("\t");
 655     pretty_print_dashed_line(line_len);
 656 
 657     /*
 658      * Print Info
 659      */
 660     for(v=0; v < job->num_procs; v++) {
 661         vpid = (pmix_proc_t*)job->procs->addr[v];
 662 
 663         printf("\t");
 664 
 665         if( 0 >= (int)job->num_apps ) {
 666             if( 0 == vpid->name.vpid ) {
 667                 printf("%*s | ", len_proc_name, "pmixrun");
 668             } else {
 669                 printf("%*s | ", len_proc_name, "pmixd");
 670             }
 671         }
 672         for( i = 0; i < (int)job->num_apps; ++i) {
 673             app = (pmix_app_context_t*)job->apps->addr[i];
 674             if( app->idx == vpid->app_idx ) {
 675                 printf("%*s | ", len_proc_name, app->app);
 676                 break;
 677             }
 678         }
 679 
 680         o_proc_name = pmix_util_print_name_args(&vpid->name);
 681 
 682         printf("%*s | ",  len_o_proc_name, o_proc_name);
 683         printf("%*u | ",  len_rank       , (uint)vpid->local_rank);
 684         printf("%*d | ",  len_pid        , vpid->pid);
 685         printf("%*s | ",  len_node       , (NULL == nodename[v]) ? "Unknown" : nodename[v]);
 686         printf("%*s | ",  len_state      , pmix_proc_state_to_str(vpid->state));
 687 
 688         if (NULL != nodename[v]) {
 689             free(nodename[v]);
 690         }
 691         printf("\n");
 692 
 693     }
 694     if (NULL != nodename) {
 695         free(nodename);
 696     }
 697     return PMIX_SUCCESS;
 698 }
 699 
 700 static void pretty_print_dashed_line(int len) {
 701     static const char dashes[9] = "--------";
 702 
 703     while (len >= 8) {
 704         printf("%8.8s", dashes);
 705         len -= 8;
 706     }
 707     printf("%*.*s\n", len, len, dashes);
 708 }
 709 
 710 static int gather_information(pmix_ps_mpirun_info_t *hnpinfo) {
 711     int ret;
 712 
 713     if( PMIX_SUCCESS != (ret = gather_active_jobs(hnpinfo) )) {
 714         goto cleanup;
 715     }
 716 
 717     if( PMIX_SUCCESS != (ret = gather_nodes(hnpinfo) )) {
 718         goto cleanup;
 719     }
 720 
 721     if( PMIX_SUCCESS != (ret = gather_vpid_info(hnpinfo) )) {
 722         goto cleanup;
 723     }
 724 
 725  cleanup:
 726     return ret;
 727 }
 728 
 729 static int gather_active_jobs(pmix_ps_mpirun_info_t *hnpinfo) {
 730     int ret;
 731 
 732     if (PMIX_SUCCESS != (ret = pmix_util_comm_query_job_info(&(hnpinfo->hnp->name), pmix_ps_globals.jobid,
 733                                                              &hnpinfo->num_jobs, &hnpinfo->jobs))) {
 734         PMIX_ERROR_LOG(ret);
 735     }
 736 
 737     return ret;
 738 }
 739 
 740 static int gather_nodes(pmix_ps_mpirun_info_t *hnpinfo) {
 741     int ret;
 742 
 743     if (PMIX_SUCCESS != (ret = pmix_util_comm_query_node_info(&(hnpinfo->hnp->name), NULL,
 744                                                              &hnpinfo->num_nodes, &hnpinfo->nodes))) {
 745         PMIX_ERROR_LOG(ret);
 746     }
 747     pmix_output(0, "RECEIVED %d NODES", hnpinfo->num_nodes);
 748     return ret;
 749 }
 750 
 751 static int gather_vpid_info(pmix_ps_mpirun_info_t *hnpinfo) {
 752     int ret;
 753     pmix_std_cntr_t i;
 754     int cnt;
 755     pmix_job_t *job;
 756     pmix_proc_t **procs;
 757 
 758     /*
 759      * For each Job in the HNP
 760      */
 761     for(i=0; i < hnpinfo->num_jobs; i++) {
 762         job = hnpinfo->jobs[i];
 763 
 764         /*
 765          * Skip getting the vpid's for the HNP, unless asked to do so
 766          * The HNP is always the first in the array
 767          */
 768         if( 0 == i && !pmix_ps_globals.daemons) {
 769             continue;
 770         }
 771 
 772         /* query the HNP for info on the procs in this job */
 773         if (PMIX_SUCCESS != (ret = pmix_util_comm_query_proc_info(&(hnpinfo->hnp->name),
 774                                                                   job->jobid,
 775                                                                   PMIX_VPID_WILDCARD,
 776                                                                   &cnt,
 777                                                                   &procs))) {
 778             PMIX_ERROR_LOG(ret);
 779         }
 780         job->procs->addr = (void**)procs;
 781         job->procs->size = cnt;
 782         job->num_procs = cnt;
 783     }
 784 
 785     return PMIX_SUCCESS;
 786 }
 787 
 788 static char *pretty_node_state(pmix_node_state_t state) {
 789     switch(state) {
 790     case PMIX_NODE_STATE_DOWN:
 791         return strdup("Down");
 792         break;
 793     case PMIX_NODE_STATE_UP:
 794         return strdup("Up");
 795         break;
 796     case PMIX_NODE_STATE_REBOOT:
 797         return strdup("Reboot");
 798         break;
 799     case PMIX_NODE_STATE_UNKNOWN:
 800     default:
 801         return strdup("Unknown");
 802         break;
 803     }
 804 }
 805 
 806 static int parseable_print(pmix_ps_mpirun_info_t *hnpinfo)
 807 {
 808     pmix_job_t **jobs;
 809     pmix_node_t **nodes;
 810     pmix_proc_t *proc;
 811     pmix_app_context_t *app;
 812     char *appname;
 813     int i, j;
 814     char *nodename;
 815 
 816     /* don't include the daemon job in the number of jobs reppmixd */
 817     printf("mpirun:%lu:num nodes:%d:num jobs:%d\n",
 818            (unsigned long)hnpinfo->hnp->pid, hnpinfo->num_nodes, hnpinfo->num_jobs-1);
 819 
 820     if (pmix_ps_globals.nodes) {
 821         nodes = hnpinfo->nodes;
 822         for (i=0; i < hnpinfo->num_nodes; i++) {
 823             printf("node:%s:state:%s:slots:%d:in use:%d\n",
 824                    nodes[i]->name, pretty_node_state(nodes[i]->state),
 825                    nodes[i]->slots, nodes[i]->slots_inuse);
 826         }
 827     }
 828 
 829     jobs = hnpinfo->jobs;
 830     /* skip job=0 as that's the daemon job */
 831     for (i=1; i < hnpinfo->num_jobs; i++) {
 832         printf("jobid:%d:state:%s:slots:%d:num procs:%d\n",
 833                PMIX_LOCAL_JOBID(jobs[i]->jobid),
 834                pmix_job_state_to_str(jobs[i]->state),
 835                jobs[i]->total_slots_alloc,
 836                jobs[i]->num_procs);
 837         /* print the proc info */
 838         for (j=0; j < jobs[i]->procs->size; j++) {
 839             if (NULL == (proc = (pmix_proc_t*)pmix_pointer_array_get_item(jobs[i]->procs, j))) {
 840                 continue;
 841             }
 842             app = (pmix_app_context_t*)pmix_pointer_array_get_item(jobs[i]->apps, proc->app_idx);
 843             if (NULL == app) {
 844                 appname = strdup("NULL");
 845             } else {
 846                 appname = pmix_basename(app->app);
 847             }
 848             nodename = NULL;
 849             pmix_get_attribute(&proc->attributes, PMIX_PROC_NODENAME, (void**)&nodename, PMIX_STRING);
 850             printf("process:%s:rank:%s:pid:%lu:node:%s:state:%s\n",
 851                    appname, PMIX_VPID_PRINT(proc->name.vpid),
 852                    (unsigned long)proc->pid,
 853                    (NULL == nodename) ? "unknown" : nodename,
 854                    pmix_proc_state_to_str(proc->state));
 855             free(appname);
 856             if (NULL != nodename) {
 857                 free(nodename);
 858             }
 859         }
 860     }
 861 
 862     return PMIX_SUCCESS;
 863 }
 864 #endif

/* [<][>][^][v][top][bottom][index][help] */