home *** CD-ROM | disk | FTP | other *** search
- /*
- * delete key
- *
- * 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 uerr(),putnod(),LOCK(),UNLOCK();
-
- #ifndef FPUTFGET
- LOCAL COUNT ct_nelem[MAXLEV];
- COUNT ct_tight[MAXLEV];
- COUNT ct_melem[MAXLEV];
- #endif
-
-
- /* --------------------------------------------------------------------
- routine to delete index entry checking that associated recbyt agrees
- with recbyt
-
- if pointers agree, DELCHK returns a 0; if not, it returns a 3 and
- no deletion is performed
-
- if the key value is not found, then a 4 is returned
- */
-
- COUNT DELCHK(keyno,target,recbyt)
-
- COUNT keyno;
- TEXT *target;
- POINTER recbyt;
-
- {
- VOID prpdup();
- COUNT DELKEY();
- KEYFILE *tstfnm();
-
- FAST KEYFILE *knum;
- TEXT *idxval;
-
- uerr_cod = 0;
- if ((knum = tstfnm(keyno)) == NULL)
- return(uerr_cod);
-
- cpybuf((idxval = ct_dupkey),target,knum->length);
- if (knum->autodup == DUPKEY)
- prpdup(idxval,knum,&recbyt);
-
- return(DELKEY(knum,idxval,recbyt));
- }
-
- /* --------------------------------------------------------------------
- routine to delete index entry "blind" (ie, without checking
- associated pointer for agreement); and return the associated pointer
- found in the index. cannot be used with DUPKEY.
-
- if error or no target is found, then return a zero
- */
-
- POINTER DELBLD(keyno,target)
-
- COUNT keyno;
- TEXT *target;
-
- {
- LOCAL POINTER test;
- POINTER fndkey();
- COUNT DELKEY();
- FAST KEYFILE *knum;
- KEYFILE *tstfnm();
-
- uerr_cod = 0;
- if ((knum = tstfnm(keyno)) == NULL)
- return(0);
- if (knum->autodup == DUPKEY) {
- uerr(KBLD_ERR);
- return(0);
- }
-
- if (!(test = fndkey(knum,target,'E'))) {
- uerr(KDEL_ERR);
- return(0);
- } else {
- if (DELKEY(knum,target,test))
- return(0);
- return(test);
- }
- }
-
-
- /* --------------------------------------------------------------------
- utility routine to delete key value from leaf node.
-
- NOTE: THE FOLLOWING APPLIES WHEN FPUTFGET IS DEFINED IN CTOPTN.H
-
- To support concurrent node updates, underflowed nodes (i.e., nodes
- less than half-full are not removed from the tree. A node may even
- become empty. Such under utilized nodes will be reused when key
- values from the same range of values are added back into the index.
- If key values are systematically removed from one end of the index,
- and replacements are added to the other end of the index; it will be
- necessary to rebuild or compact the index periodically to avoid wasted
- disk space. (See CTCMPC.C, the compaction utility.)
-
- */
-
- COUNT DELKEY(knum,idxval,pntr)
- PFAST KEYFILE *knum;
- TEXT *idxval;
- POINTER pntr;
- {
- COUNT npoint;
- FAST TREEBUFF *buffer;
- LONG node;
-
- LONG gtroot(),nodpnt();
- POINTER drnpnt();
- COUNT nodser(),hdrupd(),tstupd();
- TREEBUFF *getnod();
- TREEBUFF *movrgt();
- COUNT delexp();
-
- #ifndef FPUTFGET
- LONG pnode,snode;
- COUNT cmpflg;
- COUNT rtnode(),delupl(),delpbm();
-
- cmpflg = knum->ktype & COL_SUFFIX;
- #endif
- uerr_cod = btlev = 0;
- if (chkredf(knum))
- return(uerr_cod);
- if (!(node = gtroot(knum))) /* tree may be empty or gtroot err */
- if (uerr_cod)
- return(uerr_cod);
- else
- return(uerr(KDEL_ERR));
-
- while (node) { /* walk down or across tree until leaf node found */
- ct_lnode = node;
- if ((buffer = getnod(node,knum)) == NULL)
- return(uerr_cod);
- if (buffer->leaf == LEAF)
- break;
-
- if ((npoint = nodser(buffer,idxval,'L')) != -1) {
- if (npoint == -2)
- terr(220);
- #ifndef FPUTFGET
- ct_npath[++btlev] = node;
- ct_nelem[btlev] = npoint;
- if (cmpflg) {
- ct_melem[btlev] = buffer->nkv;
- ct_tight[btlev] = (buffer->nkb + buffer->klen)
- > buffer->maxb ? YES : NO;
- }
- #endif
- node = nodpnt(buffer,npoint);
- } else
- node = buffer->sucesr;
- }
-
- if (!node) /* then no leaf node found */
- terr(221);
-
- #ifdef FPUTFGET
- if (LOCK(node,knum) ||
- (buffer = movrgt(idxval,knum,getnod(node,knum))) == NULL)
- #else
- if (LOCK(node,knum) ||
- (buffer = movrgt(idxval,knum,buffer)) == NULL)
- #endif
- return(uerr_cod);
-
- if (ct_tky) {
- if (UNLOCK(buffer->nodeid,knum))
- return(uerr_cod);
- return(uerr(KDEL_ERR)); /* ct_key does not exist */
- }
-
- if (drnpnt(buffer,ct_elm) != pntr) {
- if (UNLOCK(buffer->nodeid,knum))
- return(uerr_cod);
- return(uerr(KMAT_ERR));
- }
-
- if (tstupd(knum))
- return(uerr_cod);
-
- delexp(buffer);
-
- node = buffer->nodeid; /* save for unlock */
-
- #ifdef FPUTFGET
- if (putnod(buffer,buffer->nkv) || UNLOCK(node,knum) ||
- hdrupd(knum,(POINTER) -1))
- return(uerr_cod);
- #else
- pnode = buffer->predsr;
- snode = buffer->sucesr;
- if (buffer->nkv > 0 || snode == DRNZERO || (cmpflg && delpbm(btlev))) {
- if (putnod(buffer,buffer->nkv) || UNLOCK(node,knum))
- return(uerr_cod);
- } else {
- /* empty leaf node, but not last leaf */
- if (btlev == 0) terr(242);
- if (rtnode(node,knum) || UNLOCK(node,knum))
- return(uerr_cod);
- if (pnode) {
- if ((buffer = getnod(pnode,knum)) == NULL)
- return(uerr_cod);
- buffer->sucesr = snode;
- putnod(buffer,buffer->nkv);
- }
- if (delupl(snode,knum))
- return(uerr_cod);
- if ((buffer = getnod(snode,knum)) == NULL)
- return(uerr_cod);
- buffer->predsr = pnode;
- putnod(buffer,buffer->nkv);
- }
- if (hdrupd(knum,(POINTER) -1))
- return(uerr_cod);
- #endif
- return(NO_ERROR);
- }
-
- #ifndef FPUTFGET
- COUNT rtnode(node,knum)
- LONG node;
- CTFILE *knum;
- {
- FAST TREEBUFF *buffer;
- FAST CTFILE *ctnum;
-
- TREEBUFF *getnod();
-
- if ((buffer = getnod(node,knum)) == NULL)
- return(uerr_cod);
- #ifdef CTSERVER
- ctnum = knum->hmem;
- #else
- ctnum = knum - knum->kmem;
- #endif
-
- buffer->predsr = -1L;
- buffer->sucesr = ctnum->delstk;
- buffer->bmem = 0;
- buffer->keyid = ctnum->filnum;
- putnod(buffer,0);
- ctnum->delstk = node;
- #ifdef FPUTONLY
- if (wrthdr(ctnum))
- return(uerr_cod);
- #endif
- return(NO_ERROR);
- }
-
- static COUNT delpbm(lev)
- FAST COUNT lev;
- {
- while (lev > 0) {
- if (ct_tight[lev])
- return(YES);
- if (ct_nelem[lev] != ct_melem[lev])
- break;
- lev--;
- }
- return(NO);
- }
-
- static COUNT updprd(node,knum,npoint,snode)
- LONG node;
- CTFILE *knum;
- COUNT npoint;
- LONG snode;
- {
- TREEBUFF *getnod();
- LONG nodpnt();
-
- FAST TREEBUFF *buffer;
- COUNT pass;
-
- pass = 0;
- while (btlev > 0 && npoint == 1) {
- ++pass;
- npoint = ct_nelem[btlev];
- node = ct_npath[btlev--];
- }
- btlev += pass++;
-
- if (npoint-- == 1)
- return(NO_ERROR);
-
- if ((buffer = getnod(node,knum)) == NULL)
- return(uerr_cod);
- node = nodpnt(buffer,npoint);
- while (pass-- != 0) {
- if ((buffer = getnod(node,knum)) == NULL)
- return(uerr_cod);
- node = nodpnt(buffer,buffer->nkv);
- }
- buffer->sucesr = snode;
- putnod(buffer,buffer->nkv);
- return(NO_ERROR);
- }
-
- static COUNT delupl(snode,knum)
- LONG snode;
- CTFILE *knum;
- {
- LONG node,prdnod;
- COUNT npoint,lstdel,pass;
- FAST TREEBUFF *buffer;
- TREEBUFF *prdbuf;
- TEXT lstkey[MAXLEN];
-
- TREEBUFF *getnod(),*movrgt();
- TEXT *valpnt();
- VOID insexp();
- COUNT delexp();
-
- pass = 0;
-
- del_loop:
- if ((node = ct_npath[btlev]) == 0)
- terr(241);
- npoint = ct_nelem[btlev--];
- if (pass++ && updprd(node,knum,npoint,snode))
- return(uerr_cod);
- if ((buffer = getnod(node,knum)) == NULL)
- return(uerr_cod);
- if (btlev == 0 && buffer->nkv < 3) {
- if (npoint == 1) {
- if ((knum->root = snode) == DRNZERO) terr(244);
- } else
- terr(243);
- return(rtnode(node,knum));
- }
- valpnt(buffer,npoint);
- lstdel = delexp(buffer); /* delexp does not handle DUPNONL ???? */
- if (lstdel && npoint > 1)
- cpybuf(lstkey,valpnt(buffer,npoint - 1),knum->length);
- snode = buffer->sucesr;
- if (buffer->nkv == 0) {
- if (rtnode(node,knum))
- return(uerr_cod);
- goto del_loop;
- }
- putnod(buffer,buffer->nkv);
- /* check if last entry deleted */
- /* if (!lstdel) return(NO_ERROR); */
- snode = node;
- while (lstdel && btlev > 0) {
- if ((node = ct_npath[btlev]) == DRNZERO)
- terr(245);
- npoint = ct_nelem[btlev--];
- if ((buffer = movrgt(lstkey,knum,getnod(node,knum))) == NULL)
- return(uerr_cod);
- insexp(buffer,lstkey,snode);
- buffer->nkv++;
- valpnt(buffer,npoint + 1);
- lstdel = delexp(buffer);
- if (buffer->nkb > buffer->maxb) terr(246);
- putnod(buffer,buffer->nkv);
- snode = node;
- }
-
- return(NO_ERROR);
- }
- #endif
-
- COUNT delexp(bp)
- PFAST TREEBUFF *bp;
- {
- COUNT expcnt,pfxcnt,pfxct2,sfxct2,sactlen,sbegbyt;
- COUNT colpfx,colpad,poff;
- FAST TEXT *tp;
-
- TEXT *valpnt();
-
- if (bp->lstpos == bp->nkv) { /* deleting last entry */
- bp->nkv--;
- bp->nkb -= bp->actlen;
- bp->lstpos = bp->actlen = bp->begbyt = 0;
- return(YES);
- }
-
- colpfx = bp->ktipe & COL_PREFIX;
- colpad = bp->ktipe & COL_SUFFIX;
- tp = bp->ct_kyval + bp->begbyt;
- if (bp->confg & REGULAR)
- poff = sizeof(POINTER);
- else
- poff = 0;
-
- #ifdef VARLKEYS
- if (colpfx) {
- pfxcnt = *(tp + poff) & 0x00ff;
- pfxct2 = *(tp + poff + bp->actlen) & 0x00ff;
- if (colpad)
- sfxct2 = *(tp + poff + bp->actlen + 1) & 0x00ff;
- } else
- pfxcnt = pfxct2 = 0;
- #else
- pfxcnt = pfxct2 = 0;
- #endif
-
- sactlen = bp->actlen;
- sbegbyt = bp->begbyt;
- valpnt(bp,bp->lstpos + 1);
-
- if (pfxct2 <= pfxcnt) /* applies to no prefix case as well */
- shflft(expcnt = sactlen,bp,sbegbyt+sactlen);
- #ifdef VARLKEYS
- else { /* must expand some or all of pfxct2 bytes */
- expcnt = sactlen - (pfxct2 - pfxcnt);
- colpfx = 1;
- if (colpad) {
- *(tp + poff + 1) = sfxct2;
- colpfx = 2;
- }
- if (poff) {
- *(tp + sactlen + poff) = pfxcnt;
- cpybuf(tp,tp + sactlen,poff + colpfx);
- }
- if (expcnt > 0)
- shflft(expcnt,bp,sbegbyt + sactlen + poff + colpfx);
- else { /* right shift required!!!! */
- terr(238);
- /*
- shfrgt(-expcnt,bp,sbegbyt + sactlen + poff + colpfx);
- cpybuf(bp->ct_kyval + sbegbyt + poff + colpfx,
- bp->prvexp + poff + pfxcnt,pfxct2 - pfxcnt);
- */ }
- bp->actlen += (pfxct2 - pfxcnt);
- }
- #endif
-
- bp->nkb -= expcnt;
- bp->begbyt = sbegbyt;
- bp->nkv--;
- bp->lstpos--;
- return(NO);
- }
-
- /* end of ctdelk.c */
-