/*
 * 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;

	io_u->error = 0;
	io_u->resid = 0;

	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;
}

int td_io_open_file(struct thread_data *td, struct fio_file *f)
{
	if (td->io_ops->open_file(td, f))
		return 1;

	f->last_free_lookup = 0;
	f->last_completed_pos = 0;
	f->last_pos = 0;
	f->open = 1;

	if (f->file_map)
		memset(f->file_map, 0, f->num_maps * sizeof(long));

	td->nr_open_files++;
	return 0;
}

void td_io_close_file(struct thread_data *td, struct fio_file *f)
{
	if (f->open) {
		if (td->io_ops->close_file)
			td->io_ops->close_file(td, f);
		td->nr_open_files--;
		f->open = 0;
	}
}
