/****************************************************************************
**  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 <ctype.h>
#include <inttypes.h>
#include <math.h>
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include "sion.h"

int main(int argc, char **argv)
{
  int rank, size;

  /* -------------------------- */
  /* PROLOG */
  /* -------------------------- */

  MPI_Init(&argc, &argv);
  MPI_Comm_size(MPI_COMM_WORLD, &size);
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);

  /* ------------------------------------------------------- */
  /* TEST B: write a  file with some chunks < fs block size  */
  /* ------------------------------------------------------- */
  {
#define BUFSIZE 100
#define CHUNKSIZE 1000
    int64_t chunksize;
    int sid;
    char buffer[BUFSIZE];
    int64_t bytes_written = 0;
    long sum;
    size_t bwrote;
    int i;
    sion_mpi_options options = sion_mpi_options_new();

    sion_mpi_options_set_chunksize(&options, CHUNKSIZE);
    sion_mpi_options_set_fsblksize(&options, 1000);

    for (i = 0; i < BUFSIZE; i++) {
      buffer[i] = 'A' + rank;
    }

    sid = sion_paropen_mpi_with_options("testB.out", SION_OPEN_WRITE, MPI_COMM_WORLD, &options);

    if (sid >= 0) {
      chunksize = sion_get_chunksize(sid);
      bytes_written = 0;
      while (bytes_written < chunksize) {
        bwrote = sion_fwrite(buffer, 1, BUFSIZE, sid);
        bytes_written += bwrote;
        printf("on rank %d: bytes_written=%" PRId64 "\n", rank, bytes_written);
        for (i = 0, sum = 0; i < bwrote; i++) {
          sum = sum + buffer[i];
        }
        printf("on rank %d: bwrote=%3d blocksum=%8d \n", rank, (int)bwrote, (int)sum);
      }
      sion_parclose_mpi(sid);
    } else {
      fprintf(stderr, "on rank %d: error sid = %d\n", rank, sid);
    }
  }

  fflush(stderr);
  fflush(stdout);
  MPI_Barrier(MPI_COMM_WORLD);
  printf("on rank %d: END of TEST B write\n", rank);
  MPI_Barrier(MPI_COMM_WORLD);

  /* ------------------------------------------------------- */
  /* TEST C: write a  file with some chunks > fs block size  */
  /* ------------------------------------------------------- */
  {
#define BUFSIZE2 110
#define CHUNKSIZE 1000
    int64_t chunksize;
    int sid;
    char buffer[BUFSIZE2];
    int64_t bytes_written = 0;
    long sum;
    size_t bwrote;
    int i;
    sion_mpi_options options = sion_mpi_options_new();

    sion_mpi_options_set_chunksize(&options, CHUNKSIZE);
    sion_mpi_options_set_fsblksize(&options, 100);

    for (i = 0; i < BUFSIZE2; i++) {
      buffer[i] = 'A' + rank;
    }

    sid = sion_paropen_mpi_with_options("testC.out", SION_OPEN_WRITE, MPI_COMM_WORLD, &options);

    if (sid >= 0) {
      chunksize = sion_get_chunksize(sid);
      bytes_written = 0;
      while (bytes_written < 2 * chunksize) {
        bwrote = sion_fwrite(buffer, 1, BUFSIZE2, sid);
        bytes_written += bwrote;
        printf("on rank %d: bytes_written=%" PRId64 "\n", rank, bytes_written);
        for (i = 0, sum = 0; i < bwrote; i++) {
          sum = sum + buffer[i];
        }
        printf("on rank %d: bwrote=%3d blocksum=%8d \n", rank, (int)bwrote, (int)sum);
      }
      sion_parclose_mpi(sid);
    } else {
      fprintf(stderr, "on rank %d: error sid = %d\n", rank, sid);
    }
  }

  fflush(stderr);
  fflush(stdout);
  MPI_Barrier(MPI_COMM_WORLD);
  printf("on rank %d: END of TEST C write\n", rank);
  MPI_Barrier(MPI_COMM_WORLD);

  /* -------------------------- */
  /* EPILOG */
  /* -------------------------- */
  MPI_Finalize();

  return 0;
}
