1 /*
2  * Copyright (C) by Argonne National Laboratory
3  *     See COPYRIGHT in top-level directory
4  */
5 
6 /* Change for BG/L made by Hao Yu, yuh@us.ibm.com
7  */
8 
9 #include "mpi.h"
10 #include <stdio.h>
11 #include <string.h>
12 #include <stdlib.h>
13 
handle_error(int errcode,const char * str)14 static void handle_error(int errcode, const char *str)
15 {
16     char msg[MPI_MAX_ERROR_STRING];
17     int resultlen;
18     MPI_Error_string(errcode, msg, &resultlen);
19     fprintf(stderr, "%s: %s\n", str, msg);
20     MPI_Abort(MPI_COMM_WORLD, 1);
21 }
22 
23 /* this test wants to compare the hints it gets from a file with a set of
24  * default hints.  These hints are specific to the MPI-IO implementation, so if
25  * you want to test something besides the default you'll have to use a command
26  * line argument */
27 
28 typedef struct hint_defaults {
29     int cb_buffer_size;
30     int ind_rd_buffer_size;
31     int ind_wr_buffer_size;
32     const char *romio_cb_read;
33     const char *romio_cb_write;
34     const char *cb_config_list;
35 } hint_defaults;
36 
37 hint_defaults UFS_DEFAULTS = {
38     .cb_buffer_size = 16777216,
39     .ind_rd_buffer_size = 4194304,
40     .ind_wr_buffer_size = 524288,
41     .romio_cb_read = "automatic",
42     .romio_cb_write = "automatic",
43     .cb_config_list = "*:1"
44 };
45 
46 hint_defaults BLUEGENE_DEFAULTS = {
47     .cb_buffer_size = 16777216,
48     .ind_rd_buffer_size = 4194304,
49     .ind_wr_buffer_size = 4194304,
50     .romio_cb_read = "enable",
51     .romio_cb_write = "enable",
52     .cb_config_list = NULL
53 };
54 
55 /* #undef INFO_DEBUG */
56 
57 /* Test will print out information about unexpected hint keys or values that
58  * differ from the default.  Since this is often interesting but rarely an
59  * error, default will be to increment errror cound for true error conditions
60  * but not print out these "interesting" non-error cases. */
61 
62 static int verbose = 0;
63 static int test_ufs = 0;
64 static int test_bluegene = 0;
65 
main(int argc,char ** argv)66 int main(int argc, char **argv)
67 {
68     int i, len, nkeys, flag, mynod, default_striping_factor = 0, nprocs, errs = 0;
69     MPI_File fh;
70     MPI_Info info, info_used;
71     char *filename, key[MPI_MAX_INFO_KEY], value[MPI_MAX_INFO_VAL];
72     hint_defaults *defaults;
73     int ret;
74 
75     MPI_Init(&argc, &argv);
76 
77     MPI_Comm_rank(MPI_COMM_WORLD, &mynod);
78     MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
79 
80 /* process 0 takes the file name as a command-line argument and
81    broadcasts it to other processes */
82     if (!mynod) {
83         i = 1;
84         while ((i < argc) && strcmp("-fname", *argv)) {
85             if (!strcmp("-v", *argv))
86                 verbose = 1;
87             else if (!strcmp("-u", *argv))
88                 test_ufs = 1;
89             else if (!strcmp("-b", *argv))
90                 test_bluegene = 1;
91             i++;
92             argv++;
93         }
94         if (i >= argc) {
95             fprintf(stderr, "\n*#  Usage: file_info [-v] -fname filename\n\n");
96             MPI_Abort(MPI_COMM_WORLD, 1);
97         }
98         argv++;
99         len = strlen(*argv);
100         filename = (char *) malloc(len + 1);
101         strcpy(filename, *argv);
102         MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD);
103         MPI_Bcast(filename, len + 1, MPI_CHAR, 0, MPI_COMM_WORLD);
104         MPI_Bcast(&verbose, 1, MPI_INT, 0, MPI_COMM_WORLD);
105         MPI_Bcast(&test_ufs, 1, MPI_INT, 0, MPI_COMM_WORLD);
106         MPI_Bcast(&test_bluegene, 1, MPI_INT, 0, MPI_COMM_WORLD);
107     } else {
108         MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD);
109         filename = (char *) malloc(len + 1);
110         MPI_Bcast(filename, len + 1, MPI_CHAR, 0, MPI_COMM_WORLD);
111         MPI_Bcast(&verbose, 1, MPI_INT, 0, MPI_COMM_WORLD);
112         MPI_Bcast(&test_ufs, 1, MPI_INT, 0, MPI_COMM_WORLD);
113         MPI_Bcast(&test_bluegene, 1, MPI_INT, 0, MPI_COMM_WORLD);
114     }
115     if (test_ufs) {
116         defaults = &UFS_DEFAULTS;
117     } else if (test_bluegene) {
118         defaults = &BLUEGENE_DEFAULTS;
119     } else {
120         defaults = NULL;
121     }
122 
123 /* open the file with MPI_INFO_NULL */
124     ret = MPI_File_open(MPI_COMM_WORLD, filename, MPI_MODE_CREATE | MPI_MODE_RDWR,
125                         MPI_INFO_NULL, &fh);
126     if (ret != MPI_SUCCESS)
127         handle_error(ret, "MPI_File_open");
128 
129 /* check the default values set by ROMIO */
130     MPI_File_get_info(fh, &info_used);
131     MPI_Info_get_nkeys(info_used, &nkeys);
132 
133     if (defaults != NULL) {
134         for (i = 0; i < nkeys; i++) {
135             MPI_Info_get_nthkey(info_used, i, key);
136             MPI_Info_get(info_used, key, MPI_MAX_INFO_VAL - 1, value, &flag);
137 #ifdef INFO_DEBUG
138             if (!mynod)
139                 fprintf(stderr, "Process %d, Default:  key = %s, value = %s\n", mynod, key, value);
140 #endif
141             if (!strcmp("striping_factor", key)) {
142                 default_striping_factor = atoi(value);
143                 /* no check */
144             } else if (!strcmp("cb_buffer_size", key)) {
145                 if (atoi(value) != defaults->cb_buffer_size) {
146                     errs++;
147                     if (verbose)
148                         fprintf(stderr, "cb_buffer_size is %d; should be %d\n",
149                                 atoi(value), defaults->cb_buffer_size);
150                 }
151             } else if (!strcmp("romio_cb_read", key)) {
152                 if (strcmp(defaults->romio_cb_read, value)) {
153                     errs++;
154                     if (verbose)
155                         fprintf(stderr, "romio_cb_read is set to %s; should be %s\n",
156                                 value, defaults->romio_cb_read);
157                 }
158             } else if (!strcmp("romio_cb_write", key)) {
159                 if (strcmp(defaults->romio_cb_write, value)) {
160                     errs++;
161                     if (verbose)
162                         fprintf(stderr, "romio_cb_write is set to %s; should be %s\n",
163                                 value, defaults->romio_cb_write);
164                 }
165             } else if (!strcmp("cb_nodes", key)) {
166                 /* unreliable test -- just ignore value */
167             } else if (!strcmp("romio_no_indep_rw", key)) {
168                 if (strcmp("false", value)) {
169                     errs++;
170                     if (verbose)
171                         fprintf(stderr, "romio_no_indep_rw is set to %s; should be %s\n",
172                                 value, "false");
173                 }
174             } else if (!strcmp("ind_rd_buffer_size", key)) {
175                 if (atoi(value) != defaults->ind_rd_buffer_size) {
176                     errs++;
177                     if (verbose)
178                         fprintf(stderr, "ind_rd_buffer_size is %d; should be %d\n",
179                                 atoi(value), defaults->ind_rd_buffer_size);
180                 }
181             } else if (!strcmp("ind_wr_buffer_size", key)) {
182                 if (atoi(value) != defaults->ind_wr_buffer_size) {
183                     errs++;
184                     if (verbose)
185                         fprintf(stderr, "ind_wr_buffer_size is %d; should be %d\n",
186                                 atoi(value), defaults->ind_wr_buffer_size);
187                 }
188             } else if (!strcmp("romio_ds_read", key)) {
189                 if (strcmp("automatic", value)) {
190                     errs++;
191                     if (verbose)
192                         fprintf(stderr, "romio_ds_read is set to %s; should be %s\n",
193                                 value, "automatic");
194                 }
195             } else if (!strcmp("romio_ds_write", key)) {
196                 /* Unreliable test -- value is file system dependent.  Ignore. */
197             } else if (!strcmp("cb_config_list", key)) {
198 #ifndef SKIP_CB_CONFIG_LIST_TEST
199                 if (strcmp(defaults->cb_config_list, value)) {
200                     errs++;
201                     if (verbose)
202                         fprintf(stderr, "cb_config_list is set to %s; should be %s\n",
203                                 value, defaults->cb_config_list);
204                 }
205 #endif
206             }
207             /* don't care about the defaults for these keys */
208             else if (!strcmp("romio_cb_pfr", key)) {
209             } else if (!strcmp("romio_cb_fr_types", key)) {
210             } else if (!strcmp("romio_cb_fr_alignment", key)) {
211             } else if (!strcmp("romio_cb_ds_threshold", key)) {
212             } else if (!strcmp("romio_cb_alltoall", key)) {
213             } else {
214                 if (verbose)
215                     fprintf(stderr, "unexpected key %s (not counted as an error)\n", key);
216             }
217         }
218     }
219     MPI_Info_free(&info_used);
220 
221     MPI_File_close(&fh);
222 
223     /* delete the file */
224     if (!mynod)
225         MPI_File_delete(filename, MPI_INFO_NULL);
226     MPI_Barrier(MPI_COMM_WORLD);
227 
228 /* set new info values. */
229 
230     MPI_Info_create(&info);
231 
232 /* The following four hints are accepted on all machines. They can
233    be specified at file-open time or later (any number of times). */
234 
235     /* buffer size for collective I/O */
236     MPI_Info_set(info, "cb_buffer_size", "8388608");
237 
238     /* number of processes that actually perform I/O in collective I/O */
239     sprintf(value, "%d", nprocs / 2);
240     MPI_Info_set(info, "cb_nodes", value);
241 
242     /* buffer size for data sieving in independent reads */
243     MPI_Info_set(info, "ind_rd_buffer_size", "2097152");
244 
245     /* buffer size for data sieving in independent writes */
246     MPI_Info_set(info, "ind_wr_buffer_size", "1048576");
247 
248 
249 /* The following three hints related to file striping are accepted only
250    on some parallel file systems and are ignored elsewhere.
251    They can be specified only at file-creation time; if specified later
252    they will be ignored. */
253 
254     /* number of I/O devices across which the file will be striped.
255      * accepted only if 0 < value < default_striping_factor;
256      * ignored otherwise */
257     if (default_striping_factor - 1 > 0) {
258         sprintf(value, "%d", default_striping_factor - 1);
259         MPI_Info_set(info, "striping_factor", value);
260     } else {
261         sprintf(value, "%d", default_striping_factor);
262         MPI_Info_set(info, "striping_factor", value);
263     }
264 
265     /* the striping unit in bytes */
266     MPI_Info_set(info, "striping_unit", "131072");
267 
268 #ifndef SKIP_CB_CONFIG_LIST_TEST
269     /* set the cb_config_list so we'll get deterministic cb_nodes output */
270     MPI_Info_set(info, "cb_config_list", "*:*");
271 #endif
272 
273     /* the I/O device number from which to start striping the file.
274      * accepted only if 0 <= value < default_striping_factor;
275      * ignored otherwise */
276     sprintf(value, "%d", default_striping_factor - 2);
277     MPI_Info_set(info, "start_iodevice", value);
278 
279 
280 /* The following hint about PFS server buffering is accepted only on
281    Intel PFS. It can be specified anytime. */
282     MPI_Info_set(info, "pfs_svr_buf", "true");
283 
284 /* open the file and set new info */
285     ret = MPI_File_open(MPI_COMM_WORLD, filename, MPI_MODE_CREATE | MPI_MODE_RDWR, info, &fh);
286     if (ret != MPI_SUCCESS)
287         handle_error(ret, "MPI_File_open");
288 
289 /* check the values set */
290     ret = MPI_File_get_info(fh, &info_used);
291     if (ret != MPI_SUCCESS)
292         handle_error(ret, "MPI_File_get_info");
293     MPI_Info_get_nkeys(info_used, &nkeys);
294 
295     for (i = 0; i < nkeys; i++) {
296         MPI_Info_get_nthkey(info_used, i, key);
297         MPI_Info_get(info_used, key, MPI_MAX_INFO_VAL - 1, value, &flag);
298 #ifdef INFO_DEBUG
299         if (!mynod)
300             fprintf(stderr, "Process %d, key = %s, value = %s\n", mynod, key, value);
301 #endif
302         if (!strcmp("striping_factor", key)) {
303             if ((default_striping_factor - 1 > 0) && (atoi(value) != default_striping_factor - 1)) {
304                 errs++;
305                 if (verbose)
306                     fprintf(stderr, "striping_factor is %d; should be %d\n",
307                             atoi(value), default_striping_factor - 1);
308             } else if (atoi(value) != default_striping_factor) {
309                 errs++;
310                 if (verbose)
311                     fprintf(stderr, "striping_factor is %d; should be %d\n",
312                             atoi(value), default_striping_factor);
313             }
314         } else if (!strcmp("cb_buffer_size", key)) {
315             if (atoi(value) != 8388608) {
316                 errs++;
317                 if (verbose)
318                     fprintf(stderr, "cb_buffer_size is %d; should be %d\n", atoi(value), 8388608);
319             }
320         }
321         /* only check the hints we set */
322         else if (!strcmp("cb_nodes", key)) {
323             /* unreliable test: just skip */
324         } else if (!strcmp("romio_no_indep_rw", key)) {
325             if (strcmp("false", value)) {
326                 errs++;
327                 if (verbose)
328                     fprintf(stderr, "romio_no_indep_rw is set to %s; should be %s\n",
329                             value, "false");
330             }
331         } else if (!strcmp("ind_rd_buffer_size", key)) {
332             if (atoi(value) != 2097152) {
333                 errs++;
334                 if (verbose)
335                     fprintf(stderr, "ind_rd_buffer_size is %d; should be %d\n",
336                             atoi(value), 2097152);
337             }
338         } else if (!strcmp("ind_wr_buffer_size", key)) {
339             if (atoi(value) != 1048576) {
340                 errs++;
341                 if (verbose)
342                     fprintf(stderr, "ind_wr_buffer_size is %d; should be %d\n",
343                             atoi(value), 1048576);
344             }
345         } else if (!strcmp("romio_ds_read", key)) {
346             if (strcmp("automatic", value)) {
347                 errs++;
348                 if (verbose)
349                     fprintf(stderr, "romio_ds_read is set to %s; should be %s\n",
350                             value, "automatic");
351             }
352         } else if (!strcmp("romio_ds_write", key)) {
353             /* Unreliable test -- value is file system dependent.  Ignore. */
354         } else if (!strcmp("cb_config_list", key)) {
355 #ifndef SKIP_CB_CONFIG_LIST_TEST
356             if (strcmp("*:*", value)) {
357                 errs++;
358                 if (verbose)
359                     fprintf(stderr, "cb_config_list is set to %s; should be %s\n", value, "*:*");
360             }
361 #endif
362         } else if (!strcmp("romio_cb_pfr", key)) {
363             if (strcmp("disable", value)) {
364                 errs++;
365                 if (verbose)
366                     fprintf(stderr, "romio_cb_pfr is set to %s; should be %s\n",
367                             value, "automatic");
368             }
369         } else if (!strcmp("romio_cb_fr_types", key)) {
370             if (strcmp("aar", value)) {
371                 errs++;
372                 if (verbose)
373                     fprintf(stderr, "romio_cb_fr_types is set to %s; should be %s\n", value, "aar");
374             }
375         } else if (!strcmp("romio_cb_fr_alignment", key)) {
376             if (strcmp("1", value)) {
377                 errs++;
378                 if (verbose)
379                     fprintf(stderr, "romio_cb_fr_alignment is set to %s; should be %s\n",
380                             value, "1");
381             }
382         } else if (!strcmp("romio_cb_ds_threshold", key)) {
383             if (strcmp("0", value)) {
384                 errs++;
385                 if (verbose)
386                     fprintf(stderr, "romio_cb_ds_threshold is set to %s; should be %s\n",
387                             value, "0");
388             }
389         } else if (!strcmp("romio_cb_alltoall", key)) {
390             if (strcmp("automatic", value)) {
391                 errs++;
392                 if (verbose)
393                     fprintf(stderr, "romio_cb_alltoall is set to %s; should be %s\n",
394                             value, "automatic");
395             }
396         }
397 
398         else {
399             if (verbose)
400                 fprintf(stderr, "unexpected key %s (not counted as an error)\n", key);
401         }
402     }
403 
404     /* Q: SHOULD WE BOTHER LOOKING AT THE OTHER PROCESSES? */
405     if (!mynod) {
406         if (errs)
407             fprintf(stderr, "Found %d errors.\n", errs);
408         else
409             printf(" No Errors\n");
410     }
411 
412     MPI_File_close(&fh);
413 
414     /* delete the file */
415     if (!mynod)
416         MPI_File_delete(filename, MPI_INFO_NULL);
417     MPI_Barrier(MPI_COMM_WORLD);
418 
419     free(filename);
420     MPI_Info_free(&info_used);
421     MPI_Info_free(&info);
422     MPI_Finalize();
423     return 0;
424 }
425