/****************************************************************************
**  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 <mpi.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "sion_const.h"
#include "sion_debug.h"
#include "sion_error_handler.h"

#ifdef SION_MPI

#include "sion_mpi.h"

struct _sion_file_check_par_args_mpi_struct {
  char *file_mode;
  int numfiles;
  MPI_Comm gComm;
  MPI_Comm lComm;
};

#define DFUNCTION "_lsion_paropen_generic_buddy"
sion_file_check_par_args_mpi *lsion_file_check_par_args_init_mpi(
  const char *file_mode, MPI_Comm gComm, int numfiles, MPI_Comm lComm)
{
  sion_file_check_par_args_mpi *cb_args;

  cb_args = malloc(sizeof(sion_file_check_par_args_mpi));
  if (cb_args == NULL) {
    _lsion_errorprint(SION_NOT_SUCCESS, _SION_ERROR_RETURN,
      "cannot allocate cb_args structure of size %lu (sion_file_check_par_args), aborting ...\n",
      (unsigned long)sizeof(sion_file_check_par_args_mpi));
    return NULL;
  }

  cb_args->file_mode = strdup(file_mode);
  cb_args->gComm = gComm;
  cb_args->lComm = lComm;
  cb_args->numfiles = numfiles;

  return cb_args;
}
#undef DFUNCTION

#define DFUNCTION "lsion_file_check_par_args_free_mpi"
int lsion_file_check_par_args_free_mpi(sion_file_check_par_args_mpi *cb_args)
{
  int rc = SION_SUCCESS;
  if (cb_args != NULL) {
    free(cb_args->file_mode);
    free(cb_args);
  }
  return rc;
}
#undef DFUNCTION

#define DFUNCTION "lsion_file_check_par_cb_mpi"
int lsion_file_check_par_cb_mpi(char *fname, void *v_args)
{
  sion_file_check_par_args_mpi *cb_args = v_args;
  int rc = SION_NOT_SUCCESS;
  int gtasks, gRank, sid;
  int64_t chunksize = 0;
  int32_t fsblksize = -1;
  int globalrank = -1;

  MPI_Comm_size(cb_args->gComm, &gtasks);
  MPI_Comm_rank(cb_args->gComm, &gRank);

  DPRINTFP((1, DFUNCTION, gRank, "enter parallel check of file %s with mode %s\n", fname, cb_args->file_mode));

  _lsion_errorprint_set_flag(_SION_ERROR_FLAG_SUPPRESS_MSG);
  sid = lsion_paropen_mpi(fname, cb_args->file_mode, &cb_args->numfiles, cb_args->gComm, &cb_args->lComm, &chunksize, &fsblksize,
    &globalrank, NULL, NULL);
  _lsion_errorprint_set_flag(_SION_ERROR_FLAG_NONE);
  if (sid < 0) {
    rc = SION_NOT_SUCCESS;
  } else {
    rc = SION_SUCCESS;
    lsion_parclose_mpi(sid);
  }

  DPRINTFP((1, DFUNCTION, gRank, "leave parallel check of file %s with mode %s rc=%d\n", fname, cb_args->file_mode, rc));
  return rc;
}
#undef DFUNCTION

#endif
