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