/*
 * testcache.c --
 *	Cache test code.
 */

#include <stdio.h>

#include "c.h"

#include "catname.h"
#include "ftup.h"
#include "heapam.h"
#include "log.h"
#include "syscache.h"
#include "tupdesc.h"

#ifndef	COMPLICATED
#define TESTKEY	"cachelang"
#define TESTDAT	"initial-cachelang-path"
#endif

RcsId("$Header: /private/postgres/src/test/RCS/testcache.c,v 1.4 1990/02/12 19:51:58 cimarron Version_2 $");

static struct catcache	*TestSysCache = NULL;

/*
 * DoAddTuple --
 */
extern
void
DoAddTuple ARGS((
	Relation	relation,
	HeapTuple	tuple
));

/*
 * DoSearchTestCache --
 *	True iff tuple is found.
 */
extern
bool
DoSearchTestCache ARGS((
	Relation	relation,
	int		id
));

/*
 * DoReplace --
 */
extern
void
DoReplace ARGS((
	Relation	relation
));

/*
 * DoShowTuple --
 */
extern
void
DoShowTuple ARGS((
	Relation	relation,
	HeapTuple	tuple
));

/*
 * DoShowAttributes --
 */
extern
void
DoShowAttributes ARGS((
	Relation	relation
));

TestMain()
{
	HeapTuple	tuple;
	Relation	relation;
	bool		immediateFlush = true;

	static NameData	relationNameData;
	static int	beenHere = 0;

	StartTransactionCommand();
	if (beenHere == 0) {
		beenHere = 1;

#ifdef	COMPLICATED
		puts("Please enter a catalog relation name");
		if (scanf("%s", relationNameData.data) != 1) {
			elog(NOTICE, "testcache: no relation specified");
			exitpg(0);
		}
		tuple = NULL;		/* XXX */
		relation = NULL;	/* XXX */
#else
		strncpy(relationNameData.data, LanguageRelationName, 16);
		{
			Datum	datum[2];

			datum[0] = NameGetDatum(TESTKEY);
			datum[1] = PointerGetDatum((Pointer)textin(TESTDAT));
			relation = RelationNameOpenHeapRelation(
				LanguageRelationName);

			tuple = FormHeapTuple(2,
				RelationGetTupleDescriptor(relation), datum,
				"  ");
		}
#endif
		DoAddTuple(relation, tuple);
		CommitTransactionCommand();
		StartTransactionCommand();

		beenHere = 2;

	} else if (beenHere > 1) {
		elog(FATAL, "testcache: giving up!");

	} else if (beenHere == 1) {
		elog(NOTICE, "testcache: %s relation may exist???--continuing!",
			relationNameData.data);

		beenHere = 2;
	}

	/* one time processing */
	DoShowAttributes(relation);
	if (!DoSearchTestCache(relation, LANNAME)) {
		Assert(RelationIsValid(relation));
		Assert(HeapTupleIsValid(tuple));

		DoAddTuple(relation, tuple);
	}
	CommitTransactionCommand();
	StartTransactionCommand();
	srand(time(0));

#ifdef	COMPLICATED
		Assert(0);
#endif

	for (;;) {
/*
		puts("\nPlease enter an operator, flags, and an integer value");
		status = scanf("%s %d %d", operatorNameData.data, &flags,
			&returnType);

		if (status <= 0) {
			break;
		} else if (status != 3) {
			elog(NOTICE, "testbtree: improper qualification specified");
			exitpg(0);
		}
*/
		puts("*****************************************");
		fprintf(stderr, "Search for it:\n");
		DoSearchTestCache(relation, LANNAME);

		if (immediateFlush) {
			SetHeapAccessMethodImmediateInvalidation(true);
		}
		fprintf(stderr, "Replace it:\n");
		DoReplace(relation);
		if (immediateFlush) {
			SetHeapAccessMethodImmediateInvalidation(false);
		}

		fprintf(stderr, "Search for it again:\n");
		DoSearchTestCache(relation, LANNAME);

		CommitTransactionCommand();
		puts("");
		sleep(1);
		StartTransactionCommand();

		immediateFlush = (bool)!immediateFlush;
	}

	RelationCloseHeapRelation(relation);

	puts("\nDone!");

	endmmgr(NULL);
}

void
DoAddTuple(relation, tuple)
	Relation	relation;
	HeapTuple	tuple;
{
	/* someday, check that the tuple does not already exist */

	RelationInsertHeapTuple(relation, tuple);
}

bool
DoSearchTestCache(relation, id)
	Relation	relation;
	int		id;
{
	HeapTuple	tuple;

	Assert(RelationIsValid(relation));

	setheapoverride(true);
	tuple = SearchSysCacheTuple(id, TESTKEY);
	setheapoverride(false);
	if (!HeapTupleIsValid) {
		puts("\t<tuple-not-found>");
		return (false);
	} else {
		DoShowTuple(relation, tuple);
	}
	return (true);
}

void
DoReplace(relation)
	Relation	relation;
{
	HeapTuple	oldTuple;
	HeapTuple	newTuple;
	Datum		datum[2];
	char		path[80];

	Assert(RelationIsValid(relation));

	sprintf(path, "%d", rand());
	datum[0] = NameGetDatum(TESTKEY);
	datum[1] = PointerGetDatum((Pointer)textin(path));
	newTuple = FormHeapTuple(2, RelationGetTupleDescriptor(relation),
		datum, "  ");

	fprintf(stderr, "Replaced it with: %s\n", path);
	oldTuple = SearchSysCacheTuple(LANNAME, TESTKEY);
/*
	SetRefreshWhenInvalidate(true);
*/
	RelationReplaceHeapTuple(relation, &oldTuple->t_ctid, newTuple,
		(double *)NULL);
/*
	SetRefreshWhenInvalidate(false);
*/
}

void
DoShowTuple(relation, tuple)
	Relation	relation;
	HeapTuple	tuple;
{
	if (!HeapTupleIsValid(tuple)) {
		puts("\t<nil>");
		return;
	}
	if (ItemPointerIsValid(&tuple->t_ctid)) {
		printf("\t[%d,%d]\n",
			ItemPointerSimpleGetPageNumber(&tuple->t_ctid),
			ItemPointerSimpleGetOffsetNumber(&tuple->t_ctid));
	}
	debugtup(tuple, RelationGetTupleDescriptor(relation));
}

void
DoShowAttributes(relation)
	Relation	relation;
{
	showatts(&relation->rd_rel->relname, relation->rd_rel->relnatts,
		RelationGetTupleDescriptor(relation));
}
