orte/mca/notifier/base/notifier_base_select.c
author rhc
Thu May 24 01:54:37 2012 +0000 (4 hours ago)
changeset 19924 81ac196149a5
parent 15647 7621aea6fcc7
permissions -rw-r--r--
Well, we dont need the -levent any more
     1 /*
     2  * Copyright (c) 2004-2008 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) 2009      Cisco Systems, Inc.  All rights reserved.
    13  * $COPYRIGHT$
    14  * 
    15  * Additional copyrights may follow
    16  * 
    17  * $HEADER$
    18  */
    19 
    20 
    21 #include "orte_config.h"
    22 
    23 #ifdef HAVE_STRING_H
    24 #include <string.h>
    25 #endif
    26 
    27 #include "opal/mca/mca.h"
    28 #include "opal/util/argv.h"
    29 #include "opal/mca/base/base.h"
    30 #include "opal/util/output.h"
    31 
    32 #include "orte/mca/notifier/base/base.h"
    33 
    34 #if !ORTE_DISABLE_FULL_SUPPORT
    35 
    36 /* Global variables */
    37 /*
    38  * orte_notifier_base_XXX_selected is set to true if at least 1 module has
    39  * been selected for the notifier XXX API interface.
    40  */
    41 bool orte_notifier_base_log_selected = false;
    42 bool orte_notifier_base_help_selected = false;
    43 bool orte_notifier_base_log_peer_selected = false;
    44 bool orte_notifier_base_log_event_selected = false;
    45 
    46 static inline char **orte_notifier_get_include_list(const char *,
    47                                                     const char *,
    48                                                     char **);
    49 static bool orte_notifier_add_module(mca_base_component_t *component,
    50                                      orte_notifier_base_module_t *module,
    51                                      int priority,
    52                                      char **include_list,
    53                                      opal_list_t *selected_modules);
    54 
    55 static void onbsp_construct(orte_notifier_base_selected_pair_t *obj)
    56 {
    57     obj->onbsp_component = NULL;
    58     obj->onbsp_module = NULL;
    59     obj->onbsp_priority = -1;
    60 }
    61 
    62 static void onbsp_destruct(orte_notifier_base_selected_pair_t *obj)
    63 {
    64     onbsp_construct(obj);
    65 }
    66 
    67 OBJ_CLASS_INSTANCE(orte_notifier_base_selected_pair_t,
    68                    opal_list_item_t,
    69                    onbsp_construct,
    70                    onbsp_destruct);
    71 
    72 
    73 /**
    74  * Function for selecting a set of components from all those that are
    75  * available.
    76  *
    77  * It is possible to select a subset of these components for any interface.
    78  * The syntax is the following:
    79  * [ -mca notifier <list0> ] [ -mca notifier_log <list1> ]
    80  *                           [ -mca notifier_help <list2> ]
    81  *                           [ -mca notifier_log_peer <list3> ]
    82  *                           [ -mca notifier_log_event <list4> ]
    83  * Rules:
    84  * . <list0> empty means nothing selected
    85  * . <list0> to <list4> = comma separated lists of component names
    86  * . <list1> to <list4> may be one of:
    87  *     . subsets of <list0>
    88  *     . "none" keyword (means empty)
    89  * . 1 of <list1> to <list4> empty means = <list0>
    90  * Last point makes it possible to preserve the way it works today
    91  *
    92  * Examples:
    93  * 1)
    94  * -mca notifier syslog,smtp
    95  *      --> syslog and smtp are selected for the log, show_help, log_peer and
    96  *          log_event interfaces.
    97  * 2)
    98  * -mca notifier_log syslog
    99  *      --> no interface is activated, no component is selected
   100  * 3)
   101  * -mca notifier syslog -mca notifier_help none
   102  *                      -mca notifier_log_peer none
   103  *                      -mca notifier_log_event none
   104  *      --> only the log interface is activated, with the syslog component
   105  * 4)
   106  * -mca notifier syslog,smtp,hnp -mca notifier_help syslog
   107  *                               -mca notifier_log_peer smtp
   108  *                               -mca notifier_log_event none
   109  *      --> the log interface is activated, with the syslog, smtp and hnp
   110  *                                               components
   111  *          the log_help interface is activated, with the syslog component
   112  *          the log_peer interface is activated, with the smtp component
   113  *          the log_event interface is not activated
   114  */
   115 int orte_notifier_base_select(void)
   116 {
   117     mca_base_component_list_item_t *cli = NULL;
   118     mca_base_component_t *component = NULL;
   119     mca_base_module_t *module = NULL;
   120     int i, ret, priority, exit_status = ORTE_SUCCESS;
   121     opal_list_item_t *item;
   122     orte_notifier_base_module_t *nmodule;
   123     char **imodules;
   124     char **imodules_log, **imodules_help, **imodules_log_peer;
   125     char **imodules_log_event = NULL;
   126     bool module_needed;
   127 
   128     /*
   129      * Register the framework MCA param and look up include list
   130      */
   131     imodules = orte_notifier_get_include_list("notifier",
   132                    "Comma-delimisted list of notifier components to use "
   133                    "(empty = none)", NULL);
   134     if (NULL == imodules) {
   135         return ORTE_SUCCESS;
   136     }
   137 
   138     /*
   139      * Also get the include lists for each interface
   140      */
   141     imodules_log = orte_notifier_get_include_list("notifier_log",
   142                        "Comma-delimisted list of notifier components to use "
   143                        "for orte_notifier_log (empty = all selected)",
   144                        imodules);
   145 
   146     imodules_help = orte_notifier_get_include_list("notifier_help",
   147                         "Comma-delimisted list of notifier components to use "
   148                         "for orte_notifier_show_help (empty = all selected)",
   149                         imodules);
   150 
   151     imodules_log_peer = orte_notifier_get_include_list("notifier_log_peer",
   152                             "Comma-delimisted list of notifier components to "
   153                             "use for orte_notifier_log_peer (empty = all "
   154                             "selected)", imodules);
   155 
   156 #if ORTE_WANT_NOTIFIER_LOG_EVENT
   157     imodules_log_event = orte_notifier_get_include_list("notifier_log_event",
   158                              "Comma-delimisted list of notifier components to "
   159                              "use for ORTE_NOTIFIER_LOG_EVENT (empty = all "
   160                              "selected)",
   161                              imodules);
   162 #endif /* ORTE_WANT_NOTIFIER_LOG_EVENT */
   163 
   164     /* Query all available components and ask if they have a module */
   165     for (item = opal_list_get_first(&orte_notifier_base_components_available);
   166          opal_list_get_end(&orte_notifier_base_components_available) != item;
   167          item = opal_list_get_next(item)) {
   168         cli = (mca_base_component_list_item_t *) item;
   169         component = (mca_base_component_t *) cli->cli_component;
   170 
   171         /* If this component is not in the include list, skip it */
   172         for (i = 0; NULL != imodules[i]; ++i) {
   173             if (0 == strcmp(imodules[i], component->mca_component_name)) {
   174                 break;
   175             }
   176         }
   177         if (NULL == imodules[i]) {
   178             continue;
   179         }
   180 
   181         /* If there's no query function, skip it */
   182         if (NULL == component->mca_query_component) {
   183             opal_output_verbose(5, orte_notifier_base_output,
   184                                 "mca:notify:select: Skipping component [%s]. It does not implement a query function",
   185                                 component->mca_component_name );
   186             continue;
   187         }
   188 
   189         /* Query the component */
   190         opal_output_verbose(5, orte_notifier_base_output,
   191                             "mca:notify:select: Querying component [%s]",
   192                             component->mca_component_name);
   193         ret = component->mca_query_component(&module, &priority);
   194 
   195         /* If no module was returned, then skip component */
   196         if (ORTE_SUCCESS != ret || NULL == module) {
   197             opal_output_verbose(5, orte_notifier_base_output,
   198                                 "mca:notify:select: Skipping component [%s]. Query failed to return a module",
   199                                 component->mca_component_name );
   200             continue;
   201         }
   202 
   203         /* If we got a module, initialize it */
   204         nmodule = (orte_notifier_base_module_t*) module;
   205         if (NULL != nmodule->init) {
   206             /* If the module doesn't want to be used, skip it */
   207             if (ORTE_SUCCESS != (ret = nmodule->init()) ) {
   208                 if (ORTE_ERR_NOT_SUPPORTED != ret &&
   209                     ORTE_ERR_NOT_IMPLEMENTED != ret) {
   210                     exit_status = ret;
   211                     goto cleanup;
   212                 }
   213 
   214                 if (NULL != nmodule->finalize) {
   215                     nmodule->finalize();
   216                 }
   217                 continue;
   218             }
   219         }
   220 
   221         /*
   222          * OK, one module has been selected for the notifier framework, and
   223          * successfully initialized.
   224          * Now we have to include it in the per interface selected modules
   225          * lists if needed.
   226          */
   227         ret = orte_notifier_add_module(component,
   228                                        nmodule,
   229                                        priority,
   230                                        imodules_log,
   231                                        &orte_notifier_log_selected_modules);
   232 
   233         orte_notifier_base_log_selected = orte_notifier_base_log_selected
   234                                           || ret;
   235         /*
   236          * This variable is set to check if the module is needed by at least
   237          * one interface.
   238          */
   239         module_needed = ret;
   240 
   241         ret = orte_notifier_add_module(component,
   242                                        nmodule,
   243                                        priority,
   244                                        imodules_help,
   245                                        &orte_notifier_help_selected_modules);
   246         orte_notifier_base_help_selected = orte_notifier_base_help_selected
   247                                            || ret;
   248         module_needed = module_needed || ret;
   249 
   250         ret = orte_notifier_add_module(component,
   251                                        nmodule,
   252                                        priority,
   253                                        imodules_log_peer,
   254                                     &orte_notifier_log_peer_selected_modules);
   255         orte_notifier_base_log_peer_selected =
   256             orte_notifier_base_log_peer_selected || ret;
   257         module_needed = module_needed || ret;
   258 
   259         ret = orte_notifier_add_module(component,
   260                                        nmodule,
   261                                        priority,
   262                                        imodules_log_event,
   263                                     &orte_notifier_log_event_selected_modules);
   264         orte_notifier_base_log_event_selected =
   265             orte_notifier_base_log_event_selected || ret;
   266         module_needed = module_needed || ret;
   267 
   268         /*
   269          * If the module is needed by at least one interface:
   270          * Unconditionally update the global list that will be used during
   271          * the close step. Else unload it.
   272          */
   273         if (module_needed) {
   274             orte_notifier_add_module(component,
   275                                      nmodule,
   276                                      priority,
   277                                      imodules,
   278                                      &orte_notifier_base_selected_modules);
   279         } else {
   280             if (NULL != nmodule->finalize) {
   281                 nmodule->finalize();
   282             }
   283         }
   284     }
   285 
   286     if (orte_notifier_base_log_event_selected) {
   287         /*
   288          * This has to be done whatever the selected module. That's why it's
   289          * done here.
   290          */
   291         orte_notifier_base_events_init();
   292     }
   293 
   294  cleanup:
   295     return exit_status;
   296 }
   297 
   298 /**
   299  * Register an mca param that represents an include list and build that list.
   300  *
   301  * @param param_name       (IN)  param name to be registered
   302  * @param help_message     (IN)  help message for that param
   303  * @param default_modules  (IN)  list of module names to be inherited if an
   304  *                               empty include list is provided
   305  * @return                       list of modules names
   306  */
   307 static inline char **orte_notifier_get_include_list(const char *param_name,
   308                                                     const char *help_message,
   309                                                     char **default_modules)
   310 {
   311     char *include_list = NULL;
   312     char **imodules;
   313 
   314     mca_base_param_reg_string_name(param_name, NULL, help_message,
   315                                    false, false, NULL, &include_list);
   316     imodules = opal_argv_split(include_list, ',');
   317     if (NULL == imodules) {
   318         /*
   319          * Inherit the default list if nothing specified
   320          */
   321         return default_modules;
   322     }
   323     if (!strcmp(include_list, "none")) {
   324         return NULL;
   325     }
   326     return imodules;
   327 }
   328 
   329 
   330 /**
   331  * Check if a component name belongs to an include list and add it to the
   332  * list of selected modules.
   333  *
   334  * @param component        (IN)  component to be included
   335  * @param module           (IN)  module to be included
   336  * @param priority         (IN)  module priority
   337  * @param include_list     (IN)  list of module names to go through
   338  * @param selected_modules (OUT) list of selected modules to be updated
   339  * @return                       true/false depending on whether the module
   340  *                               has been added or not
   341  */
   342 static bool orte_notifier_add_module(mca_base_component_t *component,
   343                                      orte_notifier_base_module_t *module,
   344                                      int priority,
   345                                      char **include_list,
   346                                      opal_list_t *selected_modules)
   347 {
   348     orte_notifier_base_selected_pair_t *pair, *pair2;
   349     char *module_name;
   350     opal_list_item_t *item;
   351     int i;
   352 
   353     if (NULL == include_list) {
   354         return false;
   355     }
   356 
   357     module_name = component->mca_component_name;
   358 
   359     /* If this component is not in the include list, skip it */
   360     for (i = 0; NULL != include_list[i]; i++) {
   361         if (!strcmp(include_list[i], module_name)) {
   362             break;
   363         }
   364     }
   365     if (NULL == include_list[i]) {
   366         return false;
   367     }
   368 
   369     /* Make an item for the list */
   370     pair = OBJ_NEW(orte_notifier_base_selected_pair_t);
   371     pair->onbsp_component = (orte_notifier_base_component_t*) component;
   372     pair->onbsp_module = module;
   373     pair->onbsp_priority = priority;
   374 
   375     /* Put it in the list in priority order */
   376     for (item = opal_list_get_first(selected_modules);
   377          opal_list_get_end(selected_modules) != item;
   378          item = opal_list_get_next(item)) {
   379         pair2 = (orte_notifier_base_selected_pair_t*) item;
   380         if (priority > pair2->onbsp_priority) {
   381             opal_list_insert_pos(selected_modules, item, &(pair->super));
   382             break;
   383         }
   384     }
   385     if (opal_list_get_end(selected_modules) == item) {
   386         opal_list_append(selected_modules, &(pair->super));
   387     }
   388 
   389     return true;
   390 }
   391 
   392 #endif