#include "defs.h"

#define	COUNT	1000
#define	FCOUNT	1

void DoIt(int Action, int count);

void
Usage(void)
{
    fprintf(stderr, "A simple history performance tester\n\n");
    fprintf(stderr, "Usage: dhisbench [-a] [-c count] [-F] [-f historyfile] [-l] [ -p processes]\n");
    fprintf(stderr, "  where:\n");
    fprintf(stderr, "\t-a\t\ttest HistoryAdd\n");
    fprintf(stderr, "\t-c COUNT\tadd/lookup COUNT records per process (default: %d)\n", COUNT);
    fprintf(stderr, "\t-F\t\tfast mode - no locking - dangerous option\n");
    fprintf(stderr, "\t-f FILE\t\tuse FILE has the history file\n");
    fprintf(stderr, "\t-l\t\ttest HistoryLookup\n");
    fprintf(stderr, "\t-p COUNT\tfork COUNT processes to do adds/lookups\n");
    fprintf(stderr, "\nWARNING: This program writes garbage entries to your history file\n\n");
    exit(1);
}

const char *HistoryFile = NULL;
int HOFlags = 0;

int
main(int ac, char **av)
{
    int i;
    int rpid;
    struct timeval tstart;
    struct timeval tend;
    double elapsed;
    int Count = COUNT;
    int Forks = FCOUNT;
    int Action = 0;

    LoadDiabloConfig(ac, av);

 
    for (i = 1; i < ac; ++i) {
	char *ptr = av[i];

	if (*ptr == '-') {
	    ptr += 2;
	    switch(ptr[-1]) {
	    case 'a':
		Action = 2;
		break;
	    case 'C':
		if (*ptr == 0)
		    ++i;
		break;
	    case 'c':
		Count = strtol(((*ptr) ? ptr : av[++i]), NULL, 0);
		break;
	    case 'F':
		HOFlags = HGF_FAST|HGF_NOSEARCH;
		break;
	    case 'f':
		HistoryFile = (*ptr) ? ptr : av[++i];
		break;
	    case 'l':
		Action = 1;
		break;
	    case 'p':
		Forks = strtol(((*ptr) ? ptr : av[++i]), NULL, 0);
		break;
	    default:
		Usage();
	    }
	}
    }

    if (Action == 0)
	Usage();
    if (Action == 1)
	HOFlags |= HGF_READONLY;

    if (HistoryFile == NULL)
	HistoryFile = PatDbExpand(DHistoryPat);

    /*
     * Create history if it doesn't exist
     */
    HistoryOpen(HistoryFile, HOFlags);
    HistoryClose();

    gettimeofday(&tstart, NULL);
    for (i = 0; i < Forks; i++)
	if (fork() == 0) {
	    DoIt(Action, Count);
	}
    i = Forks;
    while (i > 0)
	if (waitpid(-1, &rpid, 0) != -1)
	    i--;
    gettimeofday(&tend, NULL);

    elapsed = (tend.tv_sec + tend.tv_usec / 1000000.0) -
			(tstart.tv_sec + tstart.tv_usec / 1000000.0);
    printf("%s: %d\n", (Action == 1) ? "Lookups" : "Adds", Count * Forks);
    printf("Time: %.3f seconds\n", elapsed);
    printf("%.0f %s per second\n", (Count * Forks) / elapsed,
					(Action == 1) ? "lookups" : "adds");
    exit(0);
}

void
DoIt(int Action, int count)
{
    int i;
    char msgid[512];
    hash_t hv;
    History h = { 0 };

    HistoryOpen(HistoryFile, HOFlags);

    printf("pid=%d  action=%d count=%d\n", getpid(), Action, count);

    srandom(time(NULL) + getpid());

    for (i = 0; i < count; i++) {
	sprintf(msgid,"<%d%08lx$%08lx@%08lx.%08lx.%08lx>", i,
			random(), random(), random(), random(), random());
	hv = hhash(msgid);
	if (Action == 1) {
	    HistoryLookupByHash(hv, NULL);
	} else if (Action == 2) {
	    h.hv = hv;
	    h.gmt = 1;
	    HistoryAdd((char *)msgid, &h);
	}
    }
    exit(0);
}

