/*
 * blktrace output analysis: generate a timeline & gather statistics
 *
 * Copyright (C) 2006 Alan D. Brunelle <Alan.Brunelle@hp.com>
 *
 *  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */
#include <float.h>
#include "globals.h"

struct seek_bkt {
	struct rb_node rb_node;
	long long sectors;
	int nseeks;
};

/* Seeks per second */
struct sps_bkt {
	double t_start, t_last;
	unsigned long nseeks;
};

struct seeki {
	FILE *rfp, *wfp, *cfp, *sps_fp;
	struct rb_root root;
	struct sps_bkt sps;
	long long tot_seeks;
	double total_sectors;
	long long last_start, last_end;
};

static FILE *seek_open(char *str, char rw)
{
	FILE *fp;
	char *oname;

	if (seek_name == NULL) return NULL;

	oname = malloc(strlen(seek_name) + strlen(str) + 32);
	sprintf(oname, "%s_%s_%c.dat", seek_name, str, rw);
	if ((fp = my_fopen(oname, "w")) == NULL) {
		perror(oname);
		free(oname);
	} else
		add_file(fp, oname);

	return fp;
}

static void __insert(struct rb_root *root, long long sectors)
{
	struct seek_bkt *sbp;
	struct rb_node *parent = NULL;
	struct rb_node **p = &root->rb_node;

	while (*p) {
		parent = *p;
		sbp = rb_entry(parent, struct seek_bkt, rb_node);
		if (sectors < sbp->sectors)
			p = &(*p)->rb_left;
		else if (sectors > sbp->sectors)
			p = &(*p)->rb_right;
		else {
			sbp->nseeks++;
			return;
		}
	}

	sbp = malloc(sizeof(struct seek_bkt));
	sbp->nseeks = 1;
	sbp->sectors = sectors;

	rb_link_node(&sbp->rb_node, parent, p);
	rb_insert_color(&sbp->rb_node, root);
}

static void __destroy(struct rb_node *n)
{
	if (n) {
		struct seek_bkt *sbp = rb_entry(n, struct seek_bkt, rb_node);

		__destroy(n->rb_left);
		__destroy(n->rb_right);
		free(sbp);
	}
}

static void sps_emit(struct seeki *sip)
{
	double s_p_s;
	struct sps_bkt *sps = &sip->sps;
	double delta = sps->t_last - sps->t_start;

	if ((sps->nseeks == 1) || (delta < DBL_EPSILON))
		s_p_s = (double)(sps->nseeks);
	else
		s_p_s = (double)(sps->nseeks) / delta;

	fprintf(sip->sps_fp, "%15.9lf %.2lf\n", sps->t_start, s_p_s);

	sps->t_start = 0;
	sps->nseeks = 0;
}

static void sps_add(struct seeki *sip, double t)
{
	if (sip->sps_fp) {
		struct sps_bkt *sps = &sip->sps;

		if (sps->nseeks != 0 && ((t - sps->t_start) >= 1.0))
			sps_emit(sip);

		sps->t_last = t;
		if (sps->nseeks == 0) {
			sps->t_start = t;
			sps->nseeks = 1;
		} else
			sps->nseeks++;
	}
}

static int __median(struct rb_node *n, long long sofar, long long target,
		    long long *rvp)
{
	struct seek_bkt *sbp;

	sbp = rb_entry(n, struct seek_bkt, rb_node);
	if ((sofar + sbp->nseeks) >= target) {
		*rvp = sbp->sectors;
		return 1;
	}

	if (n->rb_left && __median(n->rb_left, sofar, target, rvp))
		return 1;

	if (n->rb_right && __median(n->rb_right, sofar, target, rvp))
		return 1;

	return 0;

}

static void __mode(struct rb_node *n, struct mode *mp)
{
	struct seek_bkt *sbp;

	if (n->rb_left)
		__mode(n->rb_left, mp);
	if (n->rb_right)
		__mode(n->rb_right, mp);

	sbp = rb_entry(n, struct seek_bkt, rb_node);
	if (mp->modes == NULL) {
		mp->modes = malloc(sizeof(long long));
		mp->nmds = 0;
	} else if (sbp->nseeks > mp->most_seeks)
		mp->nmds = 0;
	else if (sbp->nseeks == mp->most_seeks)
		mp->modes = realloc(mp->modes, (mp->nmds + 1) *
							sizeof(long long));
	else
		return;

	mp->most_seeks = sbp->nseeks;
	mp->modes[mp->nmds++] = sbp->sectors;
}

long long seek_dist(struct seeki *sip, struct io *iop)
{
	long long dist;
	long long start = BIT_START(iop), end = BIT_END(iop);

	if (seek_absolute)
		dist = start - sip->last_end;
	else {
		/* Some overlap means no seek */
		if (((sip->last_start <= start) && (start <= sip->last_end)) ||
		    ((sip->last_start <= end) && (end <= sip->last_end)))
			dist = 0;
		else if (start > sip->last_end)
			dist = start - sip->last_end;
		else
			dist = start - sip->last_start;

	}

	sip->last_start = start;
	sip->last_end = end;
	return dist;
}

void *seeki_alloc(struct d_info *dip, char *post)
{
	char str[256];
	struct seeki *sip = malloc(sizeof(struct seeki));

	sprintf(str, "%s%s", dip->dip_name, post);
	sip->rfp = seek_open(str, 'r');
	sip->wfp = seek_open(str, 'w');
	sip->cfp = seek_open(str, 'c');
	sip->tot_seeks = 0;
	sip->total_sectors = 0.0;
	sip->last_start = sip->last_end = 0;
	memset(&sip->root, 0, sizeof(sip->root));

	if (sps_name) {
		char *oname;

		memset(&sip->sps, 0, sizeof(sip->sps));

		oname = malloc(strlen(sps_name) + strlen(dip->dip_name) + 32);
		sprintf(oname, "%s_%s.dat", sps_name, dip->dip_name);
		if ((sip->sps_fp = my_fopen(oname, "w")) == NULL) {
			perror(oname);
			free(oname);
		} else
			add_file(sip->sps_fp, oname);
	} else
		sip->sps_fp = NULL;

	return sip;
}

void seeki_free(void *param)
{
	struct seeki *sip = param;

	if (sip->sps_fp && sip->sps.nseeks != 0)
		sps_emit(sip);

	/*
	 * Associated files are cleaned up by seek_clean
	 */
	__destroy(sip->root.rb_node);
	free(sip);
}

void seeki_add(void *handle, struct io *iop)
{
	struct seeki *sip = handle;
	char rw = IOP_READ(iop) ? 'r' : 'w';
	long long dist = seek_dist(sip, iop);
	double tstamp = BIT_TIME(iop->t.time);
	FILE *fp = IOP_READ(iop) ? sip->rfp : sip->wfp;

	if (fp)
		fprintf(fp, "%15.9lf %13lld %c\n", tstamp, dist, rw);
	if (sip->cfp)
		fprintf(sip->cfp, "%15.9lf %13lld %c\n", tstamp, dist, rw);

	dist = llabs(dist);
	sip->tot_seeks++;
	sip->total_sectors += dist;
	__insert(&sip->root, dist);

	sps_add(sip, tstamp);
}

long long seeki_nseeks(void *handle)
{
	return ((struct seeki *)handle)->tot_seeks;
}

double seeki_mean(void *handle)
{
	struct seeki *sip = handle;
	return sip->total_sectors / sip->tot_seeks;
}

long long seeki_median(void *handle)
{
	long long rval = 0LL;
	struct seeki *sip = handle;

	if (sip->root.rb_node)
		(void)__median(sip->root.rb_node, 0LL, sip->tot_seeks / 2,
			       &rval);

	return rval;
}

int seeki_mode(void *handle, struct mode *mp)
{
	struct seeki *sip = handle;
	struct rb_root *root = &sip->root;

	memset(mp, 0, sizeof(struct mode));
	if (root->rb_node)
		__mode(root->rb_node, mp);

	return mp->nmds;
}
