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-2016 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/fs/fs.h" 31 #include "ompi/mca/fs/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_fs_base_component_t *om_component; 43 mca_fs_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 fs module can be attached to each file. 51 * 52 * This module calls the query funtion on all the components that were 53 * detected by fs_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_fs_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_fs_base_component_t *component; 75 mca_fs_base_component_t *best_component; 76 mca_fs_base_module_t *module; 77 opal_list_t queried; 78 queried_module_t *om; 79 int err = MPI_SUCCESS; 80 81 /* Check and see if a preferred component was provided. If it was 82 provided then it should be used (if possible) */ 83 84 if (NULL != preferred) { 85 86 /* We have a preferred component. Check if it is available 87 and if so, whether it wants to run */ 88 opal_output_verbose(10, ompi_fs_base_framework.framework_output, 89 "fs:base:file_select: Checking preferred component: %s", 90 preferred->mca_component_name); 91 92 /* query the component for its priority and get its module 93 structure. This is necessary to proceed */ 94 95 component = (mca_fs_base_component_t *)preferred; 96 module = component->fsm_file_query (file, &priority); 97 if (NULL != module && 98 NULL != module->fs_module_init) { 99 100 /* this query seems to have returned something legitimate 101 * and we can now go ahead and initialize the 102 * file with it * but first, the functions which 103 * are null need to be filled in */ 104 105 /*fill_null_pointers (module);*/ 106 file->f_fs = module; 107 file->f_fs_component = preferred; 108 109 return module->fs_module_init(file); 110 } 111 /* His preferred component is present, but is unable to 112 * run. This is not a good sign. We should try selecting 113 * some other component We let it fall through and select 114 * from the list of available components 115 */ 116 } /*end of selection for preferred component */ 117 118 /* 119 * We fall till here if one of the two things happened: 120 * 1. The preferred component was provided but for some reason was 121 * not able to be selected 122 * 2. No preferred component was provided 123 * 124 * All we need to do is to go through the list of available 125 * components and find the one which has the highest priority and 126 * use that for this file 127 */ 128 129 best_component = NULL; 130 best_priority = -1; 131 OBJ_CONSTRUCT(&queried, opal_list_t); 132 133 OPAL_LIST_FOREACH(cli, &ompi_fs_base_framework.framework_components, mca_base_component_list_item_t) { 134 component = (mca_fs_base_component_t *) cli->cli_component; 135 opal_output_verbose(10, ompi_fs_base_framework.framework_output, 136 "select: initialising %s component %s", 137 component->fsm_version.mca_type_name, 138 component->fsm_version.mca_component_name); 139 140 /* 141 * we can call the query function only if there is a function :-) 142 */ 143 if (NULL == component->fsm_file_query) { 144 opal_output_verbose(10, ompi_fs_base_framework.framework_output, 145 "select: no query, ignoring the component"); 146 } else { 147 /* 148 * call the query function and see what it returns 149 */ 150 module = component->fsm_file_query (file, &priority); 151 152 if (NULL == module || 153 NULL == module->fs_module_init) { 154 /* 155 * query did not return any action which can be used 156 */ 157 opal_output_verbose(10, ompi_fs_base_framework.framework_output, 158 "select: query returned failure"); 159 } else { 160 opal_output_verbose(10, ompi_fs_base_framework.framework_output, 161 "select: query returned priority %d", 162 priority); 163 /* 164 * is this the best component we have found till now? 165 */ 166 if (priority > best_priority) { 167 best_priority = priority; 168 best_component = component; 169 } 170 171 om = OBJ_NEW(queried_module_t); 172 /* 173 * check if we have run out of space 174 */ 175 if (NULL == om) { 176 OBJ_DESTRUCT(&queried); 177 return OMPI_ERR_OUT_OF_RESOURCE; 178 } 179 om->om_component = component; 180 om->om_module = module; 181 opal_list_append(&queried, (opal_list_item_t *)om); 182 } /* end else of if (NULL == module) */ 183 } /* end else of if (NULL == component->fsm_init) */ 184 } /* end for ... end of traversal */ 185 186 /* 187 * Now we have alist of components which successfully returned 188 * their module struct. One of these components has the best 189 * priority. The rest have to be comm_unqueried to counter the 190 * effects of file_query'ing them. Finalize happens only on 191 * components which should are initialized. 192 */ 193 if (NULL == best_component) { 194 /* 195 * This typically means that there was no component which was 196 * able to run properly this time. So, we need to abort 197 */ 198 OBJ_DESTRUCT(&queried); 199 return OMPI_ERROR; 200 } 201 202 /* 203 * We now have a list of components which have successfully 204 * returned their priorities from the query. We now have to 205 * unquery() those components which have not been selected and 206 * init() the component which was selected 207 */ 208 while (NULL != (item = opal_list_remove_first(&queried))) { 209 om = (queried_module_t *) item; 210 if (om->om_component == best_component) { 211 /* 212 * this is the chosen component, we have to initialise the 213 * module of this component. 214 * 215 * ANJU: a component might not have all the functions 216 * defined. Whereever a function pointer is null in the 217 * module structure we need to fill it in with the base 218 * structure function pointers. This is yet to be done 219 */ 220 221 /* 222 * We don return here coz we still need to go through and 223 * elease the other objects 224 */ 225 226 /*fill_null_pointers (om->om_module);*/ 227 file->f_fs = om->om_module; 228 err = om->om_module->fs_module_init(file); 229 file->f_fs_component = (mca_base_component_t *)best_component; 230 } else { 231 /* 232 * this is not the "choosen one", finalize 233 */ 234 if (NULL != om->om_component->fsm_file_unquery) { 235 /* unquery the component only if they have some clean 236 * up job to do. Components which are queried but do 237 * not actually do anything typically do not have a 238 * unquery. Hence this check is necessary 239 */ 240 (void) om->om_component->fsm_file_unquery(file); 241 opal_output_verbose(10, ompi_fs_base_framework.framework_output, 242 "select: component %s is not selected", 243 om->om_component->fsm_version.mca_component_name); 244 } /* end if */ 245 } /* if not best component */ 246 OBJ_RELEASE(om); 247 } /* traversing through the entire list */ 248 249 opal_output_verbose(10, ompi_fs_base_framework.framework_output, 250 "select: component %s selected", 251 best_component->fsm_version.mca_component_name); 252 253 OBJ_DESTRUCT(&queried); 254 255 return err; 256 }