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