/* This file contains the source for a very basic program to test the
   isam library.
   The program should be linked with the isam.o and index.o files.
   To run it, give it one parameter: the isam file. If no such file
   exists, it will be created.
   The program will ask for a key; if no record with that key exists,
   you will be allowed to create it, otherwise you are offered several
   possibilities.
   -------------------------------------------------------------------------
   Author: G.D. van Albada
   University of Amsterdam
   Faculty of Science
   Informatics Institute
   dick at science.uva.nl
   Version: 0.0
   Date: December 2001 / January 2002
   -------------------------------------------------------------------------
   The program should not be considered to be a good example of production
   code - it lacks comments, naming is ad-hoc, etc.
   */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "isam.h"

void
instruct(void)
{
    char    str[256];
    printf("Do you want instuctions? (y/n) [y]\n");
    if (!fgets(str, 256, stdin))
    {
	printf("Stopping program\n");
	exit(0);
    }
    if (str[0] != 'y' && str[0] != 'Y' && str[0] != 'j' && str[0] != 'J')
	return;
    printf("This program allows you to test your isam routines.\n");
    printf("Run it as\n");
    printf("isam_test file_name\n");
    printf("If a file file_name exists, isam_test will open it together with\n");
    printf("it associated main or mutations file (if the formats are correct)\n");
    printf("If it does not exist, isam_test will try to create a mutations-\n");
    printf("file of that name.\n");
    printf("Next, isam_test will enter a loop in which it\n");
    printf("1. asks for a key value.\n");
    printf("2. attempts to read a record with that key from the file.\n");
    printf("3. if it succeeds, it will ask you if you want to delete or\n");
    printf("   modify the record.\n");
    printf("4. if it fails, isam_test will allow you to create a new record.\n");
    printf("Isam_test leaves the loop only at the end of the input file.\n");
    printf("Type a [ctrl]D to generate such an EOF from your keyboard.\n");
    printf("The program can be made to execute illegal actions, like\n");
    printf("creating a record with an existing key, or deleting a\n");
    printf("non-existent record by specifying a second command-line\n");
    printf("parameter. If this parameter is numerical with value N,\n");
    printf("an illegal command will be generated every 1 in N\n");
    printf("commands; otherwise N will be set to 4\n");
    printf("\n");
}

int
main(int argc, char *argv[])
{
    int     rv, i;
    char    key[17], data[68], dat[68], str[256];
    char    keyx[17];
    int     N_illegal = 4, count;
    isamPtr fd;

    instruct();

    if (argc < 2)
    {
	printf("isam_test needs one (file) argument\n");
	exit(23);
    }
    printf("Calling isam_open for %s\n", argv[1]);
    fd = isam_open(argv[1], 1);
    printf("Isam_open returned %p\n", fd);
    if (fd == NULL)
    {
	isam_perror("I.e.");
	if (isam_error == ISAM_NO_SUCH_FILE || isam_error == ISAM_OPEN_FAIL)
	{
	    printf("Now attempting to use isam_create\n");
	    fd = isam_create(argv[1], 17, 68, 12, 160);
	    printf("Isam_create returned %p\n", fd);
	    if (fd == NULL)
	    {
		isam_perror("I.e.");
		printf("Stopping program\n");
		exit(-3);
	    }
	} else
	{
	    printf("Stopping program\n");
	    exit(-3);
	}
    }
    if (argc == 3)
    {
	sscanf(argv[2], "%d", &N_illegal);
	N_illegal = (N_illegal < 2) ? 2 : N_illegal;
	printf("Attempting an illegal action every 1 out of %d times\n",
	       N_illegal);
    } else
    {
	N_illegal = 1 << 30;
    }
    printf("Give key >");
    count = 1;
    while (fgets(str, 256, stdin))
    {
	i = strlen(str);
	while (i && str[i] < ' ')
	{
	    str[i] = '\0';
	    i--;
	}
	str[16] = '\0';
	strcpy(key, str);
	rv = isam_readByKey(fd, key, data);
	if (rv)
	{
	    isam_perror("Not found: ");
	    printf("No record with key '%s' found\n", key);
	} else
	{
	    printf("Key: '%s'\nData: '%s'\n", key, data);
	}
	if (count++ >= N_illegal)
	{
	    count = 1;
	    rv = (rv) ? 0 : -1;
	    printf("Attempting illegal action - beware!\n");
	}
	if (rv)
	{
	    printf("Create a record with key '%s' ?\n", key);
	    if (!fgets(str, 256, stdin))
	    {
		printf("Stopping program\n");
		if (isam_close(fd))
		{
		    isam_perror("Isam_closed failed miserably");
		}
		exit(0);
	    }
	    if (str[0] == 'y' || str[0] == 'Y')
	    {
		for (i = 0; i < 68; i++)
		    data[i] = '#';
		printf("Give data >");
		if (!fgets(str, 256, stdin))
		{
		    printf("Stopping program\n");
		    if (isam_close(fd))
		    {
			isam_perror("Isam_closed failed miserably");
		    }
		    exit(0);
		}
		i = strlen(str);
		while (i && str[i] < ' ')
		{
		    str[i] = '\0';
		    i--;
		}
		str[67] = '\0';
		for (i = 0; i < 68; i++)
		    data[i] = '#';
		strcpy(data, str);
		if (isam_writeNew(fd, key, data))
		    isam_perror("Error in isam_writeNew");
	    } else
	    {
	        strcpy(keyx, key);
		isam_setKey(fd, key);
		rv = isam_readNext(fd, key, data);
		printf("Next record :");
		if (rv)
		{
		    isam_perror("Not found: ");
		    printf("No record with key > '%s' found\n", key);
		} else
		{
		    printf("Key: '%s'\nData: '%s'\n", key, data);
		}
		isam_setKey(fd, keyx);
		rv = isam_readPrev(fd, key, data);
		printf("Preceding record :");
		if (rv)
		{
		    isam_perror("Not found: ");
		    printf("No record with key < '%s' found\n", keyx);
		} else
		{
		    printf("Key: '%s'\nData: '%s'\n", key, data);
		}
	    }
	} else
	{
	    nogeens:
    printf("[N]ext, [P]revious, [D]elete or [U]pdate record with this key?\n");
	    if (!fgets(str, 256, stdin))
	    {
		printf("Stopping program\n");
		if (isam_close(fd))
		{
		    isam_perror("Isam_closed failed miserably");
		}
		exit(0);
	    }
	    if (count++ >= N_illegal)
	    {
		count = 1;
		data[0]++;
		data[17] = '\0';
		printf("Attempting illegal action - beware!\n");
	    }
	    switch (str[0])
	    {
	    case 'd':
	    case 'D':
		if (isam_delete(fd, key, data))
		    isam_perror("Error in isam_delete");
		break;
	    case 'u':
	    case 'U':
		printf("Give data >");
		if (!fgets(str, 256, stdin))
		{
		    printf("Stopping program\n");
		    if (isam_close(fd))
		    {
			isam_perror("Isam_closed failed miserably");
		    }
		    exit(0);
		}
		i = strlen(str);
		while (i && str[i] < ' ')
		{
		    str[i] = '\0';
		    i--;
		}
		str[67] = '\0';
		for (i = 0; i < 68; i++)
		    dat[i] = '#';
		strcpy(dat, str);
		if (isam_update(fd, key, data, dat))
		    isam_perror("Error in isam_update");
		break;
	    case 'n':
	    case 'N':
		rv = isam_readNext(fd, key, data);
		printf("Next record :");
		if (rv)
		{
		    isam_perror("Not found: ");
		    printf("No record with key > '%s' found\n", key);
		    break;
		} else
		{
		    printf("Key: '%s'\nData: '%s'\n", key, data);
		}
		goto nogeens;
	    case 'p':
	    case 'P':
		rv = isam_readPrev(fd, key, data);
		printf("Preceding record :");
		if (rv)
		{
		    isam_perror("Not found: ");
		    printf("No record with key < '%s' found\n", key);
		    break;
		} else
		{
		    printf("Key: '%s'\nData: '%s'\n", key, data);
		}
		goto nogeens;
	    }
	}
	printf("Give key >");
    }
    printf("Normal end of programme\n");
    isam_close(fd);
    return 0;
}
