#include <gpk_std.h>
#include <stdio.h>
#include <assert.h>
#include <sys/types.h>
#include <unistd.h>

C static char fileheadermagic[] = "MYDB1gpk";
struct filehdr	{
	char magic[16];
	long tree_head;
	long branch_free_list;
	long leaf_free_list;
	};

C static long LEAFFREE =  30341437L;
C static long LEAFMAGIC =  34343431L;
struct leaf	{
	long leafmagic;
			/* key recycled as next item in free list */
	long key, time, seqn;
	long ahash, vhash;
	/* Value goes here... */
	};


struct leafptr	{
	long loc, len;
	short isleaf;	/* 0 for branch, 1 for leaf */
	};


#define NFS	8
#define NLEAF	10

C static long BRANCHFREE = 2723623L;
C static long BRANCHMAGIC = 2323621L;
struct branch	{
	long branchmagic;
	long n;			/* Number of filled slots. */
					/* Recycled as ptr to next in free list. */
	char fs[NFS];		/* First few chars of first leaf node. */
	char ls[NFS];		/* First few chars of last leaf node. */
	struct leafptr lp[NLEAF];
	};


struct rtn_leaf	{
	long key, time, seqn;
	long leafloc, lastbranchloc;
	char *av;
	};


enum cmp_e	{TOOSMALL=-1, MATCH=0, TOOBIG=1, NOTTHERE};

static enum cmp_e ckleaf(char *av, long avn, int fd, long loc, long len,
						long brloc, int ofd)
{
 assert(ofd >= 0);
 assert(fd >= 0);
 assert(loc >= 0);
 assert(len >= sizeof(leaf));

 int ok = lseek(fd, loc, SEEK_SET)!=(-1);
 assert(ok);

 char *buf = new char[len+sizeof(leaf)+1];
 ok = read(fd, buf, len+sizeof(leaf)))==len+sizeof(leaf);
 assert(ok);
 struct leaf lf;
 memcpy(&lf, buf, sizeof(leaf));

 if(lf.leafmagic == LEAFFREE)
	return NOTTHERE;

 assert(lf.leafmagic == LEAFMAGIC);

 C long l = avn<len ? avn : len;
 int cmp = 0;

 if(l != 0)
	cmp = memcmp(&buf[sizeof(leaf)], av, l);

 if(cmp==0 && avn==len)	{
	char *b = new char[1000 + len];
	assert(b);
	buf[sizeof(leaf)+len] = '\0';
	int bl = sprintf(b, "*key=%ld *time=%ld *seqn=%ld *brloc=%ld",
						lf.key, lf.time, lf.seqn, brloc);
	strncat(b, &buf[sizeof(leaf)], len+1);
	strncat(b, "\n");
	bl += len+1;
	ok = write(ofd, b, bl)==bl;
	assert(ok);
	return MATCH;
	}
 return cmp>0||avn>len ? TOOBIG : TOOSMALL;
}


static enum cmp_e find(char *av, long avn, int fd, long loc, int ofd)
{
 enum cmp_e rv = NOTTHERE;
 assert(fd >= 0);
 assert(loc >= 0);

 int ok = lseek(fd, loc, SEEK_SET)!=(-1);
 assert(ok);

 struct branch br;
 ok = read(fd, &br, sizeof(br))==sizeof(br);
 assert(ok);

 if(br.branchmagic == BRANCHFREE)
	return NOTTHERE;

 assert(br.branchmagic == BRANCHMAGIC);

 if(memcmp(br.fs, av, avn<FSN ? avn : fsn) > 0)
	return TOOBIG;
 if(memcmp(br.ls, av, avn<FSN ? avn : fsn) < 0)
	return TOOSMALL;

 int i;
 for(i=0; i<n; i++)	{
	enum cmp_e tmp;

	if(br.lp[i].isleaf)	{
		tmp = ckleaf(av, avn, fd, br.lp[i].loc, br.lp[i].len, loc, ofd);
	else
		tmp = find(av, avn, fd, br.lp[i].loc, ofd);

	if(tmp == TOOSMALL)
		rv = TOOSMALL;
	if(tmp == TOOBIG)
		break;
	}

 return rv;
}

int 


int mdb_delete(int fd, long leafloc, long brloc, int ofd)
{
}
