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 }