SIONlib  2.0.0-rc.1
Scalable I/O library for parallel access to task-local files
sion_generic.c
1 /****************************************************************************
2 ** SIONLIB http://www.fz-juelich.de/jsc/sionlib **
3 *****************************************************************************
4 ** Copyright (c) 2008-2018 **
5 ** Forschungszentrum Juelich, Juelich Supercomputing Centre **
6 ** **
7 ** See the file COPYRIGHT in the package base directory for details **
8 ****************************************************************************/
9 
10 #define _XOPEN_SOURCE 700
11 
12 #include <stdint.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 
17 #include "sion_common.h"
18 #include "sion_const.h"
19 #include "sion_debug.h"
20 #include "sion_error_handler.h"
21 #include "sion_fd.h"
22 #include "sion_filedesc.h"
23 #include "sion_flags.h"
24 #include "sion_generic.h"
25 #include "sion_generic_apidesc.h"
26 #include "sion_generic_buddy.h"
27 #include "sion_generic_internal.h"
28 #include "sion_generic_mapped.h"
29 #include "sion_internal.h"
30 
31 int sion_generic_create_api(char *name)
32 {
33  int apiid = SION_ID_UNDEF;
34  _sion_generic_apidesc *sion_apidesc;
35 
36  sion_apidesc = _sion_generic_alloc_apidesc();
37  if (!sion_apidesc) {
38  return _sion_errorprint(
39  SION_ID_NOT_VALID, _SION_ERROR_RETURN, "_sion_generic_create_api: problems to alloc apidesc, aborting ...\n");
40  }
41  _sion_generic_init_apidesc(sion_apidesc);
42 
43  if (name == NULL) {
44  return _sion_errorprint(
45  SION_ID_NOT_VALID, _SION_ERROR_RETURN, "_sion_generic_create_api: name for API not given, aborting ...\n");
46  }
47 
48  sion_apidesc->name = strdup(name);
49 
50  apiid = _sion_newvcd(sion_apidesc, SION_APIDESCRIPTOR);
51  sion_apidesc->aid = apiid;
52  sion_apidesc->level = SION_GENERIC_API_LEVEL_NONE;
53 
54  DPRINTFP((2, "_sion_generic_create_api", _SION_DEFAULT_RANK, "API created with name %s apiid=%d\n", sion_apidesc->name, apiid));
55 
56  return apiid;
57 }
58 
60 {
61  _sion_generic_apidesc *sion_apidesc;
62  int rc = SION_SUCCESS;
63 
64  if ((aid < 0) || (_sion_vcdtype(aid) != SION_APIDESCRIPTOR) || !(sion_apidesc = _sion_vcdtovcon(aid))) {
65  return _sion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN, "sion_free_api: invalid sion_apidesc %d", aid);
66  }
67  _sion_freevcd(aid);
68  rc = _sion_generic_free_apidesc(sion_apidesc);
69 
70  return rc;
71 }
72 
73 int sion_generic_register_create_local_commgroup_cb(int aid, int create_lcg_cb(void **, void *, int, int, int, int, int, int))
74 {
75  _sion_generic_apidesc *sion_apidesc;
76  int rc = SION_SUCCESS;
77 
78  if ((aid < 0) || (_sion_vcdtype(aid) != SION_APIDESCRIPTOR) || !(sion_apidesc = _sion_vcdtovcon(aid))) {
79  return _sion_errorprint(
80  SION_NOT_SUCCESS, _SION_ERROR_RETURN, "sion_generic_register_create_local_commgroup_cb: invalid sion_apidesc %d", aid);
81  }
82 
83  if (sion_apidesc->create_lcg_cb != NULL) {
84  return _sion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
85  "sion_generic_register_create_local_commgroup_cb: update_cb already registered for apiid=%d", aid);
86  }
87  sion_apidesc->create_lcg_cb = create_lcg_cb;
88 
89  _sion_generic_update_api_level(sion_apidesc);
90 
91  DPRINTFP((2, "sion_generic_register_create_local_commgroup_cb", _SION_DEFAULT_RANK,
92  "create_lcg_cb registered for apiid=%s (%d)\n", sion_apidesc->name, aid));
93 
94  return rc;
95 }
96 
97 int sion_generic_register_free_local_commgroup_cb(int aid, int free_lcg_cb(void *))
98 {
99  _sion_generic_apidesc *sion_apidesc;
100  int rc = SION_SUCCESS;
101 
102  if ((aid < 0) || (_sion_vcdtype(aid) != SION_APIDESCRIPTOR) || !(sion_apidesc = _sion_vcdtovcon(aid))) {
103  return _sion_errorprint(
104  SION_NOT_SUCCESS, _SION_ERROR_RETURN, "sion_generic_register_free_local_commgroup_cb: invalid sion_apidesc %d", aid);
105  }
106 
107  if (sion_apidesc->free_lcg_cb != NULL) {
108  return _sion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
109  "sion_generic_register_free_local_commgroup_cb: update_cb already registered for apiid=%d", aid);
110  }
111  sion_apidesc->free_lcg_cb = free_lcg_cb;
112 
113  _sion_generic_update_api_level(sion_apidesc);
114 
115  DPRINTFP((2, "sion_generic_register_free_local_commgroup_cb", _SION_DEFAULT_RANK, "free_lcg_cb registered for apiid=%s (%d)\n",
116  sion_apidesc->name, aid));
117 
118  return rc;
119 }
120 
121 int sion_generic_register_barrier_cb(int aid, int barrier_cb(void *))
122 {
123  _sion_generic_apidesc *sion_apidesc;
124  int rc = SION_SUCCESS;
125 
126  if ((aid < 0) || (_sion_vcdtype(aid) != SION_APIDESCRIPTOR) || !(sion_apidesc = _sion_vcdtovcon(aid))) {
127  return _sion_errorprint(
128  SION_NOT_SUCCESS, _SION_ERROR_RETURN, "sion_generic_register_barrier_cb: invalid sion_apidesc %d", aid);
129  }
130 
131  if (sion_apidesc->barrier_cb != NULL) {
132  return _sion_errorprint(
133  SION_NOT_SUCCESS, _SION_ERROR_RETURN, "sion_generic_register_barrier_cb: barrier_cb already registered for apiid=%d", aid);
134  }
135  sion_apidesc->barrier_cb = barrier_cb;
136 
137  _sion_generic_update_api_level(sion_apidesc);
138 
139  DPRINTFP((2, "sion_generic_register_barrier_cb", _SION_DEFAULT_RANK, "barrier_cb registered for apiid=%s (%d)\n",
140  sion_apidesc->name, aid));
141 
142  return rc;
143 }
144 
145 int sion_generic_register_bcastr_cb(int aid, int bcastr_cb(void *, void *, int, int, int))
146 {
147  _sion_generic_apidesc *sion_apidesc;
148  int rc = SION_SUCCESS;
149 
150  if ((aid < 0) || (_sion_vcdtype(aid) != SION_APIDESCRIPTOR) || !(sion_apidesc = _sion_vcdtovcon(aid))) {
151  return _sion_errorprint(
152  SION_NOT_SUCCESS, _SION_ERROR_RETURN, "sion_generic_register_bcastr_cb: invalid sion_apidesc %d", aid);
153  }
154 
155  if (sion_apidesc->bcastr_cb != NULL) {
156  return _sion_errorprint(
157  SION_NOT_SUCCESS, _SION_ERROR_RETURN, "sion_generic_register_bcastr_cb: bcastr_cb already registered for apiid=%d", aid);
158  }
159  sion_apidesc->bcastr_cb = bcastr_cb;
160 
161  _sion_generic_update_api_level(sion_apidesc);
162 
163  DPRINTFP((2, "sion_generic_register_bcastr_cb", _SION_DEFAULT_RANK, "bcastr_cb registered for apiid=%s (%d)\n",
164  sion_apidesc->name, aid));
165 
166  return rc;
167 }
168 
169 int sion_generic_register_gatherr_cb(int aid, int gatherr_cb(void *, void *, void *, int, int, int))
170 {
171  _sion_generic_apidesc *sion_apidesc;
172  int rc = SION_SUCCESS;
173 
174  if ((aid < 0) || (_sion_vcdtype(aid) != SION_APIDESCRIPTOR) || !(sion_apidesc = _sion_vcdtovcon(aid))) {
175  return _sion_errorprint(
176  SION_NOT_SUCCESS, _SION_ERROR_RETURN, "sion_generic_register_gatherr_cb: invalid sion_apidesc %d", aid);
177  }
178 
179  if (sion_apidesc->gatherr_cb != NULL) {
180  return _sion_errorprint(
181  SION_NOT_SUCCESS, _SION_ERROR_RETURN, "sion_generic_register_gatherr_cb: gatherr_cb already registered for apiid=%d", aid);
182  }
183  sion_apidesc->gatherr_cb = gatherr_cb;
184 
185  _sion_generic_update_api_level(sion_apidesc);
186 
187  DPRINTFP((2, "sion_generic_register_gatherr_cb", _SION_DEFAULT_RANK, "gatherr_cb registered for apiid=%s (%d)\n",
188  sion_apidesc->name, aid));
189 
190  return rc;
191 }
192 
193 int sion_generic_register_gathervr_cb(int aid, int gathervr_cb(void *, void *, void *, int, int *, int, int))
194 {
195  _sion_generic_apidesc *sion_apidesc;
196  int rc = SION_SUCCESS;
197 
198  if ((aid < 0) || (_sion_vcdtype(aid) != SION_APIDESCRIPTOR) || !(sion_apidesc = _sion_vcdtovcon(aid))) {
199  return _sion_errorprint(
200  SION_NOT_SUCCESS, _SION_ERROR_RETURN, "sion_generic_register_gathervr_cb: invalid sion_apidesc %d", aid);
201  }
202 
203  if (sion_apidesc->gathervr_cb != NULL) {
204  return _sion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
205  "sion_generic_register_gathervr_cb: gathervr_cb already registered for apiid=%d", aid);
206  }
207  sion_apidesc->gathervr_cb = gathervr_cb;
208 
209  _sion_generic_update_api_level(sion_apidesc);
210 
211  DPRINTFP((2, "sion_generic_register_gathervr_cb", _SION_DEFAULT_RANK, "gathervr_cb registered for apiid=%s (%d)\n",
212  sion_apidesc->name, aid));
213 
214  return rc;
215 }
216 
217 int sion_generic_register_scatterr_cb(int aid, int scatterr_cb(void *, void *, void *, int, int, int))
218 {
219  _sion_generic_apidesc *sion_apidesc;
220  int rc = SION_SUCCESS;
221 
222  if ((aid < 0) || (_sion_vcdtype(aid) != SION_APIDESCRIPTOR) || !(sion_apidesc = _sion_vcdtovcon(aid))) {
223  return _sion_errorprint(
224  SION_NOT_SUCCESS, _SION_ERROR_RETURN, "sion_generic_register_scatterr_cb: invalid sion_apidesc %d", aid);
225  }
226 
227  if (sion_apidesc->scatterr_cb != NULL) {
228  return _sion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
229  "sion_generic_register_scatterr_cb: scatterr_cb already registered for apiid=%d", aid);
230  }
231  sion_apidesc->scatterr_cb = scatterr_cb;
232 
233  _sion_generic_update_api_level(sion_apidesc);
234 
235  DPRINTFP((2, "sion_generic_register_scatterr_cb", _SION_DEFAULT_RANK, "scatterr_cb registered for apiid=%s (%d)\n",
236  sion_apidesc->name, aid));
237 
238  return rc;
239 }
240 
241 int sion_generic_register_scattervr_cb(int aid, int scattervr_cb(void *, void *, void *, int, int *, int, int))
242 {
243  _sion_generic_apidesc *sion_apidesc;
244  int rc = SION_SUCCESS;
245 
246  if ((aid < 0) || (_sion_vcdtype(aid) != SION_APIDESCRIPTOR) || !(sion_apidesc = _sion_vcdtovcon(aid))) {
247  return _sion_errorprint(
248  SION_NOT_SUCCESS, _SION_ERROR_RETURN, "sion_generic_register_scattervr_cb: invalid sion_apidesc %d", aid);
249  }
250 
251  if (sion_apidesc->scattervr_cb != NULL) {
252  return _sion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
253  "sion_generic_register_scattervr_cb: scattervr_cb already registered for apiid=%d", aid);
254  }
255  sion_apidesc->scattervr_cb = scattervr_cb;
256 
257  _sion_generic_update_api_level(sion_apidesc);
258 
259  DPRINTFP((2, "sion_generic_register_scattervr_cb", _SION_DEFAULT_RANK, "scattervr_cb registered for apiid=%s (%d)\n",
260  sion_apidesc->name, aid));
261 
262  return rc;
263 }
264 
266  int64_t gather_execute_cb(const void *, int64_t, void *, int, int, int, int, int64_t process_cb(const void *, int64_t *, int),
267  void *, bool spec_iterator_cb(void *, int64_t *)))
268 {
269  _sion_generic_apidesc *sion_apidesc;
270  int rc = SION_SUCCESS;
271 
272  if ((aid < 0) || (_sion_vcdtype(aid) != SION_APIDESCRIPTOR) || !(sion_apidesc = _sion_vcdtovcon(aid))) {
273  return _sion_errorprint(
274  SION_NOT_SUCCESS, _SION_ERROR_RETURN, "sion_generic_register_gather_and_execute_cb: invalid sion_apidesc %d", aid);
275  }
276 
277  if (sion_apidesc->gather_execute_cb != NULL) {
278  return _sion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
279  "sion_generic_register_gather_and_execute_cb: scattervr_cb already registered for apiid=%d", aid);
280  }
281  sion_apidesc->gather_execute_cb = gather_execute_cb;
282 
283  _sion_generic_update_api_level(sion_apidesc);
284 
285  DPRINTFP((2, "sion_generic_register_gather_and_execute_cb", _SION_DEFAULT_RANK,
286  "gather_execute_cb registered for apiid=%s (%d)\n", sion_apidesc->name, aid));
287 
288  return rc;
289 }
290 
292  int64_t execute_scatter_cb(void *, int64_t, void *, int, int, int, int, int64_t process_cb(void *, int64_t *, int), void *,
293  bool spec_iterator_cb(void *, int64_t *)))
294 {
295  _sion_generic_apidesc *sion_apidesc;
296  int rc = SION_SUCCESS;
297 
298  if ((aid < 0) || (_sion_vcdtype(aid) != SION_APIDESCRIPTOR) || !(sion_apidesc = _sion_vcdtovcon(aid))) {
299  return _sion_errorprint(
300  SION_NOT_SUCCESS, _SION_ERROR_RETURN, "sion_generic_register_execute_and_scatter_cb: invalid sion_apidesc %d", aid);
301  }
302 
303  if (sion_apidesc->execute_scatter_cb != NULL) {
304  return _sion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
305  "sion_generic_register_execute_and_scatter_cb: scattervr_cb already registered for apiid=%d", aid);
306  }
307  sion_apidesc->execute_scatter_cb = execute_scatter_cb;
308 
309  DPRINTFP((2, "sion_generic_register_execute_and_scatter_cb", _SION_DEFAULT_RANK,
310  "gather_execute_cb registered for apiid=%s (%d)\n", sion_apidesc->name, aid));
311 
312  return rc;
313 }
314 
315 int sion_generic_register_get_multi_filename_cb(int aid, char *get_multi_filename_cb(const char *, int))
316 {
317  _sion_generic_apidesc *sion_apidesc;
318  int rc = 0;
319 
320  if ((aid < 0) || (_sion_vcdtype(aid) != SION_APIDESCRIPTOR) || !(sion_apidesc = _sion_vcdtovcon(aid))) {
321  return _sion_errorprint(-1, _SION_ERROR_RETURN, "sion_generic_register_get_multi_filename_cb: invalid sion_apidesc %d", aid);
322  }
323 
324  if (sion_apidesc->get_multi_filename_cb != NULL) {
325  return _sion_errorprint(-1, _SION_ERROR_RETURN,
326  "sion_generic_register_get_multi_filename_cb: get_multi_filename_cb already registered for apiid=%d", aid);
327  }
328  sion_apidesc->get_multi_filename_cb = get_multi_filename_cb;
329 
330  _sion_generic_update_api_level(sion_apidesc);
331 
332  DPRINTFP((2, "sion_generic_register_get_multi_filename_cb", -1, "get_multi_filename_cb registered for apiid=%s (%d)\n",
333  sion_apidesc->name, aid));
334 
335  return rc;
336 }
337 
338 int sion_generic_register_get_capability_cb(int aid, int get_capability_cb(void *))
339 {
340  _sion_generic_apidesc *sion_apidesc;
341  int rc = SION_SUCCESS;
342 
343  if ((aid < 0) || (_sion_vcdtype(aid) != SION_APIDESCRIPTOR) || !(sion_apidesc = _sion_vcdtovcon(aid))) {
344  return _sion_errorprint(
345  SION_NOT_SUCCESS, _SION_ERROR_RETURN, "sion_generic_register_get_capability_cb: invalid sion_apidesc %d", aid);
346  }
347 
348  if (sion_apidesc->get_capability_cb != NULL) {
349  return _sion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
350  "sion_generic_register_get_capability_cb: get_capability_cb already registered for apiid=%d", aid);
351  }
352  sion_apidesc->get_capability_cb = get_capability_cb;
353 
354  _sion_generic_update_api_level(sion_apidesc);
355 
356  DPRINTFP((2, "sion_generic_register_get_capability_cb", _SION_DEFAULT_RANK, "get_capability_cb registered for apiid=%s (%d)\n",
357  sion_apidesc->name, aid));
358 
359  return rc;
360 }
361 
362 int sion_generic_paropen(int aid, const char *fname, const char *file_mode, int64_t *chunksize, int32_t *fsblksize,
363  void *gcommgroup, int grank, int gsize, int *filenumber, int *numfiles, const int *lrank, const int *lsize, FILE **fileptr,
364  char **newfname)
365 {
366  int sid;
367  _sion_flags_store *flags_store = _sion_parse_flags(file_mode);
368  if (!flags_store) {
369  return _sion_errorprint(
370  SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_paropen: could not parse file mode in %s, aborting ...\n", file_mode);
371  }
372  sid = _sion_generic_paropen(aid, fname, flags_store, chunksize, fsblksize, gcommgroup, grank, gsize, filenumber, numfiles,
373  lrank, lsize, fileptr, newfname);
374  _sion_flags_destroy_store(&flags_store);
375  return sid;
376 }
377 
378 int _sion_generic_paropen(int aid, const char *fname, const _sion_flags_store *flags_store, int64_t *chunksize,
379  int32_t *fsblksize, void *gcommgroup, int grank, int gsize, int *filenumber, int *numfiles, const int *lrank, const int *lsize,
380  FILE **fileptr, char **newfname)
381 {
382  int rc, sid = SION_ID_UNDEF;
383  int32_t lfsblksize;
384  int64_t lchunksize;
385  int help_globalrank;
386  char *nfname = NULL;
387  _sion_filedesc *sion_filedesc;
388  _sion_generic_apidesc *sion_apidesc;
389  _sion_generic_gendata *sion_gendata;
390 
391  DPRINTFTS(grank, "enter sion_generic_paropen");
392  DPRINTFP((1, "sion_generic_paropen", grank,
393  "enter generic parallel open of FILE %s (global: %d of %d, local: %d of %d, file: %d of %d )\n", fname, grank, gsize, *lrank,
394  *lsize, *filenumber, *numfiles));
395 
396  if ((aid < 0) || (_sion_vcdtype(aid) != SION_APIDESCRIPTOR) || !(sion_apidesc = _sion_vcdtovcon(aid))) {
397  return _sion_errorprint(
398  SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_register_scattervr_cb: invalid sion_apidesc %d", aid);
399  }
400 
401  if ((sion_apidesc->level != SION_GENERIC_API_LEVEL_STD) && (sion_apidesc->level != SION_GENERIC_API_LEVEL_FULL)) {
402  return _sion_errorprint(SION_ID_NOT_VALID, _SION_ERROR_RETURN,
403  "sion_generic_paropen: API %s not correctly initalized, aborting", sion_apidesc->name);
404  }
405 
406  /* check parameters */
407  if ((grank < 0) || (grank >= gsize)) {
408  return _sion_errorprint(
409  SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_paropen: global rank %d not valid (0..%d)", grank, gsize);
410  }
411 
412 #ifdef HACK_SCALASCA
413  /* hack for scalasca */
414  if (strstr(fname, ".def") != NULL) {
415  lfsblksize = 65536;
416  lchunksize = 65536;
417  } else {
418 #endif
419  lfsblksize = *fsblksize;
420  lchunksize = *chunksize;
421 #ifdef HACK_SCALASCA
422  }
423 #endif
424  DPRINTFP((1, "sion_generic_paropen", grank, "setting fsblksize = %d for file %s\n", lfsblksize, fname));
425 
426  /* create data container */
427  sion_gendata = _sion_generic_alloc_gendata();
428  if (!sion_gendata) {
429  return _sion_errorprint(
430  SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_paropen: problems to alloc gendata, aborting ...\n");
431  }
432  _sion_generic_init_gendata(sion_gendata);
433 
434  sion_gendata->aid = aid;
435  sion_gendata->apidesc = sion_apidesc;
436  sion_gendata->comm_data_global = gcommgroup;
437  sion_gendata->comm_data_local = NULL;
438  sion_gendata->grank = grank;
439  sion_gendata->gsize = gsize;
440 
441  if (flags_store->mask & _SION_FMODE_WRITE) {
442  if (lrank == NULL) {
443  return _sion_errorprint(SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_paropen: No lrank variable given");
444  }
445  if (lsize == NULL) {
446  return _sion_errorprint(SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_paropen: No lsize variable given");
447  }
448  if ((*lrank < 0) || (*lrank >= *lsize)) {
449  return _sion_errorprint(
450  SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_paropen: local rank %d not valid (0..%d)", *lrank, *lsize);
451  }
452  sion_gendata->lrank = *lrank;
453  sion_gendata->lsize = *lsize;
454 
455  if (filenumber == NULL) {
456  return _sion_errorprint(SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_paropen: No filenumber variable given");
457  }
458  if (numfiles == NULL) {
459  return _sion_errorprint(SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_paropen: No numfiles variable given");
460  }
461  if ((*filenumber < 0) || (*filenumber >= *numfiles)) {
462  return _sion_errorprint(
463  SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_paropen: file number %d not valid (0..%d)", *filenumber, *numfiles);
464  }
465  sion_gendata->filenumber = *filenumber;
466  sion_gendata->numfiles = *numfiles;
467 
468  } else if (flags_store->mask & _SION_FMODE_READ) {
469  /* file mode READ */
470 
471  DPRINTFP((1, "sion_generic_paropen", grank, "READ: buddy=%d\n", flags_store->mask & _SION_FMODE_BUDDY));
472 
473  /* get number of files and filenumber */
474  if (!(flags_store->mask & _SION_FMODE_BUDDY)) {
475  rc = _sion_generic_get_and_distribute_info_from_file(sion_gendata, fname);
476  *numfiles = sion_gendata->numfiles;
477  *filenumber = sion_gendata->filenumber;
478  if (rc != SION_SUCCESS) {
479  return _sion_errorprint(SION_ID_NOT_VALID, _SION_ERROR_RETURN,
480  "sion_generic_paropen: error in _sion_generic_get_and_distribute_info_from_file");
481  }
482 
483  } else {
484  /* buddy will determine file layout later, but need local commgroup to optimize file operations */
485 
486  sion_gendata->lrank = *lrank;
487  sion_gendata->lsize = *lsize;
488 
489  if (filenumber == NULL) {
490  return _sion_errorprint(SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_paropen: No filenumber variable given");
491  }
492  if (numfiles == NULL) {
493  return _sion_errorprint(SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_paropen: No numfiles variable given");
494  }
495  if ((*filenumber < 0) || (*filenumber >= *numfiles)) {
496  return _sion_errorprint(SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_paropen: file number %d not valid (0..%d)",
497  *filenumber, *numfiles);
498  }
499  sion_gendata->filenumber = *filenumber;
500  sion_gendata->numfiles = *numfiles;
501  }
502 
503  } else {
504  return _sion_errorprint(SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_paropen: unknown file mode");
505  }
506 
507  /* generate local commgroup according to information from file (read) or parameter (write) */
508  rc = sion_apidesc->create_lcg_cb(&sion_gendata->comm_data_local, sion_gendata->comm_data_global, sion_gendata->grank,
509  sion_gendata->gsize, sion_gendata->lrank, sion_gendata->lsize, sion_gendata->filenumber, sion_gendata->numfiles);
510  if (rc) {
511  return _sion_errorprint(
512  SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_paropen_generic: error in create_local_commgroup callback function");
513  }
514 
515  /* set up parameters of call to generic open */
516  nfname = (sion_apidesc->get_multi_filename_cb ? sion_apidesc->get_multi_filename_cb : _sion_get_multi_filename)(
517  fname, sion_gendata->filenumber);
518  help_globalrank = sion_gendata->grank;
519 
520  sid = _sion_newvcd(NULL, SION_FILEDESCRIPTOR);
521 
522  if (!(flags_store->mask & _SION_FMODE_BUDDY)) {
523  /* STANDARD */
524  /* FIXME: add debug output for flags_store
525  DPRINTFP((1, "sion_generic_paropen", grank, "call parallel open of %d files (current name %s) in %s mode\n", sion_gendata->numfiles, nfname, file_mode)); */
526  DPRINTFP(
527  (1, "sion_generic_paropen", grank, "call parallel open of %d files (current name %s)\n", sion_gendata->numfiles, nfname));
528  rc = _sion_paropen_generic_one_file(sid, nfname, flags_store, &sion_gendata->numfiles, &sion_gendata->filenumber, &lchunksize,
529  &lfsblksize, sion_gendata->lrank, sion_gendata->lsize, &help_globalrank, _SION_INTERNAL_FLAG_NORMAL, fileptr, sion_gendata,
530  NULL);
531  /* FIXME: add debug output for flags_store
532  DPRINTFP((1, "sion_generic_paropen", sion_gendata->grank, "leave parallel open of %d files in %s mode #tasks=%d sid=%d globalrank=%d\n", sion_gendata->numfiles,
533  file_mode, sion_gendata->lsize, sid, sion_gendata->grank)); */
534  DPRINTFP((1, "sion_generic_paropen", sion_gendata->grank, "leave parallel open of %d files #tasks=%d sid=%d globalrank=%d\n",
535  sion_gendata->numfiles, sion_gendata->lsize, sid, sion_gendata->grank));
536 
537  } else {
538  /* branch BUDDY Checkpointing */
539  /* FIXME: add debug output for flags_store
540  DPRINTFP((1, "sion_generic_paropen", grank, "call parallel buddy open of %d files (current name %s) in %s mode\n", sion_gendata->numfiles, nfname, file_mode)); */
541  DPRINTFP((1, "sion_generic_paropen", grank, "call parallel buddy open of %d files (current name %s)\n",
542  sion_gendata->numfiles, nfname));
543  rc = _sion_paropen_generic_buddy(sid, fname, flags_store, &sion_gendata->numfiles, &sion_gendata->filenumber, &lchunksize,
544  &lfsblksize, sion_gendata->lrank, sion_gendata->lsize, &help_globalrank, fileptr, sion_gendata);
545  /* FIXME: add debug output for flags_store
546  DPRINTFP((1, "sion_generic_paropen", sion_gendata->grank, "leave parallel buddy open of %d files in %s mode #tasks=%d sid=%d globalrank=%d rc=%d\n", sion_gendata->numfiles,
547  file_mode, sion_gendata->lsize, sid, sion_gendata->grank, rc)); */
548  DPRINTFP((1, "sion_generic_paropen", sion_gendata->grank,
549  "leave parallel buddy open of %d files #tasks=%d sid=%d globalrank=%d rc=%d\n", sion_gendata->numfiles, sion_gendata->lsize,
550  sid, sion_gendata->grank, rc));
551  }
552 
553  /* test sid and get internal data structure */
554  if ((rc < 0) || (sid < 0) || (_sion_vcdtype(sid) != SION_FILEDESCRIPTOR) || !(sion_filedesc = _sion_vcdtovcon(sid))) {
555  DPRINTFP((1, "sion_generic_paropen", sion_gendata->grank, "invalid rc %d or sion_filedesc %d", rc, sid));
556  return _sion_errorprint(
557  SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_paropen: invalid rc %d or sion_filedesc %d", rc, sid);
558  }
559 
560  if (newfname != NULL) {
561  *newfname = nfname;
562  } else {
563  free(nfname);
564  }
565 
566  /* OUTPUT parameters */
567  *fsblksize = lfsblksize;
568  *chunksize = lchunksize;
569 
570  /* Bug? */
571 
572  DPRINTFP((1, "sion_generic_paropen", grank, "leave parallel open of file %s sid=%d\n", fname, sid));
573  DPRINTFTS(-1, "leave sion_generic_paropen");
574 
575  return sid;
576 }
577 
578 int sion_generic_parclose(int sid)
579 {
580  ONLY_DEBUG(int grank);
581  int rc = SION_SUCCESS;
582  _sion_filedesc *sion_filedesc;
583  _sion_generic_gendata *sion_gendata;
584  _sion_generic_apidesc *sion_apidesc;
585 
586  DPRINTFTS(-1, "enter sion_generic_parclose");
587 
588  if ((sid < 0) || (_sion_vcdtype(sid) != SION_FILEDESCRIPTOR) || !(sion_filedesc = _sion_vcdtovcon(sid))) {
589  return _sion_errorprint(SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_parclose: invalid sion_filedesc %d", sid);
590  }
591  sion_gendata = sion_filedesc->dataptr;
592  sion_apidesc = sion_gendata->apidesc;
593 
594  ONLY_DEBUG(grank = sion_gendata->grank);
595 
596  DPRINTFP((1, "sion_generic_parclose", grank, "enter parallel close of sid %d (%d file)\n", sid, sion_filedesc->nfiles));
597 
598  if (!sion_filedesc->usebuddy) {
599  rc = _sion_parclose_generic(sid, sion_filedesc->rank, sion_filedesc->ntasks, _SION_INTERNAL_FLAG_NORMAL, sion_gendata, NULL);
600  } else {
601  rc = _sion_parclose_generic_buddy(sid, sion_filedesc->rank, sion_filedesc->ntasks, sion_gendata);
602  }
603 
604  if (sion_apidesc->free_lcg_cb && sion_gendata->comm_data_local) {
605  sion_apidesc->free_lcg_cb(sion_gendata->comm_data_local);
606  }
607 
608  _sion_freevcd(sid);
609 
610  sion_apidesc->barrier_cb(sion_gendata->comm_data_global);
611 
612  free(sion_gendata);
613 
614  DPRINTFP((1, "sion_generic_parclose", grank, "leave parallel close of sid %d\n", sid));
615  DPRINTFTS(-1, "leave sion_generic_parclose");
616 
617  return rc;
618 }
619 
620 int sion_generic_paropen_mapped(int aid, char *fname, const char *file_mode, int *numFiles, void *gcommgroup, int grank,
621  int gsize, int *nlocaltasks, int **globalranks, int64_t **chunksizes, int **mapping_filenrs, int **mapping_lranks,
622  int32_t *fsblksize, FILE **fileptr)
623 {
624  int sid;
625  _sion_flags_store *flags_store = _sion_parse_flags(file_mode);
626  if (!flags_store) {
627  return _sion_errorprint(SION_ID_NOT_VALID, _SION_ERROR_RETURN,
628  "sion_generic_paropen_mapped: could not parse file mode in %s, aborting ...\n", file_mode);
629  }
630  sid = _sion_generic_paropen_mapped(aid, fname, flags_store, numFiles, gcommgroup, grank, gsize, nlocaltasks, globalranks,
631  chunksizes, mapping_filenrs, mapping_lranks, fsblksize, fileptr);
632  _sion_flags_destroy_store(&flags_store);
633  return sid;
634 }
635 
636 int _sion_generic_paropen_mapped(int aid, char *fname, const _sion_flags_store *flags_store, int *numFiles, void *gcommgroup,
637  int grank, int gsize, int *nlocaltasks, int **globalranks, int64_t **chunksizes, int **mapping_filenrs, int **mapping_lranks,
638  int32_t *fsblksize, FILE **fileptr)
639 {
640  int rc, sid = SION_ID_UNDEF;
641  _sion_filedesc *sion_filedesc;
642  _sion_generic_apidesc *sion_apidesc;
643  _sion_generic_gendata *sion_gendata;
644 
645  DPRINTFTS(grank, "enter sion_generic_paropen_mapped");
646  DPRINTFP((1, "sion_generic_paropen_mapped", grank,
647  "enter generic parallel mapped open of file %s (global: %d of %d, nlocaltasks %d)\n", fname, grank, gsize, *nlocaltasks));
648 
649  if ((aid < 0) || (_sion_vcdtype(aid) != SION_APIDESCRIPTOR) || !(sion_apidesc = _sion_vcdtovcon(aid))) {
650  return _sion_errorprint(
651  SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_register_scattervr_cb: invalid sion_apidesc %d", aid);
652  }
653 
654  if ((!sion_apidesc->create_lcg_cb) || (!sion_apidesc->free_lcg_cb) || (!sion_apidesc->barrier_cb) || (!sion_apidesc->bcastr_cb)
655  || (!sion_apidesc->gatherr_cb) || (!sion_apidesc->gathervr_cb) || (!sion_apidesc->scatterr_cb)
656  || (!sion_apidesc->scattervr_cb)) {
657  return _sion_errorprint(SION_ID_NOT_VALID, _SION_ERROR_RETURN,
658  "sion_generic_paropen_mapped: API %s not correctly initalized, aborting", sion_apidesc->name);
659  }
660 
661  /* check parameters */
662  if ((grank < 0) || (grank >= gsize)) {
663  return _sion_errorprint(
664  SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_paropen_mapped: global rank %d not valid (0..%d)", grank, gsize);
665  }
666 
667  /* create data container */
668  sion_gendata = _sion_generic_alloc_gendata();
669  if (!sion_gendata) {
670  return _sion_errorprint(
671  SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_paropen_mapped: problems to alloc gendata, aborting ...\n");
672  }
673  _sion_generic_init_gendata(sion_gendata);
674 
675  sion_gendata->aid = aid;
676  sion_gendata->apidesc = sion_apidesc;
677  sion_gendata->comm_data_global = gcommgroup;
678  sion_gendata->grank = grank;
679  sion_gendata->gsize = gsize;
680  sion_gendata->lrank = -1;
681  sion_gendata->lsize = -1;
682  sion_gendata->filenumber = -1;
683  sion_gendata->numfiles = -1;
684  sion_gendata->comm_data_local = NULL;
685 
686  if (!(flags_store->mask & (_SION_FMODE_WRITE | _SION_FMODE_READ))) {
687  return _sion_errorprint(SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_paropen_mapped: unknown file mode");
688  }
689 
690  sid = _sion_newvcd(NULL, SION_FILEDESCRIPTOR);
691 
692  // FIXME: re-enable debug output of file mode
693  // DPRINTFP((1, "sion_generic_paropen_mapped", grank, "enter parallel mapped open in %s mode\n", file_mode));
694  DPRINTFP((1, "sion_generic_paropen_mapped", grank, "enter parallel mapped open\n"));
695  rc = _sion_paropen_mapped_generic(sid, fname, flags_store->mask, numFiles, nlocaltasks, globalranks, chunksizes,
696  mapping_filenrs, mapping_lranks, fsblksize, grank, gsize, _SION_INTERNAL_FLAG_NORMAL, fileptr, sion_gendata);
697  sion_gendata->numfiles = *numFiles;
698  // FIXME: re-enable debug output of file mode
699  // DPRINTFP((1, "sion_generic_paropen_mapped", sion_gendata->grank, "leave parallel open of %d files in %s mode #tasks=%d sid=%d globalrank=%d\n", sion_gendata->numfiles,
700  // file_mode, sion_gendata->lsize, sid, sion_gendata->grank));
701  DPRINTFP(
702  (1, "sion_generic_paropen_mapped", sion_gendata->grank, "leave parallel open of %d files #tasks=%d sid=%d globalrank=%d\n",
703  sion_gendata->numfiles, sion_gendata->lsize, sid, sion_gendata->grank));
704 
705  /* test sid again and get internal data structure */
706  if ((sid < 0) || (_sion_vcdtype(sid) != SION_FILEDESCRIPTOR) || !(sion_filedesc = _sion_vcdtovcon(sid))) {
707  return _sion_errorprint(SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_paropen_mapped: invalid sion_filedesc %d", sid);
708  }
709 
710  /* store additional data */
711  sion_filedesc->dataptr = sion_gendata;
712 
713  /* Bug? */
714 
715  DPRINTFP((1, "sion_generic_paropen_mapped", grank, "leave parallel open of file %s sid=%d\n", fname, sid));
716  DPRINTFTS(-1, "leave sion_generic_paropen_mapped");
717 
718  return rc;
719 }
720 
721 int sion_generic_parclose_mapped(int sid)
722 {
723  int grank, gsize, rc;
724  _sion_filedesc *sion_filedesc;
725  _sion_generic_gendata *sion_gendata;
726 
727  DPRINTFTS(-1, "enter sion_generic_parclose_mapped");
728  if ((sid < 0) || (_sion_vcdtype(sid) != SION_FILEDESCRIPTOR) || !(sion_filedesc = _sion_vcdtovcon(sid))) {
729  return _sion_errorprint(SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_parclose_mapped: invalid sion_filedesc %d", sid);
730  }
731  sion_gendata = sion_filedesc->dataptr;
732 
733  grank = sion_gendata->grank;
734  gsize = sion_gendata->gsize;
735 
736  DPRINTFP((1, "sion_generic_parclose_mapped", grank, "enter parallel close of sid %d\n", sid));
737 
738  DPRINTFP((1, "sion_generic_parclose_mapped", grank, "closing %d file(s)\n", sion_filedesc->nfiles));
739 
740  rc = _sion_parclose_mapped_generic(sid, grank, gsize, sion_gendata);
741 
742  _sion_freevcd(sid);
743 
744  _sion_generic_free_gendata(sion_gendata);
745 
746  DPRINTFP((1, "sion_generic_parclose_mapped", grank, "leave parallel close of sid %d\n", sid));
747  DPRINTFTS(-1, "leave sion_generic_parclose_mapped");
748 
749  return rc;
750 }
751 
752 int _sion_generic_get_and_distribute_info_from_file(_sion_generic_gendata *sion_gendata, const char *fname)
753 {
754  int sid = -1, ntasks = -1, nfiles = -1, t = 0;
755  int rc = SION_SUCCESS;
756  int32_t fsblksize;
757  int *tasksinfile;
758  int mapping_size = -1;
759  int32_t *mapping = NULL;
760  int32_t lpos[2];
761  _sion_generic_apidesc *sion_apidesc;
762 
763  sion_apidesc = sion_gendata->apidesc;
764 
765  if (sion_gendata->grank == 0) {
766  /* open and get mapping of sion file */
767  DPRINTFP((1, "_sion_generic_get_and_distribute_info_from_file", sion_gendata->grank, "before open\n"));
768  sid = _sion_open_read(fname, _SION_FMODE_READ | _SION_FMODE_ANSI, _SION_READ_MASTER_ONLY_OF_MULTI_FILES, &ntasks, &nfiles,
769  NULL, &fsblksize, NULL, NULL);
770  if (sid >= 0) {
771  DPRINTFP((1, "_sion_generic_get_and_distribute_info_from_file", sion_gendata->grank, "after open\n"));
772  rc = sion_get_mapping(sid, &mapping_size, &mapping, &sion_gendata->numfiles);
773  DPRINTFP((1, "_sion_generic_get_and_distribute_info_from_file", sion_gendata->grank, "sion file %d files\n",
774  sion_gendata->numfiles));
775  } else {
776  sion_gendata->numfiles = -1;
777  }
778  }
779 
780  /* each task has to know if more than file was used in sion file */
781  sion_apidesc->bcastr_cb(&sion_gendata->numfiles, sion_gendata->comm_data_global, _SION_INT32, 1, 0);
782 
783  if ((sion_gendata->grank == 0) && (sion_gendata->numfiles > 1)) {
784  if (mapping_size != sion_gendata->gsize) {
785  return _sion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
786  "_sion_generic_get_and_distribute_info_from_file: Incorrect sum of ntasks of files %d <> %d\n", mapping_size,
787  sion_gendata->gsize);
788  }
789  }
790 
791  if (sion_gendata->numfiles < 0) {
792  return _sion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
793  "_sion_generic_get_and_distribute_info_from_file: could not get numfiles from sion file\n");
794  }
795 
796  if (sion_gendata->numfiles > 1) {
797  DPRINTFP((1, "_sion_generic_get_and_distribute_info_from_file", sion_gendata->grank, "before scatter\n"));
798  if (sion_gendata->grank == 0) {
799  for (t = 0; t < mapping_size; t++) {
800  DPRINTFP((1, "_sion_generic_get_and_distribute_info_from_file", sion_gendata->grank, " %d -> (%d,%d)\n", t,
801  mapping[t * 2], mapping[t * 2 + 1]));
802  }
803  }
804 
805  sion_apidesc->scatterr_cb(mapping, lpos, sion_gendata->comm_data_global, _SION_INT32, 2, 0);
806  sion_gendata->filenumber = lpos[0];
807  sion_gendata->lrank = lpos[1];
808  DPRINTFP((1, "_sion_generic_get_and_distribute_info_from_file", sion_gendata->grank, "after scatter filenum+lrank (%d,%d)\n",
809  sion_gendata->filenumber, sion_gendata->lrank));
810 
811  if (sion_gendata->grank == 0) {
812  tasksinfile = malloc(sion_gendata->numfiles * sizeof(int));
813  if (tasksinfile == NULL) {
814  return _sion_errorprint(SION_ID_NOT_VALID, _SION_ERROR_RETURN,
815  "_sion_generic_get_and_distribute_info_from_file: Cannot allocate memory for tasksinfile counter vector");
816  }
817  for (t = 0; t < sion_gendata->numfiles; t++) {
818  tasksinfile[t] = 0; /* init counter */
819  }
820  for (t = 0; t < mapping_size; t++) {
821  tasksinfile[mapping[t * 2]]++; /* count tasks in file */
822  }
823  for (t = 0; t < mapping_size; t++) {
824  mapping[t * 2 + 1] = tasksinfile[mapping[t * 2]]; /* set 2nd value of mapping to lsize */
825  }
826  }
827  sion_apidesc->scatterr_cb(mapping, lpos, sion_gendata->comm_data_global, _SION_INT32, 2, 0);
828  sion_gendata->lsize = lpos[1];
829  DPRINTFP((1, "_sion_generic_get_and_distribute_info_from_file", sion_gendata->grank, "after scatter lsize (%d, %d of %d)\n",
830  sion_gendata->filenumber, sion_gendata->lrank, sion_gendata->lsize));
831 
832  if (sion_gendata->grank == 0) {
833  free(tasksinfile);
834  }
835  /* WARNING: mapping file of sion file is now destroyed and should not be used until close */
836 
837  } else {
838  sion_gendata->filenumber = 0;
839  sion_gendata->lrank = sion_gendata->grank;
840  sion_gendata->lsize = sion_gendata->gsize;
841  DPRINTFP((1, "_sion_generic_get_and_distribute_info_from_file", sion_gendata->grank,
842  "only one file -> filenumber=%d lRank=%d\n", sion_gendata->filenumber, sion_gendata->lrank));
843  }
844 
845  if (sion_gendata->grank == 0) {
846  /* frees also mapping vector */
847  if (sid >= 0) {
848  _sion_close_sid(sid);
849  }
850  }
851 
852  return rc;
853 }
854 
855 int sion_generic_parreinit(int sid, int64_t chunksize)
856 {
857  int grank, gsize, rc;
858  _sion_filedesc *sion_filedesc;
859  _sion_generic_gendata *sion_gendata;
860 
861  if ((sid < 0) || (_sion_vcdtype(sid) != SION_FILEDESCRIPTOR) || !(sion_filedesc = _sion_vcdtovcon(sid))) {
862  return _sion_errorprint(SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_parreinit: invalid sion_filedesc %d", sid);
863  }
864  sion_gendata = sion_filedesc->dataptr;
865 
866  grank = sion_gendata->grank;
867  gsize = sion_gendata->gsize;
868 
869  DPRINTFP((1, "sion_generic_parreinit", grank, "enter parallel reinit of sid %d\n", sid));
870 
871  rc = _sion_parreinit_generic(sid, chunksize, grank, gsize, sion_gendata);
872 
873  DPRINTFP((1, "sion_generic_parreinit", grank, "leave parallel reinit of sid %d\n", sid));
874 
875  return rc;
876 }
int sion_get_mapping(int sid, int *mapping_size, int32_t **mapping, int *numfiles)
Returns pointers to the internal field mapping.
Definition: sion_common.c:126
int sion_generic_register_scatterr_cb(int aid, sion_scatterr_cb cb)
register callback for communication
int sion_generic_register_scattervr_cb(int aid, sion_scattervr_cb cb)
register callback for communication
#define _SION_INT32
a 32 bit signed integer
Definition: sion_const.h:106
int sion_generic_paropen(int aid, const char *fname, const char *file_mode, int64_t *chunksize, int32_t *fsblksize, void *gcommgroup, int grank, int gsize, int *filenumber, int *numfiles, const int *lrank, const int *lsize, FILE **fileptr, char **newfname)
Open a sion file a generic interface.
Definition: sion_generic.c:362
int sion_generic_register_free_local_commgroup_cb(int aid, sion_free_lcg_cb cb)
register callback to free local communication group
int sion_generic_create_api(char *name)
Create new api.
Definition: sion_generic.c:31
int sion_generic_register_barrier_cb(int aid, sion_barrier_cb cb)
register callback for communication
int sion_generic_free_api(int aid)
free new api
Definition: sion_generic.c:59
int sion_generic_register_gather_and_execute_cb(int aid, sion_gather_execute_cb cb)
register callback for communication
int sion_generic_register_gatherr_cb(int aid, sion_gatherr_cb cb)
register callback for communication
int sion_generic_register_gathervr_cb(int aid, sion_gathervr_cb cb)
register callback for communication
int sion_generic_register_bcastr_cb(int aid, sion_bcastr_cb cb)
register callback for communication
int sion_generic_paropen_mapped(int aid, char *fname, const char *file_mode, int *numFiles, void *gcommgroup, int grank, int gsize, int *nlocaltasks, int **globalranks, int64_t **chunksizes, int **mapping_filenrs, int **mapping_lranks, int32_t *fsblksize, FILE **fileptr)
Definition: sion_generic.c:620
int sion_generic_register_create_local_commgroup_cb(int aid, sion_create_lcg_cb cb)
register callback to create local communication group
int sion_generic_register_execute_and_scatter_cb(int aid, sion_execute_scatter_cb cb)
register callback for communication