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

/*!
  \cond sion_internal
  \file
  example meta data format

  \code
  Metadata 1:

  M11: SIONSTR                          4 bytes
       endianness                       uint32_t
       sion_version                     int32_t (not in data structure)
       sion_version_patchlevel          int32_t (not in data structure)
       sion_fileformat_version          int32_t
       fsblksize                        int32_t
       ntasks                           int32_t
       nfiles                           int32_t
       filenumber                       int32_t
       flag1                            int64_t
       flag2                            int64_t

  M12: globalranks(ntasks)              ntasks*int64_t
       chunksizes(ntasks)               ntasks*int64_t

  M13: sizes(ntasks)                    ntasks*int64_t

  M14: maxusedchunks                    int32_t
       start_of_varheader               int64_t

  Metadata 2: (starts at sion_filedesc->start_of_varheader)

  M22: mapping_size                     int32_t
       mapping                          mapping_size*2**int32_t
  \endcode

 */

#ifndef SION_SION_METADATA_H
#define SION_SION_METADATA_H

#include <stdint.h>

#include "sion_filedesc.h"

#define SION_ID "sion" /*!< Sion identification string (offset: 0x00) */

/* WRITE */
/*!\brief Write the SION Meta Block 1
 *
 * @param  *sion_filedesc       pointer to internal data structure, contaiing all meta data
 *
 * @retval SION_SUCESS if okay
 */
int _sion_write_header(_sion_filedesc *sion_filedesc); /* writes M11, M12  */

/*!\brief Write mapping into the SION Meta Block 2
 *
 * @param  *sion_filedesc       pointer to internal data structure, containing all meta data
 * @param  *mapping_size        number of tasks in map
 * @param  *mapping             pointer to map
 *
 * @retval SION_SUCESS if okay
 */
int _sion_write_header_var_part_mapping(_sion_filedesc *sion_filedesc, int32_t mapping_size, int32_t *mapping); /* writes M22  */

/* READ */
/*!\brief Read part of the SION Meta Block 1
 *
 * @param  *sion_filedesc       pointer to internal data structure, contaiing all meta data
 *
 * @retval SION_SUCESS if okay
 */
int _sion_read_header_fix_part(_sion_filedesc *sion_filedesc); /* reads  M11 */

/*!\brief Read the second part of SION Meta Block 1
 *
 * @param       *sion_filedesc  pointer to internal data structure, containing all meta data
 *
 * @retval       SION_SUCESS if okay
 */
int _sion_read_header_var_part(_sion_filedesc *sion_filedesc); /* reads  M12, M13, M14 */

/*!\brief Read the SION Meta Block 2
 *
 * @param       *sion_filedesc  pointer to internal data structure, contaiing all meta data
 *
 * @retval      SION_SUCESS if okay
 */
int _sion_read_header_var_part_blocksizes(_sion_filedesc *sion_filedesc); /* reads  M21 */

/*!\brief Read the SION Meta Block 2
 *
 * @param       *sion_filedesc  pointer to internal data structure, contaiing all meta data
 *
 * @retval SION_SUCESS if okay
 */
int _sion_read_header_var_part_blocksizes_rank(_sion_filedesc *sion_filedesc); /* reads part of M21 (one rank) */

/*!\brief Read the size of the mapping data at end of SION Meta Block 2
 *
 * @param       *sion_filedesc  pointer to internal data structure, contaiing all meta data
 *
 *  file pointer will be set to the correct position
 *
 * @retval SION_SUCESS if okay
 */
int _sion_read_header_var_part_mapping_size(_sion_filedesc *sion_filedesc); /* reads part of M22 */

/*!\brief Read the mapping data at end of SION Meta Block 2
 *
 * @param       *sion_filedesc  pointer to internal data structure, contaiing all meta data
 *
 *  file pointer will be set to the correct position
 *
 * @retval SION_SUCESS if okay
 */
int _sion_read_header_var_part_mapping(_sion_filedesc *sion_filedesc); /* reads  M22 */

/*!\brief Read the mapping data at end of SION Meta Block 2
 *
 * @param       *sion_filedesc  pointer to internal data structure, contaiing all meta data
 *
 *  file pointer will be set to the correct position
 *
 * @retval SION_SUCESS if okay
 */
int _sion_read_header_var_part_mapping_rank(_sion_filedesc *sion_filedesc); /* reads part of M22 (one rank) */

/// \brief write the sizes of all logical files to the file header
///
/// \param[in,out] filedesc the file to write to
/// \param[in] sizes array of size `filedesc->ntasks` that contains the sizes of all logical files
///
/// \returns `SION_SUCCESS` if okay
int _sion_write_header_sizes_from_field(_sion_filedesc *filedesc, int64_t *sizes); /* writes M13 */

/// \brief write the sizes of all logical files to the file header
///
/// \param[in,out] filedesc the file to write to
///
/// \returns `SION_SUCCESS` if okay
int _sion_write_header_sizes(_sion_filedesc *filedesc); /* writes M13 */

/* for parallel support, don't read all blocksizes of all tasks in memory */
/*!\brief Read the block sizes from Meta Block 2
 *
 * @param       *sion_filedesc  pointer to internal data structure, contaiing all meta data
 * @param       field_size      size of field
 * @param       field           field where blocksizes will be stored
 *
 * @retval       SION_SUCESS if okay
 */
int _sion_read_header_var_part_blockcount_to_field(_sion_filedesc *sion_filedesc, int field_size, int64_t *field);

/*!\brief Read the next set of blocksizes from Meta Block 2
 *        Assuming that filepointer is at the correct position
 *
 * @param       *sion_filedesc  pointer to internal data structure, contaiing all meta data
 * @param       field_size      size of field
 * @param       field           field where blocksizes will be stored
 *
 * @retval       SION_SUCESS if okay
 */
int _sion_read_header_var_part_nextblocksizes_to_field(_sion_filedesc *sion_filedesc, int field_size, int64_t *field);

#endif

/// \endcond
