/****************************************************************************
**  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       **
****************************************************************************/

#ifndef SION_SION_OMP_H
#define SION_SION_OMP_H

#ifdef SION_OMP

/// \defgroup omp OpenMP Parallel API
/// @{
/// \brief Open (and close) SIONlib files from multiple OpenMP threads in parallel

#include <stdint.h>
#include <stdio.h>

#include "sion_const.h"

#ifdef __cplusplus
extern "C" {
#endif

/// \brief Holds non-essential arguments for `lsion_paropen_omp()`.
///
/// These are:
/// - the sizes of chunks for the logical file opened by this task,
/// - the size of a file system block to assume,
/// - whether and in what mode to use SIONlib's key-value mechanism,
/// - whether to use collective I/O,
/// - what low-level API to use for file system access,
/// - the endianness of user data in the file.
typedef struct sion_omp_options sion_omp_options;

/// \brief Open a SIONlib file from multiple OpenMP threads.
///
/// This function opens a distinct logical file in a SIONlib container for each
/// OpenMP thread that calls it.
///
/// \param[in] filename name of file, should be equal on all threads
/// \param[in] mode whether to open the file for reading or writing
/// \param[in] options additional options, or `NULL`
///
/// \returns a SIONlib file handle or -1 if an error occurred
int lsion_paropen_omp(const char *filename, sion_open_mode mode, const sion_omp_options *options);

/// \brief closes a SIONlib file previously opened in OpenMP mode
///
/// \param[in] sid SIONlib file id
///
/// \returns success value (SION_SUCCESS or SION_NOT_SUCCESS)
int lsion_parclose_omp(int sid);

/// \brief Allocates and initializes an instance of `sion_omp_options`
///
/// \returns a pointer to the new instance or `NULL` if allocation failed
sion_omp_options *lsion_omp_options_new();

/// \brief Delete an instance of `sion_omp_options`
///
/// \param[in] options a pointer to the instance to delete
void lsion_omp_options_delete(sion_omp_options *options);

/// \brief Set the chunk size of a logical file in the container
///
/// \param[in,out] options an options object
/// \param[in] chunksize chunk sizes for the logical file opened by this process
void lsion_omp_options_set_chunksize(sion_omp_options *options, int64_t chunksize);

/// \brief Set the file system block size to assume.
///
/// \param[in,out] options an options object
/// \param[in] fsblksize the file system block size
void lsion_omp_options_set_fsblksize(sion_omp_options *options, int32_t fsblksize);

/// \brief Set the key-value mode to use for a container.
///
/// \param[in,out] options an options object
/// \param[in] keyval_mode the key-value mode to use
void lsion_omp_options_set_keyval_mode(sion_omp_options *options, sion_keyval_mode keyval_mode);

/// \brief Enable collective I/O
///
/// The size of collector groups will be determined via heuristics.
///
/// \see collective
///
/// \param[in] options an options object
void lsion_omp_options_set_collective(sion_omp_options *options);

/// \brief Enable collective I/O
///
/// \see collective
///
/// \param[in] options an options object
/// \param[in] size size of the collector groups
void lsion_omp_options_set_collective_size(sion_omp_options *options, int32_t size);

/// \brief Use collective merging
///
/// \see collective
///
/// \param[in] options an options object
void lsion_omp_options_set_collective_merge(sion_omp_options *options);

/// \brief Set the low-level API to use for opening a container.
///
/// \param[in,out] options an options object
/// \param[in] lowlevel_api the low-level API to use
void lsion_omp_options_set_lowlevel_api(sion_omp_options *options, sion_lowlevel_api lowlevel_api);

/// \brief Set the endianness for the contents of a container
///
/// \param[in,out] options an options object
/// \param[in] endianness the endianness of the contents
void lsion_omp_options_set_endianness(sion_omp_options *options, sion_endianness endianness);

#ifdef __cplusplus
}
#endif

/// @}

#endif

#endif
