/*========================================================================
 * Copyright (C) VMware, Inc. 1986-2011.  All Rights Reserved..
 *
 * Name - asyncio.c
 *
 * Description - Verify that async disk I/O is functional on a Unix host
 *
 * $Id: asyncio.c,v 1.10 2008-01-09 22:50:48 stever Exp $
 *
 *========================================================================
 */
#include "flag.ht"

#if defined(FLG_LINUX_UNIX)
#define FLG_LINUX_USE_LIBPOSIXAIO 1
#endif

#if defined(FLG_APPLE_UNIX)
#include <unistd.h>
#endif

#include "aio.hf"

#include "global.ht"

#undef strerror

enum { BUFFER_SIZE = 1024 };

static char buff[BUFFER_SIZE];


static void showErrno(int num)
{
  printf("  errno = %d (%s)\n", num, strerror(num));
}


static int doWrite(int fd)
{
  struct aiocb aioReq;
  int done, ioErr;

  memset(&aioReq, 0, sizeof(aioReq));
  aioReq.aio_buf = buff;
  aioReq.aio_nbytes = sizeof(buff);
  aioReq.aio_offset = 0;
  aioReq.aio_fildes = fd;

  if (aio_write(&aioReq) != 0) {
    fprintf(stderr, "aio_write() failed\n");
    showErrno(errno);
    return 1;
    }
  done = 0;
  ioErr = 0;
  for (;;) {
    struct aiocb *aioList[1];
    int status;
    aioList[0] = &aioReq;
    status = aio_suspend(aioList, 1, NULL);
    if (status == 0) {
      break;
    } else {
      int errNum = errno;
      if (errNum == EINTR) {
        ioErr = aio_error(&aioReq);
        if ( ioErr == EINPROGRESS) {
          continue;
        } else {
          done = 1;
          break;
        }
      }
      fprintf(stderr, "aio_suspend failed\n");
      showErrno(errNum);
      return 1;
    }
  }
  if (! done) {
    ioErr = aio_error(&aioReq); 
  }
  if (ioErr != 0) {
    fprintf(stderr, "aio_error says write failed with: ");
    showErrno(ioErr); 
  }
  return 0;
}

int main(int argc, char *argv[])
{
  int result = 0;
  int fd;

  if (argc != 2) {
    fprintf(stderr, "Usage: asyncio <scratchFile>\n");
    fprintf(stderr, "    scratchFile is the file to write with\n");

    fprintf(stderr, "Tests validity of async disk i/o on this host.\n");
    return 1;
    }

  fd = open(argv[1], O_RDWR, S_IREAD|S_IWRITE|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
  if (fd == -1) {
    fprintf(stderr, "open() failure on %s\n", argv[1]);
    showErrno(errno);
    return 1;
    }

  if (doWrite(fd))
    result = 1;

  return result;
}
