home *** CD-ROM | disk | FTP | other *** search
- /* (C) Copyright 1984,85,86,87 Walter L. Peacock All Rights Reserved */
- /* b t r g e t s . c : 9/02/84: retrieve function for get calls */
- /*----------------------------------------------------------------------------
- * btrgets() processes the retrieval type CBTREE calls: GETREC, GETPAR,
- * GETALL, GETNXT, GETPRV, GETSEQ, GETKEYS, GETLY, GETLE, GETGT and GETGE.
- * (Note: GETFRST and GETLAST are handled by cbtree() ).
- *---------------------------------------------------------------------------*/
-
- #include "cbtree.h"
-
- char *strcpy();
- char *strnncpy();
-
- int btrgets(fdidx, idxblk, hdrloc, sl, dupflg, btparmst) /* return error code */
-
- int fdidx; /* index-file file descriptor */
- struct btidxblk *idxblk; /* index block semi-image */
- int hdrloc; /* .btpage index for matched key */
- unsigned sl; /* string length of search key */
- unsigned *dupflg; /* TRUE if duplicate keys exist */
- struct btcommo *btparmst; /* from user */
- {
- extern int strcmp();
- extern int strncmp();
- extern void free_svkey();
- extern void free();
- extern int mtch_loc();
- extern int wrap_hdr();
- struct btidx **btidxpp; /* where to put btidx pointer */
- register int i;
- long savbtptr = 0L;
- char *savskey, *calloc();
- long *lp;
- int match;
- char *keyp; /* general use key pointer */
- int comp;
-
- if ((btparmst->btoptype == GETSEQ ||
- btparmst->btoptype == GETALL ||
- btparmst->btoptype == NEWLOC ||
- btparmst->btoptype == GETKEYS) &&
- btparmst->btrecnum == (long *)NULL)
- {
- if ((btparmst->btrecnum = (long *)calloc(btparmst->btmax + 1,
- sizeof(long) )) == (long *)NULL)
- ckerror(- CK_NOMEM, "78");
- }
-
- switch (btparmst->btoptype)
- {
-
- case GETREC: /* GETREC only returns BTCALLOK if an EXACT match occurs. */
- /* Use GETALL or GETPAR to search on partial key matches. */
-
- if (strcmp(btparmst->btkey, idxblk->btpage[hdrloc].skeynme) == 0)
- {
- btparmst->btloc = idxblk->btpage[hdrloc].btptr;
- strcpy(btparmst->btkey, idxblk->btpage[hdrloc].skeynme);
- return(BTCALLOK);
- }
- else
- return(BTNOTFND);
-
-
- case GETGT : /* return FIRST key which is greater than, */
- case GETGE : /* greater than or equal to, */
- case GETLT : /* less than, or */
- case GETLE : /* less than or equal to the supplied PARTIAL key. */
-
- match = (
- strncmp(btparmst->btkey, idxblk->btpage[hdrloc].skeynme, sl) == 0);
-
- if (btparmst->btoptype == GETGT && match) /* return NEXT */
- {
- /*** skip ahead to next unique key ***/
- repeat
- {
- if ((hdrloc = wrap_hdr(hdrloc + 1, idxblk, fdidx, btparmst))
- == BTNOTFND)
- return (BTNOTFND);
- }
- while(strncmp(btparmst->btkey, idxblk->btpage[hdrloc].skeynme, sl) == 0);
- }
-
- else if ((btparmst->btoptype == GETLE && !match) || /* PREVIOUS */
- (btparmst->btoptype == GETLT))
- {
- if ((hdrloc = wrap_hdr(hdrloc-1, idxblk, fdidx, btparmst))
- == BTNOTFND)
- return (BTNOTFND);
- }
-
- if (idxblk->btpage[hdrloc].btptr == 0L) /* end of index file */
- return (BTNOTFND);
-
- strcpy(btparmst->btkey, idxblk->btpage[hdrloc].skeynme);
- btparmst->btloc = idxblk->btpage[hdrloc].btptr;
- return (BTCALLOK);
-
-
- case GETALL:
- if(!*dupflg) /* no duplicate keys, so return located record */
- {
- btparmst->btloc = btparmst->btrecnum[0] = idxblk->btpage[hdrloc].btptr;
- btparmst->btrecnum[1] = 0L;
- strcpy(btparmst->btkey, idxblk->btpage[hdrloc].skeynme);
- free_svkey(btparmst); /* in case this is not the first pass */
- return(BTCALLOK);
- }
-
- /* duplicates exist, find all of them: Return up to */
- /* btparmst->btmax record locations */
-
- /* match on btloc if not zero */
- if (btparmst->btloc > 0) /* we've already matched on one key */
- { /* find continuation point */
- if ((hdrloc = mtch_loc(hdrloc,idxblk,fdidx,btparmst)) == BTNOTFND)
- {
- free_svkey(btparmst);
- return (BTNOTFND);
- }
-
- /* now position hdrloc just AFTER matching record entry */
- if ((hdrloc = wrap_hdr(hdrloc + 1,idxblk,fdidx,btparmst)) == BTNOTFND)
- {
- free_svkey(btparmst);
- return (BTNOTFND);
- }
- }
-
- i = btparmst->btmax; /* # of records to actually give back */
- lp = btparmst->btrecnum; /* long pointer: where to put them */
- while ((comp =
- strncmp(btparmst->btkey, idxblk->btpage[hdrloc].skeynme, sl)) == 0)
- {
- if (i-- == 0 || (*lp = idxblk->btpage[hdrloc].btptr) == 0L)
- break; /* we done */
- ++lp; /* ready for next record */
-
- /* check next entry ... */
- if (hdrloc + 1 >= idxblk->cellicnt) /* end of this index blk */
- {
- if (idxblk->fwdpage < 2) /* no more index blocks */
- break;
-
- if (!savbtptr) /* only allocate once. */
- if ( !(savskey = calloc(btparmst->btkeylen+1, 1)))
- ckerror(- CK_NOMEM, "25");
-
- savbtptr = idxblk->btpage[hdrloc].btptr; /* remember it */
- strcpy(savskey, idxblk->btpage[hdrloc].skeynme);
-
- getidxr(fdidx, idxblk->fwdpage,idxblk,btparmst->btidxlen,
- btparmst->btkeylen);
- hdrloc = 0;
- }
- else
- ++hdrloc; /* end-of-tree */
- } /* end while (strncmp()) */
- *lp = 0L; /* end marker: place last record into btstruct */
-
- if (lp == btparmst->btrecnum) /* none */
- {
- free_svkey(btparmst);
- return (BTNOTFND);
- }
-
- if ((comp == 0 && i == -1) || /* search NOT yet exhausted */
- (comp != 0 && i == 0)) /* Search exhausted Block FULL */
- {
- if (btparmst->btsvkey == NULL)
- if ((btparmst->btsvkey =
- calloc(btparmst->btkeylen + 1, 1)) == NULL)
- ckerror(- CK_NOMEM, "77");
- keyp = btparmst->btsvkey; /* where to put copy of key */
- }
- else /* Search exhausted Block NOT full */
- {
- free_svkey(btparmst);
- keyp = btparmst->btkey; /* give user last key matched */
- }
-
- if (hdrloc > 0) /* remember where we are now */
- {
- btparmst->btloc = idxblk->btpage[hdrloc - 1].btptr;
- strcpy(keyp, idxblk->btpage[hdrloc - 1].skeynme);
- }
- else /* hdrloc == 0 */
- {
- if (savbtptr == 0L) /* this will happen on a zero-length idx */
- {
- free_svkey(btparmst);
- return (BTNOTFND);
- }
- btparmst->btloc = savbtptr; /* last key was at the end */
- strcpy(keyp, savskey); /* of the previous node. */
- }
- if (savbtptr)
- FREE(savskey);
-
- return(BTCALLOK);
-
-
- case GETKEYS: /* Return all partially matching KEYS and RECORD LOCATIONS */
-
- if (btparmst->btloc > 0) /* we've already matched on one key */
- { /* find continuation point */
- if ((hdrloc = mtch_loc(hdrloc,idxblk,fdidx,btparmst)) == BTNOTFND)
- {
- free_svkey(btparmst);
- return (BTNOTFND);
- }
-
- /* now position hdrloc just AFTER matching record entry */
- if ((hdrloc = wrap_hdr(hdrloc + 1,idxblk,fdidx,btparmst)) == BTNOTFND)
- {
- free_svkey(btparmst);
- return (BTNOTFND);
- }
- }
-
- i = btparmst->btmax; /* # pointers to give back */
- btidxpp = (struct btidx **)btparmst->btrecnum; /* where to put them */
- while ((comp =
- strncmp(btparmst->btkey, idxblk->btpage[hdrloc].skeynme, sl)) == 0)
- {
- if (i-- == 0 || idxblk->btpage[hdrloc].btptr == 0L)
- break;
- if ((*btidxpp = (struct btidx *)calloc(sizeof(struct btidx), 1))
- == (struct btidx *)NULL)
- ckerror(- CK_NOMEM, "75");
- (*btidxpp)->btptr = idxblk->btpage[hdrloc].btptr;
- if (((*btidxpp)->skeynme = calloc(btparmst->btkeylen + 1, 1))
- == NULL)
- ckerror(- CK_NOMEM, "76");
- strnncpy((*btidxpp)->skeynme, idxblk->btpage[hdrloc].skeynme,
- btparmst->btkeylen);
- btidxpp++; /* next pointer */
- if ((hdrloc = wrap_hdr(hdrloc+1, idxblk, fdidx, btparmst))
- == BTNOTFND)
- break; /* end of index */
- } /* end while (i--) */
-
- *btidxpp = (struct btidx *)NULL; /* end of list marker */
-
- if ((long *)btidxpp == btparmst->btrecnum) /* none */
- {
- free_svkey(btparmst);
- return (BTNOTFND);
- }
-
- if ((comp == 0 && i == -1) || /* search NOT yet exhausted */
- (comp != 0 && i == 0)) /* Search exhausted Block FULL */
- {
- if (btparmst->btsvkey == NULL)
- if ((btparmst->btsvkey =
- calloc(btparmst->btkeylen + 1, 1)) == NULL)
- ckerror(- CK_NOMEM, "18");
- keyp = btparmst->btsvkey; /* where to put copy of key */
- }
- else /* no more left in this search */
- {
- free_svkey(btparmst);
- keyp = btparmst->btkey; /* give user last key matched */
- }
-
- /* now remember where we are so we can pick up from here next time */
- if (hdrloc > 0)
- {
- btparmst->btloc = idxblk->btpage[hdrloc - 1].btptr;
- strcpy(keyp, idxblk->btpage[hdrloc - 1].skeynme);
- }
- else
- {
- btparmst->btloc = (*(btidxpp - 1))->btptr; /* last key was at end */
- strcpy(keyp, (*(btidxpp - 1))->skeynme); /* of the previous node. */
- }
- return(BTCALLOK);
-
- } /* end switch() */
-
- /*****************************************/
- /* */
- /* I N T E R L U D E */
- /* */
- /* The following functions check for */
- /* a match between btloc and hdrloc */
- /* */
- /*****************************************/
- if (btparmst->btloc > 0)
- {
- if ((hdrloc = mtch_loc(hdrloc,idxblk,fdidx,btparmst)) == BTNOTFND)
- return (BTNOTFND);
-
- /* now do a little twiddling */
- if (btparmst->btoptype == GETNXT || btparmst->btoptype == GETSEQ)
- {
- /* position hdrloc just AFTER matching record entry */
- if ((hdrloc = wrap_hdr(hdrloc +1,idxblk,fdidx,btparmst)) == BTNOTFND)
- return (BTNOTFND);
- }
- }
-
-
- switch (btparmst->btoptype) /* back on the road again... */
- {
-
- default:
- return(BTCOMMO); /* btcommo structure error */
-
-
- case GETPAR: /* get record matching the partial key */
-
- if (strncmp(btparmst->btkey, idxblk->btpage[hdrloc].skeynme, sl) == 0)
- {
- if((savbtptr = idxblk->btpage[hdrloc].btptr) == 0)
- return(BTNOTFND);
- btparmst->btloc = savbtptr;
- strcpy(btparmst->btkey, idxblk->btpage[hdrloc].skeynme);
- return(BTCALLOK);
- }
- else
- return(BTNOTFND);
-
-
- case GETNXT:
-
- if ((savbtptr = idxblk->btpage[hdrloc].btptr) == 0L)
- return(BTNOTFND);
- btparmst->btloc = savbtptr;
- strcpy(btparmst->btkey, idxblk->btpage[hdrloc].skeynme);
- return(BTCALLOK);
-
-
- case GETSEQ: /* return a block of index-sequential record numbers */
-
- i = btparmst->btmax; /* # records max to give back */
- lp = btparmst->btrecnum; /* where to put them */
- while (i-- != 0)
- {
- if ((*lp = idxblk->btpage[hdrloc].btptr) == 0L)
- break;
-
- ++lp; /* bump these AFTER the assignment */
-
- if (hdrloc + 1 >= idxblk->cellicnt)
- {
- if (idxblk->fwdpage < 2)
- break;
-
- if (savbtptr == 0L)
- if ((savskey = calloc(btparmst->btkeylen+1, 1)) == NULL)
- ckerror(- CK_NOMEM, "26");
-
- savbtptr = idxblk->btpage[hdrloc].btptr;
- strcpy(savskey, idxblk->btpage[hdrloc].skeynme);
-
- getidxr(fdidx, idxblk->fwdpage, idxblk, btparmst->btidxlen,
- btparmst->btkeylen);
- hdrloc = 0;
- }
- else
- ++hdrloc;
- } /* end while (i...) */
-
- *lp = 0L; /* place last record into btstruct */
- if (lp == btparmst->btrecnum) /* none */
- return (BTNOTFND);
- if (hdrloc > 0)
- {
- btparmst->btloc = idxblk->btpage[hdrloc - 1].btptr;
- strcpy(btparmst->btkey, idxblk->btpage[hdrloc - 1].skeynme);
- }
- else
- {
- if (savbtptr == 0L) /* this will happen on a zero-length idx */
- return (BTNOTFND);
- btparmst->btloc = savbtptr; /* last key was at end */
- strcpy(btparmst->btkey, savskey); /* of the previous node. */
- }
- if (savbtptr)
- FREE(savskey);
-
- return(BTCALLOK);
-
-
- case GETPRV: /* return index-previous KEY and RECORD NUMBER */
-
- /* position hdrloc just BEFORE matching record entry */
- if ((hdrloc = wrap_hdr(hdrloc-1, idxblk, fdidx, btparmst)) == BTNOTFND)
- return (BTNOTFND);
-
- strcpy(btparmst->btkey, idxblk->btpage[hdrloc].skeynme);
- btparmst->btloc = idxblk->btpage[hdrloc].btptr;
- return(BTCALLOK);
-
- } /* end second switch() */
- #if TC
- #else
- return(BTCOMMO); /* should never get here */
- #endif
- }
-
- /********************************************/
-
- int mtch_loc(hdrloc, idxblk, fdidx, btparmst) /* match btloc to hdrloc */
-
- int hdrloc; /* .btpage index for matched key */
- struct btidxblk *idxblk; /* index block semi-image */
- int fdidx; /* index-file file descriptor */
- struct btcommo *btparmst; /* from user */
- {
- extern int wrap_hdr();
-
- while (btparmst->btloc != idxblk->btpage[hdrloc].btptr)
- {
- if ((hdrloc = wrap_hdr(hdrloc + 1,idxblk,fdidx,btparmst)) == BTNOTFND)
- return (BTNOTFND);
- }
- return (hdrloc);
- }
-
- /********************************************/
-
- int wrap_hdr(hdrloc, idxblk, fdidx, btparmst) /* wrap hdrloc to next block */
-
- int hdrloc; /* .btpage index for matched key */
- struct btidxblk *idxblk; /* index block semi-image */
- int fdidx; /* index-file file descriptor */
- struct btcommo *btparmst; /* from user */
- {
- if (hdrloc < 0) /* yes, this IS needed */
- {
- while (hdrloc < 0)
- {
- if (idxblk->bwdpage > 1)
- {
- getidxr(fdidx, idxblk->bwdpage, idxblk, btparmst->btidxlen,
- btparmst->btkeylen);
- hdrloc = idxblk->cellicnt + hdrloc; /* proper place in new blk */
- }
- else
- return(BTNOTFND);
- }
- return (hdrloc);
- }
-
- if (hdrloc >= idxblk->cellicnt) /* we're off the edge */
- {
- if (idxblk->fwdpage > 1) /* are there further records */
- {
- getidxr(fdidx, idxblk->fwdpage, idxblk, /* get next */
- btparmst->btidxlen, btparmst->btkeylen);
- return(0); /* now we're at beginning of next block */
- }
- else /* no more further records: continuation not found. */
- {
- btparmst->btrecnum[0] = 0L; /* tell the human */
- return(BTNOTFND);
- }
- }
- return (hdrloc);
- }
-
- /************************/
-
- void free_svkey(btparmst)
-
- struct btcommo *btparmst;
- {
- extern void free();
-
- if (btparmst->btsvkey != NULL)
- {
- FREE(btparmst->btsvkey);
- }
- }
-
- /************************/
-
- void free_gtkey(btparmst) /* free get key array */
-
- struct btcommo *btparmst;
- {
- extern void free();
- struct btidx **btidxpp;
- unsigned i = btparmst->btmax;
-
- btidxpp = (struct btidx **)btparmst->btrecnum;
-
- while (i-- != 0 && *btidxpp != (struct btidx *)NULL)
- {
- FREE((*btidxpp)->skeynme);
- FREE(*btidxpp);
- ++btidxpp;
- }
- }
-
-