This commit is contained in:
Oliver Lehmann 1989-10-26 13:38:01 +00:00
parent d0d9668d32
commit b51ff19095
2 changed files with 484 additions and 0 deletions

View File

@ -0,0 +1,240 @@
# 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);
}

View File

@ -0,0 +1,244 @@
# include "gen.h"
# include "../h/dbs.h"
# include "../h/aux.h"
# include "../h/access.h"
# include "../h/lock.h"
/*
** AArelopen -- Open a relation into a descriptor
**
** AArelopen will open the named relation into the given descriptor
** according to the mode specified. When searching for a name,
** a relation owner by the current user will be searched for first.
** If none is found then one owned by the DBA will be search for.
**
** There are several available modes for opening a relation. The
** most common are
** mode 0 -- open for reading
** mode 2 -- open for writing (mode 1 works identically).
** Other modes which can be used to optimize performance:
** mode -1 -- get catalog AA_REL tuple and tid only.
** Does not open the relation.
** mode -2 -- open relation for reading after a previous
** call of mode -1.
** mode -3 -- open relation for writing after a previous
** call of mode -1.
** mode -4 -- open relation for reading. Assumes that relation
** was previously open (eg relation & attributed
** have been filled) and file was closed by AArelclose.
** mode -5 -- open relation for writing. Same assumptions as
** mode -4.
**
** Parameters:
** d - a pointer to a DESC (defined in dbs.h)
** mode - can be 2, 0, -1, -2, -3, -4, -5
** name - a null terminated name (only first 12 chars looked at)
**
** Returns:
** 1 - relation does not exist
** 0 - ok
** <0 - error. Refer to the error codes in access.h
**
** Side Effects:
** Opens the physical file if required. Fill the
** descriptor structure. Initializes the access methods
** if necessary.
*/
AArelopen(d, mode, name)
register DESC *d;
int mode;
char *name;
{
register int retval;
register int filemode;
char filename[MAXNAME + 3];
extern char *AArelpath();
# ifdef xATR1
AAtTfp(90, -1, "OPENR: %.12s,%d\n", name, mode);
# endif
# ifdef xATM
if (AAtTf(76, 2))
timtrace(21, 0);
# endif
AAam_start();
/* process according to mode */
filemode = 0;
switch (mode)
{
case -1:
retval = AAgetrel_tuple(d, name);
break;
case 1:
case 2:
filemode = 2;
case 0:
if (retval = AAgetrel_tuple(d, name))
break;
case -2:
case -3:
if (retval = AAgetatt_tuples(d))
break;
case -5:
if (mode == -3 || mode == -5)
filemode = 2;
case -4:
AAam_clearkeys(d);
/* descriptor is filled. open file */
AAdbname(d->reldum.relid, d->reldum.relowner, filename);
/* can't open a view */
if (d->reldum.relstat & S_VIEW)
{
retval = AAam_error(AMOPNVIEW_ERR); /* view */
break;
}
if ((d->relfp = open(AArelpath(filename), filemode)) < 0)
{
retval = AAam_error(AMNOFILE_ERR); /* can't open file */
break;
}
if (filemode == 2)
{
d->relopn = RELWOPEN(d->relfp);
d->reldum.relock[1] = P_EXCL;
}
else
{
d->relopn = RELROPEN(d->relfp);
d->reldum.relock[1] = P_SHR;
}
d->reldum.relock[0] = d->reldum.relock[1];
d->reladds = 0;
retval = 0;
break;
default:
AAsyserr(10017, mode, name);
}
# ifdef xATR1
if (AAtTf(90, 4) && mode != -1 && retval != 1)
AAprdesc(d);
AAtTfp(90, -1, "OPENR: rets %d\n", retval);
# endif
# ifdef xATM
if (AAtTf(76, 2))
timtrace(22, 0);
# endif
return (retval);
}
/*
** AAgetrel_tuple
** Get the tuple for the relation specified by 'name'
** and put it in the descriptor 'd'.
**
** First a relation named 'name' owned
** by the current user is searched for. If that fails,
** then a relation owned by the dba is searched for.
*/
AAgetrel_tuple(d, name)
register DESC *d;
register char *name;
{
register int i;
struct relation rel;
AAam_clearkeys(&AAdmin.adreld);
/* make believe catalog AA_REL is read only for concurrency */
/* that means, readed pages are not locked */
AAdmin.adreld.relopn = RELROPEN(AAdmin.adreld.relfp);
/* catalog AA_REL is open. Search for relation 'name' */
AAam_setkey(&AAdmin.adreld, &rel, name, RELID);
AAam_setkey(&AAdmin.adreld, &rel, AAusercode, RELOWNER);
if ((i = AAgetequal(&AAdmin.adreld, &rel, d, &d->reltid)) == 1)
{
/* not a user relation. try relation owner by dba */
AAam_setkey(&AAdmin.adreld, &rel, AAdmin.adhdr.adowner, RELOWNER);
i = AAgetequal(&AAdmin.adreld, &rel, d, &d->reltid);
}
/* free all buffers connected with catalog AA_REL */
AAam_flush_rel(&AAdmin.adreld, TRUE);
# ifdef xATR1
AAtTfp(90, 1, "GET_RELTUPLE: %d\n", i);
# endif
/* restore catalog AA_REL to read/write mode */
AAdmin.adreld.relopn = RELWOPEN(AAdmin.adreld.relfp);
return (i);
}
AAgetatt_tuples(d)
register DESC *d;
{
register int i;
register int dom;
register int numatts;
struct attribute attr;
struct attribute attkey;
struct tup_id tid1;
struct tup_id tid2;
AAam_clearkeys(&AAdmin.adattd);
/* zero all format types */
for (i = 0; i <= d->reldum.relatts; i++)
d->relfrmt[i] = 0;
/* prepare to scan attribute relation */
AAam_setkey(&AAdmin.adattd, &attkey, d->reldum.relid, ATTRELID);
AAam_setkey(&AAdmin.adattd, &attkey, d->reldum.relowner, ATTOWNER);
if (i = AAam_find(&AAdmin.adattd, EXACTKEY, &tid1, &tid2, &attkey))
return (i);
numatts = d->reldum.relatts;
while (numatts && !AAam_get(&AAdmin.adattd, &tid1, &tid2, &attr, TRUE))
{
/* does this attribute belong? */
if (AAbequal(&attr, &attkey, MAXNAME + 2))
{
/* this attribute belongs */
dom = attr.attid; /* get domain number */
if (d->relfrmt[dom])
break; /* duplicate attribute. force error */
numatts--;
d->reloff[dom] = attr.attoff;
d->relfrmt[dom] = attr.attfrmt;
d->relfrml[dom] = attr.attfrml;
d->relxtra[dom] = attr.attxtra;
}
}
/* make sure all the atributes were there */
for (dom = 1; dom <= d->reldum.relatts; dom++)
if (!d->relfrmt[dom])
numatts = 1; /* force an error */
if (numatts)
i = AAam_error(AMNOATTS_ERR);
AAam_flush_rel(&AAdmin.adattd, TRUE);
# ifdef xATR1
AAtTfp(90, 3, "GET_ATTR: ret %d\n", i);
# endif
return (i);
}