home *** CD-ROM | disk | FTP | other *** search
- /*
- * index file kernel
- *
- * This program is the CONFIDENTIAL and PROPRIETARY property
- * of FairCom(R) Corporation. Any unauthorized use, reproduction or
- * transfer of this program is strictly prohibited.
- *
- * Copyright (c) 1984, 1985, 1986, 1987, 1988, 1989 FairCom Corporation
- * (Subject to limited distribution and
- * restricted disclosure only.)
- * *** ALL RIGHTS RESERVED ***
- *
- * 4006 West Broadway
- * Columbia, MO 65203
- *
- *
- * c-tree(R) Version 4.3
- * Release C
- * February 7, 1989 17:30
- *
- */
-
- #include "ctstdr.h" /* standard i/o header */
- #include "ctoptn.h" /* c-tree configuration options */
- #include "cterrc.h" /* c-tree error codes */
- #include "ctstrc.h" /* c-tree data structures */
- #include "ctgvar.h" /* c-tree global variables */
-
- COUNT ctio();
- #ifdef FPUTFGET
- COUNT redhdr();
- #endif
-
- /* --------------------------------------------------------------------
- general purpose node search function. works with leaf and non-leaf nodes.
- returns relative position in node of key value satisfying search request
- as well as setting the global variable ct_elm to this value. also sets
- the global variable ct_tky which indicates the sense of the comparison
- between the target key value (pointed to by idxval) and the key values
- actually in the index structure. if search is not satisfied, nodser
- returns a value of -2. if idxval greater than high key, then nodser
- returns a value of -1.
- */
-
- COUNT nodser(buffer,idxval,stratg)
- PFAST TREEBUFF *buffer; /*pointer to buffer containing node */
- TEXT *idxval; /* pointer to target key value */
- TEXT stratg; /* search strategy: E == eq L == le S == le (from
- * leaf node)
- */
- {
- COUNT compar();
- TEXT *valpnt(),*hghpnt();
-
- COUNT begser,endser,size,poff;
- FAST KEYFILE *knum;
-
- knum = ct_key + buffer->keyid; /* determine key number pointer */
-
- begser = 1;
- endser = buffer->nkv;
- ct_tkp = poff = 0;
-
- /* high key comparison
- */
- if ((buffer->leaf == LEAF &&
- (compar(idxval,hghpnt(buffer),knum) > 0 ||
- (stratg == 'S' && !endser && buffer->sucesr))) ||
- (buffer->leaf == NOLEAF && !buffer->ktipe &&
- compar(idxval,valpnt(buffer,endser),knum) > 0)) {
- /* target exceeds high key value for node */
- ct_tky = 1;
- ct_elm = 0;
- return(-1);
- }
-
- /* check for empty (leaf) node
- */
- if (!endser) {
- ct_elm = 0;
- ct_tky = -1;
- return(-2);
- }
-
- /* binary search of node if fixed length keys
- */
-
- if (!buffer->ktipe) {
- while ((size = endser - begser + 1) > 3) {
- ct_elm = begser + size / 2;
- ct_tky = compar(idxval,valpnt(buffer,ct_elm),knum);
- if (ct_tky > 0)
- begser = ct_elm + 1;
- else if (!ct_tky)
- return (ct_elm);
- else
- endser = ct_elm;
- }
- if (begser > endser) /* then corrupt node */
- terr(207);
- }
-
- #ifdef VARLKEYS
- else if (buffer->lstpos) {
- if (buffer->confg & REGULAR)
- poff = sizeof(POINTER);
- ct_tkp = compar(idxval,buffer->keyexp + poff,knum);
- ct_sfxctp = buffer->cursfx;
- if (ct_tkp > 0)
- begser = buffer->lstpos + 1;
- else if (ct_tkp == 0) {
- ct_tky = 0;
- ct_tkp = -1;
- return(ct_elm = buffer->lstpos);
- } else
- ct_tkp = 0;
- }
- #endif
-
- /* perform sequential search over remaining possibilities */
-
- for (ct_elm = begser; ct_elm <= endser; ct_elm++) {
- ct_tky = compar(idxval,valpnt(buffer,ct_elm),knum);
- if (ct_tky > 0) {
- ct_tkp = ct_tky;
- ct_sfxctp = buffer->cursfx;
- } else if (ct_tky < 0 && stratg == 'E')
- return(-2);
- else
- return(ct_elm);
- }
- if ((stratg == 'S' && buffer->sucesr) || (buffer->ktipe &&
- buffer->leaf == NOLEAF)) {
- ct_tky = 1;
- ct_elm = 0;
- return(-1);
- } else {
- ct_tky = ct_tkp;
- ct_elm = buffer->nkv + 1;
- return(-2);
- }
- }
-
- VOID setnul(s)
-
- TEXT *s;
-
- {
- *s = '\0';
- }
-
-
- /* --------------------------------------------------------------------
- getnod searches the buffer area for the requested b-tree node (specified
- by node number and key number (pointer)). if found, it returns pointer to
- buffer; else it pushes out the least recently used node and reads the
- requested node into the vacated buffer, passing back a pointer to this
- buffer.
- */
-
- TREEBUFF *getnod(node,knum)
- LONG node; /* node number requested */
- KEYFILE *knum; /* key number pointer */
- {
- TREEBUFF *lrubuf(); /* function returning pointer to least
- recently used buffer */
- COUNT rednod(); /* function to read node */
- VOID inracs(); /* update buffer age & check for rollover */
-
- #ifdef FPUTFGET
- CTFILE *ctnum;
- #endif
- TREEBUFF *getflg;
- FAST TREEBUFF *fndbuf;
- /* pointers to buffers */
- FAST COUNT i; /* counter */
- FAST UCOUNT lstusd; /* store for finding node (buffer) with lowest
- node access number; ie lru buffer */
-
- if (node == NODEZERO)
- terr(237);
- getflg = fndbuf = ct_btree;
- lstusd = fndbuf->nodacs;
- for (i = 0; i++ < ct_mxbuf; fndbuf++) {
- if (fndbuf->nodeid == node && fndbuf->keyid == knum->filnum) {
-
- #ifdef FPUTFGET
- if (fndbuf->update == 'y')
- terr(208);
- ctnum = knum - knum->kmem;
- if ((ctnum->flmode & SHARED) &&
- rednod(fndbuf,node,knum))
- return(NULL);
- #endif
-
- inracs(fndbuf); /* node found; update node
- access count and return
- pointer to buffer
- */
- return(fndbuf);
- }
- if (fndbuf->nodacs < lstusd) /* set getflg to buffer pointer
- with lowest nodacs */
- lstusd = (getflg = fndbuf)->nodacs;
- }
-
-
- /* node not found in buffers. read node into lru buffer */
-
- if ((fndbuf = lrubuf(getflg)) == NULL) /* then error in lrubuf */
- return(NULL);
- if (rednod(fndbuf,node,knum)) /* then error in rednod */
- return(NULL);
- return(fndbuf);
- }
-
-
- /* --------------------------------------------------------------------
- return pointer to buffer containing lru buffer. if lru buffer contains
- an updated node, write out the node to appropriate index file
- */
-
- TREEBUFF *lrubuf(getflg)
- TREEBUFF *getflg; /* if non-zero, then pointer to buffer
- containing lru buffer; ie, the lru buffer
- has already been determined */
- {
- COUNT wrtnod(); /* write updated node back to disk */
- FAST COUNT i; /* counter */
- FAST TREEBUFF *fndbuf; /* pointer to buffer */
- FAST UCOUNT lstusd; /* store to determine buffer with lowest
- node access number */
-
- if (!getflg) { /* lru buffer has not been determined yet */
- getflg = fndbuf = ct_btree;
- lstusd = fndbuf->nodacs;
- for (i = 1, ++fndbuf; i++ < ct_mxbuf; fndbuf++)
- if (fndbuf->nodacs < lstusd)
- lstusd = (getflg = fndbuf)->nodacs;
- }
-
- #ifdef CTSERVER
- #ifdef EXTRABFR
- if (getflg->keyid != -1) { /* make sure buffer in use */
- wrtxnod(getflg);
- return(getflg);
- }
- #endif
- #endif
-
- if (getflg->update == 'y') /* lru node has been updated. write it */
- if (wrtnod(getflg)) /* then write error */
- return(NULL);
- return(getflg); /* return lru buffer ptr */
- }
-
-
- /* --------------------------------------------------------------------
- increment buffer age & check for roll over
- */
-
- VOID inracs(buffer)
-
- PFAST TREEBUFF *buffer;
-
- {
- FAST TREEBUFF *tmpbuf;
- FAST COUNT i;
- LOCAL UCOUNT minage;
-
- if (++ct_lacs) /* then buffer age did not rollover */
- buffer->nodacs = ct_lacs;
- else { /* buffer age rollover. must adjust all buffer ages */
- tmpbuf = ct_btree;
- minage = MAXAGE;
- for (i = 0; i++ < ct_mxbuf; tmpbuf++)
- if (tmpbuf->nodacs < minage && tmpbuf->nodacs)
- minage = tmpbuf->nodacs;
- ct_lacs = MAXAGE - (--minage);
- tmpbuf = ct_btree;
- for (i = 0; i++ < ct_mxbuf; tmpbuf++)
- if (tmpbuf->nodacs)
- tmpbuf->nodacs -= minage;
- buffer->nodacs = ++ct_lacs;
- }
- }
-
-
- /* --------------------------------------------------------------------
- read b-tree node from the index file pointed to by knum into the
- b-tree buffer. returns non-zero value if error.
- */
-
- COUNT rednod(buffer,node,knum)
- PFAST TREEBUFF *buffer;
- PFAST KEYFILE *knum;
- LONG node;
- {
- CTFILE *ctnum;
-
- VOID inracs();
- COUNT uerr();
-
- /* update buffer status information */
-
- buffer->nodeid = node;
- buffer->keyid = knum->filnum;
- buffer->update = 'n';
- buffer->klen = knum->length;
- buffer->ktipe = knum->ktype & COL_BOTH;
- buffer->lstpos = buffer->actlen = buffer->begbyt = 0;
- inracs(buffer);
-
- /* read node into buffer */
-
- if (knum->kmem > 0)
- #ifdef CTSERVER
- ctnum = knum->hmem;
- #else
- ctnum = knum - knum->kmem;
- #endif
- else
- ctnum = knum;
-
- #ifdef CTSERVER
- #ifdef EXTRABFR
- if(!redxnod(buffer,node,knum))
- #endif
- #endif
- if (ctio(CTREAD,ctnum,node,buffer->nodorg,ctnum->recsiz))
- return(uerr_cod);
-
- /* move node status info to TREEBUFF area */
-
- cpybuf(&buffer->sucesr,buffer->nodorg,STATUS);
-
- #ifdef UNIFRMAT
- revbyt(&buffer->sucesr,6);
- revwrd(&buffer->sucesr,2);
- #endif
-
- /* check member number */
-
- if (buffer->bmem != knum->kmem)
- terr(231);
-
- if (buffer->leaf == LEAF) {
- buffer->maxkv = knum->maxkvl;
- buffer->maxb = knum->maxkbl;
- if (knum->autodup == DUPKEY)
- buffer->confg = DUPLEAF;
- else
- buffer->confg = REGULAR;
- } else {
- buffer->maxkv = knum->maxkvn;
- buffer->maxb = knum->maxkbn;
- if (knum->autodup == DUPKEY)
- buffer->confg = DUPNONL;
- else
- buffer->confg = REGULAR;
- }
-
- return(NO_ERROR);
- }
-
-
- /* --------------------------------------------------------------------
- return the number of entries in the index file pointed to by knum
- */
-
- POINTER IDXENT(keyno)
- PFAST COUNT keyno;
- {
- KEYFILE *tstfnm();
- KEYFILE *knum;
- #ifdef FPUTFGET
- CTFILE *ctnum;
- #endif
-
- uerr_cod = 0;
- if ((knum = tstfnm(keyno)) == NULL) /* then error condition */
- return(DRNZERO);
- else if (knum->clstyp == DAT_CLOSE) {
- uerr_cod = FMOD_ERR;
- return(DRNZERO);
- }
-
- #ifdef FPUTFGET
- ctnum = knum - knum->kmem;
- if ((ctnum->flmode & SHARED) &&
- redhdr(knum - knum->kmem)) /* then error */
- return(DRNZERO);
- #endif
-
- return(knum->nument);
- }
-
-
-
- /* --------------------------------------------------------------------
- return root node #
- */
-
- LONG gtroot(knum)
- PFAST KEYFILE *knum;
- {
- #ifdef FPUTFGET
- CTFILE *ctnum;
-
- ctnum = knum - knum->kmem;
- if ((ctnum->flmode & SHARED) && redhdr(knum - knum->kmem))
- return(DRNZERO);
- #endif
-
- return(knum->root);
- }
-
-
- /* --------------------------------------------------------------------
- return pointer to key value in designated position of buffer
- */
-
- TEXT *valpnt(buffer,ct_elm)
-
- PFAST TREEBUFF *buffer;
- PFAST COUNT ct_elm;
-
- {
- #ifdef VARLKEYS
- TEXT *expval(); /* expval will determine where to put drn */
- #endif
-
- if (!buffer->ktipe) {
- buffer->lstpos = ct_elm;
- buffer->actlen = buffer->klen;
- if (buffer->confg & REGULAR) {
- buffer->actlen += sizeof(POINTER);
- return(buffer->ct_kyval + (buffer->begbyt =
- (ct_elm-1) * buffer->actlen) + sizeof(POINTER));
- } else
- return(buffer->ct_kyval + (buffer->begbyt = (ct_elm-1) *
- buffer->klen));
- }
-
- #ifdef VARLKEYS
- else
- return(expval(buffer,ct_elm));
- #else
- else
- terr(239);
- #endif
- }
-
- TEXT *hghpnt(buffer)
- PFAST TREEBUFF *buffer;
- {
- COUNT i;
-
- i = buffer->klen;
-
- #ifdef VARLKEYS
- if (buffer->ktipe & COL_PREFIX)
- i++;
- if (buffer->ktipe & COL_SUFFIX)
- i++;
- #endif
-
- if (buffer->confg & REGULAR)
- return(buffer->ct_kyval + (buffer->maxkv - 1) *
- (i + sizeof(POINTER)) + sizeof(POINTER));
- else
- return(buffer->ct_kyval + (buffer->maxkv - 1) * i);
- }
-
-
- /* --------------------------------------------------------------------
- return node pointer value
- */
-
- LONG nodpnt(buffer,ct_elm)
-
- TREEBUFF *buffer;
- PFAST COUNT ct_elm;
-
- {
- POINTER tp;
-
- if (buffer->confg == DUPLEAF)
- terr(209);
- cpybuf(&tp,valpnt(buffer,ct_elm) - sizeof(POINTER),sizeof(POINTER));
- #ifdef UNIFRMAT
- revobj(&tp,sizeof(POINTER));
- #endif
- return((LONG ) tp);
- }
-
- /* --------------------------------------------------------------------
- return drn pointer value
- */
-
- #ifdef LOW_HIGH
-
- POINTER drnpnt(buffer,ct_elm)
-
- TREEBUFF *buffer;
- COUNT ct_elm;
-
- {
- FAST TEXT *tp,*pp;
- FAST COUNT i;
- POINTER pntr;
-
- pp = (TEXT *) &pntr;
- tp = valpnt(buffer,ct_elm);
- if (buffer->confg & REGULAR)
- cpybuf(pp,tp - sizeof(POINTER),sizeof(POINTER));
- else {
- tp += buffer->klen;
- for (i = 0; i++ < sizeof(POINTER);)
- *pp++ = *--tp;
- }
- return(pntr);
- }
-
- #else
-
- POINTER drnpnt(buffer,ct_elm)
-
- PFAST TREEBUFF *buffer;
- PFAST COUNT ct_elm;
-
- {
- FAST TEXT *tp;
- POINTER pntr;
-
- tp = valpnt(buffer,ct_elm) - sizeof(POINTER);
- if (buffer->confg == DUPLEAF)
- tp += buffer->klen;
- cpybuf(&pntr,tp,sizeof(POINTER));
- #ifdef UNIFRMAT
- if (buffer->confg != DUPLEAF)
- revobj(&pntr,sizeof(POINTER));
- #endif
- return(pntr);
- }
-
- #endif
-
- #ifdef VARLKEYS
-
- TEXT *expval(bp,n)
- TREEBUFF *bp;
- COUNT n;
- {
- COUNT kl,kls; /* key length, - drp suffix */
- COUNT implen,colpfx,colpad,sfxcnt;
- FAST TEXT *ip,*tp;
- TEXT *retval;
-
- if (n < 1 || n > (bp->nkv + 1))
- terr(232);
-
- kl = kls = bp->klen;
- retval = bp->keyexp;
- if (bp->confg & REGULAR) {
- retval += sizeof(POINTER);
- if (bp->confg == DUPNONL)
- kls = kl - sizeof(POINTER);
- } else
- kls = kl - sizeof(POINTER);
-
- if (n == bp->lstpos)
- return(retval);
- else
- ip = bp->ct_kyval;
-
- colpfx = bp->ktipe & COL_PREFIX;
- colpad = bp->ktipe & COL_SUFFIX;
-
- if (n > bp->lstpos) {
- ip += (bp->begbyt + bp->actlen);
- n -= bp->lstpos;
- } else
- bp->lstpos = bp->actlen = bp->begbyt = 0;
-
- while (n > 0) {
- tp = bp->keyexp;
- bp->lstpos++;
- n--;
- bp->begbyt += bp->actlen;
-
- if (bp->confg & REGULAR) {
- cpybuf(tp,ip,bp->actlen = sizeof(POINTER));
- tp += sizeof(POINTER);
- ip += sizeof(POINTER);
- } else
- bp->actlen = 0;
-
- implen = 0;
- if (colpfx) {
- bp->actlen++;
- tp += (implen = (*ip++ & 0x00ff));
- }
- if (colpad) {
- bp->actlen++;
- implen += (bp->cursfx = sfxcnt = (*ip++ & 0x00ff));
- } else
- sfxcnt = 0;
- if (implen > kls)
- terr(233);
-
- if (implen < kls) {
- bp->actlen += (implen = kls - implen);
- cpybuf(tp,ip,implen);
- tp += implen;
- ip += implen;
- }
-
- while (sfxcnt-- > 0)
- *tp++ = PADDING;
- if (kls < kl) {
- cpybuf(tp,ip,sizeof(POINTER));
- ip += sizeof(POINTER);
- bp->actlen += sizeof(POINTER);
- }
- }
- return(retval);
- }
- #endif
-
- /* end of ctkrnl.c */
-