This source file includes following definitions.
- cbfunc
- notification_fn
- evhandler_reg_callbk
- main
- pretty_print
- pretty_print_nodes
- pretty_print_jobs
- pretty_print_vpids
- pretty_print_dashed_line
- gather_information
- gather_active_jobs
- gather_nodes
- gather_vpid_info
- pretty_node_state
- parseable_print
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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
42 #include <stdlib.h>
43 #ifdef HAVE_SYS_STAT_H
44 #include <sys/stat.h>
45 #endif
46 #ifdef HAVE_SYS_TYPES_H
47 #include <sys/types.h>
48 #endif
49 #ifdef HAVE_SYS_WAIT_H
50 #include <sys/wait.h>
51 #endif
52 #include <string.h>
53 #ifdef HAVE_DIRENT_H
54 #include <dirent.h>
55 #endif
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
78
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
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
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
152 { NULL,
153 '\0', NULL, NULL,
154 0,
155 NULL, PMIX_CMD_LINE_TYPE_NULL,
156 NULL }
157 };
158
159
160
161
162
163
164
165
166
167
168
169
170
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
181
182
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
193
194 if (NULL != release_fn) {
195 release_fn(release_cbdata);
196 }
197
198
199 PMIX_WAKEUP_THREAD(&mq->lock.lock);
200 }
201
202
203
204
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
214 if (NULL != cbfunc) {
215 cbfunc(PMIX_EVENT_ACTION_COMPLETE, NULL, 0, NULL, NULL, cbdata);
216 }
217 }
218
219
220
221
222
223
224
225
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
252
253 signal(SIGPIPE, SIG_IGN);
254
255
256 if (!pmix_output_init()) {
257 return PMIX_ERROR;
258 }
259
260
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
268 pmix_show_help_init();
269
270
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
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
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
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
314 exit(0);
315 }
316
317
318
319
320
321 PMIX_INFO_CREATE(info, 1);
322 PMIX_INFO_LOAD(&info[0], PMIX_CONNECT_SYSTEM_FIRST, NULL, PMIX_BOOL);
323
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
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
338
339
340
341
342 nq = 1;
343 PMIX_QUERY_CREATE(query, nq);
344 PMIX_ARGV_APPEND(rc, query[0].keys, PMIX_QUERY_NAMESPACES);
345
346 PMIX_CONSTRUCT_LOCK(&myquery_data.lock.lock);
347 myquery_data.info = NULL;
348 myquery_data.ninfo = 0;
349
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
359
360 if (1 != myquery_data.ninfo) {
361
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
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
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
394
395 if( pmix_ps_globals.nodes )
396 pretty_print_nodes(hnpinfo->nodes, hnpinfo->num_nodes);
397
398
399
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
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
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
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
490 if ((0 == (mask & job->jobid)) && !pmix_ps_globals.daemons) {
491 continue;
492 }
493
494
495 jobstr = PMIX_JOBID_PRINT(job->jobid);
496
497
498
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
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
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");
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
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
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
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
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
760
761 for(i=0; i < hnpinfo->num_jobs; i++) {
762 job = hnpinfo->jobs[i];
763
764
765
766
767
768 if( 0 == i && !pmix_ps_globals.daemons) {
769 continue;
770 }
771
772
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
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
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
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