SIONlib  2.0.0-rc.2
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-2019 **
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 
363 {
364  ONLY_DEBUG(int grank);
365  int rc = SION_SUCCESS;
366  _sion_filedesc *sion_filedesc;
367  _sion_generic_gendata *sion_gendata;
368  _sion_generic_apidesc *sion_apidesc;
369 
370  DPRINTFTS(-1, "enter sion_generic_parclose");
371 
372  if ((sid < 0) || (_sion_vcdtype(sid) != SION_FILEDESCRIPTOR) || !(sion_filedesc = _sion_vcdtovcon(sid))) {
373  return _sion_errorprint(SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_parclose: invalid sion_filedesc %d", sid);
374  }
375  sion_gendata = sion_filedesc->dataptr;
376  sion_apidesc = sion_gendata->apidesc;
377 
378  ONLY_DEBUG(grank = sion_gendata->grank);
379 
380  DPRINTFP((1, "sion_generic_parclose", grank, "enter parallel close of sid %d (%d file)\n", sid, sion_filedesc->nfiles));
381 
382  if (!sion_filedesc->usebuddy) {
383  rc = _sion_parclose_generic(sid, sion_filedesc->rank, sion_filedesc->ntasks, _SION_INTERNAL_FLAG_NORMAL, sion_gendata, NULL);
384  } else {
385  rc = _sion_parclose_generic_buddy(sid, sion_filedesc->rank, sion_filedesc->ntasks, sion_gendata);
386  }
387 
388  if (sion_apidesc->free_lcg_cb && sion_gendata->comm_data_local) {
389  sion_apidesc->free_lcg_cb(sion_gendata->comm_data_local);
390  }
391 
392  _sion_freevcd(sid);
393 
394  sion_apidesc->barrier_cb(sion_gendata->comm_data_global);
395 
396  free(sion_gendata);
397 
398  DPRINTFP((1, "sion_generic_parclose", grank, "leave parallel close of sid %d\n", sid));
399  DPRINTFTS(-1, "leave sion_generic_parclose");
400 
401  return rc;
402 }
403 
404 int sion_generic_paropen_mapped(int aid, char *fname, const char *file_mode, int *numFiles, void *gcommgroup, int grank,
405  int gsize, int *nlocaltasks, int **globalranks, int64_t **chunksizes, int **mapping_filenrs, int **mapping_lranks,
406  int32_t *fsblksize, FILE **fileptr)
407 {
408  int sid;
409  _sion_flags_store *flags_store = _sion_parse_flags(file_mode);
410  if (!flags_store) {
411  return _sion_errorprint(SION_ID_NOT_VALID, _SION_ERROR_RETURN,
412  "sion_generic_paropen_mapped: could not parse file mode in %s, aborting ...\n", file_mode);
413  }
414  sid = _sion_generic_paropen_mapped(aid, fname, flags_store, numFiles, gcommgroup, grank, gsize, nlocaltasks, globalranks,
415  chunksizes, mapping_filenrs, mapping_lranks, fsblksize, fileptr);
416  _sion_flags_destroy_store(&flags_store);
417  return sid;
418 }
419 
420 int _sion_generic_paropen_mapped(int aid, char *fname, const _sion_flags_store *flags_store, int *numFiles, void *gcommgroup,
421  int grank, int gsize, int *nlocaltasks, int **globalranks, int64_t **chunksizes, int **mapping_filenrs, int **mapping_lranks,
422  int32_t *fsblksize, FILE **fileptr)
423 {
424  int rc, sid = SION_ID_UNDEF;
425  _sion_filedesc *sion_filedesc;
426  _sion_generic_apidesc *sion_apidesc;
427  _sion_generic_gendata *sion_gendata;
428 
429  DPRINTFTS(grank, "enter sion_generic_paropen_mapped");
430  DPRINTFP((1, "sion_generic_paropen_mapped", grank,
431  "enter generic parallel mapped open of file %s (global: %d of %d, nlocaltasks %d)\n", fname, grank, gsize, *nlocaltasks));
432 
433  if ((aid < 0) || (_sion_vcdtype(aid) != SION_APIDESCRIPTOR) || !(sion_apidesc = _sion_vcdtovcon(aid))) {
434  return _sion_errorprint(
435  SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_register_scattervr_cb: invalid sion_apidesc %d", aid);
436  }
437 
438  if ((!sion_apidesc->create_lcg_cb) || (!sion_apidesc->free_lcg_cb) || (!sion_apidesc->barrier_cb) || (!sion_apidesc->bcastr_cb)
439  || (!sion_apidesc->gatherr_cb) || (!sion_apidesc->gathervr_cb) || (!sion_apidesc->scatterr_cb)
440  || (!sion_apidesc->scattervr_cb)) {
441  return _sion_errorprint(SION_ID_NOT_VALID, _SION_ERROR_RETURN,
442  "sion_generic_paropen_mapped: API %s not correctly initalized, aborting", sion_apidesc->name);
443  }
444 
445  /* check parameters */
446  if ((grank < 0) || (grank >= gsize)) {
447  return _sion_errorprint(
448  SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_paropen_mapped: global rank %d not valid (0..%d)", grank, gsize);
449  }
450 
451  /* create data container */
452  sion_gendata = _sion_generic_alloc_gendata();
453  if (!sion_gendata) {
454  return _sion_errorprint(
455  SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_paropen_mapped: problems to alloc gendata, aborting ...\n");
456  }
457  _sion_generic_init_gendata(sion_gendata);
458 
459  sion_gendata->aid = aid;
460  sion_gendata->apidesc = sion_apidesc;
461  sion_gendata->comm_data_global = gcommgroup;
462  sion_gendata->grank = grank;
463  sion_gendata->gsize = gsize;
464  sion_gendata->lrank = -1;
465  sion_gendata->lsize = -1;
466  sion_gendata->filenumber = -1;
467  sion_gendata->numfiles = -1;
468  sion_gendata->comm_data_local = NULL;
469 
470  if (!(flags_store->mask & (_SION_FMODE_WRITE | _SION_FMODE_READ))) {
471  return _sion_errorprint(SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_paropen_mapped: unknown file mode");
472  }
473 
474  sid = _sion_newvcd(NULL, SION_FILEDESCRIPTOR);
475 
476  // FIXME: re-enable debug output of file mode
477  // DPRINTFP((1, "sion_generic_paropen_mapped", grank, "enter parallel mapped open in %s mode\n", file_mode));
478  DPRINTFP((1, "sion_generic_paropen_mapped", grank, "enter parallel mapped open\n"));
479  rc = _sion_paropen_mapped_generic(sid, fname, flags_store->mask, numFiles, nlocaltasks, globalranks, chunksizes,
480  mapping_filenrs, mapping_lranks, fsblksize, grank, gsize, _SION_INTERNAL_FLAG_NORMAL, fileptr, sion_gendata);
481  sion_gendata->numfiles = *numFiles;
482  // FIXME: re-enable debug output of file mode
483  // 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,
484  // file_mode, sion_gendata->lsize, sid, sion_gendata->grank));
485  DPRINTFP(
486  (1, "sion_generic_paropen_mapped", sion_gendata->grank, "leave parallel open of %d files #tasks=%d sid=%d globalrank=%d\n",
487  sion_gendata->numfiles, sion_gendata->lsize, sid, sion_gendata->grank));
488 
489  /* test sid again and get internal data structure */
490  if ((sid < 0) || (_sion_vcdtype(sid) != SION_FILEDESCRIPTOR) || !(sion_filedesc = _sion_vcdtovcon(sid))) {
491  return _sion_errorprint(SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_paropen_mapped: invalid sion_filedesc %d", sid);
492  }
493 
494  /* store additional data */
495  sion_filedesc->dataptr = sion_gendata;
496 
497  /* Bug? */
498 
499  DPRINTFP((1, "sion_generic_paropen_mapped", grank, "leave parallel open of file %s sid=%d\n", fname, sid));
500  DPRINTFTS(-1, "leave sion_generic_paropen_mapped");
501 
502  return rc;
503 }
504 
505 int sion_generic_parclose_mapped(int sid)
506 {
507  int grank, gsize, rc;
508  _sion_filedesc *sion_filedesc;
509  _sion_generic_gendata *sion_gendata;
510 
511  DPRINTFTS(-1, "enter sion_generic_parclose_mapped");
512  if ((sid < 0) || (_sion_vcdtype(sid) != SION_FILEDESCRIPTOR) || !(sion_filedesc = _sion_vcdtovcon(sid))) {
513  return _sion_errorprint(SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_parclose_mapped: invalid sion_filedesc %d", sid);
514  }
515  sion_gendata = sion_filedesc->dataptr;
516 
517  grank = sion_gendata->grank;
518  gsize = sion_gendata->gsize;
519 
520  DPRINTFP((1, "sion_generic_parclose_mapped", grank, "enter parallel close of sid %d\n", sid));
521 
522  DPRINTFP((1, "sion_generic_parclose_mapped", grank, "closing %d file(s)\n", sion_filedesc->nfiles));
523 
524  rc = _sion_parclose_mapped_generic(sid, grank, gsize, sion_gendata);
525 
526  _sion_freevcd(sid);
527 
528  _sion_generic_free_gendata(sion_gendata);
529 
530  DPRINTFP((1, "sion_generic_parclose_mapped", grank, "leave parallel close of sid %d\n", sid));
531  DPRINTFTS(-1, "leave sion_generic_parclose_mapped");
532 
533  return rc;
534 }
535 
536 int _sion_generic_get_and_distribute_info_from_file(_sion_generic_gendata *sion_gendata, const char *fname)
537 {
538  int sid = -1, t = 0;
539  int rc = SION_SUCCESS;
540  int *tasksinfile;
541  int mapping_size = -1;
542  int32_t *mapping = NULL;
543  int32_t lpos[2];
544  _sion_generic_apidesc *sion_apidesc;
545 
546  sion_apidesc = sion_gendata->apidesc;
547 
548  if (sion_gendata->grank == 0) {
549  /* open and get mapping of sion file */
550  DPRINTFP((1, "_sion_generic_get_and_distribute_info_from_file", sion_gendata->grank, "before open\n"));
551  sid = _sion_open_read(fname, _SION_READ_MASTER_ONLY_OF_MULTI_FILES, &SION_OPTIONS_INIT);
552  if (sid >= 0) {
553  DPRINTFP((1, "_sion_generic_get_and_distribute_info_from_file", sion_gendata->grank, "after open\n"));
554  rc = sion_get_mapping(sid, &mapping_size, &mapping, &sion_gendata->numfiles);
555  DPRINTFP((1, "_sion_generic_get_and_distribute_info_from_file", sion_gendata->grank, "sion file %d files\n",
556  sion_gendata->numfiles));
557  } else {
558  sion_gendata->numfiles = -1;
559  }
560  }
561 
562  /* each task has to know if more than file was used in sion file */
563  sion_apidesc->bcastr_cb(&sion_gendata->numfiles, sion_gendata->comm_data_global, _SION_INT32, 1, 0);
564 
565  if ((sion_gendata->grank == 0) && (sion_gendata->numfiles > 1)) {
566  if (mapping_size != sion_gendata->gsize) {
567  return _sion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
568  "_sion_generic_get_and_distribute_info_from_file: Incorrect sum of ntasks of files %d <> %d\n", mapping_size,
569  sion_gendata->gsize);
570  }
571  }
572 
573  if (sion_gendata->numfiles < 0) {
574  return _sion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
575  "_sion_generic_get_and_distribute_info_from_file: could not get numfiles from sion file\n");
576  }
577 
578  if (sion_gendata->numfiles > 1) {
579  DPRINTFP((1, "_sion_generic_get_and_distribute_info_from_file", sion_gendata->grank, "before scatter\n"));
580  if (sion_gendata->grank == 0) {
581  for (t = 0; t < mapping_size; t++) {
582  DPRINTFP((1, "_sion_generic_get_and_distribute_info_from_file", sion_gendata->grank, " %d -> (%d,%d)\n", t,
583  mapping[t * 2], mapping[t * 2 + 1]));
584  }
585  }
586 
587  sion_apidesc->scatterr_cb(mapping, lpos, sion_gendata->comm_data_global, _SION_INT32, 2, 0);
588  sion_gendata->filenumber = lpos[0];
589  sion_gendata->lrank = lpos[1];
590  DPRINTFP((1, "_sion_generic_get_and_distribute_info_from_file", sion_gendata->grank, "after scatter filenum+lrank (%d,%d)\n",
591  sion_gendata->filenumber, sion_gendata->lrank));
592 
593  if (sion_gendata->grank == 0) {
594  tasksinfile = malloc(sion_gendata->numfiles * sizeof(int));
595  if (tasksinfile == NULL) {
596  return _sion_errorprint(SION_ID_NOT_VALID, _SION_ERROR_RETURN,
597  "_sion_generic_get_and_distribute_info_from_file: Cannot allocate memory for tasksinfile counter vector");
598  }
599  for (t = 0; t < sion_gendata->numfiles; t++) {
600  tasksinfile[t] = 0; /* init counter */
601  }
602  for (t = 0; t < mapping_size; t++) {
603  tasksinfile[mapping[t * 2]]++; /* count tasks in file */
604  }
605  for (t = 0; t < mapping_size; t++) {
606  mapping[t * 2 + 1] = tasksinfile[mapping[t * 2]]; /* set 2nd value of mapping to lsize */
607  }
608  }
609  sion_apidesc->scatterr_cb(mapping, lpos, sion_gendata->comm_data_global, _SION_INT32, 2, 0);
610  sion_gendata->lsize = lpos[1];
611  DPRINTFP((1, "_sion_generic_get_and_distribute_info_from_file", sion_gendata->grank, "after scatter lsize (%d, %d of %d)\n",
612  sion_gendata->filenumber, sion_gendata->lrank, sion_gendata->lsize));
613 
614  if (sion_gendata->grank == 0) {
615  free(tasksinfile);
616  }
617  /* WARNING: mapping file of sion file is now destroyed and should not be used until close */
618 
619  } else {
620  sion_gendata->filenumber = 0;
621  sion_gendata->lrank = sion_gendata->grank;
622  sion_gendata->lsize = sion_gendata->gsize;
623  DPRINTFP((1, "_sion_generic_get_and_distribute_info_from_file", sion_gendata->grank,
624  "only one file -> filenumber=%d lRank=%d\n", sion_gendata->filenumber, sion_gendata->lrank));
625  }
626 
627  if (sion_gendata->grank == 0) {
628  /* frees also mapping vector */
629  if (sid >= 0) {
630  _sion_close_sid(sid);
631  }
632  }
633 
634  return rc;
635 }
636 
637 int sion_generic_parreinit(int sid, int64_t chunksize)
638 {
639  int grank, gsize, rc;
640  _sion_filedesc *sion_filedesc;
641  _sion_generic_gendata *sion_gendata;
642 
643  if ((sid < 0) || (_sion_vcdtype(sid) != SION_FILEDESCRIPTOR) || !(sion_filedesc = _sion_vcdtovcon(sid))) {
644  return _sion_errorprint(SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_parreinit: invalid sion_filedesc %d", sid);
645  }
646  sion_gendata = sion_filedesc->dataptr;
647 
648  grank = sion_gendata->grank;
649  gsize = sion_gendata->gsize;
650 
651  DPRINTFP((1, "sion_generic_parreinit", grank, "enter parallel reinit of sid %d\n", sid));
652 
653  rc = _sion_parreinit_generic(sid, chunksize, grank, gsize, sion_gendata);
654 
655  DPRINTFP((1, "sion_generic_parreinit", grank, "leave parallel reinit of sid %d\n", sid));
656 
657  return rc;
658 }
659 
661 {
662  sion_generic_options *options = malloc(sizeof(sion_generic_options));
663  if (options) {
664  *options = SION_GENERIC_OPTIONS_INIT;
665  }
666  return options;
667 }
668 
670 {
671  free(options);
672 }
673 
675 {
676  options->chunksize = chunksize;
677 }
678 
680 {
681  options->fsblksize = fsblksize;
682 }
683 
685 {
686  options->keyval_mode = keyval_mode;
687 }
688 
690 {
692 }
693 
695 {
696  options->buddylevel = buddylevel;
697 }
698 
700 {
701  options->collsize = -1;
702 }
703 
705 {
706  options->collsize = size;
707 }
708 
710 {
711  if (options->collsize == 0) {
712  options->collsize = -1;
713  }
714  options->collective_merge = true;
715 }
716 
718 {
719  options->lowlevel_api = lowlevel_api;
720 }
721 
723 {
724  options->endianness = endianness;
725 }
726 
727 int sion_generic_paropen(int aid, const char *fname, sion_open_mode mode, void *gcommgroup, int grank, int gsize, int filenumber,
728  int numfiles, int lrank, int lsize, const sion_generic_options *options_)
729 {
730  sion_generic_options options = (options_) ? *options_ : SION_GENERIC_OPTIONS_INIT;
731 
732  DPRINTFTS(grank, "enter sion_generic_paropen");
733  DPRINTFP((1, "sion_generic_paropen", grank,
734  "enter generic parallel open of FILE %s (global: %d of %d, local: %d of %d, file: %d of %d )\n", fname, grank, gsize, lrank,
735  lsize, filenumber, numfiles));
736 
737  _sion_generic_apidesc *apidesc;
738  if ((aid < 0) || (_sion_vcdtype(aid) != SION_APIDESCRIPTOR) || !(apidesc = _sion_vcdtovcon(aid))) {
739  return _sion_errorprint(SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_register_scattervr_cb: invalid apidesc %d", aid);
740  }
741 
742  if ((apidesc->level != SION_GENERIC_API_LEVEL_STD) && (apidesc->level != SION_GENERIC_API_LEVEL_FULL)) {
743  return _sion_errorprint(
744  SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_paropen: API %s not correctly initalized, aborting", apidesc->name);
745  }
746 
747  /* check parameters */
748  if ((grank < 0) || (grank >= gsize)) {
749  return _sion_errorprint(
750  SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_paropen: global rank %d not valid (0..%d)", grank, gsize);
751  }
752 
753 #ifdef HACK_SCALASCA
754  /* hack for scalasca */
755  if (strstr(fname, ".def") != NULL) {
756  options.fsblksize = 65536;
757  options.chunksize = 65536;
758  }
759 #endif
760  DPRINTFP((1, "sion_generic_paropen", grank, "setting fsblksize = %d for file %s\n", options.fsblksize, fname));
761 
762  /* create data container */
763  _sion_generic_gendata *gendata = _sion_generic_alloc_gendata();
764  if (!gendata) {
765  return _sion_errorprint(
766  SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_paropen: problems to alloc gendata, aborting ...\n");
767  }
768  _sion_generic_init_gendata(gendata);
769 
770  gendata->aid = aid;
771  gendata->apidesc = apidesc;
772  gendata->comm_data_global = gcommgroup;
773  gendata->comm_data_local = NULL;
774  gendata->grank = grank;
775  gendata->gsize = gsize;
776 
777  if (mode == SION_OPEN_WRITE) {
778  if ((lrank < 0) || (lrank >= lsize)) {
779  return _sion_errorprint(
780  SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_paropen: local rank %d not valid (0..%d)", lrank, lsize);
781  }
782  gendata->lrank = lrank;
783  gendata->lsize = lsize;
784 
785  if ((filenumber < 0) || (filenumber >= numfiles)) {
786  return _sion_errorprint(
787  SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_paropen: file number %d not valid (0..%d)", filenumber, numfiles);
788  }
789  gendata->filenumber = filenumber;
790  gendata->numfiles = numfiles;
791 
792  } else if (mode == SION_OPEN_READ) {
793  /* file mode READ */
794 
795  DPRINTFP((1, "sion_generic_paropen", grank, "READ: buddylevel=%d\n", options.buddylevel));
796 
797  /* get number of files and filenumber */
798  if (!options.buddylevel) {
799  int rc = _sion_generic_get_and_distribute_info_from_file(gendata, fname);
800  if (rc != SION_SUCCESS) {
801  return _sion_errorprint(SION_ID_NOT_VALID, _SION_ERROR_RETURN,
802  "sion_generic_paropen: error in _sion_generic_get_and_distribute_info_from_file");
803  }
804  } else {
805  /* buddy will determine file layout later, but need local commgroup to optimize file operations */
806 
807  gendata->lrank = lrank;
808  gendata->lsize = lsize;
809 
810  if ((filenumber < 0) || (filenumber >= numfiles)) {
811  return _sion_errorprint(
812  SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_paropen: file number %d not valid (0..%d)", filenumber, numfiles);
813  }
814  gendata->filenumber = filenumber;
815  gendata->numfiles = numfiles;
816  }
817 
818  } else {
819  return _sion_errorprint(SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_paropen: unknown file mode");
820  }
821 
822  /* generate local commgroup according to information from file (read) or parameter (write) */
823  int rc = apidesc->create_lcg_cb(&gendata->comm_data_local, gendata->comm_data_global, gendata->grank, gendata->gsize,
824  gendata->lrank, gendata->lsize, gendata->filenumber, gendata->numfiles);
825  if (rc) {
826  return _sion_errorprint(
827  SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_paropen_generic: error in create_local_commgroup callback function");
828  }
829 
830  /* set up parameters of call to generic open */
831  char *nfname =
832  (apidesc->get_multi_filename_cb ? apidesc->get_multi_filename_cb : _sion_get_multi_filename)(fname, gendata->filenumber);
833 
834  int sid = _sion_newvcd(NULL, SION_FILEDESCRIPTOR);
835 
836  if (!options.buddylevel) {
837  /* STANDARD */
838  /* FIXME: add debug output for flags_store
839  DPRINTFP((1, "sion_generic_paropen", grank, "call parallel open of %d files (current name %s) in %s mode\n", gendata->numfiles, nfname, file_mode)); */
840  DPRINTFP((1, "sion_generic_paropen", grank, "call parallel open of %d files (current name %s)\n", gendata->numfiles, nfname));
841  rc = _sion_paropen_generic_one_file(sid, nfname, mode, gendata->numfiles, gendata->filenumber, gendata->lrank, gendata->lsize,
842  gendata->grank, _SION_INTERNAL_FLAG_NORMAL, gendata, NULL, &options);
843  /* FIXME: add debug output for flags_store
844  DPRINTFP((1, "sion_generic_paropen", gendata->grank, "leave parallel open of %d files in %s mode #tasks=%d sid=%d globalrank=%d\n", gendata->numfiles,
845  file_mode, gendata->lsize, sid, gendata->grank)); */
846  DPRINTFP((1, "sion_generic_paropen", gendata->grank, "leave parallel open of %d files #tasks=%d sid=%d globalrank=%d\n",
847  gendata->numfiles, gendata->lsize, sid, gendata->grank));
848 
849  } else {
850  /* branch BUDDY Checkpointing */
851  /* FIXME: add debug output for flags_store
852  DPRINTFP((1, "sion_generic_paropen", grank, "call parallel buddy open of %d files (current name %s) in %s mode\n", gendata->numfiles, nfname, file_mode)); */
853  DPRINTFP(
854  (1, "sion_generic_paropen", grank, "call parallel buddy open of %d files (current name %s)\n", gendata->numfiles, nfname));
855  rc = _sion_paropen_generic_buddy(sid, fname, mode, gendata->numfiles, gendata->filenumber, gendata->lrank, gendata->lsize,
856  gendata->grank, gendata, &options);
857  /* FIXME: add debug output for flags_store
858  DPRINTFP((1, "sion_generic_paropen", gendata->grank, "leave parallel buddy open of %d files in %s mode #tasks=%d sid=%d globalrank=%d rc=%d\n", gendata->numfiles,
859  file_mode, gendata->lsize, sid, gendata->grank, rc)); */
860  DPRINTFP(
861  (1, "sion_generic_paropen", gendata->grank, "leave parallel buddy open of %d files #tasks=%d sid=%d globalrank=%d rc=%d\n",
862  gendata->numfiles, gendata->lsize, sid, gendata->grank, rc));
863  }
864 
865  /* test sid and get internal data structure */
866  _sion_filedesc *filedesc;
867  if ((rc < 0) || (sid < 0) || (_sion_vcdtype(sid) != SION_FILEDESCRIPTOR) || !(filedesc = _sion_vcdtovcon(sid))) {
868  DPRINTFP((1, "sion_generic_paropen", gendata->grank, "invalid rc %d or filedesc %d", rc, sid));
869  return _sion_errorprint(SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_generic_paropen: invalid rc %d or filedesc %d", rc, sid);
870  }
871 
872  free(nfname);
873 
874  /* Bug? */
875 
876  DPRINTFP((1, "sion_generic_paropen", grank, "leave parallel open of file %s sid=%d\n", fname, sid));
877  DPRINTFTS(-1, "leave sion_generic_paropen");
878 
879  return sid;
880 }
sion_lowlevel_api
specifies a low-level API to use for file system access
Definition: sion_enums.h:19
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:109
int sion_generic_register_scatterr_cb(int aid, sion_scatterr_cb cb)
register callback for communication
int sion_generic_paropen(int aid, const char *fname, sion_open_mode mode, void *gcommgroup, int grank, int gsize, int filenumber, int numfiles, int lrank, int lsize, const sion_generic_options *options_)
Open a SIONlib file through a generic interface.
Definition: sion_generic.c:727
void sion_generic_options_set_collective_size(sion_generic_options *options, int32_t size)
Enable collective I/O.
Definition: sion_generic.c:704
void sion_generic_options_delete(sion_generic_options *options)
Delete an instance of sion_generic_options
Definition: sion_generic.c:669
int sion_generic_register_scattervr_cb(int aid, sion_scattervr_cb cb)
register callback for communication
void sion_generic_options_set_collective(sion_generic_options *options)
Enable collective I/O.
Definition: sion_generic.c:699
#define _SION_INT32
a 32 bit signed integer
Definition: sion_const.h:115
void sion_generic_options_set_buddy(sion_generic_options *options)
Enable buddy checkpointing mechanism.
Definition: sion_generic.c:689
void sion_generic_options_set_collective_merge(sion_generic_options *options)
Use collective merging.
Definition: sion_generic.c:709
void sion_generic_options_set_endianness(sion_generic_options *options, sion_endianness endianness)
Set the endianness for the contents of a container.
Definition: sion_generic.c:722
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
void sion_generic_options_set_keyval_mode(sion_generic_options *options, sion_keyval_mode keyval_mode)
Set the key-value mode to use for a container.
Definition: sion_generic.c:684
void sion_generic_options_set_fsblksize(sion_generic_options *options, int32_t fsblksize)
Set the file system block size to assume.
Definition: sion_generic.c:679
void sion_generic_options_set_chunksize(sion_generic_options *options, int64_t chunksize)
Set the chunk size of a logical file in the container.
Definition: sion_generic.c:674
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
open the file for reading only
Definition: sion_enums.h:29
int sion_generic_register_gatherr_cb(int aid, sion_gatherr_cb cb)
register callback for communication
sion_keyval_mode
specifies whether to use SIONlib's key-value mechanism for accessing file content and if so in what m...
Definition: sion_enums.h:35
int sion_generic_parclose(int sid)
Close a SIONlib file.
Definition: sion_generic.c:362
sion_generic_options * sion_generic_options_new()
Allocates and initializes an instance of sion_generic_options
Definition: sion_generic.c:660
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
sion_endianness
declares the endianness of user data written to a file
Definition: sion_enums.h:63
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:404
sion_open_mode
specifies for what type of access to open a file
Definition: sion_enums.h:27
void sion_generic_options_set_buddylevel(sion_generic_options *options, int32_t buddylevel)
Enable buddy checkpointing mechanism.
Definition: sion_generic.c:694
struct sion_generic_options sion_generic_options
Holds non-essential arguments for sion_generic_paropen().
Definition: sion_generic.h:253
int sion_generic_register_create_local_commgroup_cb(int aid, sion_create_lcg_cb cb)
register callback to create local communication group
void sion_generic_options_set_lowlevel_api(sion_generic_options *options, sion_lowlevel_api lowlevel_api)
Set the low-level API to use for opening a container.
Definition: sion_generic.c:717
open the file for writing only
Definition: sion_enums.h:31
int sion_generic_register_execute_and_scatter_cb(int aid, sion_execute_scatter_cb cb)
register callback for communication