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
mca_fs_base_file_select(struct ompio_file_t * file,mca_base_component_t * preferred)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 }
257