root/ompi/mca/io/base/io_base_file_select.c

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

DEFINITIONS

This source file includes following definitions.
  1. mca_io_base_file_select
  2. avail_io_compare
  3. check_components
  4. check_one_component
  5. query
  6. query_2_0_0
  7. unquery
  8. module_init

   1 /*
   2  * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
   3  *                         University Research and Technology
   4  *                         Corporation.  All rights reserved.
   5  * Copyright (c) 2004-2005 The University of Tennessee and The University
   6  *                         of Tennessee Research Foundation.  All rights
   7  *                         reserved.
   8  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
   9  *                         University of Stuttgart.  All rights reserved.
  10  * Copyright (c) 2004-2005 The Regents of the University of California.
  11  *                         All rights reserved.
  12  * Copyright (c) 2008      Sun Microsystems, Inc.  All rights reserved.
  13  * Copyright (c) 2008-2011 University of Houston. All rights reserved.
  14  * Copyright (c) 2015      Research Organization for Information Science
  15  *                         and Technology (RIST). All rights reserved.
  16  * Copyright (c) 2016-2017 IBM Corporation. All rights reserved.
  17  * $COPYRIGHT$
  18  *
  19  * Additional copyrights may follow
  20  *
  21  * $HEADER$
  22  */
  23 
  24 #include "ompi_config.h"
  25 
  26 #include <stdio.h>
  27 #include <string.h>
  28 #include <stdlib.h>
  29 
  30 #include "mpi.h"
  31 #include "ompi/file/file.h"
  32 #include "opal/util/argv.h"
  33 #include "opal/util/output.h"
  34 #include "opal/util/info.h"
  35 #include "opal/class/opal_list.h"
  36 #include "opal/class/opal_object.h"
  37 #include "ompi/mca/mca.h"
  38 #include "opal/mca/base/base.h"
  39 #include "ompi/mca/io/io.h"
  40 #include "ompi/mca/io/base/base.h"
  41 #include "ompi/mca/io/base/io_base_request.h"
  42 #include "ompi/mca/fs/fs.h"
  43 #include "ompi/mca/fs/base/base.h"
  44 #include "ompi/mca/fcoll/fcoll.h"
  45 #include "ompi/mca/fcoll/base/base.h"
  46 #include "ompi/mca/fbtl/fbtl.h"
  47 #include "ompi/mca/fbtl/base/base.h"
  48 #include "ompi/mca/sharedfp/sharedfp.h"
  49 #include "ompi/mca/sharedfp/base/base.h"
  50 
  51 opal_mutex_t ompi_mpi_ompio_bootstrap_mutex = OPAL_MUTEX_STATIC_INIT;
  52 /*
  53  * Local types
  54  */
  55 struct avail_io_t {
  56     opal_list_item_t super;
  57 
  58     mca_io_base_version_t ai_version;
  59 
  60     int ai_priority;
  61     mca_io_base_components_t ai_component;
  62     mca_io_base_modules_t ai_module;
  63     struct mca_io_base_file_t *ai_module_data;
  64 };
  65 typedef struct avail_io_t avail_io_t;
  66 
  67 /*
  68  * Local functions
  69  */
  70 static opal_list_t *check_components(opal_list_t *components,
  71                                      ompi_file_t *file,
  72                                      char **names, int num_names);
  73 static avail_io_t *check_one_component(ompi_file_t *file,
  74                                        const mca_base_component_t *component);
  75 
  76 static avail_io_t *query(const mca_base_component_t *component,
  77                          ompi_file_t *file);
  78 static avail_io_t *query_2_0_0(const mca_io_base_component_2_0_0_t *io_component,
  79                                ompi_file_t *file);
  80 
  81 static void unquery(avail_io_t *avail, ompi_file_t *file);
  82 
  83 static int module_init(ompi_file_t *file);
  84 
  85 
  86 /*
  87  * Stuff for the OBJ interface
  88  */
  89 static OBJ_CLASS_INSTANCE(avail_io_t, opal_list_item_t, NULL, NULL);
  90 
  91 
  92 /*
  93  * This function is called at the initialization time of every
  94  * file.  It is used to select which io component will be
  95  * active for a given file.
  96  */
  97 int mca_io_base_file_select(ompi_file_t *file,
  98                             mca_base_component_t *preferred)
  99 {
 100     int err;
 101     char *str;
 102     opal_list_t *selectable;
 103     opal_list_item_t *item;
 104     avail_io_t *avail, selected;
 105 
 106     /* Announce */
 107 
 108     opal_output_verbose(10, ompi_io_base_framework.framework_output,
 109                         "io:base:file_select: new file: %s",
 110                         file->f_filename);
 111 
 112     /* Initialize all the relevant pointers, since they're used as
 113        sentinel values */
 114 
 115     file->f_io_version = MCA_IO_BASE_V_NONE;
 116     file->f_io_selected_data = NULL;
 117 
 118     /* Compute the intersection of all of my available components with
 119        the components from all the other processes in this file */
 120 
 121     /* JMS CONTINUE HERE */
 122 
 123     /* See if a preferred component was provided.  If so, try to
 124        select it.  If we don't succeed, fall through and do a normal
 125        selection. */
 126 
 127     err = OMPI_ERROR;
 128     if (NULL != preferred) {
 129         str = &(preferred->mca_component_name[0]);
 130 
 131         opal_output_verbose(10, ompi_io_base_framework.framework_output,
 132                             "io:base:file_select: Checking preferred module: %s",
 133                             str);
 134         selectable = check_components(&ompi_io_base_framework.framework_components,
 135                                       file, &str, 1);
 136 
 137         /* If we didn't get a preferred module, then call again
 138            without a preferred module.  This makes the logic below
 139            dramatically simpler. */
 140 
 141         if (NULL == selectable) {
 142             return mca_io_base_file_select(file, NULL);
 143         }
 144 
 145         /* We only fall through here if we were able to select one of
 146            the preferred modules */
 147     }
 148 
 149     /* Nope -- a specific [set of] component[s] was not requested.  Go
 150        check them all. */
 151 
 152     else {
 153         opal_output_verbose(10, ompi_io_base_framework.framework_output,
 154                             "io:base:file_select: Checking all available modules");
 155         selectable = check_components(&ompi_io_base_framework.framework_components,
 156                                       file, NULL, 0);
 157     }
 158 
 159     /* Upon return from the above, the modules list will contain the
 160        list of modules that returned (priority >= 0).  If we have no
 161        io modules available, it's an error */
 162 
 163     if (NULL == selectable) {
 164         /* There's no modules available.  Doh! */
 165         /* show_help */
 166         return OMPI_ERROR;
 167     }
 168 
 169     /* Do some kind of collective operation to find a module that
 170        everyone has available */
 171 
 172 #if 1
 173     /* For the moment, just take the top module off the list */
 174     /* MSC actually take the buttom */
 175     item = opal_list_remove_last(selectable);
 176     avail = (avail_io_t *) item;
 177     selected = *avail;
 178     OBJ_RELEASE(avail);
 179 #else
 180     /* JMS CONTINUE HERE */
 181 #endif
 182 
 183     /* Everything left in the selectable list is therefore unwanted,
 184        and we call their unquery() method (because they all had
 185        query() invoked, but will never have init() invoked in this
 186        scope). */
 187 
 188     for (item = opal_list_remove_first(selectable); item != NULL;
 189          item = opal_list_remove_first(selectable)) {
 190         avail = (avail_io_t *) item;
 191         unquery(avail, file);
 192         OBJ_RELEASE(item);
 193     }
 194     OBJ_RELEASE(selectable);
 195 
 196     /* Save the pointers of the selected module on the ompi_file_t */
 197 
 198     file->f_io_version = selected.ai_version;
 199     file->f_io_selected_component = selected.ai_component;
 200     file->f_io_selected_module = selected.ai_module;
 201     file->f_io_selected_data = selected.ai_module_data;
 202 
 203     if (!strcmp (selected.ai_component.v2_0_0.io_version.mca_component_name,
 204                  "ompio")) {
 205         int ret;
 206 
 207         opal_mutex_lock(&ompi_mpi_ompio_bootstrap_mutex);
 208         if (OMPI_SUCCESS != (ret = mca_base_framework_open(&ompi_fs_base_framework, 0))) {
 209             opal_mutex_unlock(&ompi_mpi_ompio_bootstrap_mutex);
 210             return err;
 211         }
 212         if (OMPI_SUCCESS != (ret = mca_base_framework_open(&ompi_fcoll_base_framework, 0))) {
 213             opal_mutex_unlock(&ompi_mpi_ompio_bootstrap_mutex);
 214             return err;
 215         }
 216         if (OMPI_SUCCESS != (ret = mca_base_framework_open(&ompi_fbtl_base_framework, 0))) {
 217             opal_mutex_unlock(&ompi_mpi_ompio_bootstrap_mutex);
 218             return err;
 219         }
 220         if (OMPI_SUCCESS != (ret = mca_base_framework_open(&ompi_sharedfp_base_framework, 0))) {
 221             opal_mutex_unlock(&ompi_mpi_ompio_bootstrap_mutex);
 222             return err;
 223         }
 224         opal_mutex_unlock(&ompi_mpi_ompio_bootstrap_mutex);
 225 
 226         if (OMPI_SUCCESS !=
 227             (ret = mca_fs_base_find_available(OPAL_ENABLE_PROGRESS_THREADS, 1))) {
 228             return err;
 229         }
 230         if (OMPI_SUCCESS !=
 231             (ret = mca_fcoll_base_find_available(OPAL_ENABLE_PROGRESS_THREADS, 1))) {
 232             return err;
 233         }
 234         if (OMPI_SUCCESS !=
 235             (ret = mca_fbtl_base_find_available(OPAL_ENABLE_PROGRESS_THREADS, 1))) {
 236             return err;
 237         }
 238         if (OMPI_SUCCESS !=
 239             (ret = mca_sharedfp_base_find_available(OPAL_ENABLE_PROGRESS_THREADS, 1))) {
 240             return err;
 241         }
 242 
 243     }
 244     /* Finally -- intialize the selected module. */
 245 
 246     if (OMPI_SUCCESS != (err = module_init(file))) {
 247         return err;
 248     }
 249 
 250     /* Announce the winner */
 251 
 252     opal_output_verbose(10, ompi_io_base_framework.framework_output,
 253                         "io:base:file_select: Selected io module %s",
 254                         selected.ai_component.v2_0_0.io_version.mca_component_name);
 255 
 256     return OMPI_SUCCESS;
 257 }
 258 
 259 static int avail_io_compare (opal_list_item_t **itema,
 260                              opal_list_item_t **itemb)
 261 {
 262     const avail_io_t *availa = (const avail_io_t *) *itema;
 263     const avail_io_t *availb = (const avail_io_t *) *itemb;
 264 
 265     /* highest component last */
 266     if (availa->ai_priority > availb->ai_priority) {
 267         return 1;
 268     } else if (availa->ai_priority < availb->ai_priority) {
 269         return -1;
 270     } else {
 271         return 0;
 272     }
 273 }
 274 
 275 /*
 276  * For each component in the list, if it is in the list of names (or
 277  * the list of names is NULL), then check and see if it wants to run,
 278  * and do the resulting priority comparison.  Make a list of
 279  * (component, module) tuples (of type avail_io_t) to be only those
 280  * who returned that they want to run, and put them in priority order.
 281  */
 282 static opal_list_t *check_components(opal_list_t *components,
 283                                      ompi_file_t *file,
 284                                      char **names, int num_names)
 285 {
 286     int i;
 287     const mca_base_component_t *component;
 288     mca_base_component_list_item_t *cli;
 289     bool want_to_check;
 290     opal_list_t *selectable;
 291     avail_io_t *avail;
 292 
 293     /* Make a list of the components that query successfully */
 294 
 295     selectable = OBJ_NEW(opal_list_t);
 296 
 297     /* Scan through the list of components.  This nested loop is
 298        O(N^2), but we should never have too many components and/or
 299        names, so this *hopefully* shouldn't matter... */
 300 
 301     OPAL_LIST_FOREACH(cli, components, mca_base_component_list_item_t) {
 302         component = cli->cli_component;
 303 
 304         /* If we have a list of names, scan through it */
 305 
 306         if (0 == num_names) {
 307             want_to_check = true;
 308         } else {
 309             want_to_check = false;
 310             for (i = 0; i < num_names; ++i) {
 311                 if (0 == strcmp(names[i], component->mca_component_name)) {
 312                     want_to_check = true;
 313                 }
 314             }
 315         }
 316 
 317         /* If we determined that we want to check this component, then
 318            do so */
 319 
 320         if (want_to_check) {
 321             avail = check_one_component(file, component);
 322             if (NULL != avail) {
 323                 /* Put this item on the list in priority order
 324                    (highest priority first).  Should it go first? */
 325                 /* MSC actually put it Lowest priority first */
 326                 /* NTH sorted later */
 327                 opal_list_append(selectable, (opal_list_item_t*)avail);
 328             }
 329         }
 330     }
 331 
 332     /* If we didn't find any available components, return an error */
 333 
 334     if (0 == opal_list_get_size(selectable)) {
 335         OBJ_RELEASE(selectable);
 336         return NULL;
 337     }
 338 
 339     opal_list_sort(selectable, avail_io_compare);
 340 
 341     /* All done */
 342 
 343     return selectable;
 344 }
 345 
 346 /*
 347  * Check a single component
 348  */
 349 static avail_io_t *check_one_component(ompi_file_t *file,
 350                                        const mca_base_component_t *component)
 351 {
 352     avail_io_t *avail;
 353 
 354     avail = query(component, file);
 355     if (NULL != avail) {
 356         avail->ai_priority = (avail->ai_priority < 100) ?
 357             avail->ai_priority : 100;
 358         avail->ai_priority = (avail->ai_priority < 0) ?
 359             0 : avail->ai_priority;
 360         opal_output_verbose(10, ompi_io_base_framework.framework_output,
 361                             "io:base:file_select: component available: %s, priority: %d",
 362                             component->mca_component_name,
 363                             avail->ai_priority);
 364     } else {
 365         opal_output_verbose(10, ompi_io_base_framework.framework_output,
 366                             "io:base:file_select: component not available: %s",
 367                             component->mca_component_name);
 368     }
 369 
 370     return avail;
 371 }
 372 
 373 
 374 /**************************************************************************
 375  * Query functions
 376  **************************************************************************/
 377 
 378 /*
 379  * Take any version of a io module, query it, and return the right
 380  * module struct
 381  */
 382 static avail_io_t *query(const mca_base_component_t *component,
 383                          ompi_file_t *file)
 384 {
 385     const mca_io_base_component_2_0_0_t *ioc_200;
 386 
 387     /* MCA version check */
 388 
 389     if (MCA_BASE_VERSION_MAJOR == component->mca_major_version &&
 390         MCA_BASE_VERSION_MINOR == component->mca_minor_version &&
 391         MCA_BASE_VERSION_RELEASE == component->mca_release_version) {
 392         ioc_200 = (mca_io_base_component_2_0_0_t *) component;
 393 
 394         return query_2_0_0(ioc_200, file);
 395     }
 396 
 397     /* Unknown io API version -- return error */
 398 
 399     return NULL;
 400 }
 401 
 402 
 403 static avail_io_t *query_2_0_0(const mca_io_base_component_2_0_0_t *component,
 404                                ompi_file_t *file)
 405 {
 406     int priority;
 407     avail_io_t *avail;
 408     const mca_io_base_module_2_0_0_t *module;
 409     struct mca_io_base_file_t *module_data;
 410 
 411     /* Query v2.0.0 */
 412 
 413     avail = NULL;
 414     module_data = NULL;
 415     module = component->io_file_query(file, &module_data, &priority);
 416     if (NULL != module) {
 417         avail = OBJ_NEW(avail_io_t);
 418         avail->ai_version = MCA_IO_BASE_V_2_0_0;
 419         avail->ai_priority = priority;
 420         avail->ai_component.v2_0_0 = *component;
 421         avail->ai_module.v2_0_0 = *module;
 422         avail->ai_module_data = module_data;
 423     }
 424 
 425     return avail;
 426 }
 427 
 428 
 429 /**************************************************************************
 430  * Unquery functions
 431  **************************************************************************/
 432 
 433 static void unquery(avail_io_t *avail, ompi_file_t *file)
 434 {
 435     const mca_io_base_component_2_0_0_t *ioc_200;
 436 
 437     switch(avail->ai_version) {
 438     case MCA_IO_BASE_V_2_0_0:
 439         ioc_200 = &(avail->ai_component.v2_0_0);
 440         ioc_200->io_file_unquery(file, avail->ai_module_data);
 441         break;
 442 
 443     default:
 444         break;
 445     }
 446 }
 447 
 448 
 449 /**************************************************************************
 450  * Module_Init functions
 451  **************************************************************************/
 452 
 453 /*
 454  * Initialize a module
 455  */
 456 static int module_init(ompi_file_t *file)
 457 {
 458     const mca_io_base_module_2_0_0_t *iom_200;
 459 
 460     switch(file->f_io_version) {
 461     case MCA_IO_BASE_V_2_0_0:
 462         iom_200 = &(file->f_io_selected_module.v2_0_0);
 463         return iom_200->io_module_file_open(file->f_comm, file->f_filename,
 464                                             file->f_amode, file->super.s_info,
 465                                             file);
 466         break;
 467 
 468     default:
 469         return OMPI_ERROR;
 470         break;
 471     }
 472 
 473     /* No way to reach here */
 474 }

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