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

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

DEFINITIONS

This source file includes following definitions.
  1. cbfunc
  2. notification_fn
  3. evhandler_reg_callbk
  4. main

   1 /*
   2  * Copyright (c) 2004-2010 The Trustees of Indiana University and Indiana
   3  *                         University Research and Technology
   4  *                         Corporation.  All rights reserved.
   5  * Copyright (c) 2004-2011 The University of Tennessee and The University
   6  *                         of Tennessee Research Foundation.  All rights
   7  *                         reserved.
   8  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
   9  *                         University of Stuttgart.  All rights reserved.
  10  * Copyright (c) 2004-2005 The Regents of the University of California.
  11  *                         All rights reserved.
  12  * Copyright (c) 2006-2013 Los Alamos National Security, LLC.
  13  *                         All rights reserved.
  14  * Copyright (c) 2009-2012 Cisco Systems, Inc.  All rights reserved.
  15  * Copyright (c) 2011      Oak Ridge National Labs.  All rights reserved.
  16  * Copyright (c) 2013-2019 Intel, Inc.  All rights reserved.
  17  * Copyright (c) 2015      Mellanox Technologies, Inc.  All rights reserved.
  18  * $COPYRIGHT$
  19  *
  20  * Additional copyrights may follow
  21  *
  22  * $HEADER$
  23  *
  24  */
  25 
  26 #include "pmix_config.h"
  27 #include "pmix_common.h"
  28 
  29 #include <stdio.h>
  30 #include <stdlib.h>
  31 #include <unistd.h>
  32 #include <time.h>
  33 #include <pthread.h>
  34 
  35 #include <pmix_tool.h>
  36 #include "src/common/pmix_attributes.h"
  37 #include "src/mca/base/base.h"
  38 #include "src/mca/pinstalldirs/base/base.h"
  39 #include "src/threads/threads.h"
  40 #include "src/util/cmd_line.h"
  41 #include "src/util/keyval_parse.h"
  42 #include "src/util/show_help.h"
  43 #include "src/runtime/pmix_rte.h"
  44 
  45 typedef struct {
  46     pmix_lock_t lock;
  47     pmix_status_t status;
  48 } mylock_t;
  49 
  50 static pmix_proc_t myproc;
  51 
  52 /* define a structure for collecting returned
  53  * info from a query */
  54 typedef struct {
  55     pmix_lock_t lock;
  56     pmix_status_t status;
  57     pmix_info_t *info;
  58     size_t ninfo;
  59 } myquery_data_t;
  60 
  61 
  62 /* this is a callback function for the PMIx_Query
  63  * API. The query will callback with a status indicating
  64  * if the request could be fully satisfied, partially
  65  * satisfied, or completely failed. The info parameter
  66  * contains an array of the returned data, with the
  67  * info->key field being the key that was provided in
  68  * the query call. Thus, you can correlate the returned
  69  * data in the info->value field to the requested key.
  70  *
  71  * Once we have dealt with the returned data, we must
  72  * call the release_fn so that the PMIx library can
  73  * cleanup */
  74 static void cbfunc(pmix_status_t status,
  75                    pmix_info_t *info, size_t ninfo,
  76                    void *cbdata,
  77                    pmix_release_cbfunc_t release_fn,
  78                    void *release_cbdata)
  79 {
  80     myquery_data_t *mq = (myquery_data_t*)cbdata;
  81     size_t n;
  82 
  83     mq->status = status;
  84     /* save the returned info - the PMIx library "owns" it
  85      * and will release it and perform other cleanup actions
  86      * when release_fn is called */
  87     if (0 < ninfo) {
  88         PMIX_INFO_CREATE(mq->info, ninfo);
  89         mq->ninfo = ninfo;
  90         for (n=0; n < ninfo; n++) {
  91             PMIX_INFO_XFER(&mq->info[n], &info[n]);
  92         }
  93     }
  94 
  95     /* let the library release the data and cleanup from
  96      * the operation */
  97     if (NULL != release_fn) {
  98         release_fn(release_cbdata);
  99     }
 100 
 101     /* release the block */
 102     PMIX_WAKEUP_THREAD(&mq->lock);
 103 }
 104 
 105 /* this is the event notification function we pass down below
 106  * when registering for general events - i.e.,, the default
 107  * handler. We don't technically need to register one, but it
 108  * is usually good practice to catch any events that occur */
 109 static void notification_fn(size_t evhdlr_registration_id,
 110                             pmix_status_t status,
 111                             const pmix_proc_t *source,
 112                             pmix_info_t info[], size_t ninfo,
 113                             pmix_info_t results[], size_t nresults,
 114                             pmix_event_notification_cbfunc_fn_t cbfunc,
 115                             void *cbdata)
 116 {
 117     /* this example doesn't do anything with default events */
 118     if (NULL != cbfunc) {
 119         cbfunc(PMIX_EVENT_ACTION_COMPLETE, NULL, 0, NULL, NULL, cbdata);
 120     }
 121 }
 122 
 123 /* event handler registration is done asynchronously because it
 124  * may involve the PMIx server registering with the host RM for
 125  * external events. So we provide a callback function that returns
 126  * the status of the request (success or an error), plus a numerical index
 127  * to the registered event. The index is used later on to deregister
 128  * an event handler - if we don't explicitly deregister it, then the
 129  * PMIx server will do so when it see us exit */
 130 static void evhandler_reg_callbk(pmix_status_t status,
 131                                  size_t evhandler_ref,
 132                                  void *cbdata)
 133 {
 134     mylock_t *lock = (mylock_t*)cbdata;
 135 
 136     if (PMIX_SUCCESS != status) {
 137         fprintf(stderr, "Client %s:%d EVENT HANDLER REGISTRATION FAILED WITH STATUS %d, ref=%lu\n",
 138                    myproc.nspace, myproc.rank, status, (unsigned long)evhandler_ref);
 139     }
 140     lock->status = status;
 141     PMIX_WAKEUP_THREAD(&lock->lock);
 142 }
 143 
 144 /*****************************************
 145  * Global Vars for Command line Arguments
 146  *****************************************/
 147 typedef struct {
 148     bool help;
 149     bool verbose;
 150     pid_t pid;
 151     char *nspace;
 152     char *uri;
 153     bool sysfirst;
 154     bool system;
 155     char *client;
 156     char *server;
 157     char *tool;
 158     char *host;
 159     bool clientfns;
 160     bool serverfns;
 161     bool toolfns;
 162     bool hostfns;
 163 } pmix_pattrs_globals_t;
 164 
 165 pmix_pattrs_globals_t pmix_pattrs_globals = {0};
 166 
 167 pmix_cmd_line_init_t cmd_line_opts[] = {
 168     { NULL,
 169       'h', NULL, "help",
 170       0,
 171       &pmix_pattrs_globals.help, PMIX_CMD_LINE_TYPE_BOOL,
 172       "This help message" },
 173 
 174     { NULL,
 175       'v', NULL, "verbose",
 176       0,
 177       &pmix_pattrs_globals.verbose, PMIX_CMD_LINE_TYPE_BOOL,
 178       "Be Verbose" },
 179 
 180     { NULL,
 181       'p', NULL, "pid",
 182       1,
 183       &pmix_pattrs_globals.pid, PMIX_CMD_LINE_TYPE_INT,
 184       "Specify server pid to connect to" },
 185 
 186     { NULL,
 187       'n', NULL, "nspace",
 188       1,
 189       &pmix_pattrs_globals.nspace, PMIX_CMD_LINE_TYPE_STRING,
 190       "Specify server nspace to connect to" },
 191 
 192     { NULL,
 193       '\0', NULL, "uri",
 194       1,
 195       &pmix_pattrs_globals.uri, PMIX_CMD_LINE_TYPE_STRING,
 196       "Specify URI of server to connect to" },
 197 
 198     { NULL,
 199       '\0', NULL, "system-server-first",
 200       0,
 201       &pmix_pattrs_globals.sysfirst, PMIX_CMD_LINE_TYPE_BOOL,
 202       "Look for the system server first" },
 203 
 204     { NULL,
 205       '\0', NULL, "system-server",
 206       0,
 207       &pmix_pattrs_globals.system, PMIX_CMD_LINE_TYPE_BOOL,
 208       "Specifically connect to the system server" },
 209 
 210     { NULL,
 211       'c', NULL, "client",
 212       1,
 213       &pmix_pattrs_globals.client, PMIX_CMD_LINE_TYPE_STRING,
 214       "Comma-delimited list of client function whose attributes are to be printed (function or all)" },
 215 
 216     { NULL,
 217       's', NULL, "server",
 218       1,
 219       &pmix_pattrs_globals.server, PMIX_CMD_LINE_TYPE_STRING,
 220       "Comma-delimited list of server function whose attributes are to be printed (function or all)" },
 221 
 222     { NULL,
 223       't', NULL, "tool",
 224       1,
 225       &pmix_pattrs_globals.tool, PMIX_CMD_LINE_TYPE_STRING,
 226       "Comma-delimited list of tool function whose attributes are to be printed (function or all)" },
 227 
 228     { NULL,
 229       'h', NULL, "host",
 230       1,
 231       &pmix_pattrs_globals.host, PMIX_CMD_LINE_TYPE_STRING,
 232       "Comma-delimited list of host function whose attributes are to be printed (function or all)" },
 233 
 234     { NULL,
 235       '\0', NULL, "client-fns",
 236       0,
 237       &pmix_pattrs_globals.clientfns, PMIX_CMD_LINE_TYPE_BOOL,
 238       "List the functions supported in this client library" },
 239 
 240     { NULL,
 241       '\0', NULL, "server-fns",
 242       0,
 243       &pmix_pattrs_globals.serverfns, PMIX_CMD_LINE_TYPE_BOOL,
 244       "List the functions supported in this server library" },
 245 
 246     { NULL,
 247       '\0', NULL, "tool-fns",
 248       0,
 249       &pmix_pattrs_globals.toolfns, PMIX_CMD_LINE_TYPE_BOOL,
 250       "List the functions supported in this tool library" },
 251 
 252     { NULL,
 253       '\0', NULL, "host-fns",
 254       0,
 255       &pmix_pattrs_globals.hostfns, PMIX_CMD_LINE_TYPE_BOOL,
 256       "List the functions supported by this host environment" },
 257 
 258 
 259     /* End of list */
 260     { NULL,
 261       '\0', NULL, NULL,
 262       0,
 263       NULL, PMIX_CMD_LINE_TYPE_NULL,
 264       NULL }
 265 };
 266 
 267 int main(int argc, char **argv)
 268 {
 269     pmix_status_t rc;
 270     pmix_info_t *info;
 271     mylock_t mylock;
 272     pmix_cmd_line_t cmd_line;
 273     char **fns;
 274     size_t n, m;
 275     myquery_data_t mq;
 276     pmix_query_t query;
 277     pmix_regattr_t *reg;
 278     char **ans = NULL;
 279 
 280     /* protect against problems if someone passes us thru a pipe
 281      * and then abnormally terminates the pipe early */
 282     signal(SIGPIPE, SIG_IGN);
 283 
 284     /* initialize the output system */
 285     if (!pmix_output_init()) {
 286         return PMIX_ERROR;
 287     }
 288 
 289     /* initialize install dirs code */
 290     if (PMIX_SUCCESS != (rc = pmix_mca_base_framework_open(&pmix_pinstalldirs_base_framework, 0))) {
 291         fprintf(stderr, "pmix_pinstalldirs_base_open() failed -- process will likely abort (%s:%d, returned %d instead of PMIX_SUCCESS)\n",
 292                 __FILE__, __LINE__, rc);
 293         return rc;
 294     }
 295 
 296     /* initialize the help system */
 297     pmix_show_help_init();
 298 
 299     /* keyval lex-based parser */
 300     if (PMIX_SUCCESS != (rc = pmix_util_keyval_parse_init())) {
 301         fprintf(stderr, "pmix_util_keyval_parse_init failed with %d\n", rc);
 302         return PMIX_ERROR;
 303     }
 304 
 305     /* Setup the parameter system */
 306     if (PMIX_SUCCESS != (rc = pmix_mca_base_var_init())) {
 307         fprintf(stderr, "pmix_mca_base_var_init failed with %d\n", rc);
 308         return PMIX_ERROR;
 309     }
 310 
 311     /* register params for pmix */
 312     if (PMIX_SUCCESS != (rc = pmix_register_params())) {
 313         fprintf(stderr, "pmix_register_params failed with %d\n", rc);
 314         return PMIX_ERROR;
 315     }
 316 
 317     /* Parse the command line options */
 318     pmix_cmd_line_create(&cmd_line, cmd_line_opts);
 319 
 320     rc = pmix_cmd_line_parse(&cmd_line, false, false, argc, argv);
 321 
 322     if (PMIX_SUCCESS != rc) {
 323         if (PMIX_ERR_SILENT != rc) {
 324             fprintf(stderr, "%s: command line error (%s)\n", argv[0],
 325                     PMIx_Error_string(rc));
 326         }
 327         return rc;
 328     }
 329 
 330     if (pmix_pattrs_globals.help) {
 331         char *str, *args = NULL;
 332         args = pmix_cmd_line_get_usage_msg(&cmd_line);
 333         str = pmix_show_help_string("help-pattrs.txt", "usage", true,
 334                                     args);
 335         if (NULL != str) {
 336             printf("%s", str);
 337             free(str);
 338         }
 339         free(args);
 340         /* If we show the help message, that should be all we do */
 341         exit(0);
 342     }
 343 
 344     /* cannot list functions and get attributes at same time */
 345     if ((pmix_pattrs_globals.clientfns || pmix_pattrs_globals.serverfns || pmix_pattrs_globals.toolfns || pmix_pattrs_globals.hostfns)
 346         && (pmix_pattrs_globals.client || pmix_pattrs_globals.server || pmix_pattrs_globals.tool || NULL != pmix_pattrs_globals.host)) {
 347         fprintf(stderr, "Cannot request both a list of functions and attributes at same time\n");
 348         exit(1);
 349     }
 350 
 351     /* if they are asking for client, server, or tool attrs, then
 352      * we don't need to connect to anyone - just register the
 353      * attrs and report */
 354     if (pmix_pattrs_globals.clientfns || pmix_pattrs_globals.serverfns || pmix_pattrs_globals.toolfns ||
 355         pmix_pattrs_globals.client || pmix_pattrs_globals.server || pmix_pattrs_globals.tool) {
 356         PMIX_INFO_CREATE(info, 1);
 357         PMIX_INFO_LOAD(&info[0], PMIX_TOOL_DO_NOT_CONNECT, NULL, PMIX_BOOL);
 358         rc = PMIx_tool_init(&myproc, info, 1);
 359         if (PMIX_SUCCESS != rc) {
 360             fprintf(stderr, "PMIx_tool_init failed: %s\n", PMIx_Error_string(rc));
 361             exit(rc);
 362         }
 363         if (pmix_pattrs_globals.clientfns) {
 364             pmix_register_client_attrs();
 365             fns = pmix_attributes_print_functions(PMIX_CLIENT_FUNCTIONS);
 366         } else if (pmix_pattrs_globals.serverfns) {
 367             pmix_register_server_attrs();
 368             fns = pmix_attributes_print_functions(PMIX_SERVER_FUNCTIONS);
 369         } else if (pmix_pattrs_globals.toolfns) {
 370             pmix_register_tool_attrs();
 371             fns = pmix_attributes_print_functions(PMIX_TOOL_FUNCTIONS);
 372         } else if (NULL != pmix_pattrs_globals.client) {
 373             pmix_register_client_attrs();
 374             fns = pmix_attributes_print_attr(PMIX_CLIENT_ATTRIBUTES, pmix_pattrs_globals.client);
 375         } else if (NULL != pmix_pattrs_globals.server) {
 376             pmix_register_server_attrs();
 377             fns = pmix_attributes_print_attr(PMIX_SERVER_ATTRIBUTES, pmix_pattrs_globals.server);
 378         } else if (NULL != pmix_pattrs_globals.tool) {
 379             pmix_register_tool_attrs();
 380             fns = pmix_attributes_print_attr(PMIX_TOOL_ATTRIBUTES, pmix_pattrs_globals.tool);
 381         }
 382         if (NULL != fns) {
 383             for (n=0; NULL != fns[n]; n++) {
 384                 fprintf(stderr, "%s\n", fns[n]);
 385             }
 386         }
 387         goto done;
 388     }
 389 
 390     /* if they didn't give us an option, then we can't do anything */
 391     if (!pmix_pattrs_globals.hostfns && NULL == pmix_pattrs_globals.host) {
 392         char *str, *args = NULL;
 393         args = pmix_cmd_line_get_usage_msg(&cmd_line);
 394         str = pmix_show_help_string("help-pattrs.txt", "usage", true,
 395                                     args);
 396         if (NULL != str) {
 397             printf("%s", str);
 398             free(str);
 399         }
 400         free(args);
 401         exit(1);
 402     }
 403 
 404     /* if we were given the pid of a starter, then direct that
 405      * we connect to it */
 406     n = 1;
 407     PMIX_INFO_CREATE(info, n);
 408     if (0 < pmix_pattrs_globals.pid) {
 409         PMIX_INFO_LOAD(&info[0], PMIX_SERVER_PIDINFO, &pmix_pattrs_globals.pid, PMIX_PID);
 410     } else if (NULL != pmix_pattrs_globals.nspace) {
 411         PMIX_INFO_LOAD(&info[0], PMIX_SERVER_NSPACE, pmix_pattrs_globals.nspace, PMIX_STRING);
 412     } else if (NULL != pmix_pattrs_globals.uri) {
 413         PMIX_INFO_LOAD(&info[0], PMIX_SERVER_URI, pmix_pattrs_globals.uri, PMIX_STRING);
 414     } else if (pmix_pattrs_globals.sysfirst) {
 415         /* otherwise, use the system connection first, if available */
 416         PMIX_INFO_LOAD(&info[0], PMIX_CONNECT_SYSTEM_FIRST, NULL, PMIX_BOOL);
 417     } else if (pmix_pattrs_globals.system) {
 418         PMIX_INFO_LOAD(&info[0], PMIX_CONNECT_TO_SYSTEM, NULL, PMIX_BOOL);
 419     } else {
 420         PMIX_INFO_FREE(info, 1);
 421         n = 0;
 422     }
 423     /* init as a tool */
 424     if (PMIX_SUCCESS != (rc = PMIx_tool_init(&myproc, info, n))) {
 425         fprintf(stderr, "PMIx_tool_init failed: %s\n", PMIx_Error_string(rc));
 426         exit(rc);
 427     }
 428     PMIX_INFO_FREE(info, 1);
 429 
 430     /* register a default event handler */
 431     PMIX_CONSTRUCT_LOCK(&mylock.lock);
 432     PMIx_Register_event_handler(NULL, 0, NULL, 0,
 433                                 notification_fn, evhandler_reg_callbk, (void*)&mylock);
 434     PMIX_WAIT_THREAD(&mylock.lock);
 435     if (PMIX_SUCCESS != mylock.status) {
 436         fprintf(stderr, "PMIx_Register_event_handler returned bad status: %d\n", rc);
 437         PMIX_DESTRUCT_LOCK(&mylock.lock);
 438         goto done;
 439     }
 440     PMIX_DESTRUCT_LOCK(&mylock.lock);
 441 
 442     /* generate the query */
 443     PMIX_QUERY_CONSTRUCT(&query);
 444     pmix_argv_append_nosize(&query.keys, PMIX_QUERY_ATTRIBUTE_SUPPORT);
 445     PMIX_QUERY_QUALIFIERS_CREATE(&query, 1);
 446     if (pmix_pattrs_globals.hostfns) {
 447         PMIX_INFO_LOAD(&query.qualifiers[0], PMIX_HOST_FUNCTIONS, NULL, PMIX_BOOL);
 448     } else {
 449         PMIX_INFO_LOAD(&query.qualifiers[0], PMIX_HOST_ATTRIBUTES, pmix_pattrs_globals.host, PMIX_STRING);
 450     }
 451     PMIX_CONSTRUCT_LOCK(&mq.lock);
 452     rc = PMIx_Query_info_nb(&query, 1, cbfunc,(void*)&mq);
 453     if (PMIX_SUCCESS != rc) {
 454         fprintf(stderr, "PMIx_Notify_event failed: %d\n", rc);
 455         goto done;
 456     }
 457     PMIX_WAIT_THREAD(&mq.lock);
 458     PMIX_DESTRUCT_LOCK(&mq.lock);
 459     if (PMIX_SUCCESS != mq.status) {
 460         fprintf(stderr, "PMIx_Query returned: %s\n", PMIx_Error_string(mq.status));
 461     } else {
 462         /* print out the returned value(s) */
 463         for (n=0; n < mq.ninfo; n++) {
 464             if (PMIX_CHECK_KEY(&mq.info[n], PMIX_HOST_FUNCTIONS)) {
 465                 fns = pmix_argv_split(mq.info[n].value.data.string, ',');
 466                 fprintf(stderr, "HOST SUPPORTED FUNCTIONS:\n");
 467                 for (m=0; NULL != fns[m]; m++) {
 468                     fprintf(stderr, "\t%s\n", fns[m]);
 469                 }
 470                 pmix_argv_free(fns);
 471             } else {
 472                 pmix_attributes_print_headers(&ans, PMIX_HOST_ATTRIBUTES);
 473                 if (PMIX_DATA_ARRAY == mq.info[n].value.type) {
 474                     info = (pmix_info_t*)mq.info[n].value.data.darray->array;
 475                     for (m=0; m < mq.info[n].value.data.darray->size; m++) {
 476                         reg = (pmix_regattr_t*)info[m].value.data.darray->array;
 477                         pmix_attributes_print_attrs(&ans, info[m].key, reg, info[0].value.data.darray->size);
 478                     }
 479                 } else {
 480                     reg = (pmix_regattr_t*)mq.info[n].value.data.ptr;
 481                     pmix_attributes_print_attrs(&ans, mq.info[n].key, reg, 1);
 482                 }
 483                 for (m=0; NULL != ans[m]; m++) {
 484                     fprintf(stderr, "%s\n", ans[m]);
 485                 }
 486                 pmix_argv_free(ans);
 487                 ans = NULL;
 488             }
 489         }
 490     }
 491 
 492   done:
 493     PMIx_tool_finalize();
 494 
 495     return(rc);
 496 }

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