root/opal/mca/pmix/ext2x/ext2x.c

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

DEFINITIONS

This source file includes following definitions.
  1. legacy_get
  2. opcbfunc
  3. ext2x_get_nspace
  4. ext2x_register_jobid
  5. event_hdlr_complete
  6. return_local_event_hdlr
  7. ext2x_event_hdlr
  8. ext2x_convert_rank
  9. ext2x_convert_opalrank
  10. ext2x_convert_opalrc
  11. ext2x_convert_rc
  12. ext2x_convert_scope
  13. ext2x_convert_opalscope
  14. ext2x_convert_opalrange
  15. ext2x_convert_range
  16. ext2x_convert_persist
  17. ext2x_convert_opalpersist
  18. ext2x_convert_jobid
  19. ext2x_value_load
  20. ext2x_value_unload
  21. errreg_cbfunc
  22. register_handler
  23. deregister_handler
  24. notify_complete
  25. notify_event
  26. relcbfunc
  27. infocbfunc
  28. ext2x_query
  29. ext2x_log
  30. ext2x_convert_allocdir
  31. evcon
  32. evdes
  33. opcon
  34. opdes
  35. ocadcon
  36. ocaddes
  37. tscon
  38. tsdes
  39. dmcon
  40. dmdes

   1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
   2 /*
   3  * Copyright (c) 2014-2018 Intel, Inc. All rights reserved.
   4  * Copyright (c) 2014-2017 Research Organization for Information Science
   5  *                         and Technology (RIST). All rights reserved.
   6  * Copyright (c) 2014-2015 Mellanox Technologies, Inc.
   7  *                         All rights reserved.
   8  * Copyright (c) 2016      Cisco Systems, Inc.  All rights reserved.
   9  * Copyright (c) 2017      Los Alamos National Security, LLC. All rights
  10  *                         reserved.
  11  * $COPYRIGHT$
  12  *
  13  * Additional copyrights may follow
  14  *
  15  * $HEADER$
  16  */
  17 
  18 #include "opal_config.h"
  19 #include "opal/constants.h"
  20 #include "opal/types.h"
  21 
  22 #ifdef HAVE_STRING_H
  23 #include <string.h>
  24 #endif
  25 #ifdef HAVE_UNISTD_H
  26 #include <unistd.h>
  27 #endif
  28 
  29 #include "opal/dss/dss.h"
  30 #include "opal/mca/event/event.h"
  31 #include "opal/mca/hwloc/base/base.h"
  32 #include "opal/runtime/opal.h"
  33 #include "opal/runtime/opal_progress_threads.h"
  34 #include "opal/threads/threads.h"
  35 #include "opal/util/argv.h"
  36 #include "opal/util/error.h"
  37 #include "opal/util/opal_environ.h"
  38 #include "opal/util/output.h"
  39 #include "opal/util/proc.h"
  40 #include "opal/util/show_help.h"
  41 #include "opal/util/string_copy.h"
  42 
  43 #include "ext2x.h"
  44 #include "opal/mca/pmix/base/base.h"
  45 #include "opal/mca/pmix/pmix_types.h"
  46 
  47 #include <pmix_common.h>
  48 #include <pmix.h>
  49 
  50 /****    C.O.M.M.O.N   I.N.T.E.R.F.A.C.E.S     ****/
  51 
  52 /* These are functions used by both client and server to
  53  * access common functions in the embedded PMIx library */
  54 static bool legacy_get(void);
  55 static const char *ext2x_get_nspace(opal_jobid_t jobid);
  56 static void ext2x_register_jobid(opal_jobid_t jobid, const char *nspace);
  57 static void register_handler(opal_list_t *event_codes,
  58                              opal_list_t *info,
  59                              opal_pmix_notification_fn_t evhandler,
  60                              opal_pmix_evhandler_reg_cbfunc_t cbfunc,
  61                              void *cbdata);
  62 static void deregister_handler(size_t evhandler,
  63                                opal_pmix_op_cbfunc_t cbfunc,
  64                                void *cbdata);
  65 static int notify_event(int status,
  66                         const opal_process_name_t *source,
  67                         opal_pmix_data_range_t range,
  68                         opal_list_t *info,
  69                         opal_pmix_op_cbfunc_t cbfunc, void *cbdata);
  70 static void ext2x_query(opal_list_t *queries,
  71                          opal_pmix_info_cbfunc_t cbfunc, void *cbdata);
  72 static void ext2x_log(opal_list_t *info,
  73                        opal_pmix_op_cbfunc_t cbfunc, void *cbdata);
  74 
  75 const opal_pmix_base_module_t opal_pmix_ext2x_module = {
  76     .legacy_get = legacy_get,
  77     /* client APIs */
  78     .init = ext2x_client_init,
  79     .finalize = ext2x_client_finalize,
  80     .initialized = ext2x_initialized,
  81     .abort = ext2x_abort,
  82     .commit = ext2x_commit,
  83     .fence = ext2x_fence,
  84     .fence_nb = ext2x_fencenb,
  85     .put = ext2x_put,
  86     .get = ext2x_get,
  87     .get_nb = ext2x_getnb,
  88     .publish = ext2x_publish,
  89     .publish_nb = ext2x_publishnb,
  90     .lookup = ext2x_lookup,
  91     .lookup_nb = ext2x_lookupnb,
  92     .unpublish = ext2x_unpublish,
  93     .unpublish_nb = ext2x_unpublishnb,
  94     .spawn = ext2x_spawn,
  95     .spawn_nb = ext2x_spawnnb,
  96     .connect = ext2x_connect,
  97     .connect_nb = ext2x_connectnb,
  98     .disconnect = ext2x_disconnect,
  99     .disconnect_nb = ext2x_disconnectnb,
 100     .resolve_peers = ext2x_resolve_peers,
 101     .resolve_nodes = ext2x_resolve_nodes,
 102     .query = ext2x_query,
 103     .log = ext2x_log,
 104     .allocate = ext2x_allocate,
 105     .job_control = ext2x_job_control,
 106     /* server APIs */
 107     .server_init = ext2x_server_init,
 108     .server_finalize = ext2x_server_finalize,
 109     .generate_regex = ext2x_server_gen_regex,
 110     .generate_ppn = ext2x_server_gen_ppn,
 111     .server_register_nspace = ext2x_server_register_nspace,
 112     .server_deregister_nspace = ext2x_server_deregister_nspace,
 113     .server_register_client = ext2x_server_register_client,
 114     .server_deregister_client = ext2x_server_deregister_client,
 115     .server_setup_fork = ext2x_server_setup_fork,
 116     .server_dmodex_request = ext2x_server_dmodex,
 117     .server_notify_event = ext2x_server_notify_event,
 118     /* tool APIs */
 119     .tool_init = ext2x_tool_init,
 120     .tool_finalize = ext2x_tool_fini,
 121     /* utility APIs */
 122     .get_version = PMIx_Get_version,
 123     .register_evhandler = register_handler,
 124     .deregister_evhandler = deregister_handler,
 125     .notify_event = notify_event,
 126     .store_local = ext2x_store_local,
 127     .get_nspace = ext2x_get_nspace,
 128     .register_jobid = ext2x_register_jobid
 129 };
 130 
 131 static bool legacy_get(void)
 132 {
 133     return mca_pmix_ext2x_component.legacy_get;
 134 }
 135 
 136 static void opcbfunc(pmix_status_t status, void *cbdata)
 137 {
 138     ext2x_opcaddy_t *op = (ext2x_opcaddy_t*)cbdata;
 139 
 140     OPAL_ACQUIRE_OBJECT(op);
 141 
 142     if (NULL != op->opcbfunc) {
 143         op->opcbfunc(ext2x_convert_rc(status), op->cbdata);
 144     }
 145     OBJ_RELEASE(op);
 146 }
 147 
 148 
 149 static const char *ext2x_get_nspace(opal_jobid_t jobid)
 150 {
 151     opal_ext2x_jobid_trkr_t *jptr;
 152 
 153     OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
 154 
 155     OPAL_LIST_FOREACH(jptr, &mca_pmix_ext2x_component.jobids, opal_ext2x_jobid_trkr_t) {
 156         if (jptr->jobid == jobid) {
 157             OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 158             return jptr->nspace;
 159         }
 160     }
 161     OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 162     return NULL;
 163 }
 164 
 165 static void ext2x_register_jobid(opal_jobid_t jobid, const char *nspace)
 166 {
 167     opal_ext2x_jobid_trkr_t *jptr;
 168 
 169     OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
 170 
 171     /* if we don't already have it, add this to our jobid tracker */
 172     OPAL_LIST_FOREACH(jptr, &mca_pmix_ext2x_component.jobids, opal_ext2x_jobid_trkr_t) {
 173         if (jptr->jobid == jobid) {
 174             OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 175             return;
 176         }
 177     }
 178     jptr = OBJ_NEW(opal_ext2x_jobid_trkr_t);
 179     (void)opal_string_copy(jptr->nspace, nspace, PMIX_MAX_NSLEN);
 180     jptr->jobid = jobid;
 181     opal_list_append(&mca_pmix_ext2x_component.jobids, &jptr->super);
 182     OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 183 }
 184 
 185 static void event_hdlr_complete(pmix_status_t status, void *cbdata)
 186 {
 187     ext2x_opcaddy_t *op = (ext2x_opcaddy_t*)cbdata;
 188 
 189     OBJ_RELEASE(op);
 190 }
 191 
 192 static void return_local_event_hdlr(int status, opal_list_t *results,
 193                                     opal_pmix_op_cbfunc_t cbfunc, void *thiscbdata,
 194                                     void *notification_cbdata)
 195 {
 196     ext2x_threadshift_t *cd = (ext2x_threadshift_t*)notification_cbdata;
 197     ext2x_opcaddy_t *op;
 198     opal_value_t *kv;
 199     pmix_status_t pstatus;
 200     size_t n;
 201 
 202     OPAL_ACQUIRE_OBJECT(cd);
 203     if (NULL != cd->pmixcbfunc) {
 204         op = OBJ_NEW(ext2x_opcaddy_t);
 205 
 206         if (NULL != results && 0 < (op->ninfo = opal_list_get_size(results))) {
 207             /* convert the list of results to an array of info */
 208             PMIX_INFO_CREATE(op->info, op->ninfo);
 209             n=0;
 210             OPAL_LIST_FOREACH(kv, cd->info, opal_value_t) {
 211                 (void)opal_string_copy(op->info[n].key, kv->key, PMIX_MAX_KEYLEN);
 212                 ext2x_value_load(&op->info[n].value, kv);
 213                 ++n;
 214             }
 215         }
 216         /* convert the status */
 217         pstatus = ext2x_convert_opalrc(status);
 218         /* call the library's callback function */
 219         cd->pmixcbfunc(pstatus, op->info, op->ninfo, event_hdlr_complete, op, cd->cbdata);
 220     }
 221 
 222     /* release the threadshift object */
 223     if (NULL != cd->info) {
 224         OPAL_LIST_RELEASE(cd->info);
 225     }
 226     OBJ_RELEASE(cd);
 227 
 228     /* release the caller */
 229     if (NULL != cbfunc) {
 230         cbfunc(OPAL_SUCCESS, thiscbdata);
 231     }
 232 }
 233 
 234 /* this function will be called by the PMIx client library
 235  * whenever it receives notification of an event. The
 236  * notification can come from an ORTE daemon (when launched
 237  * by mpirun), directly from a RM (when direct launched), or
 238  * from another process (via the local daemon).
 239  * The call will occur in the PMIx event base */
 240 void ext2x_event_hdlr(size_t evhdlr_registration_id,
 241                        pmix_status_t status, const pmix_proc_t *source,
 242                        pmix_info_t info[], size_t ninfo,
 243                        pmix_info_t results[], size_t nresults,
 244                        pmix_event_notification_cbfunc_fn_t cbfunc,
 245                        void *cbdata)
 246 {
 247     ext2x_threadshift_t *cd;
 248     int rc;
 249     opal_value_t *iptr;
 250     size_t n;
 251     opal_ext2x_event_t *event;
 252 
 253     opal_output_verbose(2, opal_pmix_base_framework.framework_output,
 254                         "%s RECEIVED NOTIFICATION OF STATUS %d",
 255                         OPAL_NAME_PRINT(OPAL_PROC_MY_NAME), status);
 256 
 257     OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
 258 
 259     cd = OBJ_NEW(ext2x_threadshift_t);
 260     cd->id = evhdlr_registration_id;
 261     cd->pmixcbfunc = cbfunc;
 262     cd->cbdata = cbdata;
 263 
 264     /* convert the incoming status */
 265     cd->status = ext2x_convert_rc(status);
 266     opal_output_verbose(2, opal_pmix_base_framework.framework_output,
 267                         "%s CONVERTED STATUS %d TO STATUS %d",
 268                         OPAL_NAME_PRINT(OPAL_PROC_MY_NAME), status, cd->status);
 269 
 270     /* convert the nspace/rank to an opal_process_name_t */
 271     if (NULL == source) {
 272         cd->pname.jobid = OPAL_NAME_INVALID->jobid;
 273         cd->pname.vpid = OPAL_NAME_INVALID->vpid;
 274     } else {
 275         if (OPAL_SUCCESS != (rc = opal_convert_string_to_jobid(&cd->pname.jobid, source->nspace))) {
 276             OPAL_ERROR_LOG(rc);
 277             cd->pname.jobid = OPAL_NAME_INVALID->jobid;
 278         }
 279         cd->pname.vpid = ext2x_convert_rank(source->rank);
 280     }
 281 
 282     /* convert the array of info */
 283     if (NULL != info) {
 284         cd->info = OBJ_NEW(opal_list_t);
 285         for (n=0; n < ninfo; n++) {
 286             iptr = OBJ_NEW(opal_value_t);
 287             iptr->key = strdup(info[n].key);
 288             if (OPAL_SUCCESS != (rc = ext2x_value_unload(iptr, &info[n].value))) {
 289                 OPAL_ERROR_LOG(rc);
 290                 OBJ_RELEASE(iptr);
 291                 continue;
 292             }
 293             opal_list_append(cd->info, &iptr->super);
 294         }
 295     }
 296 
 297     /* convert the array of prior results */
 298     if (NULL != results) {
 299         for (n=0; n < nresults; n++) {
 300             iptr = OBJ_NEW(opal_value_t);
 301             iptr->key = strdup(results[n].key);
 302             if (OPAL_SUCCESS != (rc = ext2x_value_unload(iptr, &results[n].value))) {
 303                 OPAL_ERROR_LOG(rc);
 304                 OBJ_RELEASE(iptr);
 305                 continue;
 306             }
 307             opal_list_append(&cd->results, &iptr->super);
 308         }
 309     }
 310 
 311     /* cycle thru the registrations */
 312     OPAL_LIST_FOREACH(event, &mca_pmix_ext2x_component.events, opal_ext2x_event_t) {
 313         if (evhdlr_registration_id == event->index) {
 314             /* found it - invoke the handler, pointing its
 315              * callback function to our callback function */
 316             opal_output_verbose(2, opal_pmix_base_framework.framework_output,
 317                                 "%s _EVENT_HDLR CALLING EVHDLR",
 318                                 OPAL_NAME_PRINT(OPAL_PROC_MY_NAME));
 319             if (NULL != event->handler) {
 320                 OBJ_RETAIN(event);
 321                 OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 322                 event->handler(cd->status, &cd->pname,
 323                                cd->info, &cd->results,
 324                                return_local_event_hdlr, cd);
 325                 OBJ_RELEASE(event);
 326                 return;
 327             }
 328         }
 329     }
 330 
 331     OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 332 
 333     /* if we didn't find a match, we still have to call their final callback */
 334     if (NULL != cbfunc) {
 335         cbfunc(PMIX_SUCCESS, NULL, 0, NULL, NULL, cbdata);
 336     }
 337     OPAL_LIST_RELEASE(cd->info);
 338     OBJ_RELEASE(cd);
 339     return;
 340 }
 341 
 342 opal_vpid_t ext2x_convert_rank(pmix_rank_t rank)
 343 {
 344     switch(rank) {
 345     case PMIX_RANK_UNDEF:
 346         return OPAL_VPID_INVALID;
 347     case PMIX_RANK_WILDCARD:
 348         return OPAL_VPID_WILDCARD;
 349     default:
 350         return (opal_vpid_t)rank;
 351     }
 352 }
 353 
 354 pmix_rank_t ext2x_convert_opalrank(opal_vpid_t vpid)
 355 {
 356     switch(vpid) {
 357     case OPAL_VPID_WILDCARD:
 358         return PMIX_RANK_WILDCARD;
 359     case OPAL_VPID_INVALID:
 360         return PMIX_RANK_UNDEF;
 361     default:
 362         return (pmix_rank_t)vpid;
 363     }
 364 }
 365 
 366 pmix_status_t ext2x_convert_opalrc(int rc)
 367 {
 368     switch (rc) {
 369     case OPAL_ERR_DEBUGGER_RELEASE:
 370         return PMIX_ERR_DEBUGGER_RELEASE;
 371 
 372     case OPAL_ERR_HANDLERS_COMPLETE:
 373         return PMIX_EVENT_ACTION_COMPLETE;
 374 
 375     case OPAL_ERR_PROC_ABORTED:
 376         return PMIX_ERR_PROC_ABORTED;
 377 
 378     case OPAL_ERR_PROC_REQUESTED_ABORT:
 379         return PMIX_ERR_PROC_REQUESTED_ABORT;
 380 
 381     case OPAL_ERR_PROC_ABORTING:
 382         return PMIX_ERR_PROC_ABORTING;
 383 
 384     case OPAL_ERR_NODE_DOWN:
 385         return PMIX_ERR_NODE_DOWN;
 386 
 387     case OPAL_ERR_NODE_OFFLINE:
 388         return PMIX_ERR_NODE_OFFLINE;
 389 
 390     case OPAL_ERR_JOB_TERMINATED:
 391         return PMIX_ERR_JOB_TERMINATED;
 392 
 393     case OPAL_ERR_PROC_RESTART:
 394         return PMIX_ERR_PROC_RESTART;
 395 
 396     case OPAL_ERR_PROC_CHECKPOINT:
 397         return PMIX_ERR_PROC_CHECKPOINT;
 398 
 399     case OPAL_ERR_PROC_MIGRATE:
 400         return PMIX_ERR_PROC_MIGRATE;
 401 
 402     case OPAL_ERR_EVENT_REGISTRATION:
 403         return PMIX_ERR_EVENT_REGISTRATION;
 404 
 405     case OPAL_ERR_NOT_IMPLEMENTED:
 406     case OPAL_ERR_NOT_SUPPORTED:
 407         return PMIX_ERR_NOT_SUPPORTED;
 408 
 409     case OPAL_ERR_NOT_FOUND:
 410         return PMIX_ERR_NOT_FOUND;
 411 
 412     case OPAL_ERR_PERM:
 413     case OPAL_ERR_UNREACH:
 414     case OPAL_ERR_SERVER_NOT_AVAIL:
 415         return PMIX_ERR_UNREACH;
 416 
 417     case OPAL_ERR_BAD_PARAM:
 418         return PMIX_ERR_BAD_PARAM;
 419 
 420     case OPAL_ERR_OUT_OF_RESOURCE:
 421         return PMIX_ERR_OUT_OF_RESOURCE;
 422 
 423     case OPAL_ERR_DATA_VALUE_NOT_FOUND:
 424         return PMIX_ERR_DATA_VALUE_NOT_FOUND;
 425 
 426     case OPAL_ERR_TIMEOUT:
 427         return PMIX_ERR_TIMEOUT;
 428 
 429     case OPAL_ERR_WOULD_BLOCK:
 430         return PMIX_ERR_WOULD_BLOCK;
 431 
 432     case OPAL_EXISTS:
 433         return PMIX_EXISTS;
 434 
 435     case OPAL_ERR_PARTIAL_SUCCESS:
 436         return PMIX_QUERY_PARTIAL_SUCCESS;
 437 
 438     case OPAL_ERR_MODEL_DECLARED:
 439         return PMIX_MODEL_DECLARED;
 440 
 441     case OPAL_ERROR:
 442         return PMIX_ERROR;
 443     case OPAL_SUCCESS:
 444     case OPAL_OPERATION_SUCCEEDED:
 445         return PMIX_SUCCESS;
 446     default:
 447         return rc;
 448     }
 449 }
 450 
 451 int ext2x_convert_rc(pmix_status_t rc)
 452 {
 453     switch (rc) {
 454     case PMIX_ERR_DEBUGGER_RELEASE:
 455         return OPAL_ERR_DEBUGGER_RELEASE;
 456 
 457     case PMIX_EVENT_ACTION_COMPLETE:
 458         return OPAL_ERR_HANDLERS_COMPLETE;
 459 
 460     case PMIX_ERR_PROC_ABORTED:
 461         return OPAL_ERR_PROC_ABORTED;
 462 
 463     case PMIX_ERR_PROC_REQUESTED_ABORT:
 464         return OPAL_ERR_PROC_REQUESTED_ABORT;
 465 
 466     case PMIX_ERR_PROC_ABORTING:
 467         return OPAL_ERR_PROC_ABORTING;
 468 
 469     case PMIX_ERR_NODE_DOWN:
 470         return OPAL_ERR_NODE_DOWN;
 471 
 472     case PMIX_ERR_NODE_OFFLINE:
 473         return OPAL_ERR_NODE_OFFLINE;
 474 
 475     case PMIX_ERR_JOB_TERMINATED:
 476         return OPAL_ERR_JOB_TERMINATED;
 477 
 478     case PMIX_ERR_PROC_RESTART:
 479         return OPAL_ERR_PROC_RESTART;
 480 
 481     case PMIX_ERR_PROC_CHECKPOINT:
 482         return OPAL_ERR_PROC_CHECKPOINT;
 483 
 484     case PMIX_ERR_PROC_MIGRATE:
 485         return OPAL_ERR_PROC_MIGRATE;
 486 
 487     case PMIX_ERR_EVENT_REGISTRATION:
 488         return OPAL_ERR_EVENT_REGISTRATION;
 489 
 490     case PMIX_ERR_NOT_SUPPORTED:
 491         return OPAL_ERR_NOT_SUPPORTED;
 492 
 493     case PMIX_ERR_NOT_FOUND:
 494         return OPAL_ERR_NOT_FOUND;
 495 
 496     case PMIX_ERR_OUT_OF_RESOURCE:
 497         return OPAL_ERR_OUT_OF_RESOURCE;
 498 
 499     case PMIX_ERR_INIT:
 500         return OPAL_ERROR;
 501 
 502     case PMIX_ERR_BAD_PARAM:
 503         return OPAL_ERR_BAD_PARAM;
 504 
 505     case PMIX_ERR_UNREACH:
 506     case PMIX_ERR_NO_PERMISSIONS:
 507         return OPAL_ERR_UNREACH;
 508 
 509     case PMIX_ERR_TIMEOUT:
 510         return OPAL_ERR_TIMEOUT;
 511 
 512     case PMIX_ERR_WOULD_BLOCK:
 513         return OPAL_ERR_WOULD_BLOCK;
 514 
 515     case PMIX_ERR_LOST_CONNECTION_TO_SERVER:
 516     case PMIX_ERR_LOST_PEER_CONNECTION:
 517     case PMIX_ERR_LOST_CONNECTION_TO_CLIENT:
 518         return OPAL_ERR_COMM_FAILURE;
 519 
 520     case PMIX_EXISTS:
 521         return OPAL_EXISTS;
 522 
 523     case PMIX_QUERY_PARTIAL_SUCCESS:
 524         return OPAL_ERR_PARTIAL_SUCCESS;
 525 
 526     case PMIX_MONITOR_HEARTBEAT_ALERT:
 527         return OPAL_ERR_HEARTBEAT_ALERT;
 528 
 529     case PMIX_MONITOR_FILE_ALERT:
 530         return OPAL_ERR_FILE_ALERT;
 531 
 532     case PMIX_MODEL_DECLARED:
 533         return OPAL_ERR_MODEL_DECLARED;
 534 
 535 
 536     case PMIX_ERROR:
 537         return OPAL_ERROR;
 538     case PMIX_SUCCESS:
 539         return OPAL_SUCCESS;
 540     default:
 541         return rc;
 542     }
 543 }
 544 
 545 opal_pmix_scope_t ext2x_convert_scope(pmix_scope_t scope)
 546 {
 547     switch(scope) {
 548         case PMIX_SCOPE_UNDEF:
 549             return OPAL_PMIX_SCOPE_UNDEF;
 550         case PMIX_LOCAL:
 551             return OPAL_PMIX_LOCAL;
 552         case PMIX_REMOTE:
 553             return OPAL_PMIX_REMOTE;
 554         case PMIX_GLOBAL:
 555             return OPAL_PMIX_GLOBAL;
 556         default:
 557             return OPAL_PMIX_SCOPE_UNDEF;
 558     }
 559 }
 560 
 561 pmix_scope_t ext2x_convert_opalscope(opal_pmix_scope_t scope) {
 562     switch(scope) {
 563     case OPAL_PMIX_LOCAL:
 564         return PMIX_LOCAL;
 565     case OPAL_PMIX_REMOTE:
 566         return PMIX_REMOTE;
 567     case OPAL_PMIX_GLOBAL:
 568         return PMIX_GLOBAL;
 569     default:
 570         return PMIX_SCOPE_UNDEF;
 571     }
 572 }
 573 
 574 pmix_data_range_t ext2x_convert_opalrange(opal_pmix_data_range_t range) {
 575     switch(range) {
 576     case OPAL_PMIX_RANGE_UNDEF:
 577         return PMIX_RANGE_UNDEF;
 578     case OPAL_PMIX_RANGE_LOCAL:
 579         return PMIX_RANGE_LOCAL;
 580     case OPAL_PMIX_RANGE_NAMESPACE:
 581         return PMIX_RANGE_NAMESPACE;
 582     case OPAL_PMIX_RANGE_SESSION:
 583         return PMIX_RANGE_SESSION;
 584     case OPAL_PMIX_RANGE_GLOBAL:
 585         return PMIX_RANGE_GLOBAL;
 586     case OPAL_PMIX_RANGE_CUSTOM:
 587         return PMIX_RANGE_CUSTOM;
 588     default:
 589         return PMIX_SCOPE_UNDEF;
 590     }
 591 }
 592 
 593 opal_pmix_data_range_t ext2x_convert_range(pmix_data_range_t range) {
 594     switch(range) {
 595     case PMIX_RANGE_UNDEF:
 596         return OPAL_PMIX_RANGE_UNDEF;
 597     case PMIX_RANGE_LOCAL:
 598         return OPAL_PMIX_RANGE_LOCAL;
 599     case PMIX_RANGE_NAMESPACE:
 600         return OPAL_PMIX_RANGE_NAMESPACE;
 601     case PMIX_RANGE_SESSION:
 602         return OPAL_PMIX_RANGE_SESSION;
 603     case PMIX_RANGE_GLOBAL:
 604         return OPAL_PMIX_RANGE_GLOBAL;
 605     case PMIX_RANGE_CUSTOM:
 606         return OPAL_PMIX_RANGE_CUSTOM;
 607     default:
 608         return OPAL_PMIX_RANGE_UNDEF;
 609     }
 610 }
 611 
 612 opal_pmix_persistence_t ext2x_convert_persist(pmix_persistence_t persist)
 613 {
 614     switch(persist) {
 615         case PMIX_PERSIST_INDEF:
 616             return OPAL_PMIX_PERSIST_INDEF;
 617         case PMIX_PERSIST_FIRST_READ:
 618             return OPAL_PMIX_PERSIST_FIRST_READ;
 619         case PMIX_PERSIST_PROC:
 620             return OPAL_PMIX_PERSIST_PROC;
 621         case PMIX_PERSIST_APP:
 622             return OPAL_PMIX_PERSIST_APP;
 623         case PMIX_PERSIST_SESSION:
 624             return OPAL_PMIX_PERSIST_SESSION;
 625         default:
 626         return OPAL_PMIX_PERSIST_INDEF;
 627     }
 628 }
 629 
 630 pmix_persistence_t ext2x_convert_opalpersist(opal_pmix_persistence_t persist)
 631 {
 632     switch(persist) {
 633         case OPAL_PMIX_PERSIST_INDEF:
 634             return PMIX_PERSIST_INDEF;
 635         case OPAL_PMIX_PERSIST_FIRST_READ:
 636             return PMIX_PERSIST_FIRST_READ;
 637         case OPAL_PMIX_PERSIST_PROC:
 638             return PMIX_PERSIST_PROC;
 639         case OPAL_PMIX_PERSIST_APP:
 640             return PMIX_PERSIST_APP;
 641         case OPAL_PMIX_PERSIST_SESSION:
 642             return PMIX_PERSIST_SESSION;
 643         default:
 644             return PMIX_PERSIST_INDEF;
 645     }
 646 }
 647 
 648 char* ext2x_convert_jobid(opal_jobid_t jobid)
 649 {
 650     opal_ext2x_jobid_trkr_t *jptr;
 651 
 652     /* look thru our list of jobids and find the
 653      * corresponding nspace */
 654     OPAL_LIST_FOREACH(jptr, &mca_pmix_ext2x_component.jobids, opal_ext2x_jobid_trkr_t) {
 655         if (jptr->jobid == jobid) {
 656             return jptr->nspace;
 657         }
 658     }
 659     return NULL;
 660 }
 661 
 662 /****   RHC: NEED TO ADD SUPPORT FOR NEW PMIX DATA TYPES, INCLUDING
 663  ****   CONVERSION OF PROC STATES    ****/
 664 
 665 void ext2x_value_load(pmix_value_t *v,
 666                        opal_value_t *kv)
 667 {
 668     opal_ext2x_jobid_trkr_t *job;
 669     bool found;
 670     opal_list_t *list;
 671     opal_value_t *val;
 672     pmix_info_t *info;
 673     size_t n;
 674 
 675     switch(kv->type) {
 676         case OPAL_UNDEF:
 677             v->type = PMIX_UNDEF;
 678             break;
 679         case OPAL_BOOL:
 680             v->type = PMIX_BOOL;
 681             memcpy(&(v->data.flag), &kv->data.flag, 1);
 682             break;
 683         case OPAL_BYTE:
 684             v->type = PMIX_BYTE;
 685             memcpy(&(v->data.byte), &kv->data.byte, 1);
 686             break;
 687         case OPAL_STRING:
 688             v->type = PMIX_STRING;
 689             if (NULL != kv->data.string) {
 690                 v->data.string = strdup(kv->data.string);
 691             } else {
 692                 v->data.string = NULL;
 693             }
 694             break;
 695         case OPAL_SIZE:
 696             v->type = PMIX_SIZE;
 697             memcpy(&(v->data.size), &kv->data.size, sizeof(size_t));
 698             break;
 699         case OPAL_PID:
 700             v->type = PMIX_PID;
 701             memcpy(&(v->data.pid), &kv->data.pid, sizeof(pid_t));
 702             break;
 703         case OPAL_INT:
 704             v->type = PMIX_INT;
 705             memcpy(&(v->data.integer), &kv->data.integer, sizeof(int));
 706             break;
 707         case OPAL_INT8:
 708             v->type = PMIX_INT8;
 709             memcpy(&(v->data.int8), &kv->data.int8, 1);
 710             break;
 711         case OPAL_INT16:
 712             v->type = PMIX_INT16;
 713             memcpy(&(v->data.int16), &kv->data.int16, 2);
 714             break;
 715         case OPAL_INT32:
 716             v->type = PMIX_INT32;
 717             memcpy(&(v->data.int32), &kv->data.int32, 4);
 718             break;
 719         case OPAL_INT64:
 720             v->type = PMIX_INT64;
 721             memcpy(&(v->data.int64), &kv->data.int64, 8);
 722             break;
 723         case OPAL_UINT:
 724             v->type = PMIX_UINT;
 725             memcpy(&(v->data.uint), &kv->data.uint, sizeof(int));
 726             break;
 727         case OPAL_UINT8:
 728             v->type = PMIX_UINT8;
 729             memcpy(&(v->data.uint8), &kv->data.uint8, 1);
 730             break;
 731         case OPAL_UINT16:
 732             v->type = PMIX_UINT16;
 733             memcpy(&(v->data.uint16), &kv->data.uint16, 2);
 734             break;
 735         case OPAL_UINT32:
 736             v->type = PMIX_UINT32;
 737             memcpy(&(v->data.uint32), &kv->data.uint32, 4);
 738             break;
 739         case OPAL_UINT64:
 740             v->type = PMIX_UINT64;
 741             memcpy(&(v->data.uint64), &kv->data.uint64, 8);
 742             break;
 743         case OPAL_FLOAT:
 744             v->type = PMIX_FLOAT;
 745             memcpy(&(v->data.fval), &kv->data.fval, sizeof(float));
 746             break;
 747         case OPAL_DOUBLE:
 748             v->type = PMIX_DOUBLE;
 749             memcpy(&(v->data.dval), &kv->data.dval, sizeof(double));
 750             break;
 751         case OPAL_TIMEVAL:
 752             v->type = PMIX_TIMEVAL;
 753             memcpy(&(v->data.tv), &kv->data.tv, sizeof(struct timeval));
 754             break;
 755         case OPAL_TIME:
 756             v->type = PMIX_TIME;
 757             memcpy(&(v->data.time), &kv->data.time, sizeof(time_t));
 758             break;
 759         case OPAL_STATUS:
 760             v->type = PMIX_STATUS;
 761             v->data.status = ext2x_convert_opalrc(kv->data.status);
 762             break;
 763         case OPAL_VPID:
 764             v->type = PMIX_PROC_RANK;
 765             v->data.rank = ext2x_convert_opalrank(kv->data.name.vpid);
 766             break;
 767         case OPAL_NAME:
 768             v->type = PMIX_PROC;
 769             /* have to stringify the jobid */
 770             PMIX_PROC_CREATE(v->data.proc, 1);
 771             /* see if this job is in our list of known nspaces */
 772             found = false;
 773             OPAL_LIST_FOREACH(job, &mca_pmix_ext2x_component.jobids, opal_ext2x_jobid_trkr_t) {
 774                 if (job->jobid == kv->data.name.jobid) {
 775                     (void)opal_string_copy(v->data.proc->nspace, job->nspace, PMIX_MAX_NSLEN);
 776                     found = true;
 777                     break;
 778                 }
 779             }
 780             if (!found) {
 781                 (void)opal_snprintf_jobid(v->data.proc->nspace, PMIX_MAX_NSLEN, kv->data.name.jobid);
 782             }
 783             v->data.proc->rank = ext2x_convert_opalrank(kv->data.name.vpid);
 784             break;
 785         case OPAL_BYTE_OBJECT:
 786             v->type = PMIX_BYTE_OBJECT;
 787             if (NULL != kv->data.bo.bytes) {
 788                 v->data.bo.bytes = (char*)malloc(kv->data.bo.size);
 789                 memcpy(v->data.bo.bytes, kv->data.bo.bytes, kv->data.bo.size);
 790                 v->data.bo.size = (size_t)kv->data.bo.size;
 791             } else {
 792                 v->data.bo.bytes = NULL;
 793                 v->data.bo.size = 0;
 794             }
 795             break;
 796         case OPAL_PERSIST:
 797             v->type = PMIX_PERSIST;
 798             v->data.persist = ext2x_convert_opalpersist((opal_pmix_persistence_t)kv->data.uint8);
 799             break;
 800         case OPAL_SCOPE:
 801             v->type = PMIX_SCOPE;
 802             v->data.scope = ext2x_convert_opalscope((opal_pmix_scope_t)kv->data.uint8);
 803             break;
 804         case OPAL_DATA_RANGE:
 805             v->type = PMIX_DATA_RANGE;
 806             v->data.range = ext2x_convert_opalrange((opal_pmix_data_range_t)kv->data.uint8);
 807             break;
 808         case OPAL_PROC_STATE:
 809             v->type = PMIX_PROC_STATE;
 810             /* the OPAL layer doesn't have any concept of proc state,
 811              * so the ORTE layer is responsible for converting it */
 812             memcpy(&v->data.state, &kv->data.uint8, sizeof(uint8_t));
 813             break;
 814         case OPAL_PTR:
 815             /* if someone returned a pointer, it must be to a list of
 816              * opal_value_t's that we need to convert to a pmix_data_array
 817              * of pmix_info_t structures */
 818             list = (opal_list_t*)kv->data.ptr;
 819             v->type = PMIX_DATA_ARRAY;
 820             v->data.darray = (pmix_data_array_t*)malloc(sizeof(pmix_data_array_t));
 821             v->data.darray->type = PMIX_INFO;
 822             v->data.darray->size = opal_list_get_size(list);
 823             if (0 < v->data.darray->size) {
 824                 PMIX_INFO_CREATE(info, v->data.darray->size);
 825                 v->data.darray->array = info;
 826                 n=0;
 827                 OPAL_LIST_FOREACH(val, list, opal_value_t) {
 828                     (void)opal_string_copy(info[n].key, val->key, PMIX_MAX_KEYLEN);
 829                     ext2x_value_load(&info[n].value, val);
 830                     ++n;
 831                 }
 832             } else {
 833                 v->data.darray->array = NULL;
 834             }
 835             break;
 836         default:
 837             /* silence warnings */
 838             break;
 839     }
 840 }
 841 
 842 int ext2x_value_unload(opal_value_t *kv,
 843                        const pmix_value_t *v)
 844 {
 845     int rc=OPAL_SUCCESS;
 846     bool found;
 847     opal_ext2x_jobid_trkr_t *job;
 848     opal_list_t *lt;
 849     opal_value_t *ival;
 850     size_t n;
 851 
 852     switch(v->type) {
 853     case PMIX_UNDEF:
 854         kv->type = OPAL_UNDEF;
 855         break;
 856     case PMIX_BOOL:
 857         kv->type = OPAL_BOOL;
 858         memcpy(&kv->data.flag, &(v->data.flag), 1);
 859         break;
 860     case PMIX_BYTE:
 861         kv->type = OPAL_BYTE;
 862         memcpy(&kv->data.byte, &(v->data.byte), 1);
 863         break;
 864     case PMIX_STRING:
 865         kv->type = OPAL_STRING;
 866         if (NULL != v->data.string) {
 867             kv->data.string = strdup(v->data.string);
 868         }
 869         break;
 870     case PMIX_SIZE:
 871         kv->type = OPAL_SIZE;
 872         memcpy(&kv->data.size, &(v->data.size), sizeof(size_t));
 873         break;
 874     case PMIX_PID:
 875         kv->type = OPAL_PID;
 876         memcpy(&kv->data.pid, &(v->data.pid), sizeof(pid_t));
 877         break;
 878     case PMIX_INT:
 879         kv->type = OPAL_INT;
 880         memcpy(&kv->data.integer, &(v->data.integer), sizeof(int));
 881         break;
 882     case PMIX_INT8:
 883         kv->type = OPAL_INT8;
 884         memcpy(&kv->data.int8, &(v->data.int8), 1);
 885         break;
 886     case PMIX_INT16:
 887         kv->type = OPAL_INT16;
 888         memcpy(&kv->data.int16, &(v->data.int16), 2);
 889         break;
 890     case PMIX_INT32:
 891         kv->type = OPAL_INT32;
 892         memcpy(&kv->data.int32, &(v->data.int32), 4);
 893         break;
 894     case PMIX_INT64:
 895         kv->type = OPAL_INT64;
 896         memcpy(&kv->data.int64, &(v->data.int64), 8);
 897         break;
 898     case PMIX_UINT:
 899         kv->type = OPAL_UINT;
 900         memcpy(&kv->data.uint, &(v->data.uint), sizeof(int));
 901         break;
 902     case PMIX_UINT8:
 903         kv->type = OPAL_UINT8;
 904         memcpy(&kv->data.uint8, &(v->data.uint8), 1);
 905         break;
 906     case PMIX_UINT16:
 907         kv->type = OPAL_UINT16;
 908         memcpy(&kv->data.uint16, &(v->data.uint16), 2);
 909         break;
 910     case PMIX_UINT32:
 911         kv->type = OPAL_UINT32;
 912         memcpy(&kv->data.uint32, &(v->data.uint32), 4);
 913         break;
 914     case PMIX_UINT64:
 915         kv->type = OPAL_UINT64;
 916         memcpy(&kv->data.uint64, &(v->data.uint64), 8);
 917         break;
 918     case PMIX_FLOAT:
 919         kv->type = OPAL_FLOAT;
 920         memcpy(&kv->data.fval, &(v->data.fval), sizeof(float));
 921         break;
 922     case PMIX_DOUBLE:
 923         kv->type = OPAL_DOUBLE;
 924         memcpy(&kv->data.dval, &(v->data.dval), sizeof(double));
 925         break;
 926     case PMIX_TIMEVAL:
 927         kv->type = OPAL_TIMEVAL;
 928         memcpy(&kv->data.tv, &(v->data.tv), sizeof(struct timeval));
 929         break;
 930     case PMIX_TIME:
 931         kv->type = OPAL_TIME;
 932         memcpy(&kv->data.time, &(v->data.time), sizeof(time_t));
 933         break;
 934     case PMIX_STATUS:
 935         kv->type = OPAL_STATUS;
 936         kv->data.status = ext2x_convert_rc(v->data.status);
 937         break;
 938     case PMIX_PROC_RANK:
 939         kv->type = OPAL_VPID;
 940         kv->data.name.vpid = ext2x_convert_rank(v->data.rank);
 941         break;
 942     case PMIX_PROC:
 943         kv->type = OPAL_NAME;
 944         /* see if this job is in our list of known nspaces */
 945         found = false;
 946         OPAL_LIST_FOREACH(job, &mca_pmix_ext2x_component.jobids, opal_ext2x_jobid_trkr_t) {
 947             if (0 == strncmp(job->nspace, v->data.proc->nspace, PMIX_MAX_NSLEN)) {
 948                 kv->data.name.jobid = job->jobid;
 949                 found = true;
 950                 break;
 951             }
 952         }
 953         if (!found) {
 954             if (OPAL_SUCCESS != (rc = opal_convert_string_to_jobid(&kv->data.name.jobid, v->data.proc->nspace))) {
 955                 return ext2x_convert_opalrc(rc);
 956             }
 957         }
 958         kv->data.name.vpid = ext2x_convert_rank(v->data.proc->rank);
 959         break;
 960     case PMIX_BYTE_OBJECT:
 961         kv->type = OPAL_BYTE_OBJECT;
 962         if (NULL != v->data.bo.bytes && 0 < v->data.bo.size) {
 963             kv->data.bo.bytes = (uint8_t*)malloc(v->data.bo.size);
 964             memcpy(kv->data.bo.bytes, v->data.bo.bytes, v->data.bo.size);
 965             kv->data.bo.size = (int)v->data.bo.size;
 966         } else {
 967             kv->data.bo.bytes = NULL;
 968             kv->data.bo.size = 0;
 969         }
 970         break;
 971     case PMIX_PERSIST:
 972         kv->type = OPAL_PERSIST;
 973         kv->data.uint8 = ext2x_convert_persist(v->data.persist);
 974         break;
 975     case PMIX_SCOPE:
 976         kv->type = OPAL_SCOPE;
 977         kv->data.uint8 = ext2x_convert_scope(v->data.scope);
 978         break;
 979     case PMIX_DATA_RANGE:
 980         kv->type = OPAL_DATA_RANGE;
 981         kv->data.uint8 = ext2x_convert_range(v->data.range);
 982         break;
 983     case PMIX_PROC_STATE:
 984         kv->type = OPAL_PROC_STATE;
 985         /* the OPAL layer doesn't have any concept of proc state,
 986          * so the ORTE layer is responsible for converting it */
 987         memcpy(&kv->data.uint8, &v->data.state, sizeof(uint8_t));
 988         break;
 989     case PMIX_POINTER:
 990         kv->type = OPAL_PTR;
 991         kv->data.ptr = v->data.ptr;
 992         break;
 993     case PMIX_DATA_ARRAY:
 994         if (NULL == v->data.darray || NULL == v->data.darray->array) {
 995             kv->data.ptr = NULL;
 996             break;
 997         }
 998         lt = OBJ_NEW(opal_list_t);
 999         kv->type = OPAL_PTR;
1000         kv->data.ptr = (void*)lt;
1001         for (n=0; n < v->data.darray->size; n++) {
1002             ival = OBJ_NEW(opal_value_t);
1003             opal_list_append(lt, &ival->super);
1004             /* handle the various types */
1005             if (PMIX_INFO == v->data.darray->type) {
1006                 pmix_info_t *iptr = (pmix_info_t*)v->data.darray->array;
1007                 ival->key = strdup(iptr[n].key);
1008                 rc = ext2x_value_unload(ival, &iptr[n].value);
1009                 if (OPAL_SUCCESS != rc) {
1010                     OPAL_LIST_RELEASE(lt);
1011                     kv->type = OPAL_UNDEF;
1012                     kv->data.ptr = NULL;
1013                     break;
1014                 }
1015             }
1016         }
1017         break;
1018     default:
1019         /* silence warnings */
1020         rc = OPAL_ERROR;
1021         break;
1022     }
1023     return rc;
1024 }
1025 
1026 static void errreg_cbfunc (pmix_status_t status,
1027                            size_t errhandler_ref,
1028                            void *cbdata)
1029 {
1030     ext2x_opcaddy_t *op = (ext2x_opcaddy_t*)cbdata;
1031 
1032     OPAL_ACQUIRE_OBJECT(op);
1033     op->event->index = errhandler_ref;
1034     opal_output_verbose(5, opal_pmix_base_framework.framework_output,
1035                         "PMIX2x errreg_cbfunc - error handler registered status=%d, reference=%lu",
1036                         status, (unsigned long)errhandler_ref);
1037     if (NULL != op->evregcbfunc) {
1038         op->evregcbfunc(ext2x_convert_rc(status), errhandler_ref, op->cbdata);
1039     }
1040     OBJ_RELEASE(op);
1041 }
1042 
1043 static void register_handler(opal_list_t *event_codes,
1044                              opal_list_t *info,
1045                              opal_pmix_notification_fn_t evhandler,
1046                              opal_pmix_evhandler_reg_cbfunc_t cbfunc,
1047                              void *cbdata)
1048 {
1049     ext2x_opcaddy_t *op = (ext2x_opcaddy_t*)cbdata;
1050     size_t n;
1051     opal_value_t *kv;
1052 
1053     OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
1054     if (0 >= opal_pmix_base.initialized) {
1055         OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1056         if (NULL != cbfunc) {
1057             cbfunc(OPAL_ERR_NOT_INITIALIZED, 0, cbdata);
1058         }
1059         return;
1060     }
1061 
1062     op = OBJ_NEW(ext2x_opcaddy_t);
1063     op->evregcbfunc = cbfunc;
1064     op->cbdata = cbdata;
1065 
1066     /* convert the event codes */
1067     if (NULL != event_codes) {
1068         op->ncodes = opal_list_get_size(event_codes);
1069         op->pcodes = (pmix_status_t*)malloc(op->ncodes * sizeof(pmix_status_t));
1070         n=0;
1071         OPAL_LIST_FOREACH(kv, event_codes, opal_value_t) {
1072             op->pcodes[n] = ext2x_convert_opalrc(kv->data.integer);
1073             ++n;
1074         }
1075     }
1076 
1077     /* convert the list of info to an array of pmix_info_t */
1078     if (NULL != info && 0 < (op->ninfo = opal_list_get_size(info))) {
1079         PMIX_INFO_CREATE(op->info, op->ninfo);
1080         n=0;
1081         OPAL_LIST_FOREACH(kv, info, opal_value_t) {
1082             (void)opal_string_copy(op->info[n].key, kv->key, PMIX_MAX_KEYLEN);
1083             ext2x_value_load(&op->info[n].value, kv);
1084             ++n;
1085         }
1086     }
1087 
1088     /* register the event */
1089     op->event = OBJ_NEW(opal_ext2x_event_t);
1090     op->event->handler = evhandler;
1091     opal_list_append(&mca_pmix_ext2x_component.events, &op->event->super);
1092     OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1093 
1094     PMIx_Register_event_handler(op->pcodes, op->ncodes,
1095                                 op->info, op->ninfo,
1096                                 ext2x_event_hdlr, errreg_cbfunc, op);
1097     return;
1098 }
1099 
1100 static void deregister_handler(size_t evhandler,
1101                                opal_pmix_op_cbfunc_t cbfunc,
1102                                void *cbdata)
1103 {
1104     ext2x_opcaddy_t *op;
1105     opal_ext2x_event_t *event;
1106 
1107     OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
1108     if (0 >= opal_pmix_base.initialized) {
1109         OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1110         if (NULL != cbfunc) {
1111             cbfunc(OPAL_ERR_NOT_INITIALIZED, cbdata);
1112         }
1113         return;
1114     }
1115 
1116     /* look for this event */
1117     OPAL_LIST_FOREACH(event, &mca_pmix_ext2x_component.events, opal_ext2x_event_t) {
1118         if (evhandler == event->index) {
1119             opal_list_remove_item(&mca_pmix_ext2x_component.events, &event->super);
1120             OBJ_RELEASE(event);
1121             break;
1122         }
1123     }
1124 
1125     OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1126 
1127     op = OBJ_NEW(ext2x_opcaddy_t);
1128     op->opcbfunc = cbfunc;
1129     op->cbdata = cbdata;
1130 
1131     /* tell the library to deregister this handler */
1132     PMIx_Deregister_event_handler(evhandler, opcbfunc, op);
1133     return;
1134 }
1135 
1136 static void notify_complete(pmix_status_t status, void *cbdata)
1137 {
1138     ext2x_opcaddy_t *op = (ext2x_opcaddy_t*)cbdata;
1139     if (NULL != op->opcbfunc) {
1140         op->opcbfunc(ext2x_convert_rc(status), op->cbdata);
1141     }
1142     OBJ_RELEASE(op);
1143 }
1144 
1145 static int notify_event(int status,
1146                         const opal_process_name_t *source,
1147                         opal_pmix_data_range_t range,
1148                         opal_list_t *info,
1149                         opal_pmix_op_cbfunc_t cbfunc, void *cbdata)
1150 {
1151     ext2x_opcaddy_t *op;
1152     opal_value_t *kv;
1153     pmix_proc_t p, *pptr;
1154     pmix_status_t pstatus;
1155     size_t n;
1156     pmix_data_range_t prange;
1157     char *nsptr;
1158 
1159     OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
1160     if (0 >= opal_pmix_base.initialized) {
1161         OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1162         return OPAL_ERR_NOT_INITIALIZED;
1163     }
1164 
1165     op = OBJ_NEW(ext2x_opcaddy_t);
1166     op->opcbfunc = cbfunc;
1167     op->cbdata = cbdata;
1168 
1169     /* convert the status */
1170     pstatus = ext2x_convert_opalrc(status);
1171 
1172     /* convert the source */
1173     if (NULL == source) {
1174         pptr = NULL;
1175     } else {
1176         if (NULL == (nsptr = ext2x_convert_jobid(source->jobid))) {
1177             OBJ_RELEASE(op);
1178             OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1179             return OPAL_ERR_NOT_FOUND;
1180         }
1181         (void)opal_string_copy(p.nspace, nsptr, PMIX_MAX_NSLEN);
1182         p.rank = ext2x_convert_opalrank(source->vpid);
1183         pptr = &p;
1184     }
1185     OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1186 
1187     /* convert the range */
1188     prange = ext2x_convert_opalrange(range);
1189 
1190     /* convert the list of info */
1191     if (NULL != info && 0 < (op->ninfo = opal_list_get_size(info))) {
1192         PMIX_INFO_CREATE(op->info, op->ninfo);
1193         n=0;
1194         OPAL_LIST_FOREACH(kv, info, opal_value_t) {
1195             (void)opal_string_copy(op->info[n].key, kv->key, PMIX_MAX_KEYLEN);
1196             /* little dicey here as we need to convert a status, if
1197              * provided, and it will be an int coming down to us */
1198             if (0 == strcmp(kv->key, OPAL_PMIX_JOB_TERM_STATUS)) {
1199                 op->info[n].value.type = PMIX_STATUS;
1200                 op->info[n].value.data.status = ext2x_convert_opalrc(kv->data.integer);
1201             } else {
1202                 ext2x_value_load(&op->info[n].value, kv);
1203             }
1204             ++n;
1205         }
1206     }
1207 
1208     /* ask the library to notify our clients */
1209     pstatus = PMIx_Notify_event(pstatus, pptr, prange, op->info, op->ninfo, notify_complete, op);
1210 
1211     return ext2x_convert_rc(pstatus);
1212 }
1213 
1214 static void relcbfunc(void *cbdata)
1215 {
1216     opal_list_t *results = (opal_list_t*)cbdata;
1217     if (NULL != results) {
1218         OPAL_LIST_RELEASE(results);
1219     }
1220 }
1221 
1222 static void infocbfunc(pmix_status_t status,
1223                        pmix_info_t *info, size_t ninfo,
1224                        void *cbdata,
1225                        pmix_release_cbfunc_t release_fn,
1226                        void *release_cbdata)
1227 {
1228     ext2x_opcaddy_t *cd = (ext2x_opcaddy_t*)cbdata;
1229     int rc = OPAL_SUCCESS;
1230     opal_list_t *results = NULL;
1231     opal_value_t *iptr;
1232     size_t n;
1233 
1234     OPAL_ACQUIRE_OBJECT(cd);
1235 
1236     /* convert the array of pmix_info_t to the list of info */
1237     if (NULL != info) {
1238         results = OBJ_NEW(opal_list_t);
1239         for (n=0; n < ninfo; n++) {
1240             iptr = OBJ_NEW(opal_value_t);
1241             opal_list_append(results, &iptr->super);
1242             iptr->key = strdup(info[n].key);
1243             if (OPAL_SUCCESS != (rc = ext2x_value_unload(iptr, &info[n].value))) {
1244                 OPAL_LIST_RELEASE(results);
1245                 results = NULL;
1246                 break;
1247             }
1248         }
1249     }
1250 
1251     if (NULL != release_fn) {
1252         release_fn(release_cbdata);
1253     }
1254 
1255     /* return the values to the original requestor */
1256     if (NULL != cd->qcbfunc) {
1257         cd->qcbfunc(rc, results, cd->cbdata, relcbfunc, results);
1258     }
1259     OBJ_RELEASE(cd);
1260 }
1261 
1262 static void ext2x_query(opal_list_t *queries,
1263                          opal_pmix_info_cbfunc_t cbfunc, void *cbdata)
1264 {
1265     int rc;
1266     opal_value_t *ival;
1267     size_t n, nqueries, nq;
1268     ext2x_opcaddy_t *cd;
1269     pmix_status_t prc;
1270     opal_pmix_query_t *q;
1271 
1272     OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
1273     if (0 >= opal_pmix_base.initialized) {
1274         OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1275         if (NULL != cbfunc) {
1276             cbfunc(OPAL_ERR_NOT_INITIALIZED, NULL, cbdata, NULL, NULL);
1277         }
1278         return;
1279     }
1280     OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1281 
1282     /* create the caddy */
1283     cd = OBJ_NEW(ext2x_opcaddy_t);
1284 
1285     /* bozo check */
1286     if (NULL == queries || 0 == (nqueries = opal_list_get_size(queries))) {
1287         rc = OPAL_ERR_BAD_PARAM;
1288         goto CLEANUP;
1289     }
1290 
1291     /* setup the operation */
1292     cd->qcbfunc = cbfunc;
1293     cd->cbdata = cbdata;
1294     cd->nqueries = nqueries;
1295 
1296     /* convert the list to an array of query objects */
1297     PMIX_QUERY_CREATE(cd->queries, cd->nqueries);
1298     n=0;
1299     OPAL_LIST_FOREACH(q, queries, opal_pmix_query_t) {
1300         cd->queries[n].keys = opal_argv_copy(q->keys);
1301         cd->queries[n].nqual = opal_list_get_size(&q->qualifiers);
1302         if (0 < cd->queries[n].nqual) {
1303             PMIX_INFO_CREATE(cd->queries[n].qualifiers, cd->queries[n].nqual);
1304             nq = 0;
1305             OPAL_LIST_FOREACH(ival, &q->qualifiers, opal_value_t) {
1306                 (void)opal_string_copy(cd->queries[n].qualifiers[nq].key, ival->key, PMIX_MAX_KEYLEN);
1307                 ext2x_value_load(&cd->queries[n].qualifiers[nq].value, ival);
1308                 ++nq;
1309             }
1310         }
1311         ++n;
1312     }
1313 
1314     /* pass it down */
1315     if (PMIX_SUCCESS != (prc = PMIx_Query_info_nb(cd->queries, cd->nqueries,
1316                                                   infocbfunc, cd))) {
1317         /* do not hang! */
1318         rc = ext2x_convert_rc(prc);
1319         goto CLEANUP;
1320     }
1321 
1322     return;
1323 
1324   CLEANUP:
1325     if (NULL != cbfunc) {
1326         cbfunc(rc, NULL, cbdata, NULL, NULL);
1327     }
1328     OBJ_RELEASE(cd);
1329     return;
1330 }
1331 
1332 static void ext2x_log(opal_list_t *info,
1333                        opal_pmix_op_cbfunc_t cbfunc, void *cbdata)
1334 {
1335     int rc;
1336     opal_value_t *ival;
1337     size_t n, ninfo;
1338     ext2x_opcaddy_t *cd;
1339     pmix_status_t prc;
1340 
1341     OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
1342     if (0 >= opal_pmix_base.initialized) {
1343         OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1344         if (NULL != cbfunc) {
1345             cbfunc(OPAL_ERR_NOT_INITIALIZED, cbdata);
1346         }
1347         return;
1348     }
1349     OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1350 
1351     /* create the caddy */
1352     cd = OBJ_NEW(ext2x_opcaddy_t);
1353 
1354     /* bozo check */
1355     if (NULL == info || 0 == (ninfo = opal_list_get_size(info))) {
1356         rc = OPAL_ERR_BAD_PARAM;
1357         goto CLEANUP;
1358     }
1359 
1360     /* setup the operation */
1361     cd->opcbfunc = cbfunc;
1362     cd->cbdata = cbdata;
1363     cd->ninfo = ninfo;
1364 
1365     /* convert the list to an array of info objects */
1366     PMIX_INFO_CREATE(cd->info, cd->ninfo);
1367     n=0;
1368     OPAL_LIST_FOREACH(ival, info, opal_value_t) {
1369         (void)opal_string_copy(cd->info[n].key, ival->key, PMIX_MAX_KEYLEN);
1370         ext2x_value_load(&cd->info[n].value, ival);
1371         ++n;
1372     }
1373 
1374     /* pass it down */
1375     if (PMIX_SUCCESS != (prc = PMIx_Log_nb(cd->info, cd->ninfo, NULL, 0,
1376                                            opcbfunc, cd))) {
1377         /* do not hang! */
1378         rc = ext2x_convert_rc(prc);
1379         goto CLEANUP;
1380     }
1381 
1382     return;
1383 
1384   CLEANUP:
1385     if (NULL != cbfunc) {
1386         cbfunc(rc, cbdata);
1387     }
1388     OBJ_RELEASE(cd);
1389 }
1390 
1391 opal_pmix_alloc_directive_t ext2x_convert_allocdir(pmix_alloc_directive_t dir)
1392 {
1393     switch (dir) {
1394         case PMIX_ALLOC_NEW:
1395             return OPAL_PMIX_ALLOC_NEW;
1396         case PMIX_ALLOC_EXTEND:
1397             return OPAL_PMIX_ALLOC_EXTEND;
1398         case PMIX_ALLOC_RELEASE:
1399             return OPAL_PMIX_ALLOC_RELEASE;
1400         case PMIX_ALLOC_REAQUIRE:
1401             return OPAL_PMIX_ALLOC_REAQCUIRE;
1402         default:
1403             return OPAL_PMIX_ALLOC_UNDEF;
1404     }
1405 }
1406 
1407 /****  INSTANTIATE INTERNAL CLASSES  ****/
1408 OBJ_CLASS_INSTANCE(opal_ext2x_jobid_trkr_t,
1409                    opal_list_item_t,
1410                    NULL, NULL);
1411 
1412 static void evcon(opal_ext2x_event_t *p)
1413 {
1414     OPAL_PMIX_CONSTRUCT_LOCK(&p->lock);
1415     p->handler = NULL;
1416     p->cbdata = NULL;
1417 }
1418 static void evdes(opal_ext2x_event_t *p)
1419 {
1420     OPAL_PMIX_DESTRUCT_LOCK(&p->lock);
1421 }
1422 OBJ_CLASS_INSTANCE(opal_ext2x_event_t,
1423                    opal_list_item_t,
1424                    evcon, evdes);
1425 
1426 static void opcon(ext2x_opcaddy_t *p)
1427 {
1428     memset(&p->p, 0, sizeof(pmix_proc_t));
1429     p->nspace = NULL;
1430     p->procs = NULL;
1431     p->nprocs = 0;
1432     p->pdata = NULL;
1433     p->npdata = 0;
1434     p->error_procs = NULL;
1435     p->nerror_procs = 0;
1436     p->info = NULL;
1437     p->ninfo = 0;
1438     p->apps = NULL;
1439     p->sz = 0;
1440     OPAL_PMIX_CONSTRUCT_LOCK(&p->lock);
1441     p->codes = NULL;
1442     p->pcodes = NULL;
1443     p->ncodes = 0;
1444     p->queries = NULL;
1445     p->nqueries = 0;
1446     p->event = NULL;
1447     p->opcbfunc = NULL;
1448     p->mdxcbfunc = NULL;
1449     p->valcbfunc = NULL;
1450     p->lkcbfunc = NULL;
1451     p->spcbfunc = NULL;
1452     p->evregcbfunc = NULL;
1453     p->qcbfunc = NULL;
1454     p->cbdata = NULL;
1455 }
1456 static void opdes(ext2x_opcaddy_t *p)
1457 {
1458     OPAL_PMIX_DESTRUCT_LOCK(&p->lock);
1459     if (NULL != p->nspace) {
1460         free(p->nspace);
1461     }
1462     if (NULL != p->procs) {
1463         PMIX_PROC_FREE(p->procs, p->nprocs);
1464     }
1465     if (NULL != p->pdata) {
1466         PMIX_PDATA_FREE(p->pdata, p->npdata);
1467     }
1468     if (NULL != p->error_procs) {
1469         PMIX_PROC_FREE(p->error_procs, p->nerror_procs);
1470     }
1471     if (NULL != p->info) {
1472         PMIX_INFO_FREE(p->info, p->ninfo);
1473     }
1474     if (NULL != p->apps) {
1475         PMIX_APP_FREE(p->apps, p->sz);
1476     }
1477     if (NULL != p->pcodes) {
1478         free(p->pcodes);
1479     }
1480     if (NULL != p->queries) {
1481         PMIX_QUERY_FREE(p->queries, p->nqueries);
1482     }
1483 }
1484 OBJ_CLASS_INSTANCE(ext2x_opcaddy_t,
1485                    opal_object_t,
1486                    opcon, opdes);
1487 
1488 static void ocadcon(ext2x_opalcaddy_t *p)
1489 {
1490     OBJ_CONSTRUCT(&p->procs, opal_list_t);
1491     OBJ_CONSTRUCT(&p->info, opal_list_t);
1492     OBJ_CONSTRUCT(&p->apps, opal_list_t);
1493     p->opcbfunc = NULL;
1494     p->dmdxfunc = NULL;
1495     p->mdxcbfunc = NULL;
1496     p->lkupcbfunc = NULL;
1497     p->spwncbfunc = NULL;
1498     p->cbdata = NULL;
1499     p->odmdxfunc = NULL;
1500     p->infocbfunc = NULL;
1501     p->toolcbfunc = NULL;
1502     p->ocbdata = NULL;
1503 }
1504 static void ocaddes(ext2x_opalcaddy_t *p)
1505 {
1506     OPAL_LIST_DESTRUCT(&p->procs);
1507     OPAL_LIST_DESTRUCT(&p->info);
1508     OPAL_LIST_DESTRUCT(&p->apps);
1509 }
1510 OBJ_CLASS_INSTANCE(ext2x_opalcaddy_t,
1511                    opal_object_t,
1512                    ocadcon, ocaddes);
1513 
1514 static void tscon(ext2x_threadshift_t *p)
1515 {
1516     OPAL_PMIX_CONSTRUCT_LOCK(&p->lock);
1517     p->msg = NULL;
1518     p->strings = NULL;
1519     p->source = NULL;
1520     p->event_codes = NULL;
1521     p->info = NULL;
1522     OBJ_CONSTRUCT(&p->results, opal_list_t);
1523     p->evhandler = NULL;
1524     p->nondefault = false;
1525     p->cbfunc = NULL;
1526     p->opcbfunc = NULL;
1527     p->cbdata = NULL;
1528 }
1529 static void tsdes(ext2x_threadshift_t *p)
1530 {
1531     OPAL_PMIX_DESTRUCT_LOCK(&p->lock);
1532     if (NULL != p->strings) {
1533         free(p->strings);
1534     }
1535     OPAL_LIST_DESTRUCT(&p->results);
1536 }
1537 OBJ_CLASS_INSTANCE(ext2x_threadshift_t,
1538                    opal_object_t,
1539                    tscon, tsdes);
1540 
1541 static void dmcon(opal_ext2x_dmx_trkr_t *p)
1542 {
1543     p->nspace = NULL;
1544     p->cbfunc = NULL;
1545     p->cbdata = NULL;
1546 }
1547 static void dmdes(opal_ext2x_dmx_trkr_t *p)
1548 {
1549     if (NULL != p->nspace) {
1550         free(p->nspace);
1551     }
1552 }
1553 OBJ_CLASS_INSTANCE(opal_ext2x_dmx_trkr_t,
1554                    opal_list_item_t,
1555                    dmcon, dmdes);

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