/*
 * guasi engine
 *
 * IO engine using the GUASI library.
 *
 * This is currently disabled. To enable it, execute:
 *
 * $ export EXTFLAGS="-DFIO_HAVE_GUASI"
 * $ export EXTLIBS="-lguasi"
 *
 * before running make. You'll need the GUASI lib as well:
 *
 * http://www.xmailserver.org/guasi-lib.html
 *
 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <assert.h>

#include "../fio.h"

#ifdef FIO_HAVE_GUASI

#define GFIO_MIN_THREADS 32
#ifndef GFIO_MAX_THREADS
#define GFIO_MAX_THREADS 2000
#endif

#include <guasi.h>
#include <guasi_syscalls.h>

#ifdef GFIO_DEBUG
#define GDBG_PRINT(a) printf a
#else
#define GDBG_PRINT(a) (void) 0
#endif

struct guasi_data {
	guasi_t hctx;
	int max_reqs;
	guasi_req_t *reqs;
	struct io_u **io_us;
	int queued_nr;
	int reqs_nr;
};

static int fio_guasi_prep(struct thread_data fio_unused *td, struct io_u *io_u)
{

	GDBG_PRINT(("fio_guasi_prep(%p)\n", io_u));
	io_u->greq = NULL;

	return 0;
}

static struct io_u *fio_guasi_event(struct thread_data *td, int event)
{
	struct guasi_data *ld = td->io_ops->data;
	struct io_u *io_u;
	struct guasi_reqinfo rinf;

	GDBG_PRINT(("fio_guasi_event(%d)\n", event));
	if (guasi_req_info(ld->reqs[event], &rinf) < 0) {
		log_err("guasi_req_info(%d) FAILED!\n", event);
		return NULL;
	}
	io_u = rinf.asid;
	io_u->error = EINPROGRESS;
	GDBG_PRINT(("fio_guasi_event(%d) -> %p\n", event, io_u));
	if (rinf.status == GUASI_STATUS_COMPLETE) {
		io_u->error = rinf.result;
		if (io_u->ddir == DDIR_READ ||
		    io_u->ddir == DDIR_WRITE) {
			io_u->error = 0;
			if (rinf.result != (long) io_u->xfer_buflen) {
				if (rinf.result >= 0)
					io_u->resid = io_u->xfer_buflen - rinf.result;
				else
					io_u->error = rinf.error;
			}
		}
	}

	return io_u;
}

static int fio_guasi_getevents(struct thread_data *td, unsigned int min,
			       unsigned int max, struct timespec *t)
{
	struct guasi_data *ld = td->io_ops->data;
	int n, r;
	long timeo = -1;

	GDBG_PRINT(("fio_guasi_getevents(%d, %d)\n", min, max));
	if (min > ld->max_reqs)
		min = ld->max_reqs;
	if (max > ld->max_reqs)
		max = ld->max_reqs;
	if (t)
		timeo = t->tv_sec * 1000L + t->tv_nsec / 1000000L;
	for (n = 0; n < ld->reqs_nr; n++)
		guasi_req_free(ld->reqs[n]);
	n = 0;
	do {
		r = guasi_fetch(ld->hctx, ld->reqs + n, min - n,
				max - n, timeo);
		if (r < 0) {
			log_err("guasi_fetch() FAILED! (%d)\n", r);
			break;
		}
		n += r;
		if (n >= min)
			break;
	} while (1);
	ld->reqs_nr = n;
	GDBG_PRINT(("fio_guasi_getevents() -> %d\n", n));

	return n;
}

static int fio_guasi_queue(struct thread_data *td, struct io_u *io_u)
{
	struct guasi_data *ld = td->io_ops->data;

	fio_ro_check(td, io_u);

	GDBG_PRINT(("fio_guasi_queue(%p)\n", io_u));
	if (ld->queued_nr == (int) td->o.iodepth)
		return FIO_Q_BUSY;

	ld->io_us[ld->queued_nr] = io_u;
	ld->queued_nr++;
	return FIO_Q_QUEUED;
}

static void fio_guasi_queued(struct thread_data *td, struct io_u **io_us, int nr)
{
	int i;
	struct io_u *io_u;
	struct timeval now;

	fio_gettime(&now, NULL);
	for (i = 0; i < nr; i++) {
		io_u = io_us[i];
		memcpy(&io_u->issue_time, &now, sizeof(now));
		io_u_queued(td, io_u);
	}
}

static int fio_guasi_commit(struct thread_data *td)
{
	struct guasi_data *ld = td->io_ops->data;
	int i;
	struct io_u *io_u;
	struct fio_file *f;

	GDBG_PRINT(("fio_guasi_commit(%d)\n", ld->queued_nr));
	for (i = 0; i < ld->queued_nr; i++) {
		io_u = ld->io_us[i];
		GDBG_PRINT(("fio_guasi_commit(%d) --> %p\n", i, io_u));
		f = io_u->file;
		io_u->greq = NULL;
		if (io_u->ddir == DDIR_READ)
			io_u->greq = guasi__pread(ld->hctx, ld, io_u, 0,
						  f->fd, io_u->xfer_buf, io_u->xfer_buflen,
						  io_u->offset);
		else if (io_u->ddir == DDIR_WRITE)
			io_u->greq = guasi__pwrite(ld->hctx, ld, io_u, 0,
						   f->fd, io_u->xfer_buf, io_u->xfer_buflen,
						   io_u->offset);
		else if (io_u->ddir == DDIR_SYNC)
			io_u->greq = guasi__fsync(ld->hctx, ld, io_u, 0, f->fd);
		else {
			log_err("fio_guasi_commit() FAILED: unknow request %d\n",
				io_u->ddir);
		}
		if (io_u->greq == NULL) {
			log_err("fio_guasi_commit() FAILED: submit failed (%s)\n",
				strerror(errno));
			return -1;
		}
	}
	fio_guasi_queued(td, ld->io_us, i);
	ld->queued_nr = 0;
	GDBG_PRINT(("fio_guasi_commit() -> %d\n", i));

	return 0;
}

static int fio_guasi_cancel(struct thread_data fio_unused *td,
			    struct io_u *io_u)
{
	GDBG_PRINT(("fio_guasi_cancel(%p) req=%p\n", io_u, io_u->greq));
	if (io_u->greq != NULL)
		guasi_req_cancel(io_u->greq);

	return 0;
}

static void fio_guasi_cleanup(struct thread_data *td)
{
	struct guasi_data *ld = td->io_ops->data;
	int n;

	GDBG_PRINT(("fio_guasi_cleanup(%p)\n", ld));
	if (ld) {
		for (n = 0; n < ld->reqs_nr; n++)
			guasi_req_free(ld->reqs[n]);
		guasi_free(ld->hctx);
		free(ld->reqs);
		free(ld->io_us);
		free(ld);
		td->io_ops->data = NULL;
	}
	GDBG_PRINT(("fio_guasi_cleanup(%p) DONE\n", ld));
}

static int fio_guasi_init(struct thread_data *td)
{
	int maxthr;
	struct guasi_data *ld = malloc(sizeof(*ld));

	GDBG_PRINT(("fio_guasi_init(): depth=%d\n", td->o.iodepth));
	memset(ld, 0, sizeof(*ld));
	maxthr = td->o.iodepth > GFIO_MIN_THREADS ? td->o.iodepth: GFIO_MIN_THREADS;
	if (maxthr > GFIO_MAX_THREADS)
		maxthr = GFIO_MAX_THREADS;
	if ((ld->hctx = guasi_create(GFIO_MIN_THREADS, maxthr, 1)) == NULL) {
		td_verror(td, errno, "guasi_create");
		free(ld);
		return 1;
	}
	ld->max_reqs = td->o.iodepth;
	ld->reqs = malloc(ld->max_reqs * sizeof(guasi_req_t));
	ld->io_us = malloc(ld->max_reqs * sizeof(struct io_u *));
	memset(ld->io_us, 0, ld->max_reqs * sizeof(struct io_u *));
	ld->queued_nr = 0;
	ld->reqs_nr = 0;

	td->io_ops->data = ld;
	GDBG_PRINT(("fio_guasi_init(): depth=%d -> %p\n", td->o.iodepth, ld));

	return 0;
}

static struct ioengine_ops ioengine = {
	.name		= "guasi",
	.version	= FIO_IOOPS_VERSION,
	.init		= fio_guasi_init,
	.prep		= fio_guasi_prep,
	.queue		= fio_guasi_queue,
	.commit		= fio_guasi_commit,
	.cancel		= fio_guasi_cancel,
	.getevents	= fio_guasi_getevents,
	.event		= fio_guasi_event,
	.cleanup	= fio_guasi_cleanup,
	.open_file	= generic_open_file,
	.close_file	= generic_close_file,
};

#else /* FIO_HAVE_GUASI */

/*
 * When we have a proper configure system in place, we simply wont build
 * and install this io engine. For now install a crippled version that
 * just complains and fails to load.
 */
static int fio_guasi_init(struct thread_data fio_unused *td)
{
	fprintf(stderr, "fio: guasi not available\n");
	return 1;
}

static struct ioengine_ops ioengine = {
	.name		= "guasi",
	.version	= FIO_IOOPS_VERSION,
	.init		= fio_guasi_init,
};

#endif

static void fio_init fio_guasi_register(void)
{
	register_ioengine(&ioengine);
}

static void fio_exit fio_guasi_unregister(void)
{
	unregister_ioengine(&ioengine);
}

