/*
 * The io parts of the fio tool, includes workers for sync and mmap'ed
 * io, as well as both posix and linux libaio support.
 *
 * sync io is implemented on top of aio.
 *
 * This is not really specific to fio, if the get_io_u/put_io_u and
 * structures was pulled into this as well it would be a perfectly
 * generic io engine that could be used for other projects.
 *
 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <dlfcn.h>
#include <assert.h>

#include "fio.h"
#include "os.h"

static LIST_HEAD(engine_list);

static int check_engine_ops(struct ioengine_ops *ops)
{
	if (ops->version != FIO_IOOPS_VERSION) {
		log_err("bad ioops version %d (want %d)\n", ops->version, FIO_IOOPS_VERSION);
		return 1;
	}

	/*
	 * cpu thread doesn't need to provide anything
	 */
	if (ops->flags & FIO_CPUIO)
		return 0;

	if (!ops->queue) {
		log_err("%s: no queue handler\n", ops->name);
		return 1;
	}

	/*
	 * sync engines only need a ->queue()
	 */
	if (ops->flags & FIO_SYNCIO)
		return 0;
	
	if (!ops->event) {
		log_err("%s: no event handler\n", ops->name);
		return 1;
	}
	if (!ops->getevents) {
		log_err("%s: no getevents handler\n", ops->name);
		return 1;
	}
	if (!ops->queue) {
		log_err("%s: no queue handler\n", ops->name);
		return 1;
	}
		
	return 0;
}

void unregister_ioengine(struct ioengine_ops *ops)
{
	list_del(&ops->list);
	INIT_LIST_HEAD(&ops->list);
}

void register_ioengine(struct ioengine_ops *ops)
{
	INIT_LIST_HEAD(&ops->list);
	list_add_tail(&ops->list, &engine_list);
}

static struct ioengine_ops *find_ioengine(const char *name)
{
	struct ioengine_ops *ops;
	struct list_head *entry;

	list_for_each(entry, &engine_list) {
		ops = list_entry(entry, struct ioengine_ops, list);
		if (!strcmp(name, ops->name))
			return ops;
	}

	return NULL;
}

static struct ioengine_ops *dlopen_ioengine(struct thread_data *td,
					    const char *engine_lib)
{
	struct ioengine_ops *ops;
	void *dlhandle;

	dlerror();
	dlhandle = dlopen(engine_lib, RTLD_LAZY);
	if (!dlhandle) {
		td_vmsg(td, -1, dlerror(), "dlopen");
		return NULL;
	}

	/*
	 * Unlike the included modules, external engines should have a
	 * non-static ioengine structure that we can reference.
	 */
	ops = dlsym(dlhandle, "ioengine");
	if (!ops) {
		td_vmsg(td, -1, dlerror(), "dlsym");
		dlclose(dlhandle);
		return NULL;
	}

	ops->dlhandle = dlhandle;
	return ops;
}

struct ioengine_ops *load_ioengine(struct thread_data *td, const char *name)
{
	struct ioengine_ops *ops, *ret;
	char engine[16];

	strncpy(engine, name, sizeof(engine) - 1);

	/*
	 * linux libaio has alias names, so convert to what we want
	 */
	if (!strncmp(engine, "linuxaio", 8) || !strncmp(engine, "aio", 3))
		strcpy(engine, "libaio");

	ops = find_ioengine(engine);
	if (!ops)
		ops = dlopen_ioengine(td, name);

	if (!ops) {
		log_err("fio: engine %s not loadable\n", name);
		return NULL;
	}

	/*
	 * Check that the required methods are there.
	 */
	if (check_engine_ops(ops))
		return NULL;

	ret = malloc(sizeof(*ret));
	memcpy(ret, ops, sizeof(*ret));
	ret->data = NULL;

	return ret;
}

void close_ioengine(struct thread_data *td)
{
	if (td->io_ops->cleanup)
		td->io_ops->cleanup(td);

	if (td->io_ops->dlhandle)
		dlclose(td->io_ops->dlhandle);

#if 0
	/* we can't do this for threads, so just leak it, it's exiting */
	free(td->io_ops);
#endif
	td->io_ops = NULL;
}

int td_io_prep(struct thread_data *td, struct io_u *io_u)
{
	if (td->io_ops->prep)
		return td->io_ops->prep(td, io_u);

	return 0;
}

int td_io_getevents(struct thread_data *td, int min, int max,
		    struct timespec *t)
{
	if (min > 0 && td->io_ops->commit) {
		int r = td->io_ops->commit(td);

		if (r < 0)
			return r;
	}
	if (td->io_ops->getevents)
		return td->io_ops->getevents(td, min, max, t);

	return 0;
}

int td_io_queue(struct thread_data *td, struct io_u *io_u)
{
	int ret;

	assert((io_u->flags & IO_U_F_FLIGHT) == 0);
	io_u->flags |= IO_U_F_FLIGHT;

	if (td->io_ops->flags & FIO_SYNCIO) {
		fio_gettime(&io_u->issue_time, NULL);

		/*
		 * for a sync engine, set the timeout upfront
		 */
		if (mtime_since(&td->timeout_end, &io_u->issue_time) < IO_U_TIMEOUT)
			io_u_set_timeout(td);
	}

	if (io_u->ddir != DDIR_SYNC)
		td->io_issues[io_u->ddir]++;

	ret = td->io_ops->queue(td, io_u);

	if (ret == FIO_Q_QUEUED) {
		int r;

		td->io_u_queued++;
		if (td->io_u_queued > td->iodepth_batch) {
			r = td_io_commit(td);
			if (r < 0)
				return r;
		}
	}

	if ((td->io_ops->flags & FIO_SYNCIO) == 0) {
		fio_gettime(&io_u->issue_time, NULL);

		/*
		 * async engine, set the timeout here
		 */
		if (ret == FIO_Q_QUEUED &&
		    mtime_since(&td->timeout_end, &io_u->issue_time) < IO_U_TIMEOUT)
			io_u_set_timeout(td);
	}

	return ret;
}

int td_io_init(struct thread_data *td)
{
	if (td->io_ops->init)
		return td->io_ops->init(td);

	return 0;
}

int td_io_commit(struct thread_data *td)
{
	if (!td->cur_depth)
		return 0;

	td->io_u_queued = 0;
	if (td->io_ops->commit)
		return td->io_ops->commit(td);

	return 0;
}
