/* SDB - relation file I/O routines */

#include "bdscio.h"
#include "dbqdefs.h"

struct relation *rfind(rname)
	char *rname;
{
	struct iobuf fd;
	char filename[RNSIZE+5];
	struct relation *rptr;

	for (rptr = reltns; rptr != NULL; rptr = rptr->rl_next)
		if (db_sncmp(rname,rptr->rl_name,RNSIZE) == 0)
		return (rptr);

	make_fname(filename,rname);

	if ((copen(fd,filename)) == -1)

		{ RETERR(RELFNF) }

	if ((rptr = CALLOC(RELSIZE)) == NULL) {
		cclose (fd);
		RETERR(INSMEM)
	}

	rptr->rl_scnref = 0;

	if (cread(fd,&rptr->rl_header,512) != 512) {
		CFREE(rptr);
		cclose(fd);
		RETERR(BADHDR)
	}

	cclose(fd);

	rptr->rl_tcnt = db_cvword(rptr->rl_header.hd_tcnt);
	rptr->rl_tmax = db_cvword(rptr->rl_header.hd_tmax);
	rptr->rl_data = db_cvword(rptr->rl_header.hd_data);
	rptr->rl_size = db_cvword(rptr->rl_header.hd_size);

#ifdef DEBUG
	printf("Ropen - %d, %d, %d, %d\n",
			rptr->rl_tcnt,
			rptr->rl_tmax,
			rptr->rl_header.hd_tmax[0],
			rptr->rl_header.hd_tmax[1]);
#endif

	strncpy(rptr->rl_name,rname,RNSIZE);

	rptr->rl_next = reltns;
	reltns = rptr;

	return (rptr);
}

struct scan *db_ropen(rname)
	char *rname;
{
	struct relation *rptr;
	struct scan *sptr;
	char filename[RNSIZE+5];

	if ((rptr = rfind(rname)) == NULL)
		return (NULL);

	if ((sptr = CALLOC(SCNSIZE)) == NULL)
		{ RETERR(INSMEM) }


	if ((sptr->sc_tuple = CALLOC(RELSIZE)) == NULL) {
		CFREE(sptr);
		RETERR(INSMEM)
	}

	sptr->sc_relation = rptr;
	sptr->sc_dtnum = 0;
	sptr->sc_atnum = 0;
	sptr->sc_store = FALSE;

	if (rptr->rl_scnref++ == 0) {

		make_fname(filename,rname);

		if ((copen(rptr->rl_fd,filename)) == -1) {
			rptr->rl_scnref--;
			CFREE(sptr->sc_tuple);
			CFREE(sptr);
			RETERR(RELFNF)
		}
	}

	return (sptr);
}

int db_rclose(sptr)
	struct scan *sptr;
{
	struct relation *rptr,*lastrptr;

	if (--sptr->sc_relation->rl_scnref == 0) {
	if (sptr->sc_store) {

		db_cvbytes(sptr->sc_relation->rl_tcnt,
			sptr->sc_relation->rl_header.hd_tcnt);
		db_cvbytes(sptr->sc_relation->rl_tmax,
			sptr->sc_relation->rl_header.hd_tmax);

		cseek(sptr->sc_relation->rl_fd,0,0);
		if (cwrite(sptr->sc_relation->rl_fd,
			&sptr->sc_relation->rl_header,512) != 512) {
			cclose(sptr->sc_relation->rl_fd);
			CFREE(sptr->sc_tuple);
			CFREE(sptr);
			RETERR(BADHDR)
		}
	}

	cclose(sptr->sc_relation->rl_fd);

	lastrptr = NULL;
	for (rptr = reltns; rptr != NULL; rptr = rptr->rl_next) {
		if (rptr == sptr->sc_relation) {
			if (lastrptr == NULL)
				reltns = rptr->rl_next;
			else
				lastrptr->rl_next = rptr->rl_next;
		}
		lastrptr = rptr;
	}
	CFREE(sptr->sc_relation);
	}

	CFREE(sptr->sc_tuple);
	CFREE(sptr);

	return (TRUE);
}

db_rbegin(sptr)
	struct scan *sptr;
{
	sptr->sc_dtnum = 0;
}

int db_rfetch(sptr)
	struct scan *sptr;
{
	while (TRUE) {

		if (!db_rget(sptr,sptr->sc_dtnum + 1))
			return (FALSE);

		sptr->sc_dtnum += 1;

		if (sptr->sc_tuple[0] == ACTIVE)
			return (TRUE);
	}
}

/*	Fetch deleted tuples	*/
int db_dfetch(sptr)
	struct scan *sptr;
{
	while (TRUE) {

		if (!db_rget(sptr,sptr->sc_dtnum + 1))
			return (FALSE);

		sptr->sc_dtnum += 1;

		if (sptr->sc_tuple[0] == DELETED)
			return (TRUE);
	}
}

int db_rupdate(sptr)
	struct scan *sptr;
{
	sptr->sc_tuple[0] = ACTIVE;

	return (db_rput(sptr,sptr->sc_atnum));
}

int db_rdelete(sptr)
	struct scan *sptr;
{
	sptr->sc_tuple[0] = DELETED;

	return (db_rput(sptr,sptr->sc_atnum));
}

int db_rstore(sptr)
	struct scan *sptr;
{
	if (sptr->sc_relation->rl_tcnt == sptr->sc_relation->rl_tmax)
		{
/*			printf("Warning : rel. full - compress\n");	*/
			sptr->sc_relation->rl_tmax++;
		}

	sptr->sc_tuple[0] = ACTIVE;

	if (!db_rput(sptr,sptr->sc_relation->rl_tcnt + 1))
		return (FALSE);

	sptr->sc_relation->rl_tcnt += 1;
	sptr->sc_store = TRUE;
	return (TRUE);
}

int db_rget(sptr,tnum)
	struct scan *sptr; unsigned tnum;
{
	if (tnum == sptr->sc_atnum)
		return(TRUE);

	if (tnum > sptr->sc_relation->rl_tcnt)
		{ RETERR(TUPINP) }

	tseek(sptr,tnum);
	if (cread(sptr->sc_relation->rl_fd,
		sptr->sc_tuple,sptr->sc_relation->rl_size)
		!= sptr->sc_relation->rl_size)
	{ RETERR(TUPINP) }

	sptr->sc_atnum = tnum;

	return (TRUE);
}

int db_rput(sptr,tnum)
	struct scan *sptr; unsigned tnum;
{
	if (tnum > sptr->sc_relation->rl_tmax)
		{ RETERR(TUPOUT) }

	tseek(sptr,tnum);
	if (cwrite(sptr->sc_relation->rl_fd,
		sptr->sc_tuple,sptr->sc_relation->rl_size)
		!= sptr->sc_relation->rl_size)
	{ RETERR(TUPOUT) }

	sptr->sc_atnum = tnum;

	return (TRUE);
}

tseek(sptr,tnum)
	struct scan *sptr; unsigned tnum;
{
	unsigned offset;

	offset = sptr->sc_relation->rl_data +
		((tnum - 1) * sptr->sc_relation->rl_size);
	cseek(sptr->sc_relation->rl_fd,offset,0);
}

make_fname(fname,rname)
	char *fname,*rname;
{
	strncpy(fname,rname,RNSIZE);
	fname[RNSIZE] = 0;
	strcat(fname,".dbq");
}

int db_cvword(bytes)
	char bytes[2];
{
	return (((bytes[1] & 0377) << 8) + (bytes[0] & 0377));
}

db_cvbytes(word,bytes)
	int word;
	char bytes[2];
{
	bytes[0] = word;
	bytes[1] = word >> 8;
}

tes[0] & 0377));
}

db_c