SIONlib  2.0.0-rc.3
Scalable I/O library for parallel access to task-local files
sion_common.c
1 /****************************************************************************
2 ** SIONLIB http://www.fz-juelich.de/jsc/sionlib **
3 *****************************************************************************
4 ** Copyright (c) 2008-2021 **
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 <assert.h>
13 #include <inttypes.h>
14 #include <stdint.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 
18 #include "sion_buffer.h"
19 #include "sion_common.h"
20 #include "sion_const.h"
21 #include "sion_debug.h"
22 #include "sion_dup.h"
23 #include "sion_error_handler.h"
24 #include "sion_fd.h"
25 #include "sion_file.h"
26 #include "sion_filedesc.h"
27 #include "sion_hints.h"
28 #include "sion_internal.h"
29 #include "sion_internal_positioning.h"
30 #include "sion_internal_seek.h"
31 #include "sion_lock.h"
32 
33 sion_io_stat_t *sion_get_io_info_buddy(int sid, int roles, int flag);
34 
35 int sion_get_locations(int sid, int *ntasks, int *maxchunks, int64_t *globalskip, int64_t *start_of_varheader,
36  int64_t **sion_chunksizes, int64_t **sion_globalranks, int64_t **sion_blockcount, int64_t **sion_blocksizes)
37 {
38  int rc = SION_SUCCESS;
39  _sion_filedesc *sion_filedesc;
40 #ifdef SION_SERIAL_MASTER
41  _sion_filedesc *help;
42 #endif
43 
44  if ((sid < 0) || (_sion_vcdtype(sid) != SION_FILEDESCRIPTOR) || !(sion_filedesc = _sion_vcdtovcon(sid))) {
45  return _sion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN, "invalid sion_filedesc, aborting %d ...\n", sid);
46  }
47  DPRINTFP((1, "sion_get_locations", -1, "enter\n"));
48 
49 #ifdef SION_SERIAL_MASTER
50  if ((sion_filedesc->state == SION_FILESTATE_SEROPENMASTER) && (sion_filedesc->all_blockcount == NULL)) {
51  int i;
52 
53  /* collect info from sub files */
54  _sion_alloc_filedesc_arrays(sion_filedesc);
55  _sion_alloc_filedesc_block_arrays_only(sion_filedesc);
56 
57  for (i = 0; i < sion_filedesc->ntasks; i++) {
58  int lfile = sion_filedesc->mapping[i * 2 + 0];
59  int lrank = sion_filedesc->mapping[i * 2 + 1];
60  sion_filedesc->all_chunksizes[i] = sion_filedesc->multifiles[lfile]->all_chunksizes[lrank];
61  sion_filedesc->all_globalranks[i] = sion_filedesc->multifiles[lfile]->all_globalranks[lrank];
62  sion_filedesc->all_blockcount[i] = sion_filedesc->multifiles[lfile]->all_blockcount[lrank];
63  }
64  for (i = 0; i < sion_filedesc->ntasks; i++) {
65  int lfile = sion_filedesc->mapping[i * 2 + 0];
66  int lrank = sion_filedesc->mapping[i * 2 + 1];
67  int blknum;
68  help = sion_filedesc->multifiles[lfile];
69  for (blknum = 0; blknum < sion_filedesc->all_blockcount[i]; blknum++) {
70  sion_filedesc->all_blocksizes[sion_filedesc->ntasks * blknum + i] = help->all_blocksizes[help->ntasks * blknum + lrank];
71  }
72  }
73  }
74 #endif
75 
76  *ntasks = sion_filedesc->ntasks;
77  *maxchunks = sion_filedesc->maxusedchunks;
78  *sion_chunksizes = sion_filedesc->all_chunksizes;
79  *sion_globalranks = sion_filedesc->all_globalranks;
80  *sion_blockcount = sion_filedesc->all_blockcount;
81  *sion_blocksizes = sion_filedesc->all_blocksizes;
82  *globalskip = sion_filedesc->globalskip;
83  *start_of_varheader = sion_filedesc->start_of_varheader;
84 
85  DPRINTFP((1, "sion_get_locations", -1, "leave\n"));
86 
87  return rc;
88 }
89 
90 int sion_get_current_location(int sid, int *currentchunknr, int64_t *currentpos, int *maxchunks, int64_t **chunksizes)
91 {
92  int rc = SION_SUCCESS;
93  _sion_filedesc *sion_filedesc;
94 
95  if ((sid < 0) || (_sion_vcdtype(sid) != SION_FILEDESCRIPTOR) || !(sion_filedesc = _sion_vcdtovcon(sid))) {
96  return _sion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN, "invalid sion_filedesc, aborting %d ...\n", sid);
97  }
98  DPRINTFP((1, "sion_get_current_location", -1, "enter\n"));
99 
100  *currentchunknr = sion_filedesc->currentblocknr;
101  *currentpos = sion_filedesc->currentpos - (sion_filedesc->startpos + sion_filedesc->currentblocknr * sion_filedesc->globalskip);
102  *maxchunks = sion_filedesc->lastchunknr + 1;
103  *chunksizes = sion_filedesc->blocksizes;
104 
105  DPRINTFP((1, "sion_get_current_location", -1, "leave\n"));
106  return rc;
107 }
108 
109 int sion_get_mapping(int sid, int *mapping_size, int32_t **mapping, int *numfiles)
110 {
111  int rc = SION_SUCCESS;
112  _sion_filedesc *sion_filedesc;
113 
114  if ((sid < 0) || (_sion_vcdtype(sid) != SION_FILEDESCRIPTOR) || !(sion_filedesc = _sion_vcdtovcon(sid))) {
115  return _sion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN, "invalid sion_filedesc, aborting %d ...\n", sid);
116  }
117  DPRINTFP((1, "sion_get_mapping", -1, "enter\n"));
118 
119  if (sion_filedesc->state == SION_FILESTATE_PAROPENMAPPEDMASTER) {
120  *mapping_size = 0;
121  for (int filenr = 0; filenr < sion_filedesc->nfiles; filenr++) {
122  *mapping_size += sion_filedesc->multifiles[filenr]->nlocaltasksinfile;
123  }
124  *numfiles = sion_filedesc->nfiles;
125  *mapping = malloc(2 * sizeof(int32_t) * *mapping_size);
126  if (*mapping) {
127  int task = 0;
128  for (int filenr = 0; filenr < sion_filedesc->nfiles; filenr++) {
129  _sion_filedesc *filedesc_sub = sion_filedesc->multifiles[filenr];
130  for (int ltask = 0; ltask < filedesc_sub->nlocaltasksinfile; ltask++) {
131  (*mapping)[2 * task] = filenr;
132  (*mapping)[2 * task + 1] = filedesc_sub->all_localranks[ltask];
133  task++;
134  }
135  }
136  assert(task == *mapping_size);
137  }
138  } else {
139  if (sion_filedesc->mapping_size > 0) {
140  *mapping_size = sion_filedesc->mapping_size;
141  *mapping = sion_filedesc->mapping;
142  } else {
143  *mapping_size = -1;
144  }
145  *numfiles = sion_filedesc->nfiles;
146  }
147 
148  DPRINTFP((1, "sion_get_mapping", -1, "leave (mapping_size=%d)\n", *mapping_size));
149 
150  return rc;
151 }
152 
154 {
155  _sion_filedesc *sion_filedesc;
156 
157  DPRINTFP((1, "sion_get_file_endianness", -1, "enter (sid=%d)\n", sid));
158 
159  if ((sid < 0) || (_sion_vcdtype(sid) != SION_FILEDESCRIPTOR) || !(sion_filedesc = _sion_vcdtovcon(sid))) {
160  return _sion_errorprint(SION_SIZE_NOT_VALID, _SION_ERROR_RETURN, "invalid sion_filedesc, aborting %d ...\n", sid);
161  }
162 
163  DPRINTFP((1, "sion_get_file_endianness", -1, "leave (sid=%d)\n", sid));
164  /* return endianness of user data */
165  return (sion_filedesc->endianness >> 8) & 1;
166 }
167 
169 {
170  int swap_needed = 0;
171 
172  DPRINTFP((1, "sion_endianness_swap_needed", -1, "enter (sid=%d)\n", sid));
173 
174  swap_needed = (sion_get_file_endianness(sid) != sion_get_endianness());
175 
176  DPRINTFP((1, "sion_endianness_swap_needed", -1, "leave (swap_needed=%d)\n", swap_needed));
177 
178  return swap_needed;
179 }
180 
181 int sion_get_current_locations(int sid, int *ntasks, int64_t **sion_currentpos, int64_t **sion_currentblocknr)
182 {
183  int rc = SION_SUCCESS;
184  _sion_filedesc *sion_filedesc;
185 
186  if ((sid < 0) || (_sion_vcdtype(sid) != SION_FILEDESCRIPTOR) || !(sion_filedesc = _sion_vcdtovcon(sid))) {
187  return _sion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN, "invalid sion_filedesc, aborting %d ...\n", sid);
188  }
189  DPRINTFP((1, "sion_get_current_locations", -1, "enter\n"));
190 
191  *ntasks = sion_filedesc->ntasks;
192  *sion_currentpos = sion_filedesc->all_currentpos;
193  *sion_currentblocknr = sion_filedesc->all_currentblocknr;
194 
195  DPRINTFP((1, "sion_get_current_locations", -1, "leave\n"));
196  return rc;
197 }
198 
199 int sion_get_number_of_files(int sid)
200 {
201  _sion_filedesc *sion_filedesc;
202 
203  if ((sid < 0) || (_sion_vcdtype(sid) != SION_FILEDESCRIPTOR) || !(sion_filedesc = _sion_vcdtovcon(sid))) {
204  return _sion_errorprint(SION_SIZE_NOT_VALID, _SION_ERROR_RETURN, "invalid sion_filedesc, aborting %d ...\n", sid);
205  }
206 
207  return sion_filedesc->nfiles;
208 }
209 
210 int sion_get_filenumber(int sid)
211 {
212  _sion_filedesc *sion_filedesc;
213 
214  if ((sid < 0) || (_sion_vcdtype(sid) != SION_FILEDESCRIPTOR) || !(sion_filedesc = _sion_vcdtovcon(sid))) {
215  return _sion_errorprint(SION_SIZE_NOT_VALID, _SION_ERROR_RETURN, "invalid sion_filedesc, aborting %d ...\n", sid);
216  }
217 
218  return sion_filedesc->filenumber;
219 }
220 
221 int sion_is_serial_opened(int sid)
222 {
223  _sion_filedesc *sion_filedesc;
224 
225  if ((sid < 0) || (_sion_vcdtype(sid) != SION_FILEDESCRIPTOR) || !(sion_filedesc = _sion_vcdtovcon(sid))) {
226  return _sion_errorprint(SION_SIZE_NOT_VALID, _SION_ERROR_RETURN, "invalid sion_filedesc, aborting %d ...\n", sid);
227  }
228 
229  return sion_filedesc->state == SION_FILESTATE_SEROPEN || sion_filedesc->state == SION_FILESTATE_SEROPENRANK
230  || sion_filedesc->state == SION_FILESTATE_SEROPENMASTER;
231 }
232 
233 int sion_using_hints(int sid)
234 {
235  _sion_filedesc *sion_filedesc;
236 
237  if ((sid < 0) || (_sion_vcdtype(sid) != SION_FILEDESCRIPTOR) || !(sion_filedesc = _sion_vcdtovcon(sid))) {
238  return _sion_errorprint(SION_SIZE_NOT_VALID, _SION_ERROR_RETURN, "invalid sion_filedesc, aborting %d ...\n", sid);
239  }
240 
241  return sion_filedesc->usehints;
242 }
243 
244 int64_t sion_get_bytes_written(int sid)
245 {
246  _sion_filedesc *filedesc = _sion_get_filedesc(sid);
247  if (filedesc == NULL) {
248  return _sion_errorprint(SION_SIZE_NOT_VALID, _SION_ERROR_RETURN, "invalid sion_filedesc, aborting %d ...\n", sid);
249  }
250 
251  if (filedesc->mode == SION_FILEMODE_WRITE) {
252  if (filedesc->usebuffer) {
253  _sion_buffer_flush(filedesc);
254  }
255  return filedesc->size;
256  } else {
257  return SION_SIZE_NOT_VALID;
258  }
259 }
260 
261 int64_t sion_get_bytes_read(int sid)
262 {
263  _sion_filedesc *sion_filedesc;
264  int64_t bytes = SION_SIZE_NOT_VALID;
265 
266  if ((sid < 0) || (_sion_vcdtype(sid) != SION_FILEDESCRIPTOR) || !(sion_filedesc = _sion_vcdtovcon(sid))) {
267  return _sion_errorprint(SION_SIZE_NOT_VALID, _SION_ERROR_RETURN, "invalid sion_filedesc, aborting %d ...\n", sid);
268  }
269 
270  if (sion_filedesc->mode == SION_FILEMODE_READ) {
271  int i;
272  sion_filedesc->currentpos = _sion_file_get_position(sion_filedesc->fileptr);
273 
274  bytes = 0;
275  for (i = 0; i < sion_filedesc->currentblocknr; i++) {
276  bytes += sion_filedesc->blocksizes[i];
277  }
278  /* current chunk */
279  bytes += sion_filedesc->currentpos - (sion_filedesc->startpos + sion_filedesc->currentblocknr * sion_filedesc->globalskip);
280  }
281 
282  return bytes;
283 }
284 
285 /* return list of filenames created and the size of their payload, and the task role on this file */
286 sion_io_stat_t *sion_get_io_info(int sid)
287 {
288  return sion_get_io_info_by_spec(sid, SION_ROLE_COLLECTOR | SION_ROLE_WRITER | SION_ROLE_NOWRITER, SION_GET_IO_INFO_FLAG_NONE);
289 }
290 
291 /* return list of filenames created and the size of their payload, and the task role on this file */
292 sion_io_stat_t *sion_get_io_info_by_spec(int sid, int roles, int flag)
293 {
294  _sion_filedesc *filedesc = _sion_get_filedesc(sid);
295  if (filedesc == NULL) {
296  _sion_errorprint(0, _SION_ERROR_RETURN, "invalid sion_filedesc, aborting %d ...\n", sid);
297  return NULL;
298  }
299 
300  /* branch to buddy CP */
301  if (filedesc->usebuddy) {
302  return sion_get_io_info_buddy(sid, roles, flag);
303  } else {
304  return NULL;
305  }
306 }
307 
308 int sion_free_io_info(sion_io_stat_t *p)
309 {
310  return _sion_free_io_info(p);
311 }
312 
313 size_t sion_write(const void *data, size_t size, size_t nitems, int sid)
314 {
315  int64_t bytes_to_write, bbytes;
316  _sion_filedesc *sion_filedesc;
317  size_t rc = 0, frc;
318  void *bdata;
319 
320  DPRINTFP((1, __func__, -1, "enter size=%ld nitems=%ld\n", (long)size, (long)nitems));
321 
322  if ((sid < 0) || (_sion_vcdtype(sid) != SION_FILEDESCRIPTOR) || !(sion_filedesc = _sion_vcdtovcon(sid))) {
323  return _sion_errorprint(SION_ANSI_SIZE_NOT_VALID, _SION_ERROR_RETURN, "invalid sion_filedesc, aborting %d ...\n", sid);
324  }
325 
326  _sion_check_on_collective_mode(sion_filedesc);
327 
328  bytes_to_write = size * nitems;
329 
330  /* buffering? */
331  if (sion_filedesc->usebuffer) {
332  const char *data_ptr = data;
333  /* buffer data */
334  int64_t bytes_buffered = _sion_buffer_push(sion_filedesc, data_ptr, bytes_to_write);
335  bytes_to_write -= bytes_buffered;
336  data_ptr += bytes_buffered;
337 
338  while (bytes_to_write > 0) {
339  /* flush filled buffer to file, not all data could be bufferd */
340  _sion_buffer_get_data_ptr(sion_filedesc, &bdata, &bbytes);
341  frc = _sion_write_multi_chunk(sion_filedesc, bdata, bbytes);
342  if (frc != bbytes) {
343  return _sion_errorprint_on_rank(SION_ANSI_SIZE_NOT_VALID, _SION_ERROR_RETURN, sion_filedesc->rank,
344  "could not write data (%d bytes) to file (sid=%d) ...", (int)bbytes, sid);
345  }
346 
347  /* next try to push data into buffer */
348  bytes_buffered = _sion_buffer_push(sion_filedesc, data_ptr, bytes_to_write);
349  bytes_to_write -= bytes_buffered;
350  data_ptr += bytes_buffered;
351  }
352  /* return code: bytes stored */
353  rc = size ? nitems : 0;
354 
355  } else {
356  /* normal write */
357  frc = _sion_write_multi_chunk(sion_filedesc, data, bytes_to_write);
358  if (frc != bytes_to_write) {
359  return _sion_errorprint_on_rank(SION_ANSI_SIZE_NOT_VALID, _SION_ERROR_RETURN, sion_filedesc->rank,
360  "could not write data (%d bytes) to file (frc=%d sid=%d) ...", (int)bytes_to_write, (int)frc, sid);
361  }
362  rc = size ? nitems : 0;
363  }
364 
365  DPRINTFP((1, __func__, -1, "leave rc=%ld\n", (long)rc));
366  return rc;
367 }
368 
369 size_t sion_fwrite(const void *data, size_t size, size_t nitems, int sid)
370 {
371  return sion_write(data, size, nitems, sid);
372 }
373 
374 size_t sion_read(void *data, size_t size, size_t nitems, int sid)
375 {
376  _sion_filedesc *sion_filedesc;
377  size_t bread = 0;
378 
379  if ((sid < 0) || (_sion_vcdtype(sid) != SION_FILEDESCRIPTOR) || !(sion_filedesc = _sion_vcdtovcon(sid))) {
380  return _sion_errorprint(SION_ANSI_SIZE_NOT_VALID, _SION_ERROR_RETURN, "invalid sion_filedesc, aborting %d ...\n", sid);
381  }
382  if (!data) {
383  /* FIXME: replace SION_ANSI_SIZE_NOT_VALID? */
384  return _sion_errorprint(SION_ANSI_SIZE_NOT_VALID, _SION_ERROR_RETURN, "invalid pointer, aborting %d ...\n", data);
385  }
386 
387  DPRINTFP((1, __func__, -1, "enter\n"));
388  DPRINTFP((4, __func__, -1, " parameter size=%zu nitems=%zu\n", size, nitems));
389 
390  _sion_check_on_collective_mode(sion_filedesc);
391 
392  if (!sion_feof(sid)) {
393  bread = _sion_read_multi_chunk(sion_filedesc, data, size * nitems);
394  DPRINTFP((256, __func__, -1, " _sion_file_read returns %zu\n", bread));
395  }
396 
397  bread = size ? bread / size : 0;
398 
399  DPRINTFP((4, __func__, -1, " return value %zu\n", bread));
400  DPRINTFP((1, __func__, -1, "leave\n"));
401 
402  return bread;
403 }
404 
405 size_t sion_fread(void *data, size_t size, size_t nitems, int sid)
406 {
407  return sion_read(data, size, nitems, sid);
408 }
409 
410 int sion_seek(int sid, int64_t offset, sion_seek_mode whence)
411 {
412  /* TBD: check if not sion_open and multi file */
413  /* TBD: implement sion_open and sion_seek_fp for multi-files */
414 
415  DPRINTFP((1, __func__, -1, " enter seek with sid=%d\n", sid));
416 
417  _sion_filedesc *filedesc = _sion_get_filedesc(sid);
418  if (filedesc == NULL) {
419  return _sion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN, "sion_seek: invalid sion_filedesc, aborting %d ...\n", sid);
420  }
421 
422  /* check state */
423  if ((filedesc->mode != SION_FILEMODE_READ) && (filedesc->mode != SION_FILEMODE_WRITE)) {
424  return _sion_errorprint_on_rank(SION_NOT_SUCCESS, _SION_ERROR_RETURN, filedesc->rank,
425  "sion_seek: unknown file open state !(READ|WRITE), aborting %d ...", sid);
426  }
427  if (filedesc->usebuffer) {
428  _sion_buffer_flush(filedesc);
429  }
430  if ((filedesc->state != SION_FILESTATE_PAROPEN) && (filedesc->state != SION_FILESTATE_SEROPEN)
431  && (filedesc->state != SION_FILESTATE_SEROPENMASTER) && (filedesc->state != SION_FILESTATE_SEROPENRANK)
432  && (filedesc->state != SION_FILESTATE_PAROPENMAPPEDMASTER)) {
433  return _sion_errorprint_on_rank(SION_NOT_SUCCESS, _SION_ERROR_RETURN, filedesc->rank,
434  "sion_seek: unknown file open state !(PAR|SER|SERRANK|MAPPED), aborting %d ...", sid);
435  }
436 
437  int rc;
438  if (filedesc->mode == SION_FILEMODE_READ) { /* READ */
439  rc = _sion_seek_on_current_rank_read(filedesc, offset, whence);
440  } else { /* WRITE */
441  if (filedesc->state == SION_FILESTATE_SEROPENRANK) {
442  return _sion_errorprint_on_rank(SION_NOT_SUCCESS, _SION_ERROR_RETURN, filedesc->rank,
443  "sion_seek: seek not supported for this type (write, sion_open_rank), aborting ...");
444  } else {
445  rc = _sion_seek_on_current_rank_write(filedesc, offset, whence);
446  }
447  }
448 
449  DPRINTFP((1, __func__, -1, "leave seek rc=%d\n", rc));
450  return rc;
451 }
452 
453 int sion_seek_chunk(int sid, int32_t offset, sion_seek_mode whence)
454 {
455  DPRINTFP((1, __func__, -1, " enter seek with sid=%d\n", sid));
456 
457  _sion_filedesc *filedesc = _sion_get_filedesc(sid);
458  if (filedesc == NULL) {
459  return _sion_errorprint(
460  SION_NOT_SUCCESS, _SION_ERROR_RETURN, "sion_seek_chunk: invalid sion_filedesc, aborting %d ...\n", sid);
461  }
462 
463  int32_t new_blocknr;
464  switch (whence) {
465  case SION_SEEK_BEGINNING:
466  new_blocknr = offset;
467  break;
468  case SION_SEEK_CURRENT:
469  new_blocknr = _sion_get_current_chunk_number(filedesc) + offset;
470  break;
471  case SION_SEEK_END:
472  new_blocknr = filedesc->lastchunknr + offset;
473  break;
474  default:
475  return _sion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN, "sion_seek_block: seek mode not supported, aborting ...\n");
476  }
477 
478  if (new_blocknr < 0) {
479  return _sion_errorprint(
480  SION_NOT_SUCCESS, _SION_ERROR_RETURN, "sion_seek_chunk: cannot seek before first block, aborting ...\n");
481  }
482  if (filedesc->mode == SION_FILEMODE_READ && new_blocknr > filedesc->lastchunknr) {
483  return _sion_errorprint(
484  SION_NOT_SUCCESS, _SION_ERROR_RETURN, "sion_seek_chunk: cannot seek past last block in read mode, aborting ...\n");
485  }
486 
487  _sion_apply_hints(filedesc, SION_HINTS_FREE_TYPE_CHUNK);
488  _sion_chunk_sequence sequence = _sion_chunk_sequence_from_filedesc(filedesc);
489  _sion_range chunk = _sion_chunk_sequence_chunk_from_number(&sequence, new_blocknr);
490  filedesc->currentpos = chunk.start;
491  filedesc->currentblocknr = new_blocknr;
492  _sion_apply_hints(filedesc, SION_HINTS_ACCESS_TYPE_CHUNK);
493 
494  _sion_file_set_position(filedesc->fileptr, filedesc->currentpos);
495 
496  DPRINTFP((1, __func__, -1, "leave seek rc=%d\n", SION_SUCCESS));
497  return SION_SUCCESS;
498 }
499 
500 int sion_switch_logical_file(int sid, int file_number)
501 {
502  DPRINTFP((1, __func__, -1, " enter switch_logical_file with sid=%d\n", sid));
503 
504  _sion_filedesc *filedesc = _sion_get_filedesc(sid);
505  if (filedesc == NULL) {
506  return _sion_errorprint(
507  SION_NOT_SUCCESS, _SION_ERROR_RETURN, "sion_seek_chunk: invalid sion_filedesc, aborting %d ...\n", sid);
508  }
509 
510  int rc;
511  if (filedesc->mode == SION_FILEMODE_READ) {
512  if (filedesc->state == SION_FILESTATE_SEROPEN) {
513  rc = _sion_switch_logical_file_read(filedesc, file_number);
514  } else if (filedesc->state == SION_FILESTATE_SEROPENMASTER) {
515  rc = _sion_switch_logical_file_read_master(filedesc, file_number);
516  } else if (filedesc->state == SION_FILESTATE_PAROPENMAPPEDMASTER) {
517  rc = _sion_switch_logical_file_read_mapped(filedesc, file_number);
518  } else if ((filedesc->state == SION_FILESTATE_SEROPENRANK) || (filedesc->state == SION_FILESTATE_PAROPEN)) {
519  return _sion_errorprint_on_rank(SION_NOT_SUCCESS, _SION_ERROR_RETURN, filedesc->rank,
520  "sion_switch_logical_file: switching logical file not supported for this type (sion_open_rank, sion_paropen_...), "
521  "aborting ...\n");
522  } else {
523  return _sion_errorprint_on_rank(SION_NOT_SUCCESS, _SION_ERROR_RETURN, filedesc->rank,
524  "sion_switch_logical_file: switching logical file not supported for unknown file state, aborting ...\n");
525  }
526  } else {
527  if (filedesc->state == SION_FILESTATE_SEROPEN) {
528  rc = _sion_switch_logical_file_write(filedesc, file_number);
529  } else if (filedesc->state == SION_FILESTATE_PAROPENMAPPEDMASTER) {
530  rc = _sion_switch_logical_file_write_mapped(filedesc, file_number);
531  } else if ((filedesc->state == SION_FILESTATE_SEROPENRANK) || (filedesc->state == SION_FILESTATE_PAROPEN)) {
532  return _sion_errorprint_on_rank(SION_NOT_SUCCESS, _SION_ERROR_RETURN, filedesc->rank,
533  "sion_switch_logical_file: switching logical file not supported for this type (sion_open_rank, sion_paropen_...), "
534  "aborting ...\n");
535  } else {
536  return _sion_errorprint_on_rank(SION_NOT_SUCCESS, _SION_ERROR_RETURN, filedesc->rank,
537  "sion_switch_logical_file: switching logical file not supported for unknown file state, aborting ...\n");
538  }
539  }
540 
541  DPRINTFP((1, __func__, -1, "leave switch_logical_file rc=%d\n", rc));
542  return rc;
543 }
544 
545 int64_t sion_tell(int sid)
546 {
547  _sion_filedesc *filedesc = _sion_get_filedesc(sid);
548  if (filedesc == NULL) {
549  return _sion_errorprint(-1, _SION_ERROR_RETURN, "%s: invalid file descriptor (%d)\n", __func__, sid);
550  }
551 
552  return _sion_get_logical_position(filedesc);
553 }
554 
555 int sion_eof(int sid)
556 {
557  _sion_filedesc *filedesc = _sion_get_filedesc(sid);
558  DPRINTFP((8, __func__, -1, "enter eof sid=%d\n", sid));
559  if (!filedesc) {
560  return _sion_errorprint(SION_SIZE_NOT_VALID, _SION_ERROR_RETURN, "sion_eof: invalid filedesc, aborting %d ...\n", sid);
561  }
562 
563  int eof;
564  if (filedesc->mode == SION_FILEMODE_WRITE) {
565  DPRINTFP((64, __func__, -1, "file opened for writing, no eof\n"));
566  eof = SION_NOT_SUCCESS;
567  } else {
568  _sion_limited_chunk_sequence sequence = _sion_limited_chunk_sequence_from_filedesc(filedesc);
569  DPRINTFP((64, __func__, -1, " current position: %" PRId64 ", eof: %" PRId64 "\n", filedesc->currentpos, sequence.ubound));
570  eof = (_sion_limited_chunk_sequence_position_oob(&sequence, filedesc->currentpos)) ? SION_SUCCESS : SION_NOT_SUCCESS;
571  }
572  DPRINTFP((8, __func__, -1, "leave feof sid=%d rc=%d\n", sid, eof));
573  return eof;
574 }
575 
576 int sion_feof(int sid)
577 {
578  return sion_eof(sid);
579 }
580 
582 {
583  return sion_bytes_avail_in_chunk(sid);
584 }
585 
587 {
588  _sion_filedesc *filedesc = _sion_get_filedesc(sid);
589  if (filedesc == NULL) {
590  return _sion_errorprint(
591  SION_SIZE_NOT_VALID, _SION_ERROR_RETURN, "sion_bytes_avail_in_chunk: invalid filedesc, aborting %d ...\n", sid);
592  }
593 
594  assert(filedesc->mode == SION_FILEMODE_READ);
595 
596  _sion_limited_chunk_sequence sequence = _sion_limited_chunk_sequence_from_filedesc(filedesc);
597  int64_t bytes_avail;
598  if (_sion_limited_chunk_sequence_position_oob(&sequence, filedesc->currentpos)) {
599  bytes_avail = 0;
600  } else {
601  _sion_range chunk = _sion_limited_chunk_sequence_chunk_from_physical_position(&sequence, filedesc->currentpos);
602  bytes_avail = chunk.length;
603  }
604 
605  DPRINTFP((8, __func__, -1, "leave sid=%d rank=%4d currentpos=%lld maxpos= %lld -> bytes to read %lld\n", sid, filedesc->rank,
606  filedesc->currentpos, bytes_avail));
607 
608  return bytes_avail;
609 }
610 
611 int64_t sion_get_position(int sid)
612 {
613  _sion_filedesc *sion_filedesc;
614 
615  if ((sid < 0) || (_sion_vcdtype(sid) != SION_FILEDESCRIPTOR) || !(sion_filedesc = _sion_vcdtovcon(sid))) {
616  return _sion_errorprint(
617  SION_SIZE_NOT_VALID, _SION_ERROR_RETURN, "sion_get_position: invalid sion_filedesc, aborting %d ...\n", sid);
618  }
619 
620  return _sion_file_get_position(sion_filedesc->fileptr);
621 }
622 
623 int sion_optimize_fp_buffer(int sid)
624 {
625  int rc = SION_SUCCESS;
626  _sion_filedesc *sion_filedesc;
627 
628  if ((sid < 0) || (_sion_vcdtype(sid) != SION_FILEDESCRIPTOR) || !(sion_filedesc = _sion_vcdtovcon(sid))) {
629  return _sion_errorprint(
630  SION_NOT_SUCCESS, _SION_ERROR_RETURN, "sion_optimize_fp_buffer: invalid sion_filedesc, aborting %d ...\n", sid);
631  }
632 
633  sion_filedesc->fpbuffer = malloc(sion_filedesc->fsblksize);
634  if (sion_filedesc->fpbuffer == NULL) {
635  return _sion_errorprint_on_rank(SION_NOT_SUCCESS, _SION_ERROR_RETURN, sion_filedesc->rank,
636  "sion_optimize_fp_buffer: cannot allocate internal buffer of size %lu , aborting ...",
637  (unsigned long)sion_filedesc->fsblksize);
638  }
639  sion_filedesc->fpbuffer_size = sion_filedesc->fsblksize;
640 
641  rc = _sion_file_set_buffer(sion_filedesc->fileptr, sion_filedesc->fpbuffer, sion_filedesc->fpbuffer_size);
642  return rc;
643 }
644 
645 int sion_flush(int sid)
646 {
647  _sion_filedesc *filedesc = _sion_get_filedesc(sid);
648  if ((sid < 0) || (_sion_vcdtype(sid) != SION_FILEDESCRIPTOR) || !(filedesc = _sion_vcdtovcon(sid))) {
649  return _sion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN, "sion_flush: invalid sion_filedesc, aborting %d ...\n", sid);
650  }
651 
652  return SION_SUCCESS;
653 }
654 
655 int sion_ensure_free_space(int sid, int64_t bytes)
656 {
657  _sion_filedesc *filedesc = _sion_get_filedesc(sid);
658 
659  if (!filedesc) {
660  return _sion_errorprint(
661  SION_NOT_SUCCESS, _SION_ERROR_RETURN, "sion_ensure_free_space: invalid filedesc, returning %d ...\n", sid);
662  }
663 
664  DPRINTFP((8, "_sion_ensure_free_space", -1, "enter ensure_free sid=%d bytes=%lld\n", sid, bytes));
665 
666  if (filedesc->mode != SION_FILEMODE_WRITE) {
667  DPRINTFP((8, "_sion_ensure_free_space", -1, "invalid opened\n"));
668  return _sion_errorprint_on_rank(SION_NOT_SUCCESS, _SION_ERROR_RETURN, filedesc->rank,
669  "sion_ensure_free_space[%2d]: file is opened invalid sion_mode, returning ...", filedesc->rank);
670  }
671  if (!filedesc->usecoll) {
672  if (filedesc->fileptr == NULL) {
673  DPRINTFP((8, "_sion_ensure_free_space", -1, "file not opened\n"));
674  return _sion_errorprint_on_rank(SION_NOT_SUCCESS, _SION_ERROR_RETURN, filedesc->rank,
675  "sion_ensure_free_space[%2d]: file is not open, returning ...", filedesc->rank);
676  }
677  }
678 
679  DPRINTFP((16, "_sion_ensure_free_space", -1, " after getpos sid=%d fileposition is %lld bytes=%lld\n", sid,
680  filedesc->currentpos, bytes));
681 
682  int64_t byteswritten = filedesc->blocksizes[filedesc->currentblocknr];
683 
684  DPRINTFP((16, "_sion_ensure_free_space", -1, " sid=%d byteswritten(%lld) + new bytes (%lld) = %lld\n", sid, byteswritten, bytes,
685  byteswritten + bytes));
686 
687  DPRINTFP((8, "_sion_ensure_free_space", -1,
688  "leave ensure_free sid=%d fileposition is %lld bw+bytes=%lld <= chunksize=%lld (fsblksize=%d)\n", sid, filedesc->currentpos,
689  byteswritten + bytes, filedesc->chunksize, filedesc->fsblksize));
690 
691  return SION_SUCCESS;
692 }
693 
694 int sion_is_thread_safe()
695 {
696 #ifdef SION_PTHREADS
697  return SION_SUCCESS;
698 #else
699  return SION_NOT_SUCCESS;
700 #endif
701 }
702 
703 int sion_get_sizeof(int sid, int *numbytes, int *numfds)
704 {
705  _sion_filedesc *sion_filedesc;
706  int rc = SION_NOT_SUCCESS;
707 
708  *numbytes = SION_SIZE_NOT_VALID;
709  *numfds = SION_SIZE_NOT_VALID;
710 
711  if ((sid < 0) || (_sion_vcdtype(sid) != SION_FILEDESCRIPTOR) || !(sion_filedesc = _sion_vcdtovcon(sid))) {
712  return _sion_errorprint(
713  SION_SIZE_NOT_VALID, _SION_ERROR_RETURN, "sion_get_sizeof: invalid sion_filedesc, returning %d ...\n", sid);
714  }
715  DPRINTFP((2, "sion_get_sizeof", -1, "enter sid=%d\n", sid));
716 
717  rc = _sion_get_size_of_filedesc(sion_filedesc, numbytes, numfds);
718 
719  DPRINTFP((2, "sion_get_sizeof", -1, "leave sid=%d numbytes=%d numfds=%d\n", sid, *numbytes, *numfds));
720 
721  return rc;
722 }
723 
724 #define DFUNCTION "sion_dup"
725 int sion_dup(int sid, int mode, int rank, uint64_t key)
726 {
727  int new_sid = SION_ID_NOT_VALID;
728  _sion_filedesc *sion_filedesc;
729 
730  if ((sid < 0) || (_sion_vcdtype(sid) != SION_FILEDESCRIPTOR) || !(sion_filedesc = _sion_vcdtovcon(sid))) {
731  return _sion_errorprint(SION_ID_NOT_VALID, _SION_ERROR_RETURN, "sion_dup: invalid sion_filedesc, returning %d ...\n", sid);
732  }
733  DPRINTFP((8, DFUNCTION, -1, "enter sid=%d\n", sid));
734 
735  if (sion_filedesc->mode != SION_FILEMODE_READ) {
736  DPRINTFP((8, DFUNCTION, -1, "invalid opened\n"));
737  return _sion_errorprint_on_rank(SION_ID_NOT_VALID, _SION_ERROR_RETURN, sion_filedesc->rank,
738  DFUNCTION "[%2d]: file is not opened in read mode, returning ...", sion_filedesc->rank);
739  }
740 
741  new_sid = _sion_dup(sid, mode, rank, key);
742 
743  DPRINTFP((8, DFUNCTION, -1, "leave sid=%d new_sid=%d\n", sid, new_sid));
744 
745  return new_sid;
746 }
747 #undef DFUNCTION
748 
749 #define DFUNCTION "sion_dedup"
750 int sion_dedup(int sid)
751 {
752  int rc = 0;
753  DPRINTFP((8, DFUNCTION, -1, "enter sid=%d\n", sid));
754 
755  rc = _sion_dedup(sid);
756 
757  DPRINTFP((8, DFUNCTION, -1, "leave sid=%d rc=%d\n", sid, rc));
758 
759  return rc;
760 }
761 #undef DFUNCTION
762 
763 #define DFUNCTION "sion_lock_register_lock_callbacks"
764 int sion_lock_register_lock_callbacks(int lock(void *), int unlock(void *), void *lock_data)
765 {
766  int rc = 0;
767  DPRINTFP((8, DFUNCTION, -1, "enter\n"));
768 
769  rc = _sion_lock_register_lock_callbacks(lock, unlock, lock_data);
770 
771  DPRINTFP((8, DFUNCTION, -1, "leave rc=%d\n", rc));
772 
773  return rc;
774 }
775 #undef DFUNCTION
776 
777 #define DFUNCTION "sion_lock_user_callbacks_defined"
779 {
780  int rc = 0;
781  DPRINTFP((8, DFUNCTION, -1, "enter\n"));
782 
783  rc = _sion_lock_user_callbacks_defined();
784 
785  DPRINTFP((8, DFUNCTION, -1, "leave rc=%d\n", rc));
786 
787  return rc;
788 }
789 #undef DFUNCTION
790 
791 char *sion_get_fname(int sid)
792 {
793  _sion_filedesc *filedesc = _sion_get_filedesc(sid);
794 
795  return filedesc->fname;
796 }
797 
798 int64_t sion_get_chunksize(int sid)
799 {
800  _sion_filedesc *filedesc = _sion_get_filedesc(sid);
801 
802  return filedesc->chunksize;
803 }
804 
805 int32_t sion_get_globalrank(int sid)
806 {
807  _sion_filedesc *filedesc = _sion_get_filedesc(sid);
808 
809  return filedesc->globalrank;
810 }
811 
812 int32_t *sion_get_globalranks(int sid)
813 {
814  _sion_filedesc *filedesc = _sion_get_filedesc(sid);
815 
816  if (filedesc->state == SION_FILESTATE_PAROPENMAPPEDMASTER) {
817  int ntasks = 0;
818  for (int filenr = 0; filenr < filedesc->nfiles; filenr++) {
819  ntasks += filedesc->multifiles[filenr]->nlocaltasksinfile;
820  }
821  int32_t *globalranks = malloc(sizeof(int32_t) * ntasks);
822  if (globalranks) {
823  int task = 0;
824  for (int filenr = 0; filenr < filedesc->nfiles; filenr++) {
825  _sion_filedesc *filedesc_sub = filedesc->multifiles[filenr];
826  for (int ltask = 0; ltask < filedesc_sub->nlocaltasksinfile; ltask++) {
827  globalranks[task] = filedesc_sub->all_globalranks[ltask];
828  task++;
829  }
830  }
831  assert(ntasks == task);
832  }
833  return globalranks;
834  } else {
835  return NULL;
836  }
837 }
838 
839 int sion_get_number_of_logical_files(int sid)
840 {
841  _sion_filedesc *filedesc = _sion_get_filedesc(sid);
842 
843  return filedesc->ntasks;
844 }
845 
846 int64_t *sion_get_chunksizes(int sid)
847 {
848  _sion_filedesc *filedesc = _sion_get_filedesc(sid);
849 
850  if (filedesc->state == SION_FILESTATE_PAROPENMAPPEDMASTER) {
851  int ntasks = 0;
852  for (int filenr = 0; filenr < filedesc->nfiles; filenr++) {
853  ntasks += filedesc->multifiles[filenr]->nlocaltasksinfile;
854  }
855  int64_t *chunksizes = malloc(sizeof(int64_t) * ntasks);
856  if (chunksizes) {
857  int task = 0;
858  for (int filenr = 0; filenr < filedesc->nfiles; filenr++) {
859  _sion_filedesc *filedesc_sub = filedesc->multifiles[filenr];
860  for (int ltask = 0; ltask < filedesc_sub->nlocaltasksinfile; ltask++) {
861  chunksizes[task] = filedesc_sub->all_chunksizes[ltask];
862  task++;
863  }
864  }
865  assert(ntasks == task);
866  }
867  return chunksizes;
868  } else {
869  return filedesc->all_chunksizes;
870  }
871 }
872 
873 int32_t sion_get_fsblksize(int sid)
874 {
875  _sion_filedesc *filedesc = _sion_get_filedesc(sid);
876 
877  return filedesc->fsblksize;
878 }
879 
881 {
882  /* Are we little or big endian? From Harbison&Steele. */
883  union {
884  long l;
885  char c[sizeof(long)];
886  } u;
887 
888  u.l = 1;
889  return u.c[sizeof(long) - 1] == 1;
890 }
891 
892 int sion_get_version(int *major_version, int *minor_version, int *patch_level, int *fileformat_version)
893 {
894  *major_version = SION_VERSION_MAJOR;
895  *minor_version = SION_VERSION_MINOR;
896  *patch_level = SION_VERSION_PATCH;
897  *fileformat_version = SION_FILEFORMAT_VERSION;
898  return SION_SUCCESS;
899 }
int sion_switch_logical_file(int sid, int file_number)
moves the file pointer to a different logical file
Definition: sion_common.c:500
size_t sion_write(const void *data, size_t size, size_t nitems, int sid)
Write data to a SIONlib file.
Definition: sion_common.c:313
size_t sion_read(void *data, size_t size, size_t nitems, int sid)
Read data from SIONlib file.
Definition: sion_common.c:374
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_get_locations(int sid, int *ntasks, int *maxchunks, int64_t *globalskip, int64_t *start_of_varheader, int64_t **sion_chunksizes, int64_t **sion_globalranks, int64_t **sion_blockcount, int64_t **sion_blocksizes)
Returns pointers to internal fields.
Definition: sion_common.c:35
int sion_flush(int sid)
Flushed sion file.
Definition: sion_common.c:645
int sion_get_current_locations(int sid, int *ntasks, int64_t **sion_currentpos, int64_t **sion_currentblocknr)
Returns current position in file and pointer fiels containing chunk sizes.
Definition: sion_common.c:181
int sion_feof(int sid)
Function that indicates whether the end of this logical file has been reached.
Definition: sion_common.c:576
int sion_get_version(int *major_version, int *minor_version, int *patch_level, int *fileformat_version)
Return version numbers.
Definition: sion_common.c:892
size_t sion_fread(void *data, size_t size, size_t nitems, int sid)
Read data from a SIONlib file.
Definition: sion_common.c:405
int sion_get_endianness(void)
Return endianness.
Definition: sion_common.c:880
int sion_get_file_endianness(int sid)
Returns edianness of data in file sid.
Definition: sion_common.c:153
int sion_ensure_free_space(int sid, int64_t bytes)
Function to ensure that enough space is available for writing.
Definition: sion_common.c:655
int64_t sion_bytes_avail_in_chunk(int sid)
Function that returns the number of bytes available in the current chunk.
Definition: sion_common.c:586
int sion_eof(int sid)
Function that indicates whether the end of this logical file has been reached.
Definition: sion_common.c:555
int sion_get_current_location(int sid, int *currentchunknr, int64_t *currentpos, int *maxchunks, int64_t **chunksizes)
Returns current position in file and pointer fiels containing chunk sizes.
Definition: sion_common.c:90
int sion_endianness_swap_needed(int sid)
Returns whether or not byte swapping is needed for sid.
Definition: sion_common.c:168
int sion_seek(int sid, int64_t offset, sion_seek_mode whence)
moves the file pointer inside a logical file
Definition: sion_common.c:410
int64_t sion_tell(int sid)
Inspect position of file pointer in logical file.
Definition: sion_common.c:545
int sion_dup(int sid, int mode, int rank, uint64_t key)
Function which duplicates a sion file descriptor.
Definition: sion_common.c:725
int64_t sion_bytes_avail_in_block(int sid)
Return the number of bytes available in the current chunk.
Definition: sion_common.c:581
int sion_seek_chunk(int sid, int32_t offset, sion_seek_mode whence)
moves the file pointer by increments of entire chunks inside the logical file
Definition: sion_common.c:453
int64_t sion_get_position(int sid)
Function that returns the current file position.
Definition: sion_common.c:611
int sion_lock_user_callbacks_defined()
Function which return flag, if user callback for locking are registered.
Definition: sion_common.c:778
int sion_get_sizeof(int sid, int *numbytes, int *numfds)
Function returns size of internal data structure for sid.
Definition: sion_common.c:703
int sion_lock_register_lock_callbacks(int lock(void *), int unlock(void *), void *lock_data)
Function which registers callback funtions for lock and unlock internal access to shared data structu...
Definition: sion_common.c:764
int sion_dedup(int sid)
Function which destroy a duplicated sion file descriptor.
Definition: sion_common.c:750
size_t sion_fwrite(const void *data, size_t size, size_t nitems, int sid)
Write data to a SIONlib file.
Definition: sion_common.c:369
sion_seek_mode
determines how offsets are interpreted for seek operations
Definition: sion_enums.h:67
@ SION_SEEK_END
interpret the offset relative to the end of the file
Definition: sion_enums.h:73
@ SION_SEEK_CURRENT
interpret the offset relative to the current position in the file
Definition: sion_enums.h:71
@ SION_SEEK_BEGINNING
interpret the offset relative to the beginning of the file
Definition: sion_enums.h:69