/*
 * testlock.c --
 *	Locking test code.
 */

#include <ctype.h>
#include <stdio.h>

#include "c.h"

#include "catname.h"
#include "lmgr.h"
#include "heapam.h"
#include "off.h"
#include "pagenum.h"
#include "xcxt.h"

RcsId("$Header: /private/postgres/src/test/RCS/testlock.c,v 1.3 1989/09/05 16:54:39 mao Version_2 $");

static bool		ProcessingTransaction;
static Relation		StatisticRelation;
static PagePartition	EightPartition;

/*
 * DoProcess --
 *	Perform main processing.
 */
static
void
DoProcess ARGS((
	void
));

/*
 * DoRelation --
 *	Perform relation lock processing.
 */
static
void
DoRelation ARGS((
	String	input
));

/*
 * DoTuple --
 *	Perform tuple level lock processing.
 */
static
void
DoTuple ARGS((
	String	input
));

/*
 * DoPage --
 *	Perform page level lock processing.
 */
static
void
DoPage ARGS((
	String	input
));

/*
 * DoBye --
 *	Perform normal cleanup and exit.
 */
static
void
DoBye ARGS((
	void
));

/*
 * DoError --
 *	Perform error cleanup and exit.
 */
static
void
DoError ARGS((
	void
));

TestMain()
{
	static int	beenHere = 0;

	ProcessingTransaction = false;
	StatisticRelation = NULL;
	EightPartition = CreatePagePartition(8192, 1024);

	if (beenHere == 0) {
		beenHere = 1;
	} else {
		fputs("testlock: giving up!\n", stderr);
		DoError();
	}

	DoProcess();

	puts("testlock: finished!");

	DoBye();
}

static
void
DoProcess()
{
	int			command;
	int			mode;
	LogicalPageNumber	pageNumber;
	OffsetNumber		offsetNumber;
	char			input[80];

	puts("Please enter a granularity/transaction [rtpSC], a mode [rwRW],");
	puts("\ta page number, and a line number as appropriate.");

	for (;;) {
		printf("(%c) ", (ProcessingTransaction) ? '+' : '-');

		if (scanf("%s", input) != 1) {
			puts("No command!");
			DoBye();
		}

		command = input[0];

		switch (command) {
		case 'r':
			DoRelation(&input[1]);
			break;
		case 't':
			DoTuple(&input[1]);
			break;
		case 'p':
			DoPage(&input[1]);
			break;
		case 'S':
			ProcessingTransaction = true;
			StartTransactionCommand();
			StatisticRelation = RelationNameOpenHeapRelation(
				StatisticRelationName);
			break;
		case 'C':
			ProcessingTransaction = false;
			CommitTransactionCommand();
			break;
		default:
			fprintf(stderr, "testlock: Unknown command `%c'\n",
				command);
			DoError();
			break;
		}
	}
}

static
void
DoRelation(input)
	String	input;
{
	if (input[0] == '\0') {
		if (scanf("%s", input) != 1) {
			puts("No mode!");
			DoBye();
		}
	}

	switch (input[0]) {
	case 'r':
		RelationSetLockForRead(StatisticRelation);
		break;
	case 'w':
		RelationSetLockForWrite(StatisticRelation);
		break;
	default:
		fprintf(stderr, "testlock: Unknown mode `%c'\n", input[0]);
		DoError();
		break;
	}
}

static
void
DoTuple(input)
	String	input;
{
	LogicalPageNumber	pageNumber;
	OffsetNumber		offsetNumber;
	ItemPointerData		itemPointerData;

	if (input[0] == '\0') {
		if (scanf("%s", input) != 1) {
			puts("No mode!");
			DoBye();
		}
	}
	switch (input[0]) {
	case 'r':
		if (isdigit(input[1])) {
			pageNumber = atoi(&input[1]);
		} else {
			if (scanf("%d", &pageNumber) != 1) {
				puts("No page [block]!");
				DoBye();
			}
		}
		if (scanf("%hd", &offsetNumber) != 1) {
			puts("No line [offset]!");
			DoBye();
		}

		ItemPointerSimpleSet(&itemPointerData, pageNumber,
			offsetNumber);

		RelationSetLockForTupleRead(StatisticRelation,
			&itemPointerData);
		break;
	default:
		fprintf(stderr, "testlock: Unknown mode `%c'\n", input[0]);
		DoError();
		break;
	}
}

static
void
DoPage(input)
	String	input;
{
	LogicalPageNumber	pageNumber;
	OffsetNumber		offsetNumber;
	ItemPointerData		itemPointerData;
	int			mode;

	if (input[0] == '\0') {
		if (scanf("%s", input) != 1) {
			puts("No mode!");
			DoBye();
		}
	}

	switch (input[0]) {
	case 'r':
	case 'w':
	case 'R':
	case 'W':
		if (isdigit(input[1])) {
			pageNumber = atoi(&input[1]);
		} else {
			if (scanf("%d", &pageNumber) != 1) {
				puts("No page!");
				DoBye();
			}
		}

		ItemPointerSetLogicalPageNumber(&itemPointerData,
			EightPartition, pageNumber);
		break;
	default:
		fprintf(stderr, "testlock: Unknown mode `%c'\n", input[0]);
		DoError();
		return;
	}

	switch (input[0]) {
	case 'r':
		RelationSetLockForReadPage(StatisticRelation, EightPartition,
			&itemPointerData);
		break;
	case 'w':
		RelationSetLockForWritePage(StatisticRelation, EightPartition,
			&itemPointerData);
		break;
	case 'R':
		RelationUnsetLockForReadPage(StatisticRelation, EightPartition,
			&itemPointerData);
		break;
	case 'W':
		RelationUnsetLockForWritePage(StatisticRelation, EightPartition,
			&itemPointerData);
		break;
	default:
		fprintf(stderr, "testlock: internal error\n");
		DoError();
		break;
	}
}

static
void
DoBye()
{
	puts("Bye!");
	StatusBackendExit(0);
}

static
void
DoError()
{
	puts("Error!");
	StatusBackendExit(1);
}
