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-2017 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/fcoll/fcoll.h"
31 #include "ompi/mca/fcoll/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_fcoll_base_component_t *om_component;
43 mca_fcoll_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 fcoll module can be attached to each file.
51 *
52 * This module calls the query funtion on all the components that were
53 * detected by fcoll_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_fcoll_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_fcoll_base_component_t *component;
75 mca_fcoll_base_component_t *best_component;
76 mca_fcoll_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 if (NULL != preferred) {
84
85 /* We have a preferred component. Check if it is available
86 and if so, whether it wants to run */
87 opal_output_verbose(10, ompi_fcoll_base_framework.framework_output,
88 "fcoll:base:file_select: Checking preferred component: %s",
89 preferred->mca_component_name);
90
91 /* query the component for its priority and get its module
92 structure. This is necessary to proceed */
93
94 component = (mca_fcoll_base_component_t *)preferred;
95 module = component->fcollm_file_query (file, &priority);
96 if (NULL != module &&
97 NULL != module->fcoll_module_init) {
98
99 /* this query seems to have returned something legitimate
100 * and we can now go ahead and initialize the
101 * file with it * but first, the functions which
102 * are null need to be filled in */
103
104 /*fill_null_pointers (module);*/
105 file->f_fcoll = module;
106 file->f_fcoll_component = preferred;
107
108 return module->fcoll_module_init(file);
109 }
110 /* His preferred component is present, but is unable to
111 * run. This is not a good sign. We should try selecting
112 * some other component We let it fall through and select
113 * from the list of available components
114 */
115 } /*end of selection for preferred component */
116
117 /*
118 * We fall till here if one of the two things happened:
119 * 1. The preferred component was provided but for some reason was
120 * not able to be selected
121 * 2. No preferred component was provided
122 *
123 * All we need to do is to go through the list of available
124 * components and find the one which has the highest priority and
125 * use that for this file
126 */
127
128 best_component = NULL;
129 best_priority = -1;
130 OBJ_CONSTRUCT(&queried, opal_list_t);
131
132 OPAL_LIST_FOREACH(cli, &ompi_fcoll_base_framework.framework_components, mca_base_component_list_item_t) {
133 component = (mca_fcoll_base_component_t *) cli->cli_component;
134 opal_output_verbose(10, ompi_fcoll_base_framework.framework_output,
135 "select: initialising %s component %s",
136 component->fcollm_version.mca_type_name,
137 component->fcollm_version.mca_component_name);
138
139 /*
140 * we can call the query function only if there is a function :-)
141 */
142 if (NULL == component->fcollm_file_query) {
143 opal_output_verbose(10, ompi_fcoll_base_framework.framework_output,
144 "select: no query, ignoring the component");
145 } else {
146 /*
147 * call the query function and see what it returns
148 */
149 module = component->fcollm_file_query (file, &priority);
150
151 if (NULL == module ||
152 NULL == module->fcoll_module_init) {
153 /*
154 * query did not return any action which can be used
155 */
156 opal_output_verbose(10, ompi_fcoll_base_framework.framework_output,
157 "select: query returned failure");
158 } else {
159 opal_output_verbose(10, ompi_fcoll_base_framework.framework_output,
160 "select: query returned priority %d",
161 priority);
162 /*
163 * is this the best component we have found till now?
164 */
165 if (priority > best_priority) {
166 best_priority = priority;
167 best_component = component;
168 }
169
170 om = OBJ_NEW(queried_module_t);
171 /*
172 * check if we have run out of space
173 */
174 if (NULL == om) {
175 OBJ_DESTRUCT(&queried);
176 return OMPI_ERR_OUT_OF_RESOURCE;
177 }
178 om->om_component = component;
179 om->om_module = module;
180 opal_list_append(&queried, (opal_list_item_t *)om);
181 } /* end else of if (NULL == module) */
182 } /* end else of if (NULL == component->fcollm_init) */
183 } /* end for ... end of traversal */
184
185 /*
186 * Now we have alist of components which successfully returned
187 * their module struct. One of these components has the best
188 * priority. The rest have to be comm_unqueried to counter the
189 * effects of file_query'ing them. Finalize happens only on
190 * components which should are initialized.
191 */
192 if (NULL == best_component) {
193 /*
194 * This typically means that there was no component which was
195 * able to run properly this time. So, we need to abort
196 */
197 OBJ_DESTRUCT(&queried);
198 return OMPI_ERROR;
199 }
200
201 /*
202 * We now have a list of components which have successfully
203 * returned their priorities from the query. We now have to
204 * unquery() those components which have not been selected and
205 * init() the component which was selected
206 */
207 while (NULL != (item = opal_list_remove_first(&queried))) {
208 om = (queried_module_t *) item;
209 if (om->om_component == best_component) {
210 /*
211 * this is the chosen component, we have to initialise the
212 * module of this component.
213 *
214 * ANJU: a component might not have all the functions
215 * defined. Whereever a function pointer is null in the
216 * module structure we need to fill it in with the base
217 * structure function pointers. This is yet to be done
218 */
219
220 /*
221 * We don return here coz we still need to go through and
222 * elease the other objects
223 */
224
225 /*fill_null_pointers (om->om_module);*/
226 file->f_fcoll = om->om_module;
227 err = om->om_module->fcoll_module_init(file);
228 file->f_fcoll_component = (mca_base_component_t *)best_component;
229 /*
230 printf ("SELECTED: %s\n", best_component->fcollm_version.mca_component_name);
231 */
232 } else {
233 /*
234 * this is not the "choosen one", finalize
235 */
236 if (NULL != om->om_component->fcollm_file_unquery) {
237 /* unquery the component only if they have some clean
238 * up job to do. Components which are queried but do
239 * not actually do anything typically do not have a
240 * unquery. Hence this check is necessary
241 */
242 (void) om->om_component->fcollm_file_unquery(file);
243 opal_output_verbose(10, ompi_fcoll_base_framework.framework_output,
244 "select: component %s is not selected",
245 om->om_component->fcollm_version.mca_component_name);
246 } /* end if */
247 } /* if not best component */
248 OBJ_RELEASE(om);
249 } /* traversing through the entire list */
250
251 opal_output_verbose(10, ompi_fcoll_base_framework.framework_output,
252 "select: component %s selected",
253 best_component->fcollm_version.mca_component_name);
254
255 OBJ_DESTRUCT(&queried);
256
257 return err;
258 }
259
260 int mca_fcoll_base_query_table (struct ompio_file_t *file, char *name)
261 {
262 if (!strcmp (name, "individual")) {
263 if ((int)file->f_cc_size >= file->f_bytes_per_agg &&
264 file->f_cc_size >= file->f_stripe_size) {
265 return 1;
266 }
267 if ( 2 >= (int)file->f_size ){
268 return 1;
269 }
270 }
271 if (!strcmp (name, "vulcan")) {
272 if ( (LUSTRE != file->f_fstype)) {
273 return 1;
274 }
275 }
276 if (!strcmp (name, "dynamic")) {
277 if ((int)file->f_cc_size < file->f_bytes_per_agg &&
278 file->f_cc_size >= file->f_stripe_size) {
279 return 1;
280 }
281 }
282 if (!strcmp (name, "dynamic_gen2")) {
283 if ( LUSTRE == file->f_fstype ) {
284 return 1;
285 }
286 }
287 if (!strcmp (name, "two_phase")) {
288 #if OPAL_CUDA_SUPPORT
289 /* do not use the two_phase component with CUDA
290 buffers, since the data sieving causes trouble
291 on unmanaged GPU buffers.
292 */
293 #else
294 if ((int)file->f_cc_size < file->f_bytes_per_agg &&
295 (0 == file->f_stripe_size || file->f_cc_size < file->f_stripe_size) &&
296 (LUSTRE != file->f_fstype) ) {
297 return 1;
298 }
299 #endif
300 }
301 return 0;
302 }