This source file includes following definitions.
- clf_constructor
- clf_destructor
- process_repository_item
- file_exists
- pmix_mca_base_component_repository_add
- pmix_mca_base_component_repository_init
- pmix_mca_base_component_repository_get_components
- pmix_mca_base_component_repository_release_internal
- find_component
- pmix_mca_base_component_repository_release
- pmix_mca_base_component_repository_retain_component
- pmix_mca_base_component_repository_open
- pmix_mca_base_component_repository_finalize
- ri_constructor
- ri_destructor
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 
  20 
  21 
  22 
  23 
  24 
  25 
  26 
  27 #include <src/include/pmix_config.h>
  28 #ifdef HAVE_SYS_TYPES_H
  29 #include <sys/types.h>
  30 #endif
  31 #include <string.h>
  32 #include <stdlib.h>
  33 #include <stdio.h>
  34 #ifdef HAVE_UNISTD_H
  35 #include <unistd.h>
  36 #endif
  37 
  38 #include "src/class/pmix_list.h"
  39 #include "src/mca/mca.h"
  40 #include "src/mca/base/base.h"
  41 #include "src/mca/base/pmix_mca_base_component_repository.h"
  42 #include "src/mca/pdl/base/base.h"
  43 #include "pmix_common.h"
  44 #include "src/class/pmix_hash_table.h"
  45 #include "src/util/basename.h"
  46 #include "src/util/show_help.h"
  47 
  48 #if PMIX_HAVE_PDL_SUPPORT
  49 
  50 
  51 
  52 
  53 static void ri_constructor(pmix_mca_base_component_repository_item_t *ri);
  54 static void ri_destructor(pmix_mca_base_component_repository_item_t *ri);
  55 PMIX_CLASS_INSTANCE(pmix_mca_base_component_repository_item_t, pmix_list_item_t,
  56                     ri_constructor, ri_destructor);
  57 
  58 #endif 
  59 
  60 static void clf_constructor(pmix_object_t *obj)
  61 {
  62     pmix_mca_base_failed_component_t *cli = (pmix_mca_base_failed_component_t *) obj;
  63     cli->comp = NULL;
  64     cli->error_msg = NULL;
  65 }
  66 
  67 static void clf_destructor(pmix_object_t *obj)
  68 {
  69     pmix_mca_base_failed_component_t *cli = (pmix_mca_base_failed_component_t *) obj;
  70     cli->comp = NULL;
  71     if( NULL != cli->error_msg ) {
  72         free(cli->error_msg);
  73         cli->error_msg = NULL;
  74     }
  75 }
  76 
  77 PMIX_CLASS_INSTANCE(pmix_mca_base_failed_component_t, pmix_list_item_t,
  78                     clf_constructor, clf_destructor);
  79 
  80 
  81 
  82 
  83 
  84 static bool initialized = false;
  85 
  86 
  87 #if PMIX_HAVE_PDL_SUPPORT
  88 
  89 static pmix_hash_table_t pmix_mca_base_component_repository;
  90 
  91 
  92 #define STRINGIFYX(x) #x
  93 #define STRINGIFY(x) STRINGIFYX(x)
  94 
  95 static int process_repository_item (const char *filename, void *data)
  96 {
  97     char name[PMIX_MCA_BASE_MAX_COMPONENT_NAME_LEN + 1];
  98     char type[PMIX_MCA_BASE_MAX_TYPE_NAME_LEN + 1];
  99     pmix_mca_base_component_repository_item_t *ri;
 100     pmix_list_t *component_list;
 101     char *base;
 102     int ret;
 103 
 104     base = pmix_basename (filename);
 105     if (NULL == base) {
 106         return PMIX_ERROR;
 107     }
 108 
 109     
 110     if (0 != strncmp (base, "mca_", 4)) {
 111         free (base);
 112         return PMIX_SUCCESS;
 113     }
 114 
 115     
 116 
 117     ret = sscanf(base, "mca_%" STRINGIFY(PMIX_MCA_BASE_MAX_TYPE_NAME_LEN) "[^_]_%"
 118                  STRINGIFY(PMIX_MCA_BASE_MAX_COMPONENT_NAME_LEN) "s", type, name);
 119     if (0 > ret) {
 120         
 121         free(base);
 122         return PMIX_SUCCESS;
 123     }
 124 
 125     
 126     ret = pmix_hash_table_get_value_ptr(&pmix_mca_base_component_repository, type,
 127                                         strlen (type), (void **) &component_list);
 128     if (PMIX_SUCCESS != ret) {
 129         component_list = PMIX_NEW(pmix_list_t);
 130         if (NULL == component_list) {
 131             free (base);
 132             
 133             return PMIX_ERR_OUT_OF_RESOURCE;
 134         }
 135 
 136         ret = pmix_hash_table_set_value_ptr(&pmix_mca_base_component_repository, type,
 137                                             strlen (type), (void *) component_list);
 138         if (PMIX_SUCCESS != ret) {
 139             free (base);
 140             PMIX_RELEASE(component_list);
 141             return ret;
 142         }
 143     }
 144 
 145     
 146     PMIX_LIST_FOREACH(ri, component_list, pmix_mca_base_component_repository_item_t) {
 147         if (0 == strcmp (ri->ri_name, name)) {
 148             
 149             free (base);
 150             return PMIX_SUCCESS;
 151         }
 152     }
 153 
 154     ri = PMIX_NEW(pmix_mca_base_component_repository_item_t);
 155     if (NULL == ri) {
 156         free (base);
 157         return PMIX_ERR_OUT_OF_RESOURCE;
 158     }
 159 
 160     ri->ri_base = base;
 161 
 162     ri->ri_path = strdup (filename);
 163     if (NULL == ri->ri_path) {
 164         PMIX_RELEASE(ri);
 165         return PMIX_ERR_OUT_OF_RESOURCE;
 166     }
 167 
 168     
 169     ri->ri_type[PMIX_MCA_BASE_MAX_TYPE_NAME_LEN] = '\0';
 170     pmix_strncpy (ri->ri_type, type, PMIX_MCA_BASE_MAX_TYPE_NAME_LEN);
 171 
 172     ri->ri_name[PMIX_MCA_BASE_MAX_TYPE_NAME_LEN] = '\0';
 173     pmix_strncpy (ri->ri_name, name, PMIX_MCA_BASE_MAX_COMPONENT_NAME_LEN);
 174 
 175     pmix_list_append (component_list, &ri->super);
 176 
 177     return PMIX_SUCCESS;
 178 }
 179 
 180 static int file_exists(const char *filename, const char *ext)
 181 {
 182     char *final;
 183     int ret;
 184 
 185     if (NULL == ext) {
 186         return access (filename, F_OK) == 0;
 187     }
 188 
 189     ret = asprintf(&final, "%s.%s", filename, ext);
 190     if (0 > ret || NULL == final) {
 191         return 0;
 192     }
 193 
 194     ret = access (final, F_OK);
 195     free(final);
 196     return (0 == ret);
 197 }
 198 
 199 #endif 
 200 
 201 int pmix_mca_base_component_repository_add (const char *path)
 202 {
 203 #if PMIX_HAVE_PDL_SUPPORT
 204     char *path_to_use = NULL, *dir, *ctx;
 205     const char sep[] = {PMIX_ENV_SEP, '\0'};
 206 
 207     if (NULL == path) {
 208         
 209         return PMIX_SUCCESS;
 210     }
 211 
 212     path_to_use = strdup (path);
 213 
 214     dir = strtok_r (path_to_use, sep, &ctx);
 215     do {
 216         if ((0 == strcmp(dir, "USER_DEFAULT") || 0 == strcmp(dir, "USR_DEFAULT"))
 217             && NULL != pmix_mca_base_user_default_path) {
 218             dir = pmix_mca_base_user_default_path;
 219         } else if (0 == strcmp(dir, "SYS_DEFAULT") ||
 220                    0 == strcmp(dir, "SYSTEM_DEFAULT")) {
 221             dir = pmix_mca_base_system_default_path;
 222         }
 223 
 224         if (0 != pmix_pdl_foreachfile(dir, process_repository_item, NULL) &&
 225             !(0 == strcmp(dir, pmix_mca_base_system_default_path) || 0 == strcmp(dir, pmix_mca_base_user_default_path))) {
 226             
 227             
 228             
 229             pmix_show_help("help-pmix-mca-base.txt",
 230                            "failed to add component dir", true, dir);
 231         }
 232     } while (NULL != (dir = strtok_r (NULL, sep, &ctx)));
 233 
 234     free (path_to_use);
 235 
 236 #endif 
 237 
 238     return PMIX_SUCCESS;
 239 }
 240 
 241 
 242 
 243 
 244 
 245 int pmix_mca_base_component_repository_init(void)
 246 {
 247   
 248 
 249   if (!initialized) {
 250 #if PMIX_HAVE_PDL_SUPPORT
 251 
 252     
 253     int ret = pmix_mca_base_framework_open(&pmix_pdl_base_framework, 0);
 254     if (PMIX_SUCCESS != ret) {
 255         pmix_output(0, "%s %d:%s failed -- process will likely abort (open the dl framework returned %d instead of PMIX_SUCCESS)\n",
 256                     __FILE__, __LINE__, __func__, ret);
 257         return ret;
 258     }
 259     pmix_pdl_base_select();
 260 
 261     PMIX_CONSTRUCT(&pmix_mca_base_component_repository, pmix_hash_table_t);
 262     ret = pmix_hash_table_init (&pmix_mca_base_component_repository, 128);
 263     if (PMIX_SUCCESS != ret) {
 264         (void) pmix_mca_base_framework_close(&pmix_pdl_base_framework);
 265         return ret;
 266     }
 267 
 268     ret = pmix_mca_base_component_repository_add(pmix_mca_base_component_path);
 269     if (PMIX_SUCCESS != ret) {
 270         PMIX_DESTRUCT(&pmix_mca_base_component_repository);
 271         (void) pmix_mca_base_framework_close(&pmix_pdl_base_framework);
 272         return ret;
 273     }
 274 #endif
 275 
 276     initialized = true;
 277   }
 278 
 279   
 280 
 281   return PMIX_SUCCESS;
 282 }
 283 
 284 int pmix_mca_base_component_repository_get_components (pmix_mca_base_framework_t *framework,
 285                                                        pmix_list_t **framework_components)
 286 {
 287     *framework_components = NULL;
 288 #if PMIX_HAVE_PDL_SUPPORT
 289     return pmix_hash_table_get_value_ptr (&pmix_mca_base_component_repository, framework->framework_name,
 290                                           strlen (framework->framework_name), (void **) framework_components);
 291 #endif
 292     return PMIX_ERR_NOT_FOUND;
 293 }
 294 
 295 #if PMIX_HAVE_PDL_SUPPORT
 296 static void pmix_mca_base_component_repository_release_internal(pmix_mca_base_component_repository_item_t *ri) {
 297     int group_id;
 298 
 299     group_id = pmix_mca_base_var_group_find (NULL, ri->ri_type, ri->ri_name);
 300     if (0 <= group_id) {
 301         
 302         pmix_mca_base_var_group_deregister (group_id);
 303     }
 304 
 305     
 306     if (ri->ri_dlhandle) {
 307         pmix_pdl_close(ri->ri_dlhandle);
 308         ri->ri_dlhandle = NULL;
 309     }
 310 }
 311 #endif
 312 
 313 #if PMIX_HAVE_PDL_SUPPORT
 314 static pmix_mca_base_component_repository_item_t *find_component(const char *type, const char *name)
 315 {
 316     pmix_mca_base_component_repository_item_t *ri;
 317     pmix_list_t *component_list;
 318     int ret;
 319 
 320     ret = pmix_hash_table_get_value_ptr (&pmix_mca_base_component_repository, type,
 321                                          strlen (type), (void **) &component_list);
 322     if (PMIX_SUCCESS != ret) {
 323         
 324         return NULL;
 325     }
 326 
 327     PMIX_LIST_FOREACH(ri, component_list, pmix_mca_base_component_repository_item_t) {
 328         if (0 == strcmp (ri->ri_name, name)) {
 329             return ri;
 330         }
 331     }
 332 
 333     return NULL;
 334 }
 335 #endif
 336 
 337 void pmix_mca_base_component_repository_release(const pmix_mca_base_component_t *component)
 338 {
 339 #if PMIX_HAVE_PDL_SUPPORT
 340     pmix_mca_base_component_repository_item_t *ri;
 341 
 342     ri = find_component (component->pmix_mca_type_name, component->pmix_mca_component_name);
 343     if (NULL != ri && !(--ri->ri_refcnt)) {
 344         pmix_mca_base_component_repository_release_internal (ri);
 345     }
 346 #endif
 347 }
 348 
 349 int pmix_mca_base_component_repository_retain_component(const char *type, const char *name)
 350 {
 351 #if PMIX_HAVE_PDL_SUPPORT
 352     pmix_mca_base_component_repository_item_t *ri = find_component(type, name);
 353 
 354     if (NULL != ri) {
 355         ++ri->ri_refcnt;
 356         return PMIX_SUCCESS;
 357     }
 358 
 359     return PMIX_ERR_NOT_FOUND;
 360 #else
 361     return PMIX_ERR_NOT_SUPPORTED;
 362 #endif
 363 }
 364 
 365 int pmix_mca_base_component_repository_open(pmix_mca_base_framework_t *framework,
 366                                             pmix_mca_base_component_repository_item_t *ri)
 367 {
 368 #if PMIX_HAVE_PDL_SUPPORT
 369     pmix_mca_base_component_t *component_struct;
 370     pmix_mca_base_component_list_item_t *mitem = NULL;
 371     char *struct_name = NULL;
 372     int vl, ret;
 373 
 374     pmix_output_verbose(PMIX_MCA_BASE_VERBOSE_INFO, 0, "pmix_mca_base_component_repository_open: examining dynamic "
 375                         "%s MCA component \"%s\" at path %s", ri->ri_type, ri->ri_name, ri->ri_path);
 376 
 377     vl = pmix_mca_base_component_show_load_errors ? PMIX_MCA_BASE_VERBOSE_ERROR : PMIX_MCA_BASE_VERBOSE_INFO;
 378 
 379     
 380 
 381 
 382 
 383 
 384 
 385     PMIX_LIST_FOREACH(mitem, &framework->framework_components, pmix_mca_base_component_list_item_t) {
 386         if (0 == strcmp(mitem->cli_component->pmix_mca_component_name, ri->ri_name)) {
 387             pmix_output_verbose (PMIX_MCA_BASE_VERBOSE_INFO, 0, "pmix_mca_base_component_repository_open: already loaded (ignored)");
 388             return PMIX_ERR_BAD_PARAM;
 389         }
 390     }
 391 
 392     
 393     mitem = NULL;
 394 
 395     if (NULL != ri->ri_dlhandle) {
 396         pmix_output_verbose (PMIX_MCA_BASE_VERBOSE_INFO, 0, "pmix_mca_base_component_repository_open: already loaded. returning cached component");
 397         mitem = PMIX_NEW(pmix_mca_base_component_list_item_t);
 398         if (NULL == mitem) {
 399             return PMIX_ERR_OUT_OF_RESOURCE;
 400         }
 401 
 402         mitem->cli_component = ri->ri_component_struct;
 403         pmix_list_append (&framework->framework_components, &mitem->super);
 404 
 405         return PMIX_SUCCESS;
 406     }
 407 
 408     if (0 != strcmp (ri->ri_type, framework->framework_name)) {
 409         
 410 
 411 
 412         assert (0);
 413         return PMIX_ERR_NOT_SUPPORTED;
 414     }
 415 
 416     
 417 
 418     char *err_msg = NULL;
 419     if (PMIX_SUCCESS != pmix_pdl_open(ri->ri_path, true, false, &ri->ri_dlhandle, &err_msg)) {
 420         if (NULL == err_msg) {
 421             err_msg = "pmix_dl_open() error message was NULL!";
 422         }
 423         
 424 
 425 
 426 
 427 
 428 
 429         if (0 == strcasecmp("file not found", err_msg) &&
 430             (file_exists(ri->ri_path, "lo") ||
 431              file_exists(ri->ri_path, "so") ||
 432              file_exists(ri->ri_path, "dylib") ||
 433              file_exists(ri->ri_path, "dll"))) {
 434             err_msg = "perhaps a missing symbol, or compiled for a different version of Open MPI?";
 435         }
 436         pmix_output_verbose(vl, 0, "pmix_mca_base_component_repository_open: unable to open %s: %s (ignored)",
 437                             ri->ri_base, err_msg);
 438 
 439         if( pmix_mca_base_component_track_load_errors ) {
 440             pmix_mca_base_failed_component_t *f_comp = PMIX_NEW(pmix_mca_base_failed_component_t);
 441             f_comp->comp = ri;
 442             if (0 > asprintf(&(f_comp->error_msg), "%s", err_msg)) {
 443                 PMIX_RELEASE(f_comp);
 444                 return PMIX_ERR_BAD_PARAM;
 445             }
 446             pmix_list_append(&framework->framework_failed_components, &f_comp->super);
 447         }
 448 
 449         return PMIX_ERR_BAD_PARAM;
 450     }
 451 
 452     
 453 
 454 
 455     do {
 456         ret = asprintf (&struct_name, "mca_%s_%s_component", ri->ri_type, ri->ri_name);
 457         if (0 > ret) {
 458             ret = PMIX_ERR_OUT_OF_RESOURCE;
 459             break;
 460         }
 461 
 462         mitem = PMIX_NEW(pmix_mca_base_component_list_item_t);
 463         if (NULL == mitem) {
 464             ret = PMIX_ERR_OUT_OF_RESOURCE;
 465             break;
 466         }
 467 
 468         err_msg = NULL;
 469         ret = pmix_pdl_lookup(ri->ri_dlhandle, struct_name, (void**) &component_struct, &err_msg);
 470         if (PMIX_SUCCESS != ret || NULL == component_struct) {
 471             if (NULL == err_msg) {
 472                 err_msg = "pmix_dl_loookup() error message was NULL!";
 473             }
 474             pmix_output_verbose(vl, 0, "pmix_mca_base_component_repository_open: \"%s\" does not appear to be a valid "
 475                                 "%s MCA dynamic component (ignored): %s. ret %d", ri->ri_base, ri->ri_type, err_msg, ret);
 476 
 477             ret = PMIX_ERR_BAD_PARAM;
 478             break;
 479         }
 480 
 481         
 482         free (struct_name);
 483         struct_name = NULL;
 484 
 485         
 486 
 487         if (!(PMIX_MCA_BASE_VERSION_MAJOR == component_struct->pmix_mca_major_version &&
 488               PMIX_MCA_BASE_VERSION_MINOR == component_struct->pmix_mca_minor_version)) {
 489             pmix_output_verbose(vl, 0, "pmix_mca_base_component_repository_open: %s \"%s\" uses an MCA interface that is "
 490                                 "not recognized (component MCA v%d.%d.%d != supported MCA v%d.%d.%d) -- ignored",
 491                                 ri->ri_type, ri->ri_path, component_struct->pmix_mca_major_version,
 492                                 component_struct->pmix_mca_minor_version, component_struct->pmix_mca_release_version,
 493                                 PMIX_MCA_BASE_VERSION_MAJOR, PMIX_MCA_BASE_VERSION_MINOR, PMIX_MCA_BASE_VERSION_RELEASE);
 494             ret = PMIX_ERR_BAD_PARAM;
 495             break;
 496         }
 497 
 498         
 499 
 500         if (0 != strcmp(component_struct->pmix_mca_type_name, ri->ri_type) ||
 501             0 != strcmp(component_struct->pmix_mca_component_name, ri->ri_name)) {
 502             pmix_output_verbose(vl, 0, "Component file data does not match filename: %s (%s / %s) != %s %s -- ignored",
 503                                 ri->ri_path, ri->ri_type, ri->ri_name,
 504                                 component_struct->pmix_mca_type_name,
 505                                 component_struct->pmix_mca_component_name);
 506             ret = PMIX_ERR_BAD_PARAM;
 507             break;
 508         }
 509 
 510         
 511 
 512 
 513         ri->ri_component_struct = mitem->cli_component = component_struct;
 514         ri->ri_refcnt = 1;
 515         pmix_list_append(&framework->framework_components, &mitem->super);
 516 
 517         pmix_output_verbose (PMIX_MCA_BASE_VERBOSE_INFO, 0, "pmix_mca_base_component_repository_open: opened dynamic %s MCA "
 518                              "component \"%s\"", ri->ri_type, ri->ri_name);
 519 
 520         return PMIX_SUCCESS;
 521     } while (0);
 522 
 523     if (mitem) {
 524         PMIX_RELEASE(mitem);
 525     }
 526 
 527     if (struct_name) {
 528         free (struct_name);
 529     }
 530 
 531     pmix_pdl_close (ri->ri_dlhandle);
 532     ri->ri_dlhandle = NULL;
 533 
 534     return ret;
 535 #else
 536 
 537     
 538     return PMIX_ERR_NOT_SUPPORTED;
 539 #endif
 540 }
 541 
 542 
 543 
 544 
 545 void pmix_mca_base_component_repository_finalize(void)
 546 {
 547     if (!initialized) {
 548         return;
 549     }
 550 
 551     initialized = false;
 552 
 553 #if PMIX_HAVE_PDL_SUPPORT
 554     pmix_list_t *component_list;
 555     void *node, *key;
 556     size_t key_size;
 557     int ret;
 558 
 559     ret = pmix_hash_table_get_first_key_ptr (&pmix_mca_base_component_repository, &key, &key_size,
 560                                              (void **) &component_list, &node);
 561     while (PMIX_SUCCESS == ret) {
 562         PMIX_LIST_RELEASE(component_list);
 563         ret = pmix_hash_table_get_next_key_ptr (&pmix_mca_base_component_repository, &key,
 564                                                 &key_size, (void **) &component_list,
 565                                                 node, &node);
 566     }
 567 
 568     (void) pmix_mca_base_framework_close(&pmix_pdl_base_framework);
 569     PMIX_DESTRUCT(&pmix_mca_base_component_repository);
 570 #endif
 571 }
 572 
 573 #if PMIX_HAVE_PDL_SUPPORT
 574 
 575 
 576 
 577 
 578 static void ri_constructor (pmix_mca_base_component_repository_item_t *ri)
 579 {
 580     memset(ri->ri_type, 0, sizeof(ri->ri_type));
 581     ri->ri_dlhandle = NULL;
 582     ri->ri_component_struct = NULL;
 583     ri->ri_path = NULL;
 584 }
 585 
 586 
 587 
 588 
 589 
 590 static void ri_destructor (pmix_mca_base_component_repository_item_t *ri)
 591 {
 592     
 593     pmix_mca_base_component_repository_release_internal (ri);
 594 
 595     
 596 
 597 
 598 
 599 
 600     if (ri->ri_path) {
 601         free (ri->ri_path);
 602     }
 603 
 604     if (ri->ri_base) {
 605         free (ri->ri_base);
 606     }
 607 }
 608 
 609 #endif