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-2011 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-2011 University of Houston. All rights reserved. 13 * Copyright (c) 2018 Research Organization for Information Science 14 * and Technology (RIST). All rights reserved. 15 * $COPYRIGHT$ 16 * 17 * Additional copyrights may follow 18 * 19 * $HEADER$ 20 */ 21 22 #include "ompi_config.h" 23 24 #include <string.h> 25 26 #include "opal/class/opal_list.h" 27 #include "opal/util/argv.h" 28 #include "ompi/mca/mca.h" 29 #include "opal/mca/base/base.h" 30 #include "ompi/mca/fbtl/fbtl.h" 31 #include "ompi/mca/fbtl/base/base.h" 32 #include "ompi/mca/common/ompio/common_ompio.h" 33 34 /* 35 * This structure is needed so that we can close the modules 36 * which are not selected but were opened. mca_base_modules_close 37 * which does this job for us requires a opal_list_t which contains 38 * these modules 39 */ 40 struct queried_module_t { 41 opal_list_item_t super; 42 mca_fbtl_base_component_t *om_component; 43 mca_fbtl_base_module_t *om_module; 44 }; 45 typedef struct queried_module_t queried_module_t; 46 static OBJ_CLASS_INSTANCE(queried_module_t, opal_list_item_t, NULL, NULL); 47 48 49 /* 50 * Only one fbtl module can be attached to each file. 51 * 52 * This module calls the query funtion on all the components that were 53 * detected by fbtl_base_open. This function is called on a 54 * per-file basis. This function has the following function. 55 * 56 * 1. Iterate over the list of available_components 57 * 2. Call the query function on each of these components. 58 * 3. query function returns the structure containing pointers 59 * to its module and its priority 60 * 4. Select the module with the highest priority 61 * 5. Call the init function on the selected module so that it does the 62 * right setup for the file 63 * 6. Call finalize on all the other modules which returned 64 * their module but were unfortunate to not get selected 65 */ 66 67 int mca_fbtl_base_file_select (struct ompio_file_t *file, 68 mca_base_component_t *preferred) 69 { 70 int priority; 71 int best_priority; 72 opal_list_item_t *item; 73 mca_base_component_list_item_t *cli; 74 mca_fbtl_base_component_t *component; 75 mca_fbtl_base_component_t *best_component; 76 mca_fbtl_base_module_t *module; 77 opal_list_t queried; 78 queried_module_t *om; 79 char *str; 80 int err = MPI_SUCCESS; 81 82 /* Check and see if a preferred component was provided. If it was 83 provided then it should be used (if possible) */ 84 85 if (NULL != preferred) { 86 87 /* We have a preferred component. Check if it is available 88 and if so, whether it wants to run */ 89 90 str = &(preferred->mca_component_name[0]); 91 92 opal_output_verbose(10, ompi_fbtl_base_framework.framework_output, 93 "fbtl:base:file_select: Checking preferred component: %s", 94 str); 95 96 /* query the component for its priority and get its module 97 structure. This is necessary to proceed */ 98 99 component = (mca_fbtl_base_component_t *)preferred; 100 module = component->fbtlm_file_query (file, &priority); 101 if (NULL != module && 102 NULL != module->fbtl_module_init) { 103 104 /* this query seems to have returned something legitimate 105 * and we can now go ahead and initialize the 106 * file with it * but first, the functions which 107 * are null need to be filled in */ 108 109 /*fill_null_pointers (module);*/ 110 file->f_fbtl = module; 111 file->f_fbtl_component = preferred; 112 113 return module->fbtl_module_init(file); 114 } 115 /* His preferred component is present, but is unable to 116 * run. This is not a good sign. We should try selecting 117 * some other component We let it fall through and select 118 * from the list of available components 119 */ 120 } /*end of selection for preferred component */ 121 122 /* 123 * We fall till here if one of the two things happened: 124 * 1. The preferred component was provided but for some reason was 125 * not able to be selected 126 * 2. No preferred component was provided 127 * 128 * All we need to do is to go through the list of available 129 * components and find the one which has the highest priority and 130 * use that for this file 131 */ 132 133 best_component = NULL; 134 best_priority = -1; 135 OBJ_CONSTRUCT(&queried, opal_list_t); 136 137 OPAL_LIST_FOREACH(cli, &ompi_fbtl_base_framework.framework_components, mca_base_component_list_item_t) { 138 component = (mca_fbtl_base_component_t *) cli->cli_component; 139 opal_output_verbose(10, ompi_fbtl_base_framework.framework_output, 140 "select: initialising %s component %s", 141 component->fbtlm_version.mca_type_name, 142 component->fbtlm_version.mca_component_name); 143 144 /* 145 * we can call the query function only if there is a function :-) 146 */ 147 if (NULL == component->fbtlm_file_query) { 148 opal_output_verbose(10, ompi_fbtl_base_framework.framework_output, 149 "select: no query, ignoring the component"); 150 } else { 151 /* 152 * call the query function and see what it returns 153 */ 154 module = component->fbtlm_file_query (file, &priority); 155 156 if (NULL == module || 157 NULL == module->fbtl_module_init) { 158 /* 159 * query did not return any action which can be used 160 */ 161 opal_output_verbose(10, ompi_fbtl_base_framework.framework_output, 162 "select: query returned failure"); 163 } else { 164 opal_output_verbose(10, ompi_fbtl_base_framework.framework_output, 165 "select: query returned priority %d", 166 priority); 167 /* 168 * is this the best component we have found till now? 169 */ 170 if (priority > best_priority) { 171 best_priority = priority; 172 best_component = component; 173 } 174 175 om = OBJ_NEW(queried_module_t); 176 /* 177 * check if we have run out of space 178 */ 179 if (NULL == om) { 180 OBJ_DESTRUCT(&queried); 181 return OMPI_ERR_OUT_OF_RESOURCE; 182 } 183 om->om_component = component; 184 om->om_module = module; 185 opal_list_append(&queried, (opal_list_item_t *)om); 186 } /* end else of if (NULL == module) */ 187 } /* end else of if (NULL == component->fbtlm_init) */ 188 } /* end for ... end of traversal */ 189 190 /* 191 * Now we have alist of components which successfully returned 192 * their module struct. One of these components has the best 193 * priority. The rest have to be comm_unqueried to counter the 194 * effects of file_query'ing them. Finalize happens only on 195 * components which should are initialized. 196 */ 197 if (NULL == best_component) { 198 /* 199 * This typically means that there was no component which was 200 * able to run properly this time. So, we need to abort 201 * JMS replace with show_help 202 */ 203 OBJ_DESTRUCT(&queried); 204 return OMPI_ERROR; 205 } 206 207 /* 208 * We now have a list of components which have successfully 209 * returned their priorities from the query. We now have to 210 * unquery() those components which have not been selected and 211 * init() the component which was selected 212 */ 213 while (NULL != (item = opal_list_remove_first(&queried))) { 214 om = (queried_module_t *) item; 215 if (om->om_component == best_component) { 216 /* 217 * this is the chosen component, we have to initialise the 218 * module of this component. 219 * 220 * ANJU: a component might not have all the functions 221 * defined. Whereever a function pointer is null in the 222 * module structure we need to fill it in with the base 223 * structure function pointers. This is yet to be done 224 */ 225 226 /* 227 * We don return here coz we still need to go through and 228 * elease the other objects 229 */ 230 231 /*fill_null_pointers (om->om_module);*/ 232 file->f_fbtl = om->om_module; 233 err = om->om_module->fbtl_module_init(file); 234 file->f_fbtl_component = (mca_base_component_t *)best_component; 235 } else { 236 /* 237 * this is not the "choosen one", finalize 238 */ 239 if (NULL != om->om_component->fbtlm_file_unquery) { 240 /* unquery the component only if they have some clean 241 * up job to do. Components which are queried but do 242 * not actually do anything typically do not have a 243 * unquery. Hence this check is necessary 244 */ 245 (void) om->om_component->fbtlm_file_unquery(file); 246 opal_output_verbose(10, ompi_fbtl_base_framework.framework_output, 247 "select: component %s is not selected", 248 om->om_component->fbtlm_version.mca_component_name); 249 } /* end if */ 250 } /* if not best component */ 251 OBJ_RELEASE(om); 252 } /* traversing through the entire list */ 253 254 opal_output_verbose(10, ompi_fbtl_base_framework.framework_output, 255 "select: component %s selected", 256 best_component->fbtlm_version.mca_component_name); 257 258 OBJ_DESTRUCT(&queried); 259 260 return err; 261 }