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

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

DEFINITIONS

This source file includes following definitions.
  1. errreg_cbfunc
  2. ext2x_client_init
  3. dereg_cbfunc
  4. ext2x_client_finalize
  5. ext2x_tool_init
  6. ext2x_tool_fini
  7. ext2x_initialized
  8. ext2x_abort
  9. ext2x_store_local
  10. ext2x_commit
  11. opcbfunc
  12. ext2x_fence
  13. ext2x_fencenb
  14. ext2x_put
  15. ext2x_get
  16. val_cbfunc
  17. ext2x_getnb
  18. ext2x_publish
  19. ext2x_publishnb
  20. ext2x_lookup
  21. lk_cbfunc
  22. ext2x_lookupnb
  23. ext2x_unpublish
  24. ext2x_unpublishnb
  25. ext2x_spawn
  26. spcbfunc
  27. ext2x_spawnnb
  28. ext2x_connect
  29. ext2x_connectnb
  30. ext2x_disconnect
  31. ext2x_disconnectnb
  32. ext2x_resolve_peers
  33. ext2x_resolve_nodes
  34. relcbfunc
  35. infocbfunc
  36. ext2x_allocate
  37. ext2x_job_control

   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-2017 Mellanox Technologies, Inc.
   7  *                         All rights reserved.
   8  * Copyright (c) 2016 Cisco Systems, Inc.  All rights reserved.
   9  * Copyright (c) 2016      Los Alamos National Security, LLC. All rights
  10  *                         reserved.
  11  * Copyright (c) 2018      The University of Tennessee and The University
  12  *                         of Tennessee Research Foundation.  All rights
  13  *                         reserved.
  14  * $COPYRIGHT$
  15  *
  16  * Additional copyrights may follow
  17  *
  18  * $HEADER$
  19  */
  20 
  21 #include "opal_config.h"
  22 #include "opal/constants.h"
  23 #include "opal/types.h"
  24 
  25 #ifdef HAVE_STRING_H
  26 #include <string.h>
  27 #endif
  28 #ifdef HAVE_UNISTD_H
  29 #include <unistd.h>
  30 #endif
  31 
  32 #include "opal/hash_string.h"
  33 #include "opal/threads/threads.h"
  34 #include "opal/util/argv.h"
  35 #include "opal/util/opal_environ.h"
  36 #include "opal/util/proc.h"
  37 #include "opal/util/show_help.h"
  38 #include "opal/util/string_copy.h"
  39 
  40 #include "opal/mca/pmix/base/base.h"
  41 #include "ext2x.h"
  42 #include "pmix.h"
  43 #include "pmix_tool.h"
  44 
  45 static pmix_proc_t my_proc;
  46 static char *dbgvalue=NULL;
  47 
  48 static void errreg_cbfunc (pmix_status_t status,
  49                            size_t errhandler_ref,
  50                            void *cbdata)
  51 {
  52     opal_ext2x_event_t *event = (opal_ext2x_event_t*)cbdata;
  53 
  54     OPAL_ACQUIRE_OBJECT(event);
  55 
  56     event->index = errhandler_ref;
  57     opal_output_verbose(5, opal_pmix_base_framework.framework_output,
  58                         "PMIX client errreg_cbfunc - error handler registered status=%d, reference=%lu",
  59                         status, (unsigned long)errhandler_ref);
  60     OPAL_POST_OBJECT(event);
  61     OPAL_PMIX_WAKEUP_THREAD(&event->lock);
  62 }
  63 
  64 int ext2x_client_init(opal_list_t *ilist)
  65 {
  66     opal_process_name_t pname;
  67     pmix_status_t rc;
  68     int dbg;
  69     opal_ext2x_jobid_trkr_t *job;
  70     opal_ext2x_event_t *event;
  71     pmix_info_t *pinfo;
  72     size_t ninfo, n;
  73     opal_value_t *ival;
  74 
  75     opal_output_verbose(1, opal_pmix_base_framework.framework_output,
  76                         "PMIx_client init");
  77 
  78     OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
  79 
  80     if (0 == opal_pmix_base.initialized) {
  81         if (0 < (dbg = opal_output_get_verbosity(opal_pmix_base_framework.framework_output))) {
  82             asprintf(&dbgvalue, "PMIX_DEBUG=%d", dbg);
  83             putenv(dbgvalue);
  84         }
  85         /* check the evars for a mismatch */
  86         if (OPAL_SUCCESS != (dbg = opal_pmix_ext2x_check_evars())) {
  87             OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
  88             return dbg;
  89         }
  90     }
  91 
  92     /* convert the incoming list to info structs */
  93     if (NULL != ilist && 0 < (ninfo = opal_list_get_size(ilist))) {
  94         PMIX_INFO_CREATE(pinfo, ninfo);
  95         n=0;
  96         OPAL_LIST_FOREACH(ival, ilist, opal_value_t) {
  97             (void)opal_string_copy(pinfo[n].key, ival->key, PMIX_MAX_KEYLEN);
  98             ext2x_value_load(&pinfo[n].value, ival);
  99             ++n;
 100         }
 101     } else {
 102         pinfo = NULL;
 103         ninfo = 0;
 104     }
 105 
 106     OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 107     rc = PMIx_Init(&my_proc, pinfo, ninfo);
 108     if (NULL != pinfo) {
 109         PMIX_INFO_FREE(pinfo, ninfo);
 110     }
 111     if (PMIX_SUCCESS != rc) {
 112         dbg = ext2x_convert_rc(rc);
 113         OPAL_ERROR_LOG(dbg);
 114         return dbg;
 115     }
 116     OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
 117 
 118     ++opal_pmix_base.initialized;
 119     if (1 < opal_pmix_base.initialized) {
 120         OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 121         return OPAL_SUCCESS;
 122     }
 123 
 124     /* store our jobid and rank */
 125     if (NULL != getenv(OPAL_MCA_PREFIX"orte_launch")) {
 126         /* if we were launched by the OMPI RTE, then
 127          * the jobid is in a special format - so get it */
 128         mca_pmix_ext2x_component.native_launch = true;
 129         opal_convert_string_to_jobid(&pname.jobid, my_proc.nspace);
 130     } else {
 131         /* we were launched by someone else, so make the
 132          * jobid just be the hash of the nspace */
 133         OPAL_HASH_JOBID(my_proc.nspace, pname.jobid);
 134     }
 135     /* insert this into our list of jobids - it will be the
 136      * first, and so we'll check it first */
 137     job = OBJ_NEW(opal_ext2x_jobid_trkr_t);
 138     (void)opal_string_copy(job->nspace, my_proc.nspace, PMIX_MAX_NSLEN);
 139     job->jobid = pname.jobid;
 140     opal_list_append(&mca_pmix_ext2x_component.jobids, &job->super);
 141 
 142     pname.vpid = ext2x_convert_rank(my_proc.rank);
 143     opal_proc_set_name(&pname);
 144 
 145     /* release the thread in case the event handler fires when
 146      * registered */
 147     OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 148 
 149     /* register the default event handler */
 150     event = OBJ_NEW(opal_ext2x_event_t);
 151     opal_list_append(&mca_pmix_ext2x_component.events, &event->super);
 152     PMIX_INFO_CREATE(pinfo, 1);
 153     PMIX_INFO_LOAD(&pinfo[0], PMIX_EVENT_HDLR_NAME, "OPAL-PMIX-2X-DEFAULT", PMIX_STRING);
 154     PMIx_Register_event_handler(NULL, 0, NULL, 0, ext2x_event_hdlr, errreg_cbfunc, event);
 155     OPAL_PMIX_WAIT_THREAD(&event->lock);
 156     PMIX_INFO_FREE(pinfo, 1);
 157 
 158     return OPAL_SUCCESS;
 159 
 160 }
 161 
 162 static void dereg_cbfunc(pmix_status_t st, void *cbdata)
 163 {
 164     opal_ext2x_event_t *ev = (opal_ext2x_event_t*)cbdata;
 165     OPAL_PMIX_WAKEUP_THREAD(&ev->lock);
 166 }
 167 
 168 int ext2x_client_finalize(void)
 169 {
 170     pmix_status_t rc;
 171     opal_ext2x_event_t *event, *ev2;
 172     opal_list_t evlist;
 173     OBJ_CONSTRUCT(&evlist, opal_list_t);
 174 
 175     opal_output_verbose(1, opal_pmix_base_framework.framework_output,
 176                         "PMIx_client finalize");
 177 
 178     OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
 179     --opal_pmix_base.initialized;
 180 
 181     if (0 == opal_pmix_base.initialized) {
 182         /* deregister all event handlers */
 183         OPAL_LIST_FOREACH_SAFE(event, ev2, &mca_pmix_ext2x_component.events, opal_ext2x_event_t) {
 184             OPAL_PMIX_DESTRUCT_LOCK(&event->lock);
 185             OPAL_PMIX_CONSTRUCT_LOCK(&event->lock);
 186             PMIx_Deregister_event_handler(event->index, dereg_cbfunc, (void*)event);
 187             opal_list_remove_item(&mca_pmix_ext2x_component.events, &event->super);
 188             /* wait and release outside the loop to avoid double mutex
 189              * interlock */
 190             opal_list_append(&evlist, &event->super);
 191         }
 192     }
 193     OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 194     OPAL_LIST_FOREACH_SAFE(event, ev2, &evlist, opal_ext2x_event_t) {
 195         OPAL_PMIX_WAIT_THREAD(&event->lock);
 196         opal_list_remove_item(&evlist, &event->super);
 197         OBJ_RELEASE(event);
 198     }
 199     OBJ_DESTRUCT(&evlist);
 200     rc = PMIx_Finalize(NULL, 0);
 201 
 202     return ext2x_convert_rc(rc);
 203 }
 204 
 205 int ext2x_tool_init(opal_list_t *info)
 206 {
 207     pmix_info_t *pinfo;
 208     size_t ninfo, n;
 209     opal_ext2x_jobid_trkr_t *job;
 210     opal_value_t *val;
 211     pmix_status_t rc;
 212     int ret;
 213     opal_process_name_t pname = {OPAL_JOBID_INVALID, OPAL_VPID_INVALID};
 214     opal_ext2x_event_t *event;
 215 
 216     opal_output_verbose(1, opal_pmix_base_framework.framework_output,
 217                         "PMIx_tool init");
 218 
 219     OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
 220 
 221     /* convert the incoming list to info structs */
 222     if (NULL != info && 0 < (ninfo = opal_list_get_size(info))) {
 223         PMIX_INFO_CREATE(pinfo, ninfo);
 224         n=0;
 225         OPAL_LIST_FOREACH(val, info, opal_value_t) {
 226             (void)opal_string_copy(pinfo[n].key, val->key, PMIX_MAX_KEYLEN);
 227             ext2x_value_load(&pinfo[n].value, val);
 228             ++n;
 229             /* check to see if our name is being given from above */
 230             if (0 == strcmp(val->key, OPAL_PMIX_TOOL_NSPACE)) {
 231                 opal_convert_string_to_jobid(&pname.jobid, val->data.string);
 232                 (void)opal_string_copy(my_proc.nspace, val->data.string, PMIX_MAX_NSLEN);
 233             } else if (0 == strcmp(val->key, OPAL_PMIX_TOOL_RANK)) {
 234                 pname.vpid = val->data.name.vpid;
 235                 my_proc.rank = pname.vpid;
 236             }
 237         }
 238     } else {
 239         pinfo = NULL;
 240         ninfo = 0;
 241     }
 242     /* we are going to get our name from the server, or we were given it by the tool,
 243      * so mark as native launch so we don't convert back/forth */
 244     mca_pmix_ext2x_component.native_launch = true;
 245 
 246     OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 247     rc = PMIx_tool_init(&my_proc, pinfo, ninfo);
 248     if (NULL != pinfo) {
 249         PMIX_INFO_FREE(pinfo, ninfo);
 250     }
 251     if (PMIX_SUCCESS != rc) {
 252         ret = ext2x_convert_rc(rc);
 253         OPAL_ERROR_LOG(ret);
 254         return ret;
 255     }
 256     OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
 257 
 258     ++opal_pmix_base.initialized;
 259     if (1 < opal_pmix_base.initialized) {
 260         OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 261         return OPAL_SUCCESS;
 262     }
 263 
 264     /* store our jobid and rank */
 265     opal_convert_string_to_jobid(&pname.jobid, my_proc.nspace);
 266     pname.vpid = ext2x_convert_rank(my_proc.rank);
 267 
 268     /* insert this into our list of jobids - it will be the
 269      * first, and so we'll check it first */
 270     job = OBJ_NEW(opal_ext2x_jobid_trkr_t);
 271     (void)opal_string_copy(job->nspace, my_proc.nspace, PMIX_MAX_NSLEN);
 272     job->jobid = pname.jobid;
 273     opal_list_append(&mca_pmix_ext2x_component.jobids, &job->super);
 274 
 275     opal_proc_set_name(&pname);
 276 
 277     /* release the thread in case the event handler fires when
 278      * registered */
 279     OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 280 
 281     /* register the default event handler */
 282     event = OBJ_NEW(opal_ext2x_event_t);
 283     opal_list_append(&mca_pmix_ext2x_component.events, &event->super);
 284     PMIX_INFO_CREATE(pinfo, 1);
 285     PMIX_INFO_LOAD(&pinfo[0], PMIX_EVENT_HDLR_NAME, "OPAL-PMIX-2X-DEFAULT", PMIX_STRING);
 286     PMIx_Register_event_handler(NULL, 0, NULL, 0, ext2x_event_hdlr, errreg_cbfunc, event);
 287     OPAL_PMIX_WAIT_THREAD(&event->lock);
 288     PMIX_INFO_FREE(pinfo, 1);
 289 
 290     return OPAL_SUCCESS;
 291 }
 292 
 293 int ext2x_tool_fini(void)
 294 {
 295     pmix_status_t rc;
 296     opal_ext2x_event_t *event, *ev2;
 297 
 298     opal_output_verbose(1, opal_pmix_base_framework.framework_output,
 299                         "PMIx_tool finalize");
 300 
 301     OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
 302     --opal_pmix_base.initialized;
 303 
 304     if (0 == opal_pmix_base.initialized) {
 305         /* deregister all event handlers */
 306         OPAL_LIST_FOREACH_SAFE(event, ev2, &mca_pmix_ext2x_component.events, opal_ext2x_event_t) {
 307             OPAL_PMIX_DESTRUCT_LOCK(&event->lock);
 308             OPAL_PMIX_CONSTRUCT_LOCK(&event->lock);
 309             PMIx_Deregister_event_handler(event->index, dereg_cbfunc, (void*)event);
 310             OPAL_PMIX_WAIT_THREAD(&event->lock);
 311             opal_list_remove_item(&mca_pmix_ext2x_component.events, &event->super);
 312             OBJ_RELEASE(event);
 313         }
 314     }
 315     OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 316     rc = PMIx_tool_finalize();
 317 
 318     return ext2x_convert_rc(rc);
 319 }
 320 
 321 
 322 int ext2x_initialized(void)
 323 {
 324     int init;
 325 
 326     opal_output_verbose(1, opal_pmix_base_framework.framework_output,
 327                         "PMIx_client initialized");
 328 
 329     OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
 330     init = opal_pmix_base.initialized;
 331     OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 332 
 333     return init;
 334 }
 335 
 336 int ext2x_abort(int flag, const char *msg,
 337                  opal_list_t *procs)
 338 {
 339     pmix_status_t rc;
 340     pmix_proc_t *parray=NULL;
 341     size_t n, cnt=0;
 342     opal_namelist_t *ptr;
 343     char *nsptr;
 344 
 345     opal_output_verbose(1, opal_pmix_base_framework.framework_output,
 346                         "PMIx_client abort");
 347 
 348     OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
 349     if (0 >= opal_pmix_base.initialized) {
 350         OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 351         return OPAL_ERR_NOT_INITIALIZED;
 352     }
 353     OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 354 
 355     /* convert the list of procs to an array
 356      * of pmix_proc_t */
 357     if (NULL != procs && 0 < (cnt = opal_list_get_size(procs))) {
 358         PMIX_PROC_CREATE(parray, cnt);
 359         n=0;
 360         OPAL_LIST_FOREACH(ptr, procs, opal_namelist_t) {
 361             if (NULL == (nsptr = ext2x_convert_jobid(ptr->name.jobid))) {
 362                 PMIX_PROC_FREE(parray, cnt);
 363                 return OPAL_ERR_NOT_FOUND;
 364             }
 365             (void)opal_string_copy(parray[n].nspace, nsptr, PMIX_MAX_NSLEN);
 366             parray[n].rank = ext2x_convert_opalrank(ptr->name.vpid);
 367             ++n;
 368         }
 369     }
 370 
 371     /* call the library abort - this is a blocking call */
 372     rc = PMIx_Abort(flag, msg, parray, cnt);
 373 
 374     /* release the array */
 375     PMIX_PROC_FREE(parray, cnt);
 376 
 377     return ext2x_convert_rc(rc);
 378 }
 379 
 380 int ext2x_store_local(const opal_process_name_t *proc, opal_value_t *val)
 381 {
 382     pmix_value_t kv;
 383     pmix_status_t rc;
 384     pmix_proc_t p;
 385     char *nsptr;
 386     opal_ext2x_jobid_trkr_t *job;
 387 
 388     OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
 389 
 390     if (0 >= opal_pmix_base.initialized) {
 391         OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 392         return OPAL_ERR_NOT_INITIALIZED;
 393     }
 394     OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 395 
 396     if (NULL != proc) {
 397         if (NULL == (nsptr = ext2x_convert_jobid(proc->jobid))) {
 398             job = OBJ_NEW(opal_ext2x_jobid_trkr_t);
 399             (void)opal_snprintf_jobid(job->nspace, PMIX_MAX_NSLEN, proc->jobid);
 400             job->jobid = proc->jobid;
 401             OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
 402             opal_list_append(&mca_pmix_ext2x_component.jobids, &job->super);
 403             OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 404             nsptr = job->nspace;
 405         }
 406         (void)opal_string_copy(p.nspace, nsptr, PMIX_MAX_NSLEN);
 407         p.rank = ext2x_convert_opalrank(proc->vpid);
 408     } else {
 409         /* use our name */
 410         (void)opal_string_copy(p.nspace, my_proc.nspace, PMIX_MAX_NSLEN);
 411         p.rank = ext2x_convert_opalrank(OPAL_PROC_MY_NAME.vpid);
 412     }
 413 
 414     PMIX_VALUE_CONSTRUCT(&kv);
 415     ext2x_value_load(&kv, val);
 416     /* call the library - this is a blocking call */
 417     rc = PMIx_Store_internal(&p, val->key, &kv);
 418     PMIX_VALUE_DESTRUCT(&kv);
 419 
 420     return ext2x_convert_rc(rc);
 421 }
 422 
 423 int ext2x_commit(void)
 424 {
 425     pmix_status_t rc;
 426 
 427     OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
 428     if (0 >= opal_pmix_base.initialized) {
 429         OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 430         return OPAL_ERR_NOT_INITIALIZED;
 431     }
 432     OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 433 
 434     rc = PMIx_Commit();
 435     return ext2x_convert_rc(rc);
 436 }
 437 
 438 static void opcbfunc(pmix_status_t status, void *cbdata)
 439 {
 440     ext2x_opcaddy_t *op = (ext2x_opcaddy_t*)cbdata;
 441 
 442     OPAL_ACQUIRE_OBJECT(op);
 443     if (NULL != op->opcbfunc) {
 444         op->opcbfunc(ext2x_convert_rc(status), op->cbdata);
 445     }
 446     OBJ_RELEASE(op);
 447 }
 448 
 449 int ext2x_fence(opal_list_t *procs, int collect_data)
 450 {
 451     pmix_status_t rc;
 452     opal_namelist_t *ptr;
 453     char *nsptr;
 454     size_t cnt = 0, n;
 455     pmix_proc_t *parray = NULL;
 456     pmix_info_t info, *iptr;
 457 
 458     opal_output_verbose(1, opal_pmix_base_framework.framework_output,
 459                         "PMIx_client fence");
 460 
 461     OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
 462     if (0 >= opal_pmix_base.initialized) {
 463         OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 464         return OPAL_ERR_NOT_INITIALIZED;
 465     }
 466 
 467     /* convert the list of procs to an array
 468      * of pmix_proc_t */
 469     if (NULL != procs && 0 < (cnt = opal_list_get_size(procs))) {
 470         PMIX_PROC_CREATE(parray, cnt);
 471         n=0;
 472         OPAL_LIST_FOREACH(ptr, procs, opal_namelist_t) {
 473             if (NULL == (nsptr = ext2x_convert_jobid(ptr->name.jobid))) {
 474                 PMIX_PROC_FREE(parray, cnt);
 475                 OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 476                 return OPAL_ERR_NOT_FOUND;
 477             }
 478             (void)opal_string_copy(parray[n].nspace, nsptr, PMIX_MAX_NSLEN);
 479             parray[n].rank = ext2x_convert_opalrank(ptr->name.vpid);
 480             ++n;
 481         }
 482     }
 483     OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 484 
 485     if (collect_data) {
 486         PMIX_INFO_CONSTRUCT(&info);
 487         (void)opal_string_copy(info.key, PMIX_COLLECT_DATA, PMIX_MAX_KEYLEN);
 488         info.value.type = PMIX_BOOL;
 489         info.value.data.flag = true;
 490         iptr = &info;
 491         n = 1;
 492     } else {
 493         iptr = NULL;
 494         n = 0;
 495     }
 496 
 497     rc = PMIx_Fence(parray, cnt, iptr, n);
 498     if (collect_data) {
 499         PMIX_INFO_DESTRUCT(&info);
 500     }
 501     if (NULL != parray) {
 502         PMIX_PROC_FREE(parray, cnt);
 503     }
 504 
 505     return ext2x_convert_rc(rc);
 506 }
 507 
 508 int ext2x_fencenb(opal_list_t *procs, int collect_data,
 509                    opal_pmix_op_cbfunc_t cbfunc, void *cbdata)
 510 {
 511     pmix_status_t rc;
 512     pmix_proc_t *parray=NULL;
 513     size_t n, cnt=0;
 514     opal_namelist_t *ptr;
 515     ext2x_opcaddy_t *op;
 516     char *nsptr;
 517 
 518     opal_output_verbose(1, opal_pmix_base_framework.framework_output,
 519                         "PMIx_client fencenb");
 520 
 521     OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
 522     if (0 >= opal_pmix_base.initialized) {
 523         OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 524         return OPAL_ERR_NOT_INITIALIZED;
 525     }
 526 
 527     /* convert the list of procs to an array
 528      * of pmix_proc_t */
 529     if (NULL != procs && 0 < (cnt = opal_list_get_size(procs))) {
 530         PMIX_PROC_CREATE(parray, cnt);
 531         n=0;
 532         OPAL_LIST_FOREACH(ptr, procs, opal_namelist_t) {
 533             if (NULL == (nsptr = ext2x_convert_jobid(ptr->name.jobid))) {
 534                 PMIX_PROC_FREE(parray, cnt);
 535                 OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 536                 return OPAL_ERR_NOT_FOUND;
 537             }
 538             (void)opal_string_copy(parray[n].nspace, nsptr, PMIX_MAX_NSLEN);
 539             parray[n].rank = ext2x_convert_opalrank(ptr->name.vpid);
 540             ++n;
 541         }
 542     }
 543     OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 544 
 545     /* create the caddy */
 546     op = OBJ_NEW(ext2x_opcaddy_t);
 547     op->opcbfunc = cbfunc;
 548     op->cbdata = cbdata;
 549     op->procs = parray;
 550     op->nprocs = cnt;
 551 
 552     if (collect_data) {
 553         op->ninfo = 1;
 554         PMIX_INFO_CREATE(op->info, op->ninfo);
 555         PMIX_INFO_LOAD(&op->info[0], PMIX_COLLECT_DATA, NULL, PMIX_BOOL);
 556     }
 557 
 558     /* call the library function */
 559     rc = PMIx_Fence_nb(op->procs, op->nprocs, op->info, op->ninfo, opcbfunc, op);
 560     return ext2x_convert_rc(rc);
 561 }
 562 
 563 int ext2x_put(opal_pmix_scope_t opal_scope,
 564                opal_value_t *val)
 565 {
 566     pmix_value_t kv;
 567     pmix_scope_t pmix_scope = ext2x_convert_opalscope(opal_scope);
 568     pmix_status_t rc;
 569 
 570     opal_output_verbose(1, opal_pmix_base_framework.framework_output,
 571                         "PMIx_client put");
 572 
 573     OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
 574     if (0 >= opal_pmix_base.initialized) {
 575         OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 576         return OPAL_ERR_NOT_INITIALIZED;
 577     }
 578     OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 579 
 580     PMIX_VALUE_CONSTRUCT(&kv);
 581     ext2x_value_load(&kv, val);
 582 
 583     rc = PMIx_Put(pmix_scope, val->key, &kv);
 584     PMIX_VALUE_DESTRUCT(&kv);
 585     return ext2x_convert_rc(rc);
 586 }
 587 
 588 int ext2x_get(const opal_process_name_t *proc, const char *key,
 589                opal_list_t *info, opal_value_t **val)
 590 {
 591     pmix_status_t rc;
 592     pmix_proc_t p;
 593     char *nsptr;
 594     pmix_info_t *pinfo = NULL;
 595     size_t sz = 0, n;
 596     opal_value_t *ival;
 597     pmix_value_t *pval = NULL;
 598     int ret;
 599 
 600     opal_output_verbose(1, opal_pmix_base_framework.framework_output,
 601                         "%s ext2x:client get on proc %s key %s",
 602                         OPAL_NAME_PRINT(OPAL_PROC_MY_NAME),
 603                         (NULL == proc) ? "NULL" : OPAL_NAME_PRINT(*proc), key);
 604 
 605     OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
 606     if (0 >= opal_pmix_base.initialized) {
 607         OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 608         return OPAL_ERR_NOT_INITIALIZED;
 609     }
 610 
 611     if (NULL == proc && NULL != key) {
 612         /* if they are asking for our jobid, then return it */
 613         if (0 == strcmp(key, OPAL_PMIX_JOBID)) {
 614             (*val) = OBJ_NEW(opal_value_t);
 615             (*val)->key = strdup(key);
 616             (*val)->type = OPAL_UINT32;
 617             (*val)->data.uint32 = OPAL_PROC_MY_NAME.jobid;
 618             OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 619             return OPAL_SUCCESS;
 620         }
 621         /* if they are asking for our rank, return it */
 622         if (0 == strcmp(key, OPAL_PMIX_RANK)) {
 623             (*val) = OBJ_NEW(opal_value_t);
 624             (*val)->key = strdup(key);
 625             (*val)->type = OPAL_INT;
 626             (*val)->data.integer = ext2x_convert_rank(my_proc.rank);
 627             OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 628             return OPAL_SUCCESS;
 629         }
 630     }
 631     *val = NULL;
 632 
 633     if (NULL == proc) {
 634         (void)opal_string_copy(p.nspace, my_proc.nspace, PMIX_MAX_NSLEN);
 635         p.rank = ext2x_convert_rank(PMIX_RANK_WILDCARD);
 636     } else {
 637         if (NULL == (nsptr = ext2x_convert_jobid(proc->jobid))) {
 638             OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 639             return OPAL_ERR_NOT_FOUND;
 640         }
 641         (void)opal_string_copy(p.nspace, nsptr, PMIX_MAX_NSLEN);
 642         p.rank = ext2x_convert_opalrank(proc->vpid);
 643     }
 644     OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 645 
 646     if (NULL != info && 0 < (sz = opal_list_get_size(info))) {
 647         PMIX_INFO_CREATE(pinfo, sz);
 648         n=0;
 649         OPAL_LIST_FOREACH(ival, info, opal_value_t) {
 650             (void)opal_string_copy(pinfo[n].key, ival->key, PMIX_MAX_KEYLEN);
 651             ext2x_value_load(&pinfo[n].value, ival);
 652             ++n;
 653         }
 654     }
 655 
 656     rc = PMIx_Get(&p, key, pinfo, sz, &pval);
 657     if (PMIX_SUCCESS == rc) {
 658         ival = OBJ_NEW(opal_value_t);
 659         if (NULL != key) {
 660             ival->key = strdup(key);
 661         }
 662         if (OPAL_SUCCESS != (ret = ext2x_value_unload(ival, pval))) {
 663             rc = ext2x_convert_opalrc(ret);
 664         } else {
 665             *val = ival;
 666         }
 667         PMIX_VALUE_FREE(pval, 1);
 668     }
 669     PMIX_INFO_FREE(pinfo, sz);
 670 
 671     return ext2x_convert_rc(rc);
 672 }
 673 
 674 static void val_cbfunc(pmix_status_t status,
 675                        pmix_value_t *kv, void *cbdata)
 676 {
 677     ext2x_opcaddy_t *op = (ext2x_opcaddy_t*)cbdata;
 678     int rc;
 679     opal_value_t val, *v=NULL;
 680 
 681     OPAL_ACQUIRE_OBJECT(op);
 682     OBJ_CONSTRUCT(&val, opal_value_t);
 683     if (NULL != op->nspace) {
 684         val.key = strdup(op->nspace);
 685     }
 686     rc = ext2x_convert_opalrc(status);
 687     if (PMIX_SUCCESS == status && NULL != kv) {
 688         rc = ext2x_value_unload(&val, kv);
 689         v = &val;
 690     }
 691 
 692     if (NULL != op->valcbfunc) {
 693         op->valcbfunc(rc, v, op->cbdata);
 694     }
 695     OBJ_DESTRUCT(&val);
 696     OBJ_RELEASE(op);
 697 }
 698 
 699 int ext2x_getnb(const opal_process_name_t *proc, const char *key,
 700                  opal_list_t *info,
 701                  opal_pmix_value_cbfunc_t cbfunc, void *cbdata)
 702 {
 703     ext2x_opcaddy_t *op;
 704     opal_value_t *val;
 705     pmix_status_t rc;
 706     char *nsptr;
 707     size_t n;
 708 
 709     opal_output_verbose(1, opal_pmix_base_framework.framework_output,
 710                         "%s PMIx_client get_nb on proc %s key %s",
 711                         OPAL_NAME_PRINT(OPAL_PROC_MY_NAME),
 712                         (NULL == proc) ? "NULL" : OPAL_NAME_PRINT(*proc), key);
 713 
 714     OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
 715     if (0 >= opal_pmix_base.initialized) {
 716         OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 717         return OPAL_ERR_NOT_INITIALIZED;
 718     }
 719 
 720     if (NULL == proc) {
 721         /* if they are asking for our jobid, then return it */
 722         if (0 == strcmp(key, OPAL_PMIX_JOBID)) {
 723             if (NULL != cbfunc) {
 724                 val = OBJ_NEW(opal_value_t);
 725                 val->key = strdup(key);
 726                 val->type = OPAL_UINT32;
 727                 val->data.uint32 = OPAL_PROC_MY_NAME.jobid;
 728                 cbfunc(OPAL_SUCCESS, val, cbdata);
 729             }
 730             OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 731             return OPAL_SUCCESS;
 732         }
 733         /* if they are asking for our rank, return it */
 734         if (0 == strcmp(key, OPAL_PMIX_RANK)) {
 735             if (NULL != cbfunc) {
 736                 val = OBJ_NEW(opal_value_t);
 737                 val->key = strdup(key);
 738                 val->type = OPAL_INT;
 739                 val->data.integer = ext2x_convert_rank(my_proc.rank);
 740                 cbfunc(OPAL_SUCCESS, val, cbdata);
 741             }
 742             OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 743             return OPAL_SUCCESS;
 744         }
 745     }
 746 
 747     /* create the caddy */
 748     op = OBJ_NEW(ext2x_opcaddy_t);
 749     op->valcbfunc = cbfunc;
 750     op->cbdata = cbdata;
 751     if (NULL != key) {
 752         op->nspace = strdup(key);
 753     }
 754     if (NULL == proc) {
 755         (void)opal_string_copy(op->p.nspace, my_proc.nspace, PMIX_MAX_NSLEN);
 756         op->p.rank = ext2x_convert_rank(PMIX_RANK_WILDCARD);
 757     } else {
 758         if (NULL == (nsptr = ext2x_convert_jobid(proc->jobid))) {
 759             OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 760             return OPAL_ERR_NOT_FOUND;
 761         }
 762         (void)opal_string_copy(op->p.nspace, nsptr, PMIX_MAX_NSLEN);
 763         op->p.rank = ext2x_convert_opalrank(proc->vpid);
 764     }
 765     OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 766 
 767     if (NULL != info && 0 < (op->sz = opal_list_get_size(info))) {
 768         PMIX_INFO_CREATE(op->info, op->sz);
 769         n=0;
 770         OPAL_LIST_FOREACH(val, info, opal_value_t) {
 771             (void)opal_string_copy(op->info[n].key, val->key, PMIX_MAX_KEYLEN);
 772             ext2x_value_load(&op->info[n].value, val);
 773             ++n;
 774         }
 775     }
 776 
 777     /* call the library function */
 778     rc = PMIx_Get_nb(&op->p, key, op->info, op->sz, val_cbfunc, op);
 779     if (PMIX_SUCCESS != rc) {
 780         OBJ_RELEASE(op);
 781     }
 782 
 783     return ext2x_convert_rc(rc);
 784 }
 785 
 786 int ext2x_publish(opal_list_t *info)
 787 {
 788     pmix_info_t *pinfo;
 789     pmix_status_t ret;
 790     opal_value_t *iptr;
 791     size_t sz, n;
 792 
 793     opal_output_verbose(1, opal_pmix_base_framework.framework_output,
 794                         "PMIx_client publish");
 795 
 796     OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
 797     if (0 >= opal_pmix_base.initialized) {
 798         OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 799         return OPAL_ERR_NOT_INITIALIZED;
 800     }
 801     OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 802 
 803     if (NULL == info) {
 804         return OPAL_ERR_BAD_PARAM;
 805     }
 806 
 807     sz = opal_list_get_size(info);
 808     if (0 < sz) {
 809         PMIX_INFO_CREATE(pinfo, sz);
 810         n=0;
 811         OPAL_LIST_FOREACH(iptr, info, opal_value_t) {
 812             (void)opal_string_copy(pinfo[n].key, iptr->key, PMIX_MAX_KEYLEN);
 813             ext2x_value_load(&pinfo[n].value, iptr);
 814             ++n;
 815         }
 816     } else {
 817         pinfo = NULL;
 818     }
 819 
 820     ret = PMIx_Publish(pinfo, sz);
 821     if (0 < sz) {
 822         PMIX_INFO_FREE(pinfo, sz);
 823     }
 824 
 825     return ext2x_convert_rc(ret);
 826 }
 827 
 828 int ext2x_publishnb(opal_list_t *info,
 829                      opal_pmix_op_cbfunc_t cbfunc, void *cbdata)
 830 {
 831     pmix_status_t ret;
 832     opal_value_t *iptr;
 833     size_t n;
 834     ext2x_opcaddy_t *op;
 835 
 836     opal_output_verbose(1, opal_pmix_base_framework.framework_output,
 837                         "PMIx_client publish_nb");
 838 
 839     OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
 840     if (0 >= opal_pmix_base.initialized) {
 841         OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 842         return OPAL_ERR_NOT_INITIALIZED;
 843     }
 844     OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 845 
 846     if (NULL == info) {
 847         return OPAL_ERR_BAD_PARAM;
 848     }
 849 
 850     /* create the caddy */
 851     op = OBJ_NEW(ext2x_opcaddy_t);
 852     op->opcbfunc = cbfunc;
 853     op->cbdata = cbdata;
 854 
 855     op->sz = opal_list_get_size(info);
 856     if (0 < op->sz) {
 857         PMIX_INFO_CREATE(op->info, op->sz);
 858         n=0;
 859         OPAL_LIST_FOREACH(iptr, info, opal_value_t) {
 860             (void)opal_string_copy(op->info[n].key, iptr->key, PMIX_MAX_KEYLEN);
 861             ext2x_value_load(&op->info[n].value, iptr);
 862             ++n;
 863         }
 864     }
 865 
 866     ret = PMIx_Publish_nb(op->info, op->sz, opcbfunc, op);
 867 
 868     return ext2x_convert_rc(ret);
 869 }
 870 
 871 int ext2x_lookup(opal_list_t *data, opal_list_t *info)
 872 {
 873     opal_pmix_pdata_t *d;
 874     pmix_pdata_t *pdata;
 875     pmix_info_t *pinfo = NULL;
 876     pmix_status_t rc;
 877     size_t cnt, n, sz = 0;
 878     opal_value_t *iptr;
 879     opal_ext2x_jobid_trkr_t *jptr, *job;
 880     int ret;
 881 
 882     opal_output_verbose(1, opal_pmix_base_framework.framework_output,
 883                         "ext2x:client lookup");
 884 
 885     OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
 886     if (0 >= opal_pmix_base.initialized) {
 887         OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 888         return OPAL_ERR_NOT_INITIALIZED;
 889     }
 890     OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 891 
 892     if (NULL == data || 0 == (cnt = opal_list_get_size(data))) {
 893         return OPAL_ERR_BAD_PARAM;
 894     }
 895     PMIX_PDATA_CREATE(pdata, cnt);
 896     n = 0;
 897     OPAL_LIST_FOREACH(d, data, opal_pmix_pdata_t) {
 898         (void)opal_string_copy(pdata[n].key, d->value.key, PMIX_MAX_KEYLEN);
 899         ++n;
 900     }
 901 
 902     if (NULL != info && 0 < (sz = opal_list_get_size(info))) {
 903         PMIX_INFO_CREATE(pinfo, sz);
 904         n=0;
 905         OPAL_LIST_FOREACH(iptr, info, opal_value_t) {
 906             (void)opal_string_copy(pinfo[n].key, iptr->key, PMIX_MAX_KEYLEN);
 907             ext2x_value_load(&pinfo[n].value, iptr);
 908             ++n;
 909         }
 910     }
 911 
 912     rc = PMIx_Lookup(pdata, cnt, pinfo, sz);
 913     if (PMIX_SUCCESS == rc) {
 914         /* load the answers back into the list */
 915         n=0;
 916         OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
 917         OPAL_LIST_FOREACH(d, data, opal_pmix_pdata_t) {
 918             if (mca_pmix_ext2x_component.native_launch) {
 919                 /* if we were launched by the OMPI RTE, then
 920                  * the jobid is in a special format - so get it */
 921                 opal_convert_string_to_jobid(&d->proc.jobid, pdata[n].proc.nspace);
 922             } else {
 923                 /* we were launched by someone else, so make the
 924                  * jobid just be the hash of the nspace */
 925                 OPAL_HASH_JOBID(pdata[n].proc.nspace, d->proc.jobid);
 926             }
 927             /* if we don't already have it, add this to our jobid tracker */
 928             job = NULL;
 929             OPAL_LIST_FOREACH(jptr, &mca_pmix_ext2x_component.jobids, opal_ext2x_jobid_trkr_t) {
 930                 if (jptr->jobid == d->proc.jobid) {
 931                     job = jptr;
 932                     break;
 933                 }
 934             }
 935             if (NULL == job) {
 936                 job = OBJ_NEW(opal_ext2x_jobid_trkr_t);
 937                 (void)opal_string_copy(job->nspace, pdata[n].proc.nspace, PMIX_MAX_NSLEN);
 938                 job->jobid = d->proc.jobid;
 939                 opal_list_append(&mca_pmix_ext2x_component.jobids, &job->super);
 940             }
 941             d->proc.vpid = ext2x_convert_rank(pdata[n].proc.rank);
 942             if (OPAL_SUCCESS != (ret = ext2x_value_unload(&d->value, &pdata[n].value))) {
 943                 OPAL_ERROR_LOG(ret);
 944             }
 945         }
 946         OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
 947     }
 948     PMIX_PDATA_FREE(pdata, cnt);
 949     if (NULL != pinfo) {
 950         PMIX_INFO_FREE(pinfo, sz);
 951     }
 952     return ext2x_convert_rc(rc);
 953 }
 954 
 955 static void lk_cbfunc(pmix_status_t status,
 956                       pmix_pdata_t data[], size_t ndata,
 957                       void *cbdata)
 958 {
 959     ext2x_opcaddy_t *op = (ext2x_opcaddy_t*)cbdata;
 960     opal_pmix_pdata_t *d;
 961     opal_list_t results, *r = NULL;
 962     int rc;
 963     size_t n;
 964     opal_ext2x_jobid_trkr_t *job, *jptr;
 965 
 966     OPAL_ACQUIRE_OBJECT(op);
 967 
 968     if (NULL == op->lkcbfunc) {
 969         OBJ_RELEASE(op);
 970         return;
 971     }
 972 
 973     rc = ext2x_convert_rc(op->status);
 974     if (OPAL_SUCCESS == rc) {
 975         OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
 976         OBJ_CONSTRUCT(&results, opal_list_t);
 977         for (n=0; n < ndata; n++) {
 978             d = OBJ_NEW(opal_pmix_pdata_t);
 979             opal_list_append(&results, &d->super);
 980             if (mca_pmix_ext2x_component.native_launch) {
 981                 /* if we were launched by the OMPI RTE, then
 982                  * the jobid is in a special format - so get it */
 983                 opal_convert_string_to_jobid(&d->proc.jobid, data[n].proc.nspace);
 984             } else {
 985                 /* we were launched by someone else, so make the
 986                  * jobid just be the hash of the nspace */
 987                 OPAL_HASH_JOBID(data[n].proc.nspace, d->proc.jobid);
 988             }
 989             /* if we don't already have it, add this to our jobid tracker */
 990             job = NULL;
 991             OPAL_LIST_FOREACH(jptr, &mca_pmix_ext2x_component.jobids, opal_ext2x_jobid_trkr_t) {
 992                 if (jptr->jobid == d->proc.jobid) {
 993                     job = jptr;
 994                     break;
 995                 }
 996             }
 997             if (NULL == job) {
 998                 job = OBJ_NEW(opal_ext2x_jobid_trkr_t);
 999                 (void)opal_string_copy(job->nspace, data[n].proc.nspace, PMIX_MAX_NSLEN);
1000                 job->jobid = d->proc.jobid;
1001                 opal_list_append(&mca_pmix_ext2x_component.jobids, &job->super);
1002             }
1003             d->proc.vpid = ext2x_convert_rank(data[n].proc.rank);
1004             d->value.key = strdup(data[n].key);
1005             rc = ext2x_value_unload(&d->value, &data[n].value);
1006             if (OPAL_SUCCESS != rc) {
1007                 rc = OPAL_ERR_BAD_PARAM;
1008                 OPAL_ERROR_LOG(rc);
1009                 OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1010                 goto release;
1011             }
1012         }
1013         r = &results;
1014         OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1015     }
1016 
1017   release:
1018     /* execute the callback */
1019     op->lkcbfunc(rc, r, op->cbdata);
1020 
1021     if (NULL != r) {
1022         OPAL_LIST_DESTRUCT(&results);
1023     }
1024     OBJ_RELEASE(op);
1025 }
1026 
1027 int ext2x_lookupnb(char **keys, opal_list_t *info,
1028                     opal_pmix_lookup_cbfunc_t cbfunc, void *cbdata)
1029 {
1030     pmix_status_t ret;
1031     ext2x_opcaddy_t *op;
1032     opal_value_t *iptr;
1033     size_t n;
1034 
1035 
1036     opal_output_verbose(1, opal_pmix_base_framework.framework_output,
1037                         "ext2x:client lookup_nb");
1038 
1039     OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
1040     if (0 >= opal_pmix_base.initialized) {
1041         OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1042         return OPAL_ERR_NOT_INITIALIZED;
1043     }
1044     OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1045 
1046     /* create the caddy */
1047     op = OBJ_NEW(ext2x_opcaddy_t);
1048     op->lkcbfunc = cbfunc;
1049     op->cbdata = cbdata;
1050 
1051     if (NULL != info && 0 < (op->sz = opal_list_get_size(info))) {
1052         PMIX_INFO_CREATE(op->info, op->sz);
1053         n=0;
1054         OPAL_LIST_FOREACH(iptr, info, opal_value_t) {
1055             (void)opal_string_copy(op->info[n].key, iptr->key, PMIX_MAX_KEYLEN);
1056             ext2x_value_load(&op->info[n].value, iptr);
1057             ++n;
1058         }
1059     }
1060     ret = PMIx_Lookup_nb(keys, op->info, op->sz, lk_cbfunc, op);
1061 
1062     return ext2x_convert_rc(ret);
1063 }
1064 
1065 int ext2x_unpublish(char **keys, opal_list_t *info)
1066 {
1067     pmix_status_t ret;
1068     size_t ninfo, n;
1069     pmix_info_t *pinfo;
1070     opal_value_t *iptr;
1071 
1072     OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
1073     if (0 >= opal_pmix_base.initialized) {
1074         OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1075         return OPAL_ERR_NOT_INITIALIZED;
1076     }
1077     OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1078 
1079     if (NULL != info && 0 < (ninfo = opal_list_get_size(info))) {
1080         PMIX_INFO_CREATE(pinfo, ninfo);
1081         n=0;
1082         OPAL_LIST_FOREACH(iptr, info, opal_value_t) {
1083             (void)opal_string_copy(pinfo[n].key, iptr->key, PMIX_MAX_KEYLEN);
1084             ext2x_value_load(&pinfo[n].value, iptr);
1085             ++n;
1086         }
1087     } else {
1088         pinfo = NULL;
1089         ninfo = 0;
1090     }
1091 
1092     ret = PMIx_Unpublish(keys, pinfo, ninfo);
1093     PMIX_INFO_FREE(pinfo, ninfo);
1094 
1095     return ext2x_convert_rc(ret);
1096 }
1097 
1098 int ext2x_unpublishnb(char **keys, opal_list_t *info,
1099                        opal_pmix_op_cbfunc_t cbfunc, void *cbdata)
1100 {
1101     pmix_status_t ret;
1102     ext2x_opcaddy_t *op;
1103     opal_value_t *iptr;
1104     size_t n;
1105 
1106     OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
1107     if (0 >= opal_pmix_base.initialized) {
1108         OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1109         return OPAL_ERR_NOT_INITIALIZED;
1110     }
1111     OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1112 
1113     /* create the caddy */
1114     op = OBJ_NEW(ext2x_opcaddy_t);
1115     op->opcbfunc = cbfunc;
1116     op->cbdata = cbdata;
1117 
1118     if (NULL != info && 0 < (op->sz = opal_list_get_size(info))) {
1119         PMIX_INFO_CREATE(op->info, op->sz);
1120         n=0;
1121         OPAL_LIST_FOREACH(iptr, info, opal_value_t) {
1122             (void)opal_string_copy(op->info[n].key, iptr->key, PMIX_MAX_KEYLEN);
1123             ext2x_value_load(&op->info[n].value, iptr);
1124             ++n;
1125         }
1126     }
1127 
1128     ret = PMIx_Unpublish_nb(keys, op->info, op->sz, opcbfunc, op);
1129 
1130     return ext2x_convert_rc(ret);
1131 }
1132 
1133 int ext2x_spawn(opal_list_t *job_info, opal_list_t *apps, opal_jobid_t *jobid)
1134 {
1135     pmix_status_t rc;
1136     pmix_info_t *info = NULL;
1137     pmix_app_t *papps;
1138     size_t ninfo = 0, napps, n, m;
1139     opal_value_t *ival;
1140     opal_pmix_app_t *app;
1141     char nspace[PMIX_MAX_NSLEN+1];
1142     opal_ext2x_jobid_trkr_t *job;
1143 
1144     OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
1145     if (0 >= opal_pmix_base.initialized) {
1146         OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1147         return OPAL_ERR_NOT_INITIALIZED;
1148     }
1149     OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1150 
1151     *jobid = OPAL_JOBID_INVALID;
1152 
1153     if (NULL != job_info && 0 < (ninfo = opal_list_get_size(job_info))) {
1154         PMIX_INFO_CREATE(info, ninfo);
1155         n=0;
1156         OPAL_LIST_FOREACH(ival, job_info, opal_value_t) {
1157             (void)opal_string_copy(info[n].key, ival->key, PMIX_MAX_KEYLEN);
1158             ext2x_value_load(&info[n].value, ival);
1159             ++n;
1160         }
1161     }
1162 
1163     napps = opal_list_get_size(apps);
1164     PMIX_APP_CREATE(papps, napps);
1165     n=0;
1166     OPAL_LIST_FOREACH(app, apps, opal_pmix_app_t) {
1167         papps[n].cmd = strdup(app->cmd);
1168         if (NULL != app->argv) {
1169             papps[n].argv = opal_argv_copy(app->argv);
1170         }
1171         if (NULL != app->env) {
1172             papps[n].env = opal_argv_copy(app->env);
1173         }
1174         if (NULL != app->cwd) {
1175             papps[n].cwd = strdup(app->cwd);
1176         }
1177         papps[n].maxprocs = app->maxprocs;
1178         if (0 < (papps[n].ninfo = opal_list_get_size(&app->info))) {
1179             PMIX_INFO_CREATE(papps[n].info, papps[n].ninfo);
1180             m=0;
1181             OPAL_LIST_FOREACH(ival, &app->info, opal_value_t) {
1182                 (void)opal_string_copy(papps[n].info[m].key, ival->key, PMIX_MAX_KEYLEN);
1183                 ext2x_value_load(&papps[n].info[m].value, ival);
1184                 ++m;
1185             }
1186         }
1187         ++n;
1188     }
1189 
1190     rc = PMIx_Spawn(info, ninfo, papps, napps, nspace);
1191     if (PMIX_SUCCESS == rc) {
1192         OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
1193         if (mca_pmix_ext2x_component.native_launch) {
1194             /* if we were launched by the OMPI RTE, then
1195              * the jobid is in a special format - so get it */
1196             opal_convert_string_to_jobid(jobid, nspace);
1197         } else {
1198             /* we were launched by someone else, so make the
1199              * jobid just be the hash of the nspace */
1200             OPAL_HASH_JOBID(nspace, *jobid);
1201         }
1202         /* add this to our jobid tracker */
1203         job = OBJ_NEW(opal_ext2x_jobid_trkr_t);
1204         (void)opal_string_copy(job->nspace, nspace, PMIX_MAX_NSLEN);
1205         job->jobid = *jobid;
1206         opal_list_append(&mca_pmix_ext2x_component.jobids, &job->super);
1207         OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1208     }
1209     return rc;
1210 }
1211 
1212 static void spcbfunc(pmix_status_t status,
1213                      char *nspace, void *cbdata)
1214 {
1215     ext2x_opcaddy_t *op = (ext2x_opcaddy_t*)cbdata;
1216     opal_ext2x_jobid_trkr_t *job;
1217     opal_jobid_t jobid = OPAL_JOBID_INVALID;
1218     int rc;
1219 
1220     OPAL_ACQUIRE_OBJECT(op);
1221 
1222     rc = ext2x_convert_rc(status);
1223     if (PMIX_SUCCESS == status) {
1224         /* this is in the PMIx local thread - need to protect
1225          * the framework-level data */
1226         OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
1227         if (mca_pmix_ext2x_component.native_launch) {
1228             /* if we were launched by the OMPI RTE, then
1229              * the jobid is in a special format - so get it */
1230             opal_convert_string_to_jobid(&jobid, nspace);
1231         } else {
1232             /* we were launched by someone else, so make the
1233              * jobid just be the hash of the nspace */
1234             OPAL_HASH_JOBID(nspace, jobid);
1235         }
1236         /* add this to our jobid tracker */
1237         job = OBJ_NEW(opal_ext2x_jobid_trkr_t);
1238         (void)opal_string_copy(job->nspace, nspace, PMIX_MAX_NSLEN);
1239         job->jobid = jobid;
1240         opal_list_append(&mca_pmix_ext2x_component.jobids, &job->super);
1241         OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1242     }
1243 
1244     op->spcbfunc(rc, jobid, op->cbdata);
1245     OBJ_RELEASE(op);
1246 }
1247 
1248 int ext2x_spawnnb(opal_list_t *job_info, opal_list_t *apps,
1249                    opal_pmix_spawn_cbfunc_t cbfunc, void *cbdata)
1250 {
1251     pmix_status_t ret;
1252     ext2x_opcaddy_t *op;
1253     size_t n, m;
1254     opal_value_t *info;
1255     opal_pmix_app_t *app;
1256 
1257     OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
1258     if (0 >= opal_pmix_base.initialized) {
1259         OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1260         return OPAL_ERR_NOT_INITIALIZED;
1261     }
1262     OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1263 
1264     /* create the caddy */
1265     op = OBJ_NEW(ext2x_opcaddy_t);
1266     op->spcbfunc = cbfunc;
1267     op->cbdata = cbdata;
1268 
1269     if (NULL != job_info && 0 < (op->ninfo = opal_list_get_size(job_info))) {
1270         PMIX_INFO_CREATE(op->info, op->ninfo);
1271         n=0;
1272         OPAL_LIST_FOREACH(info, job_info, opal_value_t) {
1273             (void)opal_string_copy(op->info[n].key, info->key, PMIX_MAX_KEYLEN);
1274             ext2x_value_load(&op->info[n].value, info);
1275             ++n;
1276         }
1277     }
1278 
1279     op->sz = opal_list_get_size(apps);
1280     PMIX_APP_CREATE(op->apps, op->sz);
1281     n=0;
1282     OPAL_LIST_FOREACH(app, apps, opal_pmix_app_t) {
1283         op->apps[n].cmd = strdup(app->cmd);
1284         if (NULL != app->argv) {
1285             op->apps[n].argv = opal_argv_copy(app->argv);
1286         }
1287         if (NULL != app->env) {
1288             op->apps[n].env = opal_argv_copy(app->env);
1289         }
1290         op->apps[n].maxprocs = app->maxprocs;
1291         if (0 < (op->apps[n].ninfo = opal_list_get_size(&app->info))) {
1292             PMIX_INFO_CREATE(op->apps[n].info, op->apps[n].ninfo);
1293             m=0;
1294             OPAL_LIST_FOREACH(info, &app->info, opal_value_t) {
1295                 (void)opal_string_copy(op->apps[n].info[m].key, info->key, PMIX_MAX_KEYLEN);
1296                 ext2x_value_load(&op->apps[n].info[m].value, info);
1297                 ++m;
1298             }
1299         }
1300         ++n;
1301     }
1302 
1303     ret = PMIx_Spawn_nb(op->info, op->ninfo, op->apps, op->sz, spcbfunc, op);
1304 
1305     return ext2x_convert_rc(ret);
1306 }
1307 
1308 int ext2x_connect(opal_list_t *procs)
1309 {
1310     pmix_proc_t *p;
1311     size_t nprocs;
1312     opal_namelist_t *ptr;
1313     pmix_status_t ret;
1314     char *nsptr;
1315     size_t n;
1316 
1317     opal_output_verbose(1, opal_pmix_base_framework.framework_output,
1318                         "ext2x:client connect");
1319 
1320     /* protect against bozo error */
1321     if (NULL == procs || 0 == (nprocs = opal_list_get_size(procs))) {
1322         return OPAL_ERR_BAD_PARAM;
1323     }
1324 
1325     OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
1326     if (0 >= opal_pmix_base.initialized) {
1327         OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1328         return OPAL_ERR_NOT_INITIALIZED;
1329     }
1330 
1331     /* convert the list of procs to an array
1332      * of pmix_proc_t */
1333     PMIX_PROC_CREATE(p, nprocs);
1334     n=0;
1335     OPAL_LIST_FOREACH(ptr, procs, opal_namelist_t) {
1336         if (NULL == (nsptr = ext2x_convert_jobid(ptr->name.jobid))) {
1337             PMIX_PROC_FREE(p, nprocs);
1338             OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1339             return OPAL_ERR_NOT_FOUND;
1340         }
1341         (void)opal_string_copy(p[n].nspace, nsptr, PMIX_MAX_NSLEN);
1342         p[n].rank = ext2x_convert_opalrank(ptr->name.vpid);
1343         ++n;
1344     }
1345     OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1346 
1347     ret = PMIx_Connect(p, nprocs, NULL, 0);
1348     PMIX_PROC_FREE(p, nprocs);
1349 
1350     return ext2x_convert_rc(ret);
1351 }
1352 
1353 int ext2x_connectnb(opal_list_t *procs,
1354                      opal_pmix_op_cbfunc_t cbfunc,
1355                      void *cbdata)
1356 {
1357     ext2x_opcaddy_t *op;
1358     opal_namelist_t *ptr;
1359     pmix_status_t ret;
1360     char *nsptr;
1361     size_t n;
1362 
1363     opal_output_verbose(1, opal_pmix_base_framework.framework_output,
1364                         "ext2x:client connect NB");
1365 
1366     /* protect against bozo error */
1367     if (NULL == procs || 0 == opal_list_get_size(procs)) {
1368         return OPAL_ERR_BAD_PARAM;
1369     }
1370 
1371     OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
1372     if (0 >= opal_pmix_base.initialized) {
1373         OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1374         return OPAL_ERR_NOT_INITIALIZED;
1375     }
1376 
1377     /* create the caddy */
1378     op = OBJ_NEW(ext2x_opcaddy_t);
1379     op->opcbfunc = cbfunc;
1380     op->cbdata = cbdata;
1381     op->nprocs = opal_list_get_size(procs);
1382 
1383     /* convert the list of procs to an array
1384      * of pmix_proc_t */
1385     PMIX_PROC_CREATE(op->procs, op->nprocs);
1386     n=0;
1387     OPAL_LIST_FOREACH(ptr, procs, opal_namelist_t) {
1388         if (NULL == (nsptr = ext2x_convert_jobid(ptr->name.jobid))) {
1389             OBJ_RELEASE(op);
1390             OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1391             return OPAL_ERR_NOT_FOUND;
1392         }
1393         (void)opal_string_copy(op->procs[n].nspace, nsptr, PMIX_MAX_NSLEN);
1394         op->procs[n].rank = ext2x_convert_opalrank(ptr->name.vpid);
1395         ++n;
1396     }
1397     OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1398 
1399     ret = PMIx_Connect_nb(op->procs, op->nprocs, NULL, 0, opcbfunc, op);
1400     if (PMIX_SUCCESS != ret) {
1401         OBJ_RELEASE(op);
1402     }
1403     return ext2x_convert_rc(ret);
1404 }
1405 
1406 int ext2x_disconnect(opal_list_t *procs)
1407 {
1408     pmix_proc_t *p;
1409     size_t nprocs;
1410     opal_namelist_t *ptr;
1411     pmix_status_t ret;
1412     char *nsptr;
1413     size_t n;
1414 
1415     opal_output_verbose(1, opal_pmix_base_framework.framework_output,
1416                         "ext2x:client disconnect");
1417 
1418     /* protect against bozo error */
1419     if (NULL == procs || 0 == (nprocs = opal_list_get_size(procs))) {
1420         return OPAL_ERR_BAD_PARAM;
1421     }
1422 
1423     OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
1424     if (0 >= opal_pmix_base.initialized) {
1425         OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1426         return OPAL_ERR_NOT_INITIALIZED;
1427     }
1428 
1429     /* convert the list of procs to an array
1430      * of pmix_proc_t */
1431     PMIX_PROC_CREATE(p, nprocs);
1432     n=0;
1433     OPAL_LIST_FOREACH(ptr, procs, opal_namelist_t) {
1434         if (NULL == (nsptr = ext2x_convert_jobid(ptr->name.jobid))) {
1435             PMIX_PROC_FREE(p, nprocs);
1436             OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1437             return OPAL_ERR_NOT_FOUND;
1438         }
1439         (void)opal_string_copy(p[n].nspace, nsptr, PMIX_MAX_NSLEN);
1440         p[n].rank = ext2x_convert_opalrank(ptr->name.vpid);
1441         ++n;
1442     }
1443     OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1444 
1445     ret = PMIx_Disconnect(p, nprocs, NULL, 0);
1446     PMIX_PROC_FREE(p, nprocs);
1447 
1448     return ext2x_convert_rc(ret);
1449 }
1450 
1451 int ext2x_disconnectnb(opal_list_t *procs,
1452                         opal_pmix_op_cbfunc_t cbfunc,
1453                         void *cbdata)
1454 {
1455     ext2x_opcaddy_t *op;
1456     opal_namelist_t *ptr;
1457     pmix_status_t ret;
1458     char *nsptr;
1459     size_t n;
1460 
1461     opal_output_verbose(1, opal_pmix_base_framework.framework_output,
1462                         "ext2x:client disconnect NB");
1463 
1464     /* protect against bozo error */
1465     if (NULL == procs || 0 == opal_list_get_size(procs)) {
1466         return OPAL_ERR_BAD_PARAM;
1467     }
1468 
1469     OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
1470     if (0 >= opal_pmix_base.initialized) {
1471         OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1472         return OPAL_ERR_NOT_INITIALIZED;
1473     }
1474 
1475     /* create the caddy */
1476     op = OBJ_NEW(ext2x_opcaddy_t);
1477     op->opcbfunc = cbfunc;
1478     op->cbdata = cbdata;
1479     op->nprocs = opal_list_get_size(procs);
1480 
1481     /* convert the list of procs to an array
1482      * of pmix_proc_t */
1483     PMIX_PROC_CREATE(op->procs, op->nprocs);
1484     n=0;
1485     OPAL_LIST_FOREACH(ptr, procs, opal_namelist_t) {
1486         if (NULL == (nsptr = ext2x_convert_jobid(ptr->name.jobid))) {
1487             OBJ_RELEASE(op);
1488             OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1489             return OPAL_ERR_NOT_FOUND;
1490         }
1491         (void)opal_string_copy(op->procs[n].nspace, nsptr, PMIX_MAX_NSLEN);
1492         op->procs[n].rank = ext2x_convert_opalrank(ptr->name.vpid);
1493         ++n;
1494     }
1495     OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1496 
1497     ret = PMIx_Disconnect_nb(op->procs, op->nprocs, NULL, 0, opcbfunc, op);
1498     if (PMIX_SUCCESS != ret) {
1499         OBJ_RELEASE(op);
1500     }
1501     return ext2x_convert_rc(ret);
1502 }
1503 
1504 int ext2x_resolve_peers(const char *nodename,
1505                          opal_jobid_t jobid,
1506                          opal_list_t *procs)
1507 {
1508     pmix_status_t ret;
1509     char *nspace;
1510     pmix_proc_t *array=NULL;
1511     size_t nprocs, n;
1512     opal_namelist_t *nm;
1513     opal_ext2x_jobid_trkr_t *job;
1514 
1515     OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
1516     if (0 >= opal_pmix_base.initialized) {
1517         OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1518         return OPAL_ERR_NOT_INITIALIZED;
1519     }
1520 
1521     if (OPAL_JOBID_WILDCARD != jobid) {
1522         if (NULL == (nspace = ext2x_convert_jobid(jobid))) {
1523             OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1524             return OPAL_ERR_NOT_FOUND;
1525         }
1526     } else {
1527         nspace = NULL;
1528     }
1529     OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1530 
1531     ret = PMIx_Resolve_peers(nodename, nspace, &array, &nprocs);
1532 
1533     if (NULL != array && 0 < nprocs) {
1534         OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
1535         for (n=0; n < nprocs; n++) {
1536             nm = OBJ_NEW(opal_namelist_t);
1537             opal_list_append(procs, &nm->super);
1538             if (mca_pmix_ext2x_component.native_launch) {
1539                 /* if we were launched by the OMPI RTE, then
1540                  * the jobid is in a special format - so get it */
1541                 opal_convert_string_to_jobid(&nm->name.jobid, array[n].nspace);
1542             } else {
1543                 /* we were launched by someone else, so make the
1544                  * jobid just be the hash of the nspace */
1545                 OPAL_HASH_JOBID(array[n].nspace, nm->name.jobid);
1546             }
1547             /* if we don't already have it, add this to our jobid tracker */
1548             if (NULL == ext2x_convert_jobid(nm->name.jobid)) {
1549                 job = OBJ_NEW(opal_ext2x_jobid_trkr_t);
1550                 (void)opal_string_copy(job->nspace, array[n].nspace, PMIX_MAX_NSLEN);
1551                 job->jobid = nm->name.jobid;
1552                 opal_list_append(&mca_pmix_ext2x_component.jobids, &job->super);
1553             }
1554             nm->name.vpid = ext2x_convert_rank(array[n].rank);
1555         }
1556         OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1557     }
1558     PMIX_PROC_FREE(array, nprocs);
1559     return ext2x_convert_rc(ret);
1560 }
1561 
1562 int ext2x_resolve_nodes(opal_jobid_t jobid, char **nodelist)
1563 {
1564     pmix_status_t ret;
1565     char *nsptr;
1566 
1567     OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
1568     if (0 >= opal_pmix_base.initialized) {
1569         OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1570         return OPAL_ERR_NOT_INITIALIZED;
1571     }
1572 
1573     if (NULL == (nsptr = ext2x_convert_jobid(jobid))) {
1574         OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1575         return OPAL_ERR_NOT_FOUND;
1576     }
1577     OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1578 
1579     ret = PMIx_Resolve_nodes(nsptr, nodelist);
1580 
1581     return ext2x_convert_rc(ret);
1582 }
1583 
1584 static void relcbfunc(void *cbdata)
1585 {
1586     ext2x_opcaddy_t *op = (ext2x_opcaddy_t*)cbdata;
1587     OBJ_RELEASE(op);
1588 }
1589 
1590 static void infocbfunc(pmix_status_t status,
1591                        pmix_info_t *info, size_t ninfo,
1592                        void *cbdata,
1593                        pmix_release_cbfunc_t release_fn,
1594                        void *release_cbdata)
1595 {
1596     ext2x_opcaddy_t *op = (ext2x_opcaddy_t*)cbdata;
1597     int rc;
1598 
1599     if (NULL != release_fn) {
1600         release_fn(release_cbdata);
1601     }
1602     rc = ext2x_convert_rc(status);
1603     if (NULL != op->qcbfunc) {
1604         op->qcbfunc(rc, NULL, op->cbdata, relcbfunc, op);
1605     } else {
1606         OBJ_RELEASE(op);
1607     }
1608 }
1609 
1610 int ext2x_allocate(opal_pmix_alloc_directive_t directive,
1611                     opal_list_t *info,
1612                     opal_pmix_info_cbfunc_t cbfunc, void *cbdata)
1613 {
1614     return OPAL_ERR_NOT_SUPPORTED;
1615 }
1616 
1617 int ext2x_job_control(opal_list_t *targets,
1618                        opal_list_t *directives,
1619                        opal_pmix_info_cbfunc_t cbfunc, void *cbdata)
1620 {
1621     ext2x_opcaddy_t *op;
1622     size_t n;
1623     opal_namelist_t *ptr;
1624     opal_value_t *iptr;
1625     pmix_status_t rc;
1626     char *nsptr;
1627 
1628     OPAL_PMIX_ACQUIRE_THREAD(&opal_pmix_base.lock);
1629     if (0 >= opal_pmix_base.initialized) {
1630         OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1631         return OPAL_ERR_NOT_INITIALIZED;
1632     }
1633 
1634     /* create the caddy */
1635     op = OBJ_NEW(ext2x_opcaddy_t);
1636     op->qcbfunc = cbfunc;
1637     op->cbdata = cbdata;
1638     if (NULL != targets) {
1639         op->nprocs = opal_list_get_size(targets);
1640 
1641         /* convert the list of procs to an array
1642          * of pmix_proc_t */
1643         PMIX_PROC_CREATE(op->procs, op->nprocs);
1644         n=0;
1645         OPAL_LIST_FOREACH(ptr, targets, opal_namelist_t) {
1646             if (NULL == (nsptr = ext2x_convert_jobid(ptr->name.jobid))) {
1647                 OBJ_RELEASE(op);
1648                 OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1649                 return OPAL_ERR_NOT_FOUND;
1650             }
1651             (void)opal_string_copy(op->procs[n].nspace, nsptr, PMIX_MAX_NSLEN);
1652             op->procs[n].rank = ext2x_convert_opalrank(ptr->name.vpid);
1653             ++n;
1654         }
1655     }
1656     OPAL_PMIX_RELEASE_THREAD(&opal_pmix_base.lock);
1657 
1658     if (NULL != directives && 0 < (op->ninfo = opal_list_get_size(directives))) {
1659         PMIX_INFO_CREATE(op->info, op->ninfo);
1660         n=0;
1661         OPAL_LIST_FOREACH(iptr, directives, opal_value_t) {
1662             (void)opal_string_copy(op->info[n].key, iptr->key, PMIX_MAX_KEYLEN);
1663             ext2x_value_load(&op->info[n].value, iptr);
1664             ++n;
1665         }
1666     }
1667 
1668     rc = PMIx_Job_control_nb(op->procs,op->nprocs, op->info, op->ninfo, infocbfunc, op);
1669     if (PMIX_SUCCESS != rc) {
1670         OBJ_RELEASE(op);
1671     }
1672     return ext2x_convert_rc(rc);
1673 }

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