4.3BSD/usr/ingres/source/iutil/accbuf.c
# include <ingres.h>
# include <access.h>
# include <aux.h>
# include <lock.h>
# include <opsys.h>
# include <sccs.h>
SCCSID(@(#)accbuf.c 8.1 12/31/84)
/*
** access method buffers and other data areas for buffer maintenance
*/
struct accbuf Acc_buf[NACCBUFS]; /* the buffers */
struct accbuf *Acc_head; /* head of usage list */
struct accbuf *Acc_tail; /* tail of usage list */
struct lockreq Lock;
/*
** structs for admin file data
*/
struct admin Admin;
/*
** global flag indicating if access methods
** have been initialized.
*/
int Acc_init = FALSE;
char Acclock; /* locks enabled flag */
int Alockdes; /* file descriptor for lock device*/
int Lockrel; /* lock relations flag*/
/*
** Flush the indicated page and reset all
** important information including the name
**
** Trace Flags:
** 20.0,1
*/
resetacc(buf)
struct accbuf *buf;
{
register struct accbuf *b;
register int i;
b = buf;
if (b == 0)
b = Acc_head;
# ifdef xATR3
if (tTf(20, 0))
{
printf("RESETACC: %x=", b);
dumptid((TID *) &b->rel_tupid);
}
# endif
i = pageflush(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
**
** Trace Flags:
** 20.2,3
*/
acc_init()
{
register struct accbuf *last;
register struct accbuf *b;
struct stat stbuf;
extern int errno;
# ifdef xATR3
if (tTf(20, 2))
printf("ACC_INIT=%d\n", Acc_init);
# endif
if (Acc_init)
return; /* already initialized */
last = 0;
for (b = Acc_buf; b < &Acc_buf[NACCBUFS]; )
{
resetacc(b);
b->modb = last;
last = b;
b++;
last->modf = b;
}
last->modf = 0;
Acc_head = Acc_buf;
Acc_tail = last;
/* get the admin file */
readadmin();
/*
** Set up locking information. If the database has concurrency
** control then Lockrel = TRUE and 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 Alockdes
** = -1 and no locking will (or can) occure.
*/
Lockrel = (Admin.adhdr.adflags & A_DBCONCUR) != 0;
if (Lockrel && Alockdes < 0)
Alockdes = start_up_lock_driver();
errno = 0; /* clear in case /dev/lock isn't available */
Acclock = TRUE;
stat(".", &stbuf);
bmove((char *) &stbuf, (char *) Lock.dbnode, 4);
Acc_init = TRUE;
}
/*
** place buffer at top of LRU list
*/
top_acc(buf)
struct accbuf *buf;
{
register struct accbuf *b;
b = buf;
if (b == Acc_head)
return (0);
if (b == Acc_tail)
Acc_tail = b->modb;
else
b->modf->modb = b->modb;
b->modb->modf = b->modf;
Acc_head->modb = b;
b->modf = Acc_head;
Acc_head = b;
b->modb = 0;
return (0);
}
/*
** 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 find_page().
**
** Returns "or'ed" result from calls to pageflush.
**
** Trace Flags:
** 20.4-5
*/
flush_rel(d, resetflag)
register DESC *d;
int resetflag;
{
register struct accbuf *b;
register int i;
# ifdef xATR3
if (tTf(20, 4))
printf("flush_rel: rel=%.14s, reset=%d\n", d->reldum.relid, resetflag);
# endif
i = 0;
for (b = Acc_head; b != NULL; b = b->modf)
{
if (d->reltid.ltid == b->rel_tupid)
{
if (resetflag)
i |= resetacc(b);
else
i |= pageflush(b);
}
}
return (i);
}
/*
** CHOOSE_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.
**
** Choose_buf guarantees that the buffer will be reset
** if it was used previously for a different relation.
**
** Choose_buf -- choose a buffer for use with the given relation on
** the given page. The current algorithm is to allow only one buffer
** per relation. If a relation does not have a buffer, it is given a
** free one (if any) or else the Least Recently Used.
**
** Trace Flags:
** 29.0,1
*/
struct accbuf *
choose_buf(dx, pageid)
DESC *dx;
long pageid;
{
register struct accbuf *b, *free;
register DESC *d;
struct accbuf *mine;
d = dx;
free = mine = NULL;
for (b = Acc_head; b != 0; b = b->modf)
{
if (b->rel_tupid == -1)
free = b;
else
if (d->reltid.ltid == b->rel_tupid)
{
if (pageid == b->thispage)
{
if (d->relopn < 0)
b->filedesc = d->relfp;
return (b);
}
mine = b;
}
}
/*
** "Free" and "Mine" now reflect the current state of the buffers.
** There is no buffer with the currently requested page
*/
# ifdef xATR3
if (tTf(29, 1))
printf("choosebuf free %x,mine %x\n", free, mine);
# endif
/* no current buffer. Choose a free one or LRU */
if (free == NULL)
free = resetacc(Acc_tail) ? NULL : Acc_tail; /* error if can't reset the LRU */
if (free)
{
/* copy relevant material (in this order in case of rubout) */
free->filedesc = d->relfp;
free->rel_tupid = d->reltid.ltid;
}
# ifdef xATR1
if (tTf(29, 0))
printf("choosebuf:rets %x\n", free);
# endif
return (free);
}
/*
** ACC_CLOSE -- 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 INGRES session but must be closed
** and re-opened in the dbu's whenever a new overlay is loaded.
*/
acc_close()
{
register int i;
if (i = pageflush((struct accbuf *) NULL))
syserr("acc_close: pageflush %d", i);
close(Admin.adreld.relfp);
close(Admin.adattd.relfp);
Admin.adreld.relopn = Admin.adattd.relopn = 0;
if (Alockdes >= 0)
close(Alockdes);
Alockdes = -1;
Acc_init = FALSE;
return (0);
}