/*
 * Copyright (c) International Business Machines Corp., 2006
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
 * the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * Author: Artem B. Bityutskiy
 *
 * This test does a lot of I/O to volumes in parallel.
 */

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "libubi.h"
#define PROGRAM_NAME "io_paral"
#include "common.h"
#include "helpers.h"

#define THREADS_NUM 4
#define ITERATIONS  (1024 * 1)
#define VOL_LEBS    10

static libubi_t libubi;
static struct ubi_dev_info dev_info;
static const char *node;
static int vol_size;

static struct ubi_mkvol_request reqests[THREADS_NUM + 1];
static char vol_name[THREADS_NUM + 1][100];
static char vol_nodes[THREADS_NUM + 1][sizeof(UBI_VOLUME_PATTERN) + 99];
static unsigned char *wbufs[THREADS_NUM + 1];
static unsigned char *rbufs[THREADS_NUM + 1];

static int update_volume(int vol_id, int bytes)
{
	int i, fd, ret, written = 0, rd = 0;
	char *vol_node = vol_nodes[vol_id];
	unsigned char *wbuf = wbufs[vol_id];
	unsigned char *rbuf = rbufs[vol_id];

	fd = open(vol_node, O_RDWR);
	if (fd == -1) {
		failed("open");
		errorm("cannot open \"%s\"\n", vol_node);
		return -1;
	}

	for (i = 0; i < bytes; i++)
		wbuf[i] = rand() % 255;
	memset(rbuf, '\0', bytes);

	ret = ubi_update_start(libubi, fd, bytes);
	if (ret) {
		failed("ubi_update_start");
		errorm("volume id is %d", vol_id);
		goto err_close;
	}

	while (written < bytes) {
		int to_write = rand() % (bytes - written);

		if (to_write == 0)
			to_write = 1;

		ret = write(fd, wbuf + written, to_write);
		if (ret != to_write) {
			failed("write");
			errorm("failed to write %d bytes at offset %d "
			       "of volume %d", to_write, written,
			       vol_id);
			errorm("update: %d bytes", bytes);
			goto err_close;
		}

		written += to_write;
	}

	close(fd);

	fd = open(vol_node, O_RDONLY);
	if (fd == -1) {
		failed("open");
		errorm("cannot open \"%s\"\n", node);
		return -1;
	}

	/* read data back and check */
	while (rd < bytes) {
		int to_read = rand() % (bytes - rd);

		if (to_read == 0)
			to_read = 1;

		ret = read(fd, rbuf + rd, to_read);
		if (ret != to_read) {
			failed("read");
			errorm("failed to read %d bytes at offset %d "
			       "of volume %d", to_read, rd, vol_id);
			goto err_close;
		}

		rd += to_read;
	}

	if (memcmp(wbuf, rbuf, bytes)) {
		errorm("written and read data are different");
		goto err_close;
	}

	close(fd);
	return 0;

err_close:
	close(fd);
	return -1;
}

static void *update_thread(void *ptr)
{
	int vol_id = (long)ptr, i;

	for (i = 0; i < ITERATIONS; i++) {
		int ret, bytes = (rand() % (vol_size - 1)) + 1;
		int remove = !(rand() % 16);

		/* From time to time remove the volume */
		if (remove) {
			ret = ubi_rmvol(libubi, node, vol_id);
			if (ret) {
				failed("ubi_rmvol");
				errorm("cannot remove volume %d", vol_id);
				return NULL;
			}
			ret = ubi_mkvol(libubi, node, &reqests[vol_id]);
			if (ret) {
				failed("ubi_mkvol");
				errorm("cannot create volume %d", vol_id);
				return NULL;
			}
		}

		ret = update_volume(vol_id, bytes);
		if (ret)
			return NULL;
	}

	return NULL;
}

static void *write_thread(void *ptr)
{
	int ret, fd, vol_id = (long)ptr, i;
	char *vol_node = vol_nodes[vol_id];
	unsigned char *wbuf = wbufs[vol_id];
	unsigned char *rbuf = rbufs[vol_id];

	fd = open(vol_node, O_RDWR);
	if (fd == -1) {
		failed("open");
		errorm("cannot open \"%s\"\n", vol_node);
		return NULL;
	}

	ret = ubi_set_property(fd, UBI_VOL_PROP_DIRECT_WRITE, 1);
	if (ret) {
		failed("ubi_set_property");
		errorm("cannot set property for \"%s\"\n", vol_node);
	}

	for (i = 0; i < ITERATIONS * VOL_LEBS; i++) {
		int j, leb = rand() % VOL_LEBS;
		off_t offs = dev_info.leb_size * leb;

		ret = ubi_leb_unmap(fd, leb);
		if (ret) {
			failed("ubi_leb_unmap");
			errorm("cannot unmap LEB %d", leb);
			break;
		}

		for (j = 0; j < dev_info.leb_size; j++)
			wbuf[j] = rand() % 255;
		memset(rbuf, '\0', dev_info.leb_size);

		ret = pwrite(fd, wbuf, dev_info.leb_size, offs);
		if (ret != dev_info.leb_size) {
			failed("pwrite");
			errorm("cannot write %d bytes to offs %lld, wrote %d",
				dev_info.leb_size, offs, ret);
			break;
		}

		/* read data back and check */
		ret = pread(fd, rbuf, dev_info.leb_size, offs);
		if (ret != dev_info.leb_size) {
			failed("read");
			errorm("failed to read %d bytes at offset %d "
			       "of volume %d", dev_info.leb_size, offs,
			       vol_id);
			break;
		}

		if (memcmp(wbuf, rbuf, dev_info.leb_size)) {
			errorm("written and read data are different");
			break;
		}
	}

	close(fd);
	return NULL;
}

int main(int argc, char * const argv[])
{
	int i, ret;
	pthread_t threads[THREADS_NUM];

	seed_random_generator();
	if (initial_check(argc, argv))
		return 1;

	node = argv[1];

	libubi = libubi_open();
	if (libubi == NULL) {
		failed("libubi_open");
		return 1;
	}

	if (ubi_get_dev_info(libubi, node, &dev_info)) {
		failed("ubi_get_dev_info");
		goto close;
	}

	/*
	 * Create 1 volume more than threads count. The last volume
	 * will not change to let WL move more stuff.
	 */
	vol_size = dev_info.leb_size * VOL_LEBS;
	for (i = 0; i <= THREADS_NUM; i++) {
		reqests[i].alignment = 1;
		reqests[i].bytes = vol_size;
		reqests[i].vol_id = i;
		sprintf(vol_name[i], PROGRAM_NAME":%d", i);
		reqests[i].name = vol_name[i];
		reqests[i].vol_type = UBI_DYNAMIC_VOLUME;
		if (i == THREADS_NUM)
			reqests[i].vol_type = UBI_STATIC_VOLUME;
		sprintf(vol_nodes[i], UBI_VOLUME_PATTERN, dev_info.dev_num, i);

		if (ubi_mkvol(libubi, node, &reqests[i])) {
			failed("ubi_mkvol");
			goto remove;
		}

		wbufs[i] = malloc(vol_size);
		rbufs[i] = malloc(vol_size);
		if (!wbufs[i] || !rbufs[i]) {
			failed("malloc");
			goto remove;
		}

		ret = update_volume(i, vol_size);
		if (ret)
			goto remove;
	}

	for (i = 0; i < THREADS_NUM / 2; i++) {
		ret = pthread_create(&threads[i], NULL, &write_thread, (void *)(long)i);
		if (ret) {
			failed("pthread_create");
			goto remove;
		}
	}

	for (i = THREADS_NUM / 2; i < THREADS_NUM; i++) {
		ret = pthread_create(&threads[i], NULL, &update_thread, (void *)(long)i);
		if (ret) {
			failed("pthread_create");
			goto remove;
		}
	}

	for (i = 0; i < THREADS_NUM; i++)
		pthread_join(threads[i], NULL);

	for (i = 0; i <= THREADS_NUM; i++) {
		if (ubi_rmvol(libubi, node, i)) {
			failed("ubi_rmvol");
			goto remove;
		}
		if (wbufs[i])
			free(wbufs[i]);
		if (rbufs[i])
			free(rbufs[i]);
		wbufs[i] = NULL;
		rbufs[i] = NULL;
	}

	libubi_close(libubi);
	return 0;

remove:
	for (i = 0; i <= THREADS_NUM; i++) {
		ubi_rmvol(libubi, node, i);
		if (wbufs[i])
			free(wbufs[i]);
		if (rbufs[i])
			free(rbufs[i]);
		wbufs[i] = NULL;
		rbufs[i] = NULL;
	}

close:
	libubi_close(libubi);
	return 1;
}
