root/opal/mca/pmix/pmix4x/pmix/src/mca/base/pmix_mca_base_component_find.c

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

DEFINITIONS

This source file includes following definitions.
  1. pmix_mca_base_component_find
  2. pmix_mca_base_component_find_finalize
  3. pmix_mca_base_components_filter
  4. find_dyn_components
  5. use_component
  6. component_find_check
  7. pmix_mca_base_component_parse_requested

   1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
   2 /*
   3  * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
   4  *                         University Research and Technology
   5  *                         Corporation.  All rights reserved.
   6  * Copyright (c) 2004-2007 The University of Tennessee and The University
   7  *                         of Tennessee Research Foundation.  All rights
   8  *                         reserved.
   9  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
  10  *                         University of Stuttgart.  All rights reserved.
  11  * Copyright (c) 2004-2005 The Regents of the University of California.
  12  *                         All rights reserved.
  13  * Copyright (c) 2008-2015 Cisco Systems, Inc.  All rights reserved.
  14  * Copyright (c) 2008      Sun Microsystems, Inc.  All rights reserved.
  15  * Copyright (c) 2015      Research Organization for Information Science
  16  *                         and Technology (RIST). All rights reserved.
  17  * Copyright (c) 2014-2015 Los Alamos National Security, LLC. All rights
  18  *                         reserved.
  19  * Copyright (c) 2016-2018 Intel, Inc. All rights reserved.
  20  * $COPYRIGHT$
  21  *
  22  * Additional copyrights may follow
  23  *
  24  * $HEADER$
  25  */
  26 
  27 #include <src/include/pmix_config.h>
  28 
  29 #include <stdio.h>
  30 #include <string.h>
  31 #include <ctype.h>
  32 #include <stdlib.h>
  33 #ifdef HAVE_SYS_TYPES_H
  34 #include <sys/types.h>
  35 #endif
  36 #ifdef HAVE_SYS_STAT_H
  37 #include <sys/stat.h>
  38 #endif
  39 #ifdef HAVE_UNISTD_H
  40 #include <unistd.h>
  41 #endif
  42 #ifdef HAVE_SYS_PARAM_H
  43 #include <sys/param.h>
  44 #endif
  45 #ifdef HAVE_NETDB_H
  46 #include <netdb.h>
  47 #endif
  48 
  49 #include "src/mca/pinstalldirs/pinstalldirs.h"
  50 #include "src/util/pmix_environ.h"
  51 #include "src/util/output.h"
  52 #include "src/util/argv.h"
  53 #include "src/util/show_help.h"
  54 #include "src/class/pmix_list.h"
  55 #include "src/mca/mca.h"
  56 #include "src/mca/base/base.h"
  57 #include "src/mca/base/pmix_mca_base_component_repository.h"
  58 #include "pmix_common.h"
  59 #include "src/mca/pdl/base/base.h"
  60 
  61 #if PMIX_HAVE_PDL_SUPPORT
  62 /*
  63  * Private functions
  64  */
  65 static void find_dyn_components(const char *path, pmix_mca_base_framework_t *framework,
  66                                 const char **names, bool include_mode);
  67 
  68 #endif /* PMIX_HAVE_PDL_SUPPORT */
  69 
  70 static int component_find_check (pmix_mca_base_framework_t *framework, char **requested_component_names);
  71 
  72 /*
  73  * Dummy structure for casting for open_only logic
  74  */
  75 struct pmix_mca_base_open_only_dummy_component_t {
  76     /** MCA base component */
  77     pmix_mca_base_component_t version;
  78     /** MCA base data */
  79     pmix_mca_base_component_data_t data;
  80 };
  81 typedef struct pmix_mca_base_open_only_dummy_component_t pmix_mca_base_open_only_dummy_component_t;
  82 
  83 static char negate[] = "^";
  84 
  85 static bool use_component(const bool include_mode,
  86                           const char **requested_component_names,
  87                           const char *component_name);
  88 
  89 
  90 /*
  91  * Function to find as many components of a given type as possible.  This
  92  * includes statically-linked in components as well as opening up a
  93  * directory and looking for shared-library MCA components of the
  94  * appropriate type (load them if available).
  95  *
  96  * Return one consolidated array of (pmix_mca_base_component_t*) pointing to all
  97  * available components.
  98  */
  99 int pmix_mca_base_component_find (const char *directory, pmix_mca_base_framework_t *framework,
 100                                   bool ignore_requested, bool open_dso_components)
 101 {
 102     const pmix_mca_base_component_t **static_components = framework->framework_static_components;
 103     char **requested_component_names = NULL;
 104     pmix_mca_base_component_list_item_t *cli;
 105     bool include_mode = true;
 106     int ret;
 107 
 108     pmix_output_verbose (PMIX_MCA_BASE_VERBOSE_COMPONENT, framework->framework_output,
 109                          "mca: base: component_find: searching %s for %s components",
 110                          directory, framework->framework_name);
 111 
 112     if (!ignore_requested) {
 113         ret = pmix_mca_base_component_parse_requested (framework->framework_selection, &include_mode,
 114                                                        &requested_component_names);
 115         if (PMIX_SUCCESS != ret) {
 116             return ret;
 117         }
 118     }
 119 
 120     /* Find all the components that were statically linked in */
 121     if (static_components) {
 122         for (int i = 0 ; NULL != static_components[i]; ++i) {
 123             if ( use_component(include_mode,
 124                                (const char**)requested_component_names,
 125                                static_components[i]->pmix_mca_component_name) ) {
 126                 cli = PMIX_NEW(pmix_mca_base_component_list_item_t);
 127                 if (NULL == cli) {
 128                     ret = PMIX_ERR_OUT_OF_RESOURCE;
 129                     goto component_find_out;
 130                 }
 131                 cli->cli_component = static_components[i];
 132                 pmix_list_append(&framework->framework_components, (pmix_list_item_t *) cli);
 133             }
 134         }
 135     }
 136 
 137 #if PMIX_HAVE_PDL_SUPPORT
 138     /* Find any available dynamic components in the specified directory */
 139     if (open_dso_components && !pmix_mca_base_component_disable_dlopen) {
 140         find_dyn_components(directory, framework, (const char**)requested_component_names,
 141                             include_mode);
 142     } else {
 143         pmix_output_verbose (PMIX_MCA_BASE_VERBOSE_INFO, 0,
 144                             "pmix:mca: base: component_find: dso loading for %s MCA components disabled",
 145                             framework->framework_name);
 146     }
 147 #endif
 148 
 149     if (include_mode) {
 150         ret = component_find_check (framework, requested_component_names);
 151     } else {
 152         ret = PMIX_SUCCESS;
 153     }
 154 
 155 component_find_out:
 156 
 157     if (NULL != requested_component_names) {
 158         pmix_argv_free(requested_component_names);
 159     }
 160 
 161     /* All done */
 162 
 163     return ret;
 164 }
 165 
 166 int pmix_mca_base_component_find_finalize(void)
 167 {
 168     return PMIX_SUCCESS;
 169 }
 170 
 171 int pmix_mca_base_components_filter (pmix_mca_base_framework_t *framework, uint32_t filter_flags)
 172 {
 173     pmix_list_t *components = &framework->framework_components;
 174     int output_id = framework->framework_output;
 175     pmix_mca_base_component_list_item_t *cli, *next;
 176     char **requested_component_names = NULL;
 177     bool include_mode, can_use;
 178     int ret;
 179 
 180     assert (NULL != components);
 181 
 182     if (0 == filter_flags && NULL == framework->framework_selection) {
 183         return PMIX_SUCCESS;
 184     }
 185 
 186     ret = pmix_mca_base_component_parse_requested (framework->framework_selection, &include_mode,
 187                                               &requested_component_names);
 188     if (PMIX_SUCCESS != ret) {
 189         return ret;
 190     }
 191 
 192     PMIX_LIST_FOREACH_SAFE(cli, next, components, pmix_mca_base_component_list_item_t) {
 193         const pmix_mca_base_component_t *component = cli->cli_component;
 194         pmix_mca_base_open_only_dummy_component_t *dummy =
 195             (pmix_mca_base_open_only_dummy_component_t *) cli->cli_component;
 196 
 197         can_use = use_component(include_mode, (const char **) requested_component_names,
 198                                 cli->cli_component->pmix_mca_component_name);
 199 
 200         if (!can_use || (filter_flags & dummy->data.param_field) != filter_flags) {
 201             if (can_use && (filter_flags & PMIX_MCA_BASE_METADATA_PARAM_CHECKPOINT) &&
 202                 !(PMIX_MCA_BASE_METADATA_PARAM_CHECKPOINT & dummy->data.param_field)) {
 203                 pmix_output_verbose(PMIX_MCA_BASE_VERBOSE_COMPONENT, output_id,
 204                                     "pmix:mca: base: components_filter: "
 205                                     "(%s) Component %s is *NOT* Checkpointable - Disabled",
 206                                     component->reserved,
 207                                     component->pmix_mca_component_name);
 208             }
 209 
 210             pmix_list_remove_item(components, &cli->super);
 211 
 212             pmix_mca_base_component_unload(component, output_id);
 213 
 214             PMIX_RELEASE(cli);
 215         } else if (filter_flags & PMIX_MCA_BASE_METADATA_PARAM_CHECKPOINT) {
 216             pmix_output_verbose(PMIX_MCA_BASE_VERBOSE_COMPONENT, output_id,
 217                                 "pmix:mca: base: components_filter: "
 218                                 "(%s) Component %s is Checkpointable",
 219                                 component->reserved,
 220                                 component->pmix_mca_component_name);
 221         }
 222     }
 223 
 224     if (include_mode) {
 225         ret = component_find_check(framework, requested_component_names);
 226     } else {
 227         ret = PMIX_SUCCESS;
 228     }
 229 
 230     if (NULL != requested_component_names) {
 231         pmix_argv_free(requested_component_names);
 232     }
 233 
 234     return ret;
 235 }
 236 
 237 #if PMIX_HAVE_PDL_SUPPORT
 238 
 239 /*
 240  * Open up all directories in a given path and search for components of
 241  * the specified type (and possibly of a given name).
 242  *
 243  * Note that we use our own path iteration functionality because we
 244  * need to look at companion .ompi_info files in the same directory as
 245  * the library to generate dependencies, etc.
 246  */
 247 static void find_dyn_components(const char *path, pmix_mca_base_framework_t *framework,
 248                                 const char **names, bool include_mode)
 249 {
 250     pmix_mca_base_component_repository_item_t *ri;
 251     pmix_list_t *dy_components;
 252     int ret;
 253 
 254     pmix_output_verbose (PMIX_MCA_BASE_VERBOSE_COMPONENT, framework->framework_output,
 255                          "mca: base: find_dyn_components: checking %s for %s components",
 256                          path, framework->framework_name);
 257 
 258     if (NULL != path) {
 259         ret = pmix_mca_base_component_repository_add(path);
 260         if (PMIX_SUCCESS != ret) {
 261             return;
 262         }
 263     }
 264 
 265     ret = pmix_mca_base_component_repository_get_components(framework, &dy_components);
 266     if (PMIX_SUCCESS != ret) {
 267         return;
 268     }
 269 
 270     /* Iterate through the repository and find components that can be included */
 271     PMIX_LIST_FOREACH(ri, dy_components, pmix_mca_base_component_repository_item_t) {
 272         if (use_component(include_mode, names, ri->ri_name)) {
 273             pmix_mca_base_component_repository_open(framework, ri);
 274         }
 275     }
 276 }
 277 
 278 #endif /* PMIX_HAVE_PDL_SUPPORT */
 279 
 280 static bool use_component(const bool include_mode,
 281                           const char **requested_component_names,
 282                           const char *component_name)
 283 {
 284     bool found = false;
 285     const char **req_comp_name = requested_component_names;
 286 
 287     /*
 288      * If no selection is specified then we use all components
 289      * we can find.
 290      */
 291     if (NULL == req_comp_name) {
 292         return true;
 293     }
 294 
 295     while ( *req_comp_name != NULL ) {
 296         if ( strcmp(component_name, *req_comp_name) == 0 ) {
 297             found = true;
 298             break;
 299         }
 300         req_comp_name++;
 301     }
 302 
 303     /*
 304      * include_mode  found |   use
 305      * --------------------+------
 306      *            0      0 |  true
 307      *            0      1 | false
 308      *            1      0 | false
 309      *            1      1 |  true
 310      *
 311      * -> inverted xor
 312      * As xor is a binary operator let's implement it manually before
 313      * a compiler screws it up.
 314      */
 315 
 316     return (include_mode && found) || !(include_mode || found);
 317 }
 318 
 319 /* Ensure that *all* requested components exist.  Print a warning
 320    and abort if they do not. */
 321 static int component_find_check (pmix_mca_base_framework_t *framework, char **requested_component_names)
 322 {
 323     pmix_list_t *components = &framework->framework_components;
 324     pmix_mca_base_component_list_item_t *cli;
 325 
 326     if (NULL == requested_component_names) {
 327         return PMIX_SUCCESS;
 328     }
 329 
 330     for (int i = 0; NULL != requested_component_names[i]; ++i) {
 331         bool found = false;
 332 
 333         PMIX_LIST_FOREACH(cli, components, pmix_mca_base_component_list_item_t) {
 334             if (0 == strcmp(requested_component_names[i],
 335                             cli->cli_component->pmix_mca_component_name)) {
 336                 found = true;
 337                 break;
 338             }
 339         }
 340 
 341         if (!found) {
 342             char h[MAXHOSTNAMELEN];
 343             gethostname(h, sizeof(h));
 344             pmix_show_help("help-pmix-mca-base.txt",
 345                            "find-available:not-valid", true,
 346                            h, framework->framework_name, requested_component_names[i]);
 347             return PMIX_ERR_NOT_FOUND;
 348         }
 349     }
 350 
 351     return PMIX_SUCCESS;
 352 }
 353 
 354 int pmix_mca_base_component_parse_requested (const char *requested, bool *include_mode,
 355                                         char ***requested_component_names)
 356 {
 357     const char *requested_orig = requested;
 358 
 359     *requested_component_names = NULL;
 360     *include_mode = true;
 361 
 362     /* See if the user requested anything */
 363     if (NULL == requested || 0 == strlen (requested)) {
 364         return PMIX_SUCCESS;
 365     }
 366 
 367     /* Are we including or excluding?  We only allow the negate
 368        character to be the *first* character of the value (but be nice
 369        and allow any number of negate characters in the beginning). */
 370     *include_mode = requested[0] != negate[0];
 371 
 372     /* skip over all negate symbols at the beginning */
 373     requested += strspn (requested, negate);
 374 
 375     /* Double check to ensure that the user did not specify the negate
 376        character anywhere else in the value. */
 377     if (NULL != strstr (requested, negate)) {
 378         pmix_show_help("help-pmix-mca-base.txt",
 379                        "framework-param:too-many-negates",
 380                        true, requested_orig);
 381         return PMIX_ERROR;
 382     }
 383 
 384     /* Split up the value into individual component names */
 385     *requested_component_names = pmix_argv_split(requested, ',');
 386 
 387     /* All done */
 388     return PMIX_SUCCESS;
 389 }

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