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