1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2 /*
3 *
4 * Copyright (C) 1997 University of Chicago.
5 * See COPYRIGHT notice in top-level directory.
6 */
7
8 #include "adio.h"
9 #include "adio_extern.h"
10 #include "hint_fns.h"
11
12 void ADIOI_GEN_SetInfo(ADIO_File fd, MPI_Info users_info, int *error_code)
13 {
14 /* if fd->info is null, create a new info object.
15 Initialize fd->info to default values.
16 Initialize fd->hints to default values.
17 Examine the info object passed by the user. If it contains values that
18 ROMIO understands, override the default. */
19
20 MPI_Info info;
21 char *value;
22 int flag, nprocs=0, len;
23 int ok_to_override_cb_nodes=0;
24 static char myname[] = "ADIOI_GEN_SETINFO";
25
26
27 /* if we've already set up default hints and the user has not asked us to
28 * process any hints (MPI_INFO_NULL), then we can short-circuit hint
29 * processing */
30 if (fd->hints->initialized && fd->info == MPI_INFO_NULL) {
31 *error_code = MPI_SUCCESS;
32 return;
33 }
34
35 if (fd->info == MPI_INFO_NULL) MPI_Info_create(&(fd->info));
36 info = fd->info;
37
38 MPI_Comm_size(fd->comm, &nprocs);
39
40 /* Note that fd->hints is allocated at file open time; thus it is
41 * not necessary to allocate it, or check for allocation, here.
42 */
43
44 value = (char *) ADIOI_Malloc((MPI_MAX_INFO_VAL+1)*sizeof(char));
45 if (value == NULL) {
46 *error_code = MPIO_Err_create_code(*error_code,
47 MPIR_ERR_RECOVERABLE,
48 myname,
49 __LINE__,
50 MPI_ERR_OTHER,
51 "**nomem2",0);
52 return;
53 }
54
55 /* initialize info and hints to default values if they haven't been
56 * previously initialized
57 */
58 if (!fd->hints->initialized) {
59
60 /* buffer size for collective I/O */
61 ADIOI_Info_set(info, "cb_buffer_size", ADIOI_CB_BUFFER_SIZE_DFLT);
62 fd->hints->cb_buffer_size = atoi(ADIOI_CB_BUFFER_SIZE_DFLT);
63
64 /* default is to let romio automatically decide when to use
65 * collective buffering
66 */
67 ADIOI_Info_set(info, "romio_cb_read", "automatic");
68 fd->hints->cb_read = ADIOI_HINT_AUTO;
69 ADIOI_Info_set(info, "romio_cb_write", "automatic");
70 fd->hints->cb_write = ADIOI_HINT_AUTO;
71
72 fd->hints->cb_config_list = NULL;
73
74 /* number of processes that perform I/O in collective I/O */
75 ADIOI_Snprintf(value, MPI_MAX_INFO_VAL+1, "%d", nprocs);
76 ADIOI_Info_set(info, "cb_nodes", value);
77 fd->hints->cb_nodes = nprocs;
78
79 /* hint indicating that no indep. I/O will be performed on this file */
80 ADIOI_Info_set(info, "romio_no_indep_rw", "false");
81 fd->hints->no_indep_rw = 0;
82
83 /* hint instructing the use of persistent file realms */
84 ADIOI_Info_set(info, "romio_cb_pfr", "disable");
85 fd->hints->cb_pfr = ADIOI_HINT_DISABLE;
86
87 /* hint guiding the assignment of persistent file realms */
88 ADIOI_Info_set(info, "romio_cb_fr_types", "aar");
89 fd->hints->cb_fr_type = ADIOI_FR_AAR;
90
91 /* hint to align file realms with a certain byte value */
92 ADIOI_Info_set(info, "romio_cb_fr_alignment", "1");
93 fd->hints->cb_fr_alignment = 1;
94
95 /* hint to set a threshold percentage for a datatype's size/extent at
96 * which data sieving should be done in collective I/O */
97 ADIOI_Info_set(info, "romio_cb_ds_threshold", "0");
98 fd->hints->cb_ds_threshold = 0;
99
100 /* hint to switch between point-to-point or all-to-all for two-phase */
101 ADIOI_Info_set(info, "romio_cb_alltoall", "automatic");
102 fd->hints->cb_alltoall = ADIOI_HINT_AUTO;
103
104 /* deferred_open derived from no_indep_rw and cb_{read,write} */
105 fd->hints->deferred_open = 0;
106
107 /* buffer size for data sieving in independent reads */
108 ADIOI_Info_set(info, "ind_rd_buffer_size", ADIOI_IND_RD_BUFFER_SIZE_DFLT);
109 fd->hints->ind_rd_buffer_size = atoi(ADIOI_IND_RD_BUFFER_SIZE_DFLT);
110
111 /* buffer size for data sieving in independent writes */
112 ADIOI_Info_set(info, "ind_wr_buffer_size", ADIOI_IND_WR_BUFFER_SIZE_DFLT);
113 fd->hints->ind_wr_buffer_size = atoi(ADIOI_IND_WR_BUFFER_SIZE_DFLT);
114
115 /* default is to let romio automatically decide when to use data
116 * sieving
117 */
118 ADIOI_Info_set(info, "romio_ds_read", "automatic");
119 fd->hints->ds_read = ADIOI_HINT_AUTO;
120 ADIOI_Info_set(info, "romio_ds_write", "automatic");
121 fd->hints->ds_write = ADIOI_HINT_AUTO;
122
123 /* still to do: tune this a bit for a variety of file systems. there's
124 * no good default value so just leave it unset */
125 fd->hints->min_fdomain_size = 0;
126 fd->hints->striping_unit = 0;
127
128 fd->hints->initialized = 1;
129
130 /* ADIO_Open sets up collective buffering arrays. If we are in this
131 * path from say set_file_view, then we've don't want to adjust the
132 * array: we'll get a segfault during collective i/o. We only want to
133 * look at the users cb_nodes if it's open time */
134 ok_to_override_cb_nodes = 1;
135
136 }
137
138 /* add in user's info if supplied */
139 if (users_info != MPI_INFO_NULL) {
140 ADIOI_Info_check_and_install_int(fd, users_info, "cb_buffer_size",
141 &(fd->hints->cb_buffer_size), myname, error_code);
142
143 /* aligning file realms to certain sizes (e.g. stripe sizes)
144 * may benefit I/O performance */
145 ADIOI_Info_check_and_install_int(fd, users_info, "romio_cb_fr_alignment",
146 &(fd->hints->cb_fr_alignment), myname, error_code);
147
148 /* for collective I/O, try to be smarter about when to do data sieving
149 * using a specific threshold for the datatype size/extent
150 * (percentage 0-100%) */
151 ADIOI_Info_check_and_install_int(fd, users_info, "romio_cb_ds_threshold",
152 &(fd->hints->cb_ds_threshold), myname, error_code);
153
154 ADIOI_Info_check_and_install_enabled(fd, users_info, "romio_cb_alltoall",
155 &(fd->hints->cb_alltoall), myname, error_code);
156
157 /* new hints for enabling/disabling coll. buffering on
158 * reads/writes
159 */
160 ADIOI_Info_check_and_install_enabled(fd, users_info, "romio_cb_read",
161 &(fd->hints->cb_read), myname, error_code);
162 if (fd->hints->cb_read == ADIOI_HINT_DISABLE) {
163 /* romio_cb_read overrides no_indep_rw */
164 ADIOI_Info_set(info, "romio_no_indep_rw", "false");
165 fd->hints->no_indep_rw = ADIOI_HINT_DISABLE;
166 }
167
168 ADIOI_Info_check_and_install_enabled(fd, users_info, "romio_cb_write",
169 &(fd->hints->cb_write), myname, error_code);
170 if (fd->hints->cb_write == ADIOI_HINT_DISABLE) {
171 /* romio_cb_write overrides no_indep_rw */
172 ADIOI_Info_set(info, "romio_no_indep_rw", "false");
173 fd->hints->no_indep_rw = ADIOI_HINT_DISABLE;
174 }
175
176 /* enable/disable persistent file realms for collective I/O */
177 /* may want to check for no_indep_rdwr hint as well */
178 ADIOI_Info_check_and_install_enabled(fd, users_info, "romio_cb_pfr",
179 &(fd->hints->cb_pfr), myname, error_code);
180
181
182 /* file realm assignment types ADIOI_FR_AAR(0),
183 ADIOI_FR_FSZ(-1), ADIOI_FR_USR_REALMS(-2), all others specify
184 a regular fr size in bytes. probably not the best way... */
185 ADIOI_Info_check_and_install_int(fd, users_info, "romio_cb_fr_type",
186 &(fd->hints->cb_fr_type), myname, error_code);
187
188 /* Has the user indicated all I/O will be done collectively? */
189 ADIOI_Info_check_and_install_true(fd, users_info, "romio_no_indep_rw",
190 &(fd->hints->no_indep_rw), myname, error_code);
191 if (fd->hints->no_indep_rw == 1) {
192 /* if 'no_indep_rw' set, also hint that we will do
193 * collective buffering: if we aren't doing independent io,
194 * then we have to do collective */
195 ADIOI_Info_set(info, "romio_cb_write", "enable");
196 ADIOI_Info_set(info, "romio_cb_read", "enable");
197 fd->hints->cb_read = 1;
198 fd->hints->cb_write = 1;
199 }
200 /* new hints for enabling/disabling data sieving on
201 * reads/writes
202 */
203 ADIOI_Info_check_and_install_enabled(fd, users_info, "romio_ds_read",
204 &(fd->hints->ds_read), myname, error_code);
205 ADIOI_Info_check_and_install_enabled(fd, users_info, "romio_ds_write",
206 &(fd->hints->ds_write), myname, error_code);
207
208 if (ok_to_override_cb_nodes) {
209 /* MPI_File_open path sets up some data structrues that don't
210 * get resized in the MPI_File_set_view path, so ignore
211 * cb_nodes in the set_view case */
212 ADIOI_Info_check_and_install_int(fd, users_info, "cb_nodes",
213 &(fd->hints->cb_nodes), myname, error_code);
214 if ((fd->hints->cb_nodes <= 0) || (fd->hints->cb_nodes > nprocs)) {
215 /* can't ask for more aggregators than mpi processes, though it
216 * might be interesting to think what such oversubscription
217 * might mean... someday */
218 ADIOI_Snprintf(value, MPI_MAX_INFO_VAL+1, "%d", nprocs);
219 ADIOI_Info_set(info, "cb_nodes", value);
220 fd->hints->cb_nodes = nprocs;
221 }
222 } /* if (ok_to_override_cb_nodes) */
223
224 ADIOI_Info_check_and_install_int(fd, users_info, "ind_wr_buffer_size",
225 &(fd->hints->ind_wr_buffer_size), myname, error_code);
226 ADIOI_Info_check_and_install_int(fd, users_info, "ind_rd_buffer_size",
227 &(fd->hints->ind_rd_buffer_size), myname, error_code);
228
229 if (fd->hints->cb_config_list == NULL) {
230 /* only set cb_config_list if it isn't already set. Note that
231 * since we set it below, this ensures that the cb_config_list hint
232 * will be set at file open time either by the user or to the
233 * default */
234 /* if it has been set already, we ignore it the second time.
235 * otherwise we would get an error if someone used the same info
236 * value with a cb_config_list value in it in a couple of calls,
237 * which would be irritating. */
238 ADIOI_Info_check_and_install_str(fd, users_info, "cb_config_list",
239 &(fd->hints->cb_config_list), myname, error_code);
240
241 }
242 ADIOI_Info_check_and_install_int(fd, users_info, "romio_min_fdomain_size",
243 &(fd->hints->min_fdomain_size), myname, error_code);
244
245 /* Now we use striping unit in common code so we should
246 process hints for it. */
247 ADIOI_Info_check_and_install_int(fd, users_info, "striping_unit",
248 &(fd->hints->striping_unit), myname, error_code);
249 }
250
251 /* Begin hint post-processig: some hints take precidence over or conflict
252 * with others, or aren't supported by some file systems */
253
254 /* handle cb_config_list default value here; avoids an extra
255 * free/alloc and insures it is always set
256 */
257 if (fd->hints->cb_config_list == NULL) {
258 ADIOI_Info_set(info, "cb_config_list", ADIOI_CB_CONFIG_LIST_DFLT);
259 len = (strlen(ADIOI_CB_CONFIG_LIST_DFLT)+1) * sizeof(char);
260 fd->hints->cb_config_list = ADIOI_Malloc(len);
261 if (fd->hints->cb_config_list == NULL) {
262 ADIOI_Free(value);
263 *error_code = MPIO_Err_create_code(*error_code,
264 MPIR_ERR_RECOVERABLE,
265 myname,
266 __LINE__,
267 MPI_ERR_OTHER,
268 "**nomem2",0);
269 return;
270 }
271 ADIOI_Strncpy(fd->hints->cb_config_list, ADIOI_CB_CONFIG_LIST_DFLT, len);
272 }
273 /* deferred_open won't be set by callers, but if the user doesn't
274 * explicitly disable collecitve buffering (two-phase) and does hint that
275 * io w/o independent io is going on, we'll set this internal hint as a
276 * convenience */
277 if ( ( (fd->hints->cb_read != ADIOI_HINT_DISABLE) \
278 && (fd->hints->cb_write != ADIOI_HINT_DISABLE)\
279 && fd->hints->no_indep_rw ) ) {
280 fd->hints->deferred_open = 1;
281 } else {
282 /* setting romio_no_indep_rw enable and romio_cb_{read,write}
283 * disable at the same time doesn't make sense. honor
284 * romio_cb_{read,write} and force the no_indep_rw hint to
285 * 'disable' */
286 ADIOI_Info_set(info, "romio_no_indep_rw", "false");
287 fd->hints->no_indep_rw = 0;
288 fd->hints->deferred_open = 0;
289 }
290
291 if (ADIO_Feature(fd, ADIO_DATA_SIEVING_WRITES) == 0) {
292 /* disable data sieving for fs that do not
293 support file locking */
294 ADIOI_Info_get(info, "ind_wr_buffer_size", MPI_MAX_INFO_VAL,
295 value, &flag);
296 if (flag) {
297 /* get rid of this value if it is set */
298 ADIOI_Info_delete(info, "ind_wr_buffer_size");
299 }
300 /* note: leave ind_wr_buffer_size alone; used for other cases
301 * as well. -- Rob Ross, 04/22/2003
302 */
303 ADIOI_Info_set(info, "romio_ds_write", "disable");
304 fd->hints->ds_write = ADIOI_HINT_DISABLE;
305 }
306
307 ADIOI_Free(value);
308
309 *error_code = MPI_SUCCESS;
310 }