P8000/WEGA/contrib/ingres/dbs/src/access/accbuf.c

241 lines
5.7 KiB
C

# include "gen.h"
# include "../h/dbs.h"
# include "../h/access.h"
# include "../h/aux.h"
# include "../h/lock.h"
# include "../h/bs.h"
/* access method buffers and */
/* other data areas for buffer maintenance */
static ACCBUF AAcc_buf[NACCBUFS]; /* the buffers */
ACCBUF *AAcc_head; /* head of usage list */
ACCBUF *AAcc_tail; /* tail of usage list */
LOCKREQ AALOCKREQ;
/* structs for AA_ADMIN file data */
struct admin AAdmin;
/* global flag indicating if access methods */
/* have been initialized. */
int AAcc_init = FALSE;
/* dummy procedure for importing AAdmin via ranlib(1) */
AACCESS() {};
/* Flush the indicated page and reset all */
/* important information including the name */
AAresetacc(b)
register ACCBUF *b;
{
register int i;
if (!b)
b = AAcc_head;
# ifdef xATR3
if (AAtTfp(80, 0, "RESETACC: "))
AAdumpbuf(b);
# endif
i = AApageflush(b); /* write the page if necessary */
b->rel_tupid = -1;
b->filedesc = -1;
b->thispage = -1;
b->bufstatus = 0;
return (i);
}
/* initialize access method data areas */
AAam_start()
{
register ACCBUF *last;
register ACCBUF *b;
struct stat stbuf;
extern char *AAdbpath;
extern int errno;
# ifdef xATR3
AAtTfp(81, 0, "ACC_INIT=%d\n", AAcc_init);
# endif
if (AAcc_init)
return; /* already initialized */
last = (ACCBUF *) 0;
for (b = AAcc_buf; b < &AAcc_buf[NACCBUFS]; )
{
AAresetacc(b);
b->modb = last;
last = b;
b++;
last->modf = b;
}
last->modf = (ACCBUF *) 0;
AAcc_head = AAcc_buf;
AAcc_tail = last;
/* get the AA_ADMIN file */
AAreadadmin();
/* Set up locking information. If the database has concurrency */
/* control then the concurrency device will */
/* be opened for writing. If there is no concurrency for the */
/* data base or if the lock device isn't installed, then AAlockdes */
/* = -1 and no locking will (or can) occure. */
if ((AAdmin.adhdr.adflags & A_DBCONCUR) && AAlockdes < 0)
AAlockdes = open(AA_DBS_LOCK, 1);
errno = 0; /* clear in case AA_DBS_LOCK isn't available */
AAcclock = TRUE;
stat(AAdbpath? AAdbpath: ".", &stbuf);
AAbmove(&stbuf, &AALOCKREQ.l_db, sizeof (long));
AALOCKREQ.l_pid = getpid();
AAcc_init = TRUE;
}
/* place buffer at top of LRU list */
AAtop_acc(b)
register ACCBUF *b;
{
if (b == AAcc_head)
return;
if (b == AAcc_tail)
AAcc_tail = b->modb;
else
b->modf->modb = b->modb;
b->modb->modf = b->modf;
AAcc_head->modb = b;
b->modf = AAcc_head;
AAcc_head = b;
b->modb = (ACCBUF *) 0;
# ifdef xATR3
if (AAtTfp(80, 0, "TOP_ACC: "))
AAdumpbuf(b);
# endif
}
/* AAam_flush_rel -- flush all pages associated with the relation */
/* described by the descriptor. If resetflag is TRUE, */
/* then the buffers are reset so the pages will not be */
/* found on subsequent calls to AAfind_page(). */
/* Returns "or'ed" result from calls to AApageflush. */
AAam_flush_rel(d, resetflag)
register DESC *d;
int resetflag;
{
register ACCBUF *b;
register int i;
if (d->reldum.relock[0] & R_LOCKED)
AAunlrl(d->reltid);
for (i = 0, b = AAcc_head; b; b = b->modf)
if (d->reltid == b->rel_tupid)
i |= resetflag? AAresetacc(b): AApageflush(b);
return (i);
}
/* AAchoose_buf -- Try to find an empty buffer for assignment. */
/* If there is no empty buffer, pick the last buffer */
/* in the LRU queue and make sure it is flushed. */
/* AAchoose_buf guarantees that the buffer will be reset */
/* if it was used previously for a different relation. */
/* */
/* AAchoose_buf -- choose a buffer for use with the given relation on */
/* the given page. If a relation does not have a buffer, it */
/* is given a free one (if any) or else the Least Recently Used. */
ACCBUF *AAchoose_buf(d, pageid)
register DESC *d;
long pageid;
{
register ACCBUF *b;
register ACCBUF *free;
# ifdef xATR3
register ACCBUF *mine;
mine = (ACCBUF *) 0;
# endif
for (free = (ACCBUF *) 0, b = AAcc_head; b; b = b->modf)
{
if (b->rel_tupid == -1)
free = b;
else if (d->reltid == b->rel_tupid)
{
if (pageid == b->thispage)
{
if (d->relopn < 0)
b->filedesc = d->relfp;
return (b);
}
# ifdef xATR3
mine = b;
# endif
}
}
# ifdef xATR3
/* "Free" and "Mine" now reflect the current state of the buffers. */
/* There is no buffer with the currently requested page */
AAtTfp(82, 9, "CHOOSEBUF free 0%o,mine 0%o\n", free, mine);
# endif
/* no current buffer. Choose a free one or LRU */
if (!free) /* error if can't reset the LRU */
free = AAresetacc(AAcc_tail)? (ACCBUF *) 0: AAcc_tail;
if (free)
{
/* copy relevent material (in this order in case of rubout */
free->filedesc = d->relfp;
free->rel_tupid = d->reltid;
}
# ifdef xATR1
AAtTfp(82, 8, "CHOOSEBUF: rets 0%o\n", free);
# endif
return (free);
}
/* AAam_exit -- flush any buffers left around */
/* and then close the files for relation & attribute. */
/* The relation and attribute relation are normally left open */
/* until the end of an DBS session but must be closed */
/* and re-opened in the dbu's whenever a new overlay is loaded. */
AAam_exit()
{
register int i;
if (i = AApageflush((ACCBUF *) 0))
AAsyserr(10000, i);
close(AAdmin.adreld.relfp);
close(AAdmin.adattd.relfp);
AAdmin.adreld.relopn = AAdmin.adattd.relopn = 0;
if (AAlockdes >= 0)
close(AAlockdes);
AAlockdes = -1;
AAcc_init = FALSE;
sync();
return (0);
}
AAdumpbuf(buf)
register ACCBUF *buf;
{
printf("page# %ld, bufstatus 0%o, filedesc %u, rel_",
buf->thispage, buf->bufstatus, buf->filedesc);
AAdumptid(&buf->rel_tupid);
printf("mainpg %ld, ovflpg %ld, nxtlino 0%o, free 0%o\n",
buf->mainpg, buf->ovflopg, buf->nxtlino,
buf->linetab[LINETAB(buf->nxtlino)]);
printf("(HEAD 0%o) 0%o <- 0%o -> 0%o (0%o TAIL)\n",
AAcc_head, buf->modb, buf, buf->modf, AAcc_tail);
}