/****************************************************************************
**  SIONLIB     http://www.fz-juelich.de/jsc/sionlib                       **
*****************************************************************************
**  Copyright (c) 2008-2018                                                **
**  Forschungszentrum Juelich, Juelich Supercomputing Centre               **
**                                                                         **
**  See the file COPYRIGHT in the package base directory for details       **
****************************************************************************/

#define _XOPEN_SOURCE 700

#include <assert.h>
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "sion_common.h"
#include "sion_const.h"
#include "sion_debug.h"
#include "sion_error_handler.h"
#include "sion_file.h"
#include "sion_filedesc.h"
#include "sion_metadata.h"

#define DFUNCTION "_lsion_write_header"
int _lsion_write_header(_sion_filedesc *sion_filedesc)
{
  int rc = SION_SUCCESS;
  size_t nwrite;
  char *sionstr = SION_ID;
  uint32_t endianness_writeval;
  int32_t sion_version, sion_version_patchlevel, sion_fileformat_version;

  DPRINTFP((2, DFUNCTION, -1, "enter write\n"));
  DPRINTFP(
    (16, DFUNCTION, sion_filedesc->rank, " fileptr is at position %14lld\n", _lsion_file_get_position(sion_filedesc->fileptr)));

  /* SIONSTR */
  nwrite = _lsion_file_write(sionstr, strlen(sionstr), sion_filedesc->fileptr);
  if (nwrite != strlen(sionstr)) {
    return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
      "_lsion_write_header: cannot write header(SIONID) to file, aborting ... (%lu)\n", (unsigned long)nwrite);
  }
  DPRINTFP((32, DFUNCTION, -1, " wrote sionstr nwrite=%lu\n", (unsigned long)nwrite));

  /* endianness */
  endianness_writeval = sion_filedesc->endianness;
  nwrite = _lsion_file_write(&endianness_writeval, sizeof(endianness_writeval), sion_filedesc->fileptr);
  if (nwrite != sizeof(endianness_writeval)) {
    return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
      "_lsion_write_header: cannot write header(endianness) to file, aborting ... (%lu)\n", (unsigned long)nwrite);
  }
  DPRINTFP((32, DFUNCTION, -1, " wrote endianness 0x%x nwrite=%lu\n", endianness_writeval, (unsigned long)nwrite));

  /* VERSION Information */
  sion_version = 1000 * SION_MAIN_VERSION + SION_SUB_VERSION;
  sion_version_patchlevel = SION_VERSION_PATCHLEVEL;
  sion_fileformat_version = SION_FILEFORMAT_VERSION;

  nwrite = _lsion_file_write(&sion_version, sizeof(sion_version), sion_filedesc->fileptr);
  if (nwrite != sizeof(sion_version)) {
    return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
      "_lsion_write_header: cannot write header(sion_version) to file, aborting ... (%lu)\n", (unsigned long)nwrite);
  }
  DPRINTFP((32, DFUNCTION, -1, " wrote sion_version %ld nwrite=%lu\n", sion_version, (unsigned long)nwrite));

  nwrite = _lsion_file_write(&sion_version_patchlevel, sizeof(sion_version_patchlevel), sion_filedesc->fileptr);
  if (nwrite != sizeof(sion_version_patchlevel)) {
    return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
      "_lsion_write_header: cannot write header(sion_version_patchlevel) to file, aborting ... (%lu)\n", (unsigned long)nwrite);
  }
  DPRINTFP(
    (32, DFUNCTION, -1, " wrote sion_version_patchlevel %ld nwrite=%lu\n", sion_version_patchlevel, (unsigned long)nwrite));

  nwrite = _lsion_file_write(&sion_fileformat_version, sizeof(sion_fileformat_version), sion_filedesc->fileptr);
  if (nwrite != sizeof(sion_fileformat_version)) {
    return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
      "_lsion_write_header: cannot write header(sion_fileformat_version) to file, aborting ... (%lu)\n", (unsigned long)nwrite);
  }
  DPRINTFP(
    (32, DFUNCTION, -1, " wrote sion_fileformat_version %ld nwrite=%lu\n", sion_fileformat_version, (unsigned long)nwrite));

  /* fsblksize */
  nwrite = _lsion_file_write(&sion_filedesc->fsblksize, sizeof(sion_filedesc->fsblksize), sion_filedesc->fileptr);
  if (nwrite != sizeof(sion_filedesc->fsblksize)) {
    return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
      "_lsion_write_header: cannot write header(fsblksize) to file, aborting ... (%lu)\n", (unsigned long)nwrite);
  }
  DPRINTFP((32, DFUNCTION, -1, " wrote fsblksize %ld nwrite=%lu\n", sion_filedesc->fsblksize, (unsigned long)nwrite));

  /* ntasks */
  nwrite = _lsion_file_write(&sion_filedesc->ntasks, sizeof(sion_filedesc->ntasks), sion_filedesc->fileptr);
  if (nwrite != sizeof(sion_filedesc->ntasks)) {
    return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
      "_lsion_write_header: cannot write header(ntasks) to file, aborting ... (%lu)\n", (unsigned long)nwrite);
  }
  DPRINTFP((32, DFUNCTION, -1, " wrote ntasks %ld nwrite=%lu\n", sion_filedesc->ntasks, (unsigned long)nwrite));

  /* nfiles */
  nwrite = _lsion_file_write(&sion_filedesc->nfiles, sizeof(sion_filedesc->nfiles), sion_filedesc->fileptr);
  if (nwrite != sizeof(sion_filedesc->nfiles)) {
    return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
      "_lsion_write_header: cannot write header(nfiles) to file, aborting ... (%lu)\n", (unsigned long)nwrite);
  }
  DPRINTFP((32, DFUNCTION, -1, " wrote nfiles %d nwrite=%lu\n", sion_filedesc->nfiles, (unsigned long)nwrite));

  /* filenumber */
  nwrite = _lsion_file_write(&sion_filedesc->filenumber, sizeof(sion_filedesc->filenumber), sion_filedesc->fileptr);
  if (nwrite != sizeof(sion_filedesc->filenumber)) {
    return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
      "_lsion_write_header: cannot write header(filenumber) to file, aborting ... (%lu)\n", (unsigned long)nwrite);
  }
  DPRINTFP((32, DFUNCTION, -1, " wrote filenumber %d nwrite=%lu\n", sion_filedesc->filenumber, (unsigned long)nwrite));

  /* flag1 --> keyval-mode since file format version 5 (upper 32bit) */
  sion_filedesc->flag1 = (int64_t)sion_filedesc->keyvalmode * 1 << 32;
  nwrite = _lsion_file_write(&sion_filedesc->flag1, sizeof(sion_filedesc->flag1), sion_filedesc->fileptr);
  if (nwrite != sizeof(sion_filedesc->flag1)) {
    return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
      "_lsion_write_header: cannot write header(flag1) to file, aborting ... (%lu)\n", (unsigned long)nwrite);
  }
  DPRINTFP((32, DFUNCTION, -1, " wrote flag1 %lld nwrite=%lu\n", sion_filedesc->flag1, (unsigned long)nwrite));

  /* flag2 */
  nwrite = _lsion_file_write(&sion_filedesc->flag2, sizeof(sion_filedesc->flag2), sion_filedesc->fileptr);
  if (nwrite != sizeof(sion_filedesc->flag2)) {
    return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
      "_lsion_write_header: cannot write header(flag2) to file, aborting ... (%lu)\n", (unsigned long)nwrite);
  }
  DPRINTFP((32, DFUNCTION, -1, " wrote flag2 %d nwrite=%lu\n", sion_filedesc->flag2, (unsigned long)nwrite));

  /* globalranks */
  if (sion_filedesc->all_globalranks == NULL) {
    return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
      "_lsion_write_header: cannot write header(globalranks) to file, data not available, aborting ...\n");
  }
  nwrite = _lsion_file_write(sion_filedesc->all_globalranks, sizeof(int64_t) * sion_filedesc->ntasks, sion_filedesc->fileptr);
  if (nwrite != sizeof(int64_t) * sion_filedesc->ntasks) {
    return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
      "_lsion_write_header: cannot write header(globalranks) to file, aborting ... (%lu)\n", (unsigned long)nwrite);
  }
  DPRINTFP((32, DFUNCTION, -1, " wrote globalranks nwrite=%lu\n", (unsigned long)nwrite));

  /* chunksizes */
  if (sion_filedesc->all_chunksizes == NULL) {
    return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
      "_lsion_write_header: cannot write header(chunksizes) to file, data not available, aborting ...\n");
  }
  nwrite = _lsion_file_write(sion_filedesc->all_chunksizes, sizeof(int64_t) * sion_filedesc->ntasks, sion_filedesc->fileptr);
  if (nwrite != sizeof(int64_t) * sion_filedesc->ntasks) {
    return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
      "_lsion_write_header: cannot write header(chunksizes) to file, aborting ... (%lu)\n", (unsigned long)nwrite);
  }
  DPRINTFP((32, DFUNCTION, -1, " wrote chunksizes nwrite=%lu\n", (unsigned long)nwrite));

  _lsion_file_flush(sion_filedesc->fileptr);
  DPRINTFP((2, DFUNCTION, -1, "leave write\n"));

  return rc;
}
#undef DFUNCTION

#define DFUNCTION "_lsion_write_header_var_part_mapping"
int _lsion_write_header_var_part_mapping(_sion_filedesc *sion_filedesc, int32_t mapping_size, int32_t *mapping)
{
  int rc = SION_SUCCESS, lrank;
  size_t nwrite;

  DPRINTFP((2, DFUNCTION, -1, "enter write\n"));

  _lsion_file_set_position(sion_filedesc->fileptr, sion_filedesc->end_of_header + sion_filedesc->ntasks * sizeof(int64_t));
  DPRINTFP((16, DFUNCTION, sion_filedesc->rank, " after set fp to end_of_header + sizeof(sizes), fileptr is at position %14lld\n",
    _lsion_file_get_position(sion_filedesc->fileptr)));

  /* mapping_size */
  nwrite = _lsion_file_write(&mapping_size, sizeof(int32_t), sion_filedesc->fileptr);
  if (nwrite != sizeof(int32_t)) {
    return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
      "_lsion_write_header: cannot write header(mapping_size) to file, aborting ... (%lu)\n", (unsigned long)nwrite);
  }
  DPRINTFP((32, DFUNCTION, -1, " wrote mapping_size=%d elements nwrite=%lu\n", mapping_size, (unsigned long)nwrite));

  /* mapping */
  if (mapping_size > 0) {
    nwrite = _lsion_file_write(mapping, sizeof(int32_t) * 2 * mapping_size, sion_filedesc->fileptr);
    if (nwrite != sizeof(int32_t) * 2 * mapping_size) {
      return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
        "_lsion_write_header: cannot write header(mapping) to file, aborting ... (%lu)\n", (unsigned long)nwrite);
    }
    DPRINTFP((32, DFUNCTION, -1, " wrote mapping field %d elements  nwrite=%lu\n", 2 * mapping_size,
      (unsigned long)nwrite * 2 * mapping_size));
    for (lrank = 0; lrank < mapping_size; lrank++) {
      DPRINTFP((2048, DFUNCTION, -1, " mapping[%4d]=(%10ld,%10ld)\n", lrank, mapping[lrank * 2], mapping[lrank * 2 + 1]));
    }
  } else {
    DPRINTFP((32, DFUNCTION, -1, " wrote no mapping field\n"));
  }
  _lsion_file_flush(sion_filedesc->fileptr);
  DPRINTFP((2, DFUNCTION, -1, "leave write\n"));

  return rc;
}
#undef DFUNCTION

#define DFUNCTION "_lsion_read_header_fix_part"
int _lsion_read_header_fix_part(_sion_filedesc *sion_filedesc)
{
  int rc = SION_SUCCESS;
  size_t nread;
  char *sionstr;
  int64_t position;
  uint32_t lendianness;
  int32_t lfsblksize;
  int32_t Rsion_version, Rsion_version_patchlevel, Rsion_fileformat_version;

  DPRINTFP((2, DFUNCTION, -1, "enter read fix_part\n"));
  DPRINTFP(
    (16, DFUNCTION, sion_filedesc->rank, " fileptr is at position %14lld\n", _lsion_file_get_position(sion_filedesc->fileptr)));

  /* SION id string */
  sionstr = malloc(strlen(SION_ID));
  nread = _lsion_file_read(sionstr, strlen(SION_ID), sion_filedesc->fileptr);
  if (nread != strlen(SION_ID)) {
    return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
      "_lsion_read_header_fix_part: cannot read header(SION_ID) from file, aborting ... (%lu!=%lu)\n", (unsigned long)nread,
      (unsigned long)strlen(SION_ID));
  }
  DPRINTFP((32, DFUNCTION, -1, " sionstr  =>%c%c%c%c<\n", sionstr[0], sionstr[1], sionstr[2], sionstr[3]));
  /* Check if this is a sion file */
  if (strncmp(sionstr, SION_ID, strlen(SION_ID))) {
    return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN, "_lsion_write_header: not a sion file(ID: %c%c%c%c)\n",
      sionstr[0], sionstr[1], sionstr[2], sionstr[3]);
  }
  free(sionstr);

  /* endianness */
  nread = _lsion_file_read(&lendianness, sizeof(lendianness), sion_filedesc->fileptr);
  if (nread != sizeof(lendianness)) {
    return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
      "_lsion_write_header: cannot read header(endianness) from file, aborting ... (%lu!=%lu)\n", (unsigned long)nread,
      (unsigned long)sizeof(lendianness));
  }
  sion_filedesc->endianness = lendianness;
  /* Check only first byte. Others are set for symmetry or user data */
  sion_filedesc->swapbytes = ((sion_filedesc->endianness & 1) != lsion_get_endianness());
  DPRINTFP((32, DFUNCTION, -1, " endianness =0x%x swapbytes=%d\n", sion_filedesc->endianness, sion_filedesc->swapbytes));

  /* VERSION Information */
  nread = _lsion_file_read(&Rsion_version, sizeof(Rsion_version), sion_filedesc->fileptr);
  if (nread != sizeof(Rsion_version)) {
    return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
      "_lsion_read_header_fix_part: cannot read header(sion_version) from file, aborting ... (%lu!=%lu)\n", (unsigned long)nread,
      (unsigned long)sizeof(Rsion_version));
  }
  lsion_swap(&Rsion_version, &Rsion_version, sizeof(Rsion_version), 1, sion_filedesc->swapbytes);
  sion_filedesc->filesionversion = Rsion_version;
  DPRINTFP((32, DFUNCTION, -1, " sion_version=%d\n", Rsion_version));

  nread = _lsion_file_read(&Rsion_version_patchlevel, sizeof(Rsion_version_patchlevel), sion_filedesc->fileptr);
  if (nread != sizeof(Rsion_version_patchlevel)) {
    return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
      "_lsion_read_header_fix_part: cannot read header(sion_version_patchlevel) from file, aborting ... (%lu!=%lu)\n",
      (unsigned long)nread, (unsigned long)sizeof(Rsion_version_patchlevel));
  }
  lsion_swap(&Rsion_version_patchlevel, &Rsion_version_patchlevel, sizeof(Rsion_version_patchlevel), 1, sion_filedesc->swapbytes);
  sion_filedesc->filesionpatchlevel = Rsion_version_patchlevel;
  DPRINTFP((32, DFUNCTION, -1, " sion_version_patchlevel=%d\n", (int)Rsion_version_patchlevel));

  nread = _lsion_file_read(&Rsion_fileformat_version, sizeof(Rsion_fileformat_version), sion_filedesc->fileptr);
  if (nread != sizeof(Rsion_fileformat_version)) {
    return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
      "_lsion_read_header_fix_part: cannot read header(sion_fileformat_version) from file, aborting ... (%lu!=%lu)\n",
      (unsigned long)nread, (unsigned long)sizeof(Rsion_fileformat_version));
  }
  lsion_swap(&Rsion_fileformat_version, &Rsion_fileformat_version, sizeof(Rsion_fileformat_version), 1, sion_filedesc->swapbytes);
  sion_filedesc->fileversion = Rsion_fileformat_version;
  DPRINTFP((32, DFUNCTION, -1, " sion_fileformat_version=%d\n", (int)Rsion_fileformat_version));

  if (Rsion_fileformat_version != SION_FILEFORMAT_VERSION) {
    if (Rsion_fileformat_version < 2) {
      return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
        "sionlib: FATAL ERROR: file format version of file differs, aborting ... (%lu!=%lu)\n",
        (unsigned long)Rsion_fileformat_version, (unsigned long)SION_FILEFORMAT_VERSION);
    } else {
      _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_WARN,
        "sionlib: FATAL WARNING: old file format version of file differs, trying to read ... (%lu!=%lu)\n",
        (unsigned long)Rsion_fileformat_version, (unsigned long)SION_FILEFORMAT_VERSION);
    }
  }

  /* file block size */
  nread = _lsion_file_read(&sion_filedesc->fsblksize, sizeof(lfsblksize), sion_filedesc->fileptr);

  if (nread != sizeof(sion_filedesc->fsblksize)) {
    return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
      "_lsion_read_header_fix_part: cannot read header(fsblksize) from file, aborting ... (%lu!=%lu)\n", (unsigned long)nread,
      (unsigned long)sizeof(sion_filedesc->fsblksize));
  }
  lsion_swap(&sion_filedesc->fsblksize, &sion_filedesc->fsblksize, sizeof(sion_filedesc->fsblksize), 1, sion_filedesc->swapbytes);
  DPRINTFP((32, DFUNCTION, -1, " fsblksize=%d\n", sion_filedesc->fsblksize));

  /* number of tasks */
  nread = _lsion_file_read(&sion_filedesc->ntasks, sizeof(sion_filedesc->ntasks), sion_filedesc->fileptr);
  if (nread != sizeof(sion_filedesc->ntasks)) {
    return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
      "_lsion_read_header_fix_part: cannot read header(ntasks) from file, aborting ... (%lu!=%lu)\n", (unsigned long)nread,
      (unsigned long)sizeof(sion_filedesc->ntasks));
  }
  lsion_swap(&sion_filedesc->ntasks, &sion_filedesc->ntasks, sizeof(sion_filedesc->ntasks), 1, sion_filedesc->swapbytes);
  DPRINTFP((32, DFUNCTION, -1, " ntasks     =%d\n", sion_filedesc->ntasks));

  /* number of files */
  nread = _lsion_file_read(&sion_filedesc->nfiles, sizeof(sion_filedesc->nfiles), sion_filedesc->fileptr);
  if (nread != sizeof(sion_filedesc->nfiles)) {
    return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
      "_lsion_read_header_fix_part: cannot read header(nfiles) from file, aborting ... (%lu!=%lu)\n", (unsigned long)nread,
      (unsigned long)sizeof(sion_filedesc->nfiles));
  }
  lsion_swap(&sion_filedesc->nfiles, &sion_filedesc->nfiles, sizeof(sion_filedesc->nfiles), 1, sion_filedesc->swapbytes);
  DPRINTFP((32, DFUNCTION, -1, " nfiles     =%d\n", sion_filedesc->nfiles));

  /* current file number */
  if (sion_filedesc->fileversion >= 3) {
    nread = _lsion_file_read(&sion_filedesc->filenumber, sizeof(sion_filedesc->filenumber), sion_filedesc->fileptr);
    if (nread != sizeof(sion_filedesc->filenumber)) {
      return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
        "_lsion_read_header_fix_part: cannot read header(filenumber) from file, aborting ... (%lu!=%lu)\n", (unsigned long)nread,
        (unsigned long)sizeof(sion_filedesc->filenumber));
    }
    lsion_swap(
      &sion_filedesc->filenumber, &sion_filedesc->filenumber, sizeof(sion_filedesc->filenumber), 1, sion_filedesc->swapbytes);
  } else {
    sion_filedesc->filenumber = 1;
  }
  DPRINTFP((32, DFUNCTION, -1, " filenumber =%d\n", sion_filedesc->filenumber));

  /* flag1 */
  if (Rsion_fileformat_version >= 3) {
    nread = _lsion_file_read(&sion_filedesc->flag1, sizeof(sion_filedesc->flag1), sion_filedesc->fileptr);
    if (nread != sizeof(sion_filedesc->flag1)) {
      return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
        "_lsion_read_header_fix_part: cannot read header(flag1) from file, aborting ... (%lu!=%lu)\n", (unsigned long)nread,
        (unsigned long)sizeof(sion_filedesc->flag1));
    }
    lsion_swap(&sion_filedesc->flag1, &sion_filedesc->flag1, sizeof(sion_filedesc->flag1), 1, sion_filedesc->swapbytes);
  } else {
    sion_filedesc->flag1 = _SION_FLAG1_NONE;
  }
  DPRINTFP((32, DFUNCTION, -1, " flag1 =%lld\n", sion_filedesc->flag1));

  if (Rsion_fileformat_version >= 5) {
    /* flag1 --> keyval-mode since file format version 5 (upper 32bit) */
    sion_filedesc->keyvalmode = sion_filedesc->flag1 >> 32;
    DPRINTFP((32, DFUNCTION, -1, " keyvalmode=%d (%s)\n", (int)sion_filedesc->keyvalmode,
      lsion_keyval_type_to_str(sion_filedesc->keyvalmode)));
    if (sion_filedesc->keyvalmode == 0) {
      sion_filedesc->keyvalmode = SION_KEYVAL_NONE;
      DPRINTFP((32, DFUNCTION, -1, " keyvalmode is not set correctly in file, setting default=%d (%s)\n",
        (int)sion_filedesc->keyvalmode, lsion_keyval_type_to_str(sion_filedesc->keyvalmode)));
    }
  } else {
    sion_filedesc->keyvalmode = SION_KEYVAL_NONE; /* not implemented before version 5 of file format */
    DPRINTFP((32, DFUNCTION, -1, " file format version <5, setting default keyvalmode=%d (%s)\n", (int)sion_filedesc->keyvalmode,
      lsion_keyval_type_to_str(sion_filedesc->keyvalmode)));
  }

  /* flag2 */
  if (Rsion_fileformat_version >= 3) {
    nread = _lsion_file_read(&sion_filedesc->flag2, sizeof(sion_filedesc->flag2), sion_filedesc->fileptr);
    if (nread != sizeof(sion_filedesc->flag2)) {
      return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
        "_lsion_read_header_fix_part: cannot read header(flag2) from file, aborting ... (%lu!=%lu)\n", (unsigned long)nread,
        (unsigned long)sizeof(sion_filedesc->flag2));
    }
    lsion_swap(&sion_filedesc->flag2, &sion_filedesc->flag2, sizeof(sion_filedesc->flag2), 1, sion_filedesc->swapbytes);
  } else {
    sion_filedesc->flag2 = _SION_FLAG2_NONE;
  }
  DPRINTFP((32, DFUNCTION, -1, " flag2 =%lld\n", sion_filedesc->flag2));

  /* prefix */
  if (Rsion_fileformat_version <= 5) {
    if (-1 == (position = _lsion_file_get_position(sion_filedesc->fileptr))) {
      return _lsion_errorprint(
        SION_NOT_SUCCESS, _SION_ERROR_RETURN, "_lsion_read_header_fix_part: cannot get file position, aborting ...\n");
    }
    if (-1 == _lsion_file_set_position(sion_filedesc->fileptr, position + SION_FILENAME_LENGTH)) {
      return _lsion_errorprint(
        SION_NOT_SUCCESS, _SION_ERROR_RETURN, "_lsion_read_header_fix_part: cannot skip past header(unused), aborting ...\n");
    }
  }

  DPRINTFTS(sion_filedesc->rank, "before flush");
  _lsion_file_flush(sion_filedesc->fileptr);
  DPRINTFTS(sion_filedesc->rank, "after  flush");

  sion_filedesc->end_of_header = _lsion_file_get_position(sion_filedesc->fileptr);

  DPRINTFP((2, DFUNCTION, -1, "leave read fix_part\n"));

  return rc;
}
#undef DFUNCTION

#define DFUNCTION "_lsion_read_header_var_part"
int _lsion_read_header_var_part(_sion_filedesc *sion_filedesc)
{
  int rc = SION_SUCCESS;
  size_t nread;
  int32_t Rmaxchunks;

  DPRINTFP((32, DFUNCTION, -1, "enter read var_part\n"));
  DPRINTFP(
    (16, DFUNCTION, sion_filedesc->rank, " fileptr is at position %14lld\n", _lsion_file_get_position(sion_filedesc->fileptr)));

  /* globalranks */
  nread = _lsion_file_read(sion_filedesc->all_globalranks, sizeof(int64_t) * sion_filedesc->ntasks, sion_filedesc->fileptr);
  if (nread != sizeof(int64_t) * sion_filedesc->ntasks) {
    return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
      "_lsion_read_header_var_part: cannot read header(globalranks) from file, aborting ... (%d)\n", sion_filedesc->ntasks);
  }
  lsion_swap(sion_filedesc->all_globalranks, sion_filedesc->all_globalranks, sizeof(int64_t), sion_filedesc->ntasks,
    sion_filedesc->swapbytes);

  /* chunksizes */
  nread = _lsion_file_read(sion_filedesc->all_chunksizes, sizeof(int64_t) * sion_filedesc->ntasks, sion_filedesc->fileptr);
  if (nread != sizeof(int64_t) * sion_filedesc->ntasks) {
    return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
      "_lsion_read_header_var_part: cannot read header(chunksizes) from file, aborting ... (%d!=%lu)\n", sion_filedesc->ntasks,
      (unsigned long)nread);
  }
  lsion_swap(sion_filedesc->all_chunksizes, sion_filedesc->all_chunksizes, sizeof(int64_t), sion_filedesc->ntasks,
    sion_filedesc->swapbytes);

  /* sizes */
  if (sion_filedesc->fileversion >= 6) {
    nread = _lsion_file_read(sion_filedesc->all_sizes, sizeof(int64_t) * sion_filedesc->ntasks, sion_filedesc->fileptr);
    if (nread != sizeof(int64_t) * sion_filedesc->ntasks) {
      return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
        "_lsion_read_header_var_part: cannot read header(sizes) from file, aborting ... (%d!=%" PRId64 ")\n",
        sion_filedesc->ntasks, nread);
    }
    lsion_swap(
      sion_filedesc->all_sizes, sion_filedesc->all_sizes, sizeof(int64_t), sion_filedesc->ntasks, sion_filedesc->swapbytes);

    // synthesize maxusedchunks
    sion_filedesc->maxusedchunks = 1;
    for (int64_t itask = 0; itask < sion_filedesc->ntasks; itask++) {
      int64_t blockcount, *sizes = sion_filedesc->all_sizes, *chunksizes = sion_filedesc->all_chunksizes;
      if (sion_filedesc->all_chunksizes[itask] > 0) {
        blockcount = sizes[itask] / chunksizes[itask] + ((sizes[itask] % chunksizes[itask] > 0) ? 1 : 0);
      } else {
        blockcount = 0;
      }
      if (sion_filedesc->maxusedchunks < blockcount) {
        sion_filedesc->maxusedchunks = blockcount;
      }
    }
    DPRINTFP((32, DFUNCTION, -1, " maxchunks=%d\n", sion_filedesc->maxusedchunks));
    if (sion_filedesc->maxusedchunks > sion_filedesc->maxchunks) {
      _lsion_realloc_filedesc_blocklist(sion_filedesc, sion_filedesc->maxusedchunks);
    }
  }

  if (sion_filedesc->fileversion <= 5) {
    /* maxchunks -> maxusedchunks */
    nread = _lsion_file_read(&Rmaxchunks, sizeof(Rmaxchunks), sion_filedesc->fileptr);
    if (nread != sizeof(Rmaxchunks)) {
      return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
        "_lsion_read_header_var_part: cannot read header(maxchunks) from file, aborting ... (%lu!=%lu)\n", (unsigned long)nread,
        (unsigned long)sizeof(Rmaxchunks));
    }
    lsion_swap(&Rmaxchunks, &Rmaxchunks, sizeof(Rmaxchunks), 1, sion_filedesc->swapbytes);
    DPRINTFP((32, DFUNCTION, -1, " maxchunks=%d\n", Rmaxchunks));

    sion_filedesc->maxusedchunks = Rmaxchunks;
    if (Rmaxchunks > sion_filedesc->maxchunks) {
      _lsion_realloc_filedesc_blocklist(sion_filedesc, Rmaxchunks);
    }

    /* start_of_varheader */
    nread =
      _lsion_file_read(&sion_filedesc->start_of_varheader, sizeof(sion_filedesc->start_of_varheader), sion_filedesc->fileptr);
    if (nread != sizeof(sion_filedesc->start_of_varheader)) {
      return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
        "_lsion_read_header_var_part: cannot read header(start_of_varheader) from file, aborting ... (%lu!=%lu)\n",
        (unsigned long)nread, (unsigned long)sizeof(sion_filedesc->start_of_varheader));
    }
    if (sion_filedesc->start_of_varheader == 0) {
      return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
        "_lsion_read_header_var_part: bad value for start_of_varheader (=%lu), aborting ...\n",
        (unsigned long)sion_filedesc->start_of_varheader);
    }
    lsion_swap(&sion_filedesc->start_of_varheader, &sion_filedesc->start_of_varheader, sizeof(sion_filedesc->start_of_varheader),
      1, sion_filedesc->swapbytes);
    DPRINTFP((32, DFUNCTION, -1, " start_of_varheader=%lld\n", sion_filedesc->start_of_varheader));
  }

  DPRINTFP((32, DFUNCTION, -1, "leave read var_part\n"));

  return rc;
}
#undef DFUNCTION

#define DFUNCTION "_sion_rd_hdr_var_prt_blkcnt_to_field"
int _lsion_read_header_var_part_blockcount_to_field(_sion_filedesc *sion_filedesc, int field_size, int64_t *field)
{
  int rc = SION_SUCCESS;
  size_t nread;

  DPRINTFP((32, DFUNCTION, -1, "enter\n"));
  assert(sion_filedesc->fileversion <= 5);
  DPRINTFP(
    (16, DFUNCTION, sion_filedesc->rank, " fileptr is at position %14lld\n", _lsion_file_get_position(sion_filedesc->fileptr)));

  if (field_size < sion_filedesc->ntasks) {
    return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
      "_lsion_read_header_var_part_blockcount_to_field: cannot read header(blocksizes) field too small, aborting ... (%d<%d)\n",
      field_size, sion_filedesc->ntasks);
  }
  /* set file pointer to start of Meta Block 2 */
  _lsion_file_set_position(sion_filedesc->fileptr, sion_filedesc->start_of_varheader);

  nread = _lsion_file_read(field, sizeof(int64_t) * sion_filedesc->ntasks, sion_filedesc->fileptr);
  if (nread != sizeof(int64_t) * sion_filedesc->ntasks) {
    return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
      "_lsion_read_header_var_part_blockcount_to_field: cannot read blocksizes from meta block 2 of the file, aborting ... "
      "(%d,%d)\n",
      sion_filedesc->ntasks, nread);
  }
  lsion_swap(field, field, sizeof(int64_t), sion_filedesc->ntasks, sion_filedesc->swapbytes);

  DPRINTFP((32, DFUNCTION, -1, "leave \n"));

  return rc;
}
#undef DFUNCTION

#define DFUNCTION "_sion_rd_hdr_vr_prt_nxtblksizes_to_field"
int _lsion_read_header_var_part_nextblocksizes_to_field(_sion_filedesc *sion_filedesc, int field_size, int64_t *field)
{
  size_t nread;
  int rc = SION_SUCCESS;

  DPRINTFP((32, DFUNCTION, -1, "enter\n"));
  assert(sion_filedesc->fileversion <= 5);
  DPRINTFP(
    (16, DFUNCTION, sion_filedesc->rank, " fileptr is at position %14lld\n", _lsion_file_get_position(sion_filedesc->fileptr)));

  if (field_size < sion_filedesc->ntasks) {
    return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
      "_lsion_read_header_var_part_nextblocksizes_to_field: cannot read header(blocksizes) field too small, aborting ... "
      "(%d<%d)\n",
      field_size, sion_filedesc->ntasks);
  }
  nread = _lsion_file_read(field, sizeof(int64_t) * sion_filedesc->ntasks, sion_filedesc->fileptr);
  if (nread != sizeof(int64_t) * sion_filedesc->ntasks) {
    return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
      "_lsion_read_header_var_part_nextblocksizes_to_field: cannot read blocksizes from meta block 2 of the file, aborting ... "
      "(%d,%d)\n",
      sion_filedesc->ntasks, nread);
  }
  lsion_swap(field, field, sizeof(int64_t), sion_filedesc->ntasks, sion_filedesc->swapbytes);

  DPRINTFP((32, DFUNCTION, -1, "leave \n"));

  return rc;
}
#undef DFUNCTION

#define DFUNCTION "_lsion_read_header_var_part_blocksizes"
int _lsion_read_header_var_part_blocksizes(_sion_filedesc *sion_filedesc)
{
  int rc = SION_SUCCESS;
  size_t nread;
  int i;

  DPRINTFP((32, DFUNCTION, -1, "enter read\n"));

  if (sion_filedesc->fileversion <= 5) {
    /* file contains meta data block 2 with individual sizes for all chunks, read those */
    DPRINTFP(
      (16, DFUNCTION, sion_filedesc->rank, " fileptr is at position %14lld\n", _lsion_file_get_position(sion_filedesc->fileptr)));

    _lsion_file_set_position(sion_filedesc->fileptr, sion_filedesc->start_of_varheader);

    /* all_blockcount */
    nread = _lsion_file_read(sion_filedesc->all_blockcount, sizeof(int64_t) * sion_filedesc->ntasks, sion_filedesc->fileptr);
    if (nread != sizeof(int64_t) * sion_filedesc->ntasks) {
      return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
        "_lsion_read_header_var_part_blocksizes: cannot read header from file(sion_blockcount), aborting ... (%d)\n",
        sion_filedesc->ntasks);
    }
    lsion_swap(sion_filedesc->all_blockcount, sion_filedesc->all_blockcount, sizeof(int64_t), sion_filedesc->ntasks,
      sion_filedesc->swapbytes);
    for (i = 0; i < sion_filedesc->ntasks; i++) {
      DPRINTFP((2048, DFUNCTION, -1, " read, numblocks on task %02d is %10lld\n", i, sion_filedesc->all_blockcount[i]));
    }

    /* all_blocksizes */
    nread = _lsion_file_read(sion_filedesc->all_blocksizes, sizeof(int64_t) * sion_filedesc->ntasks * sion_filedesc->maxusedchunks,
      sion_filedesc->fileptr);
    if (nread != sizeof(int64_t) * sion_filedesc->ntasks * sion_filedesc->maxusedchunks) {
      return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
        "_lsion_read_header_var_part_blocksizes: cannot read header(sion_blocksizes) from file, aborting ... (%lu!=%lu)\n",
        (unsigned long)sion_filedesc->ntasks * sion_filedesc->maxusedchunks, (unsigned long)nread);
    }
    lsion_swap(sion_filedesc->all_blocksizes, sion_filedesc->all_blocksizes, sizeof(int64_t),
      sion_filedesc->ntasks * sion_filedesc->maxusedchunks, sion_filedesc->swapbytes);

  } else {
    /* file does not contain individual block sizes, synthesize them from the logical file size */
    DPRINTFP((16, DFUNCTION, sion_filedesc->rank, " file newer than version 5, synthesizing block counts and sizes\n"));

    int64_t *blockcounts = sion_filedesc->all_blockcount, *sizes = sion_filedesc->all_sizes,
            *chunksizes = sion_filedesc->all_chunksizes;

    for (int64_t itask = 0; itask < sion_filedesc->ntasks; itask++) {
      if (chunksizes[itask] > 0) {
        blockcounts[itask] = sizes[itask] / chunksizes[itask] + ((sizes[itask] % chunksizes[itask] > 0) ? 1 : 0);
      } else {
        blockcounts[itask] = 0;
      }
    }

    int64_t *blocksizes = sion_filedesc->all_blocksizes;

    for (int64_t ichunk = 0; ichunk < sion_filedesc->maxusedchunks; ichunk++) {
      for (int64_t itask = 0; itask < sion_filedesc->ntasks; itask++) {
        int64_t blocksize;
        if (ichunk < blockcounts[itask] - 1) {
          blocksize = chunksizes[itask];
        } else if (ichunk == blockcounts[itask] - 1) {
          blocksize = sizes[itask] - ((blockcounts[itask] - 1) * chunksizes[itask]);
        } else {
          blocksize = 0;
        }
        blocksizes[ichunk * sion_filedesc->ntasks + itask] = blocksize;
      }
    }

    for (int64_t itask = 0; itask < sion_filedesc->ntasks; itask++) {
      // FIXME: empty logical files have to have at least one block for backwards compatibility
      blockcounts[itask] += (blockcounts[itask] == 0) ? 1 : 0;
    }
  }

  for (i = 0; i < sion_filedesc->ntasks; i++) {
    DPRINTFP((2048, DFUNCTION, -1, " read, blocksize[0] on task %02d is %10lld\n", i,
      sion_filedesc->all_blocksizes[0 * sion_filedesc->ntasks + i]));
  }

  DPRINTFP((32, DFUNCTION, -1, "leave read\n"));
  return rc;
}

#undef DFUNCTION

int _lsion_read_header_var_part_mapping_size(_sion_filedesc *sion_filedesc)
{
  int64_t position = (sion_filedesc->fileversion <= 5)
    // go to second meta data block at end of file and skip past block counts and block sizes
    ? sion_filedesc->start_of_varheader + sion_filedesc->ntasks * (sion_filedesc->maxusedchunks + 1) * sizeof(int64_t)
    // go to the "end of header" and skip past globalranks, chunksizes and sizes
    : sion_filedesc->end_of_header + 3 * sion_filedesc->ntasks * sizeof(int64_t);
  _lsion_file_set_position(sion_filedesc->fileptr, position);
  if (sion_filedesc->fileversion <= 5) {
    DPRINTFP((32, __func__, -1, "calculate position %lld + %d * %d = %lld\n", sion_filedesc->start_of_varheader,
      sion_filedesc->ntasks, sion_filedesc->maxusedchunks, position));
  }
  DPRINTFP(
    (16, __func__, sion_filedesc->rank, " fileptr is at position %14lld\n", _lsion_file_get_position(sion_filedesc->fileptr)));

  /* read mapping_size */
  int64_t nread = _lsion_file_read(&sion_filedesc->mapping_size, sizeof(sion_filedesc->mapping_size), sion_filedesc->fileptr);
  if (nread != sizeof(sion_filedesc->mapping_size)) {
    return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
      "_lsion_read_header_var_part_mapping: cannot read header(mapping_size) from file, aborting ... (%d)\n", nread);
  }
  lsion_swap(
    &sion_filedesc->mapping_size, &sion_filedesc->mapping_size, sizeof(sion_filedesc->mapping_size), 1, sion_filedesc->swapbytes);
  DPRINTFP((32, __func__, -1, "mapping_size=%ld\n", (long)sion_filedesc->mapping_size));

  return SION_SUCCESS;
}

#define DFUNCTION "_lsion_read_header_var_part_mapping"
int _lsion_read_header_var_part_mapping(_sion_filedesc *sion_filedesc)
{
  int rc = SION_SUCCESS;
  size_t nread;

  DPRINTFP((32, DFUNCTION, -1, "enter read\n"));

  if (_lsion_read_header_var_part_mapping_size(sion_filedesc) != SION_SUCCESS) {
    return SION_NOT_SUCCESS;
  }

  /* allocate mapping vector */
  sion_filedesc->mapping = malloc(sion_filedesc->mapping_size * 2 * sizeof(int32_t));
  if (sion_filedesc->mapping == NULL) {
    return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
      "_lsion_read_header_var_part_mapping: cannot allocate temporary memory of size %lu (mapping), aborting ...\n",
      (unsigned long)2 * sion_filedesc->mapping_size * sizeof(int64_t));
  }
  DPRINTFP((32, DFUNCTION, -1, "alloc mapping vector size=%d (%lu bytes)\n", sion_filedesc->mapping_size,
    (long)sion_filedesc->mapping_size * 2 * sizeof(int32_t)));

  /* read mapping */
  nread = _lsion_file_read(sion_filedesc->mapping, sizeof(int32_t) * sion_filedesc->mapping_size * 2, sion_filedesc->fileptr);
  DPRINTFP((32, DFUNCTION, -1, "read mapping, %d \n", nread));
  if (nread != (sizeof(int32_t) * sion_filedesc->mapping_size * 2)) {
    return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
      "_lsion_read_header_var_part_mapping: cannot read header(mapping) from file, aborting ... (%d!=%lu)\n",
      sion_filedesc->mapping_size * 2, (unsigned long)nread);
  }
  lsion_swap(
    sion_filedesc->mapping, sion_filedesc->mapping, sizeof(int32_t), sion_filedesc->mapping_size * 2, sion_filedesc->swapbytes);

  DPRINTFP((32, DFUNCTION, -1, "leave read\n"));

  return rc;
}
#undef DFUNCTION

#define DFUNCTION "_sion_read_header_var_part_locations_rank"
/* TODO: _sion_filedesc *sion_filedesc -> fileptr */
int _lsion_read_header_var_part_blocksizes_rank(_sion_filedesc *sion_filedesc)
{
  int rc = SION_SUCCESS;
  int i, numblocks;
  size_t nread;
  int64_t position;
  int64_t helpint64;

  DPRINTFP((32, DFUNCTION, -1, "enter read for rank %d of %d\n", sion_filedesc->rank, sion_filedesc->ntasks));

  if (sion_filedesc->fileversion <= 5) {
    /* file contains meta data block 2 with individual sizes for all chunks, read those */
    _lsion_file_set_position(sion_filedesc->fileptr, sion_filedesc->start_of_varheader);

    /* read number of blocks */
    nread = _lsion_file_read(&helpint64, sizeof(int64_t), sion_filedesc->fileptr);
    lsion_swap(&helpint64, &helpint64, sizeof(int64_t), 1, sion_filedesc->swapbytes);
    numblocks = helpint64;
    if (nread != sizeof(int64_t)) {
      return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
        "_sion_read_header_var_part_locations_rank: cannot read header(numblocks) from file, aborting ... (%d)\n",
        sion_filedesc->ntasks);
    }
    sion_filedesc->maxusedchunks = numblocks;
    sion_filedesc->lastchunknr = numblocks - 1;

    /* read blocksizes */
    for (i = 0; i < numblocks; i++) {
      position = sion_filedesc->start_of_varheader + (i + 1) * sion_filedesc->ntasks * sizeof(int64_t)
        + sion_filedesc->rank * sizeof(int64_t);
      _lsion_file_set_position(sion_filedesc->fileptr, position);

      nread = _lsion_file_read(&helpint64, sizeof(int64_t), sion_filedesc->fileptr);
      if (nread != sizeof(int64_t)) {
        return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
          "_sion_read_header_var_part_locations_rank: cannot read header(blocksizes) from file, aborting ... (%d!=%lu)\n", 1,
          (unsigned long)nread);
      }
      lsion_swap(&helpint64, &helpint64, sizeof(int64_t), 1, sion_filedesc->swapbytes);
      sion_filedesc->blocksizes[i] = helpint64;
      DPRINTFP((32, "_sion_read_header_var_part_locations_rank", -1, "read blocksizes[%i], %lld start_of_varheader=%lld\n", i,
        helpint64, sion_filedesc->start_of_varheader));
    }
  } else {
    /* file does not contain individual block sizes, synthesize them from the logical file size */
    DPRINTFP((16, DFUNCTION, sion_filedesc->rank, " file newer than version 5, synthesizing block count and size\n"));

    int64_t size = sion_filedesc->all_sizes[sion_filedesc->rank], chunksize = sion_filedesc->all_chunksizes[sion_filedesc->rank];
    int64_t blockcount = size / chunksize + ((size % chunksize > 0) ? 1 : 0);

    int64_t *blocksizes = sion_filedesc->blocksizes;
    for (int64_t ichunk = 0; ichunk < blockcount; ichunk++) {
      int64_t blocksize;
      if (ichunk < blockcount - 1) {
        blocksize = chunksize;
      } else if (ichunk == blockcount - 1) {
        blocksize = size - ((blockcount - 1) * chunksize);
      } else {
        blocksize = 0;
      }
      blocksizes[ichunk] = blocksize;
    }

    blockcount += (blockcount == 0) ? 1 : 0;

    sion_filedesc->maxusedchunks = blockcount;
    sion_filedesc->lastchunknr = blockcount - 1;
  }

  DPRINTFP((32, DFUNCTION, -1, "leave read\n"));

  return rc;
}
#undef DFUNCTION

#define DFUNCTION "_lsion_read_header_var_part_mapping_rank"
int _lsion_read_header_var_part_mapping_rank(_sion_filedesc *sion_filedesc)
{
  int rc = SION_SUCCESS;
  int msize;
  size_t nread;

  DPRINTFP((32, DFUNCTION, -1, "enter read for rank %d of %d\n", sion_filedesc->rank, sion_filedesc->ntasks));

  if (_lsion_read_header_var_part_mapping_size(sion_filedesc) != SION_SUCCESS) {
    return SION_NOT_SUCCESS;
  }

  msize = sion_filedesc->mapping_size;
  DPRINTFP((32, "_lsion_read_header_var_part_mapping_rank", -1, "read mapping_size %d \n", msize));

  if ((sion_filedesc->rank < 0) || (sion_filedesc->rank >= msize)) {
    return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
      "_lsion_read_header_var_part_mapping_rank: wrong rank %d not between 0 .. %d aborting ...\n", sion_filedesc->rank, msize);
  }

  /* move to position in mapping table for rank */
  int64_t position;
  if (sion_filedesc->fileversion <= 5) {
    position = sion_filedesc->start_of_varheader + sion_filedesc->ntasks * sizeof(int64_t)
      + sion_filedesc->ntasks * sion_filedesc->maxusedchunks * sizeof(int64_t) + sizeof(int32_t)
      + 2 * sion_filedesc->rank * sizeof(int32_t);
  } else {
    position = sion_filedesc->end_of_header + 3 * sion_filedesc->ntasks * sizeof(int64_t) + sizeof(int32_t)
      + 2 * sion_filedesc->rank * sizeof(int32_t);
  }

  _lsion_file_set_position(sion_filedesc->fileptr, position);

  /* allocate mapping vector of length 1 */
  sion_filedesc->mapping_size = 1;
  /* allocate mapping vector */
  sion_filedesc->mapping = malloc(sion_filedesc->mapping_size * 2 * sizeof(int32_t));
  if (sion_filedesc->mapping == NULL) {
    return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
      "_lsion_read_header_var_part_mapping: cannot allocate temporary memory of size %lu (mapping), aborting ...\n",
      (unsigned long)2 * sion_filedesc->mapping_size * sizeof(int64_t));
  }
  DPRINTFP((32, DFUNCTION, -1, "alloc mapping vector size=%d (%lu bytes)\n", sion_filedesc->mapping_size,
    (long)sion_filedesc->mapping_size * 2 * sizeof(int32_t)));

  /* read mapping for rank */
  nread = _lsion_file_read(sion_filedesc->mapping, sizeof(int32_t) * sion_filedesc->mapping_size * 2, sion_filedesc->fileptr);
  DPRINTFP((32, DFUNCTION, -1, "read mapping, %d \n", nread));
  if (nread != (sizeof(int32_t) * sion_filedesc->mapping_size * 2)) {
    return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
      "_lsion_read_header_var_part_mapping: cannot read header(mapping) from file, aborting ... (%d!=%lu)\n",
      sion_filedesc->mapping_size * 2, (unsigned long)nread);
  }
  lsion_swap(
    sion_filedesc->mapping, sion_filedesc->mapping, sizeof(int32_t), sion_filedesc->mapping_size * 2, sion_filedesc->swapbytes);

  DPRINTFP((32, DFUNCTION, -1, "leave read filenumber=%d lrank=%d\n", sion_filedesc->mapping[0], sion_filedesc->mapping[1]));

  return rc;
}
#undef DFUNCTION

int _lsion_write_header_sizes_from_field(_sion_filedesc *filedesc, int64_t *field)
{
  DPRINTFP((32, __func__, -1, "enter\n"));
  _lsion_file_set_position(filedesc->fileptr, filedesc->end_of_header);
  DPRINTFP((16, __func__, filedesc->rank, " after set fp to end_of_header, fileptr is at position %14" PRId64 "\n",
    _lsion_file_get_position(filedesc->fileptr)));

  /* sizes */
  int64_t nwrite = _lsion_file_write(field, filedesc->ntasks * sizeof(int64_t), filedesc->fileptr);
  if (nwrite != filedesc->ntasks * sizeof(int64_t)) {
    return _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
      "_lsion_write_header: cannot write header(sizes) to file, aborting ... (%" PRId64 ")\n", nwrite);
  }
  DPRINTFP((32, __func__, -1, " wrote sizes field %d elements nwrite=%" PRId64 "\n", filedesc->ntasks, nwrite));

  _lsion_file_flush(filedesc->fileptr);
  DPRINTFP((32, __func__, -1, "leave \n"));

  return SION_SUCCESS;
}

int _lsion_write_header_sizes(_sion_filedesc *filedesc)
{
  return _lsion_write_header_sizes_from_field(filedesc, filedesc->all_sizes);
}
