home *** CD-ROM | disk | FTP | other *** search
- /*
- * METALBASE 5.1
- *
- * Released January 1st, 1993 by Huan-Ti [ t-richj@microsoft.com ]
- *
- */
-
- #include <mbase.h>
- #include "internal.h"
-
-
- /*
- * PROTOTYPES -----------------------------------------------------------------
- *
- */
-
- static long _append XARGS( (relation *, dataptr, bool) );
- static mb_err _check_dup XARGS( (relation *, dataptr, int, long) );
- static mb_err _queue_dup XARGS( (relation *, dataptr, int, long) );
- static mb_err _delete XARGS( (relation *, long) );
- static long _find_ends XARGS( (relation *, int, int) );
- static mb_err _format XARGS( (relation *, dataptr, int) );
- static mb_err _link XARGS( (relation *, long) );
- static mb_err _remove XARGS( (relation *, long) );
- static mb_err _remove_q XARGS( (relation *, long) );
- static long _search XARGS( (relation *, int, mb_action, dataptr) );
- static long _find_que XARGS( (relation *, mb_action) );
- static bool _isqueue XARGS( (relation *) );
- static mb_err _roll_queue XARGS( (relation *, bool) );
-
-
- /*
- * ROUTINES -------------------------------------------------------------------
- *
- */
-
- void
- SetError (err)
- mb_err err;
- {
- bool fNotify = FALSE;
-
- /*
- * Only send the message if we're initializing the error code--we may run
- * through this routine more than once if we're just propogating an error
- * message up to the top level.
- *
- */
-
- if (err != MB_OKAY && err != mb_errno)
- {
- fNotify = TRUE;
- }
-
- switch (mb_errno = err)
- {
- case MB_OKAY: mb_error="no error"; break;
- case MB_NO_ROOM: mb_error="MAX_REL is #defined to be too small"; break;
- case MB_NO_MEMORY:mb_error="not enough memory for requested task"; break;
- case MB_NO_OPEN: mb_error="cannot open given filename"; break;
- case MB_NO_READ: mb_error="cannot read given filename"; break;
- case MB_FORMAT: mb_error="relation is not in MB 5.0+ format"; break;
- case MB_LOCKED: mb_error="relation is locked by another user"; break;
- case MB_BUSY: mb_error="relation is too busy"; break;
- case MB_BAD_REL: mb_error="function passed bad relation struct"; break;
- case MB_NO_WRITE: mb_error="cannot write to given relation"; break;
- case MB_BAD_ARG: mb_error="one or more arguments are not valid"; break;
- case MB_BAD_REC: mb_error="a null rec pointer has been received"; break;
- case MB_CORRUPT: mb_error="a corrupt index has been detected"; break;
- case MB_BAD_DUP: mb_error="addition would violate a nodups index";break;
- case MB_NO_CURR: mb_error="current record required for operation";break;
- case MB_BAD_IDX: mb_error="the specified index does not exist"; break;
- case MB_BAD_FLD: mb_error="the specified field does not exist"; break;
- case MB_NO_SUCH: mb_error="the specified record can't be found"; break;
- case MB_UNKNOWN: mb_error="search command invalid"; break;
- case MB_NO_FIELDS: mb_error="the new relation has no fields"; break;
- case MB_NO_INDICES: mb_error="the new relation has no indices"; break;
- case MB_BAD_INDEX: mb_error="the new index is invalid"; break;
- case MB_BAD_FIELD: mb_error="the new field is invalid"; break;
- case MB_BAD_SERIAL: mb_error="the record's serial number changed"; break;
- case MB_DUP_SERIAL: mb_error="only one serial field allowed"; break;
- case MB_DISKFULL: mb_error="there is not enough free space left"; break;
- case MB_TMPDIR: mb_error="you must define a TMP directory"; break;
- case MB_TMPERR: mb_error="cannot work with temporary file"; break;
- case MB_STRUCT: mb_error="unrecognized structure alignment"; break;
- case MB_ABORTED: mb_error="operation aborted by request"; break;
- case MB_NO_QUEUE: mb_error="there are no records in queue"; break;
- case MB_NO_DATA: mb_error="the relation's .DAT file is missing"; break;
- case MB_ASSERT: mb_error="a logical assertion has failed!"; break;
- case MB_BAD_DATA: mb_error="a corrupt datafile has been detected"; break;
- case MB_ENCRYPT: mb_error="the encryption key used is invalid"; break;
- case MB_BAD_LEN: mb_error="the new field must have a length"; break;
- default: mb_error="undefined error--rebuild and pray"; break;
- }
-
- if (fNotify)
- {
- CallService (svcERROR);
- }
- }
-
-
- /*
- * SERVICE ROUTINES -----------------------------------------------------------
- *
- */
-
- static mb_err
- _link (rel, rcd) /* CACHED */
- relation *rel;
- long rcd;
- {
- register int idx;
-
- _free_cache ();
-
- if (_isqueue (rel))
- {
- Error (MB_OKAY);
- }
-
- for (idx = 0; idx < rel->nIdx; idx++)
- {
- if (_drop (rel, rcd, idx, 0L))
- {
- Error (mb_errno);
- }
- if (_check (rel, rcd, 0L, idx))
- {
- _flush_cache (rel, idx);
- Error (mb_errno);
- }
-
- _flush_cache (rel, idx);
- }
-
- SetError (MB_OKAY);
-
- lblERROR:
- return mb_errno;
- }
-
- static mb_err
- _remove (rel, bad)
- relation *rel;
- long bad;
- {
- int idx, dir;
- long rep, tmp;
- char bal;
- dataptr dat;
-
-
- /*
- * This routine simply moves the last record in the primary heap over the
- * record which is to be deleted, and adjusts all pointers to that replacement
- * record's new position. Thus, if the record to be deleted is already at
- * the end of the heap, there's nothing to do.
- *
- */
-
- lseek (rel->fhRel, POS_NUMREC, 0);
- readx (rel->fhRel, &rep, 4);
-
- if (rep == bad)
- {
- Error_2 (MB_OKAY);
- }
- if ((dat = (dataptr)malloc (rel->cbRecord + cbINDEX* rel->nIdx +1)) == NULL)
- {
- Error (MB_NO_MEMORY);
- }
-
- GO_START (rel, rep);
- readx (rel->fhRel, dat, rel->cbRecord + cbINDEX* rel->nIdx);
-
- GO_START (rel, bad);
- writx (rel->fhRel, dat, rel->cbRecord + cbINDEX* rel->nIdx);
-
- free (dat);
-
- for (idx = 0; idx < rel->nIdx; idx++)
- {
-
- /*
- * On each index, first check for a parent record, and update it:
- *
- */
-
- GO_POINT (rel, rep, idx, 0);
- readx (rel->fhRel, &tmp, 4); /* Record # of this record's parent */
-
- GO_BAL (rel, rep, idx);
- readx (rel->fhRel, &bal, 1); /* Balance and parent direction */
- dir = (bal & PARDIR); /* (interested in parent direction only) */
-
- if (tmp == 0L)
- GO_TOP (rel, idx);
- else
- GO_POINT (rel, tmp, idx, (dir ? 1 : -1));
-
- writx (rel->fhRel, &bad, 4);
-
- /*
- * Then check for a left-child:
- *
- */
-
- GO_POINT (rel, rep, idx, -1);
- readx (rel->fhRel, &tmp, 4);
- if (tmp != 0L)
- {
- GO_POINT (rel, tmp, idx, 0);
- writx (rel->fhRel, &bad, 4);
- }
-
- /*
- * Finally check for a right-child:
- *
- */
-
- GO_POINT (rel, rep, idx, 1);
- readx (rel->fhRel, &tmp, 4);
- if (tmp != 0L)
- {
- GO_POINT (rel, tmp, idx, 0);
- writx (rel->fhRel, &bad, 4);
- }
- }
-
- SetError (MB_OKAY);
-
-
- lblERROR_2:
- if (_roll_queue (rel, FALSE) != MB_OKAY) /* Move queue inward, over rec */
- {
- Error (mb_errno)
- }
-
- rep--;
- lseek (rel->fhRel, POS_NUMREC, 0);
- writx (rel->fhRel, &rep, 4);
-
- lblERROR:
- return mb_errno;
- }
-
- static long
- _append (rel, rec, fIndex)
- relation *rel;
- dataptr rec;
- bool fIndex;
- {
- register int idx;
- long rcd, temp;
- char bal;
-
-
- if (fIndex) /* Placing record before secondary (queue) heap? */
- {
- if (_roll_queue (rel, TRUE) != MB_OKAY) /* Then move queue outward */
- {
- return 0L;
- }
- }
-
- lseek (rel->fhRel, (fIndex) ? POS_NUMREC : POS_NUMQUE, 0);
- readx (rel->fhRel, &temp, 4); temp++;
- lseek (rel->fhRel, (fIndex) ? POS_NUMREC : POS_NUMQUE, 0);
- writx (rel->fhRel, &temp, 4);
-
- if (fIndex)
- rcd = temp;
- else
- {
- lseek (rel->fhRel, POS_NUMREC, 0);
- readx (rel->fhRel, &rcd, 4);
- rcd += temp;
- }
-
- GO_START (rel, rcd);
-
- temp = 0L;
- bal = BAL_EV;
-
- for (idx = 0; idx < rel->nIdx; idx++)
- {
- writx (rel->fhRel, &temp, 4); /* Write left-child as 0 (none) */
- writx (rel->fhRel, &temp, 4); /* Write right-child as 0 (none) */
- writx (rel->fhRel, &temp, 4); /* Write parent as 0 (top of tree) */
- writx (rel->fhRel, &bal, 1); /* Write parent as right, balanced even */
- }
-
- if (_recWrite (rel, rec, rcd) != MB_OKAY) /* Write the record's data */
- {
- return 0L;
- }
-
- return rcd;
- }
-
- static mb_err
- _check_dup (rel, rec, idx, ign)
- relation *rel;
- dataptr rec;
- int idx;
- long ign; /* ign == "ignore"--we'll skip this record */
- {
- dataptr mem;
- long pos;
- int dir;
-
- if (rel->fDups[idx] == TRUE || fSerialIdx(rel,idx))
- {
- Error (MB_OKAY);
- }
-
- GO_TOP (rel, idx);
- readx (rel->fhRel, &pos, 4);
-
- if ((mem = (dataptr)malloc (rel->cbRecord +1)) == (dataptr)0)
- {
- Error (mb_errno);
- }
-
- for ( ; pos != 0L; )
- {
- dir = _compare (rel, rec, _memrec(rel,mem,pos), idx);
-
- if (dir == 0) /* Found a matching record? It might be a problem */
- {
- if (pos == ign) /* (unless, of course, we just found the record */
- break; /* that we're about to update. Then it's okay). */
-
- Error_2 (MB_BAD_DUP);
- }
-
- GO_POINT (rel, pos, idx, dir);
- readx (rel->fhRel, &pos, 4);
- }
-
- SetError (MB_OKAY);
-
- lblERROR_2:
- free (mem);
-
- lblERROR:
- return mb_errno;
- }
-
- static mb_err
- _format (rel, rec, stage)
- relation *rel;
- dataptr rec;
- int stage;
- {
- register int fld;
- charptr pch;
- long nexts;
-
-
- if (! rec)
- {
- Error (MB_BAD_REC);
- }
-
- for (fld = 0; fld < rel->nFld; fld++)
- {
- pch = (char *)rec + rel->cbStart[fld];
-
- switch (stage)
- {
-
- /*
- * During stage 1, we've just received a record structure from the user, and
- * have to process it to ensure it's in the correct format to be stored
- * permanently.
- *
- */
-
- case 1: switch (rel->fldType[fld])
- {
- case T_MONEY:
- *(double *)pch = tomoney( *(double *)pch );
- break;
- }
- break;
-
- /*
- * During stage 2, the entire record is already encrypted, and we're sure that
- * the add is going to take place (stage 2 is only called for add operations).
- * So after we set the serial field, we have to reencrypt just that field.
- * Note that, as always, we expect there to be no more than one serial field...
- *
- */
-
- case 2: switch (rel->fldType[fld])
- {
- case T_SERIAL:
- GO_NEXTS (rel);
- readx (rel->fhRel, &nexts, 4);
-
- *(long *)pch = rel->serial = nexts;
- _encryptf (pch, 4, rel->mask);
-
- nexts++;
- GO_NEXTS (rel);
- writx (rel->fhRel, &nexts, 4);
- break;
- }
- break;
- }
- }
-
- SetError (MB_OKAY);
-
- lblERROR:
- return mb_errno;
- }
-
- static mb_err
- _delete (rel, bad) /* CACHED */
- relation *rel;
- long bad;
- {
- static int lastmove = -1;
- register int idx;
- long bp, rep, rp;
- int bal;
- cache *ptr;
-
-
- if (rel->fMulti)
- {
- if (_remove_m (rel, bad) != MB_OKAY)
- {
- Error (mb_errno);
- }
- }
-
- /*
- * This routine removes the given record from the index tree; its parents
- * and children are reassigned and the tree rebalanced. Of course, if the
- * record being deleted is in the queue, there's no reason to do this at
- * all...
- *
- */
-
- if (_isqueue (rel))
- {
- Error (MB_OKAY);
- }
-
- _free_cache ();
-
- for (idx = 0; idx < rel->nIdx; idx++)
- {
- ptr = _read_cache (rel, bad, idx);
- bp = ptr->parent;
- bal = ptr->parbal & BAL;
-
- if (bal != BAL_EV)
- rep = _find_seq (rel, bad, bad, idx, NUM_BAL(bal));
- else
- {
- lastmove = 0 - lastmove;
- if (! (rep = _find_seq (rel, bad, bad, idx, lastmove)))
- {
- lastmove = 0 - lastmove;
- rep = _find_seq (rel, bad, bad, idx, lastmove);
- }
- }
-
- if (! rep)
- {
- _dislink (rel, bad, idx, 0L);
- }
- else
- {
- ptr = _read_cache (rel, rep, idx);
- rp = ptr->parent;
-
- _dislink (rel, rep, idx, 0L);
- _replace (rel, bad, rep, idx);
-
- if (rp != bad)
- {
- if (_check (rel, rp, bp, idx))
- {
- _flush_cache (rel, idx);
- Error (mb_errno);
- }
- }
- }
-
- if (_check (rel, bp, 0L, idx))
- {
- _flush_cache (rel, idx);
- Error (mb_errno);
- }
-
- _flush_cache (rel, idx);
- }
-
- SetError (MB_OKAY);
-
- lblERROR:
- return mb_errno;
- }
-
- static long
- _search (rel, idx, act, comp) /* CACHED */
- relation *rel;
- int idx;
- mb_action act;
- dataptr comp;
- {
- long pos, last;
- dataptr rec;
- cache *ptr;
- int dir;
-
-
- if ((rec = (dataptr)malloc (rel->cbRecord +1)) == NULL)
- {
- return 0L; /* Appropriate error has been already set */
- }
-
- _strobe (rel, 0);
-
- ptr = _read_cache (rel, 0L, idx);
- pos = ptr->num;
-
- for (last = 0L; pos != 0L; )
- {
- _strobe (rel, 0); /* Don't let anyone think we're dead */
-
- ptr = _read_cache (rel, pos, idx);
- _memrec (rel, rec, pos);
-
- dir = _compare (rel, rec, comp, idx); /* -1 == look right */
-
- /*
- * Is it a valid record? If so, set {last} to the record number.
- *
- */
- switch (act)
- {
- case LTHN: if (dir < 0) last = pos; break;
- case LTEQ: if (dir <= 0) last = pos; break;
- case EQUL: if (dir == 0) last = pos; break;
- case GTEQ: if (dir >= 0) last = pos; break;
- case GTHN: if (dir > 0) last = pos; break;
- }
-
- /*
- * Which way should we look if we found a matches-the-comparison-record record?
- * This is to ensure clean handling of duplicate values (otherwise we'd just
- * return now, instead of setting 'last' and continuing the search.
- *
- */
- if (dir == 0)
- {
- if (act == GTHN || act == LTEQ) dir = -1;
- if (act == GTEQ || act == LTHN || act == EQUL) dir = 1;
- }
-
- pos = (dir == -1) ? ptr->right : ptr->left;
- }
-
- free (rec);
-
- return last;
- }
-
- static long
- _find_ends (rel, idx, dir) /* CACHED */
- relation *rel;
- int idx, dir;
- {
- long pos, tmp;
- cache *ptr;
-
- ptr = _read_cache (rel, 0L, idx);
-
- if ((pos = ptr->num) == 0L)
- {
- return 0L;
- }
-
- for (tmp = pos; ; pos = tmp)
- {
- _strobe (rel, 0); /* Don't let anyone think we're dead */
-
- ptr = _read_cache (rel, tmp, idx);
- tmp = _cache_field (ptr, dir);
-
- if (tmp == 0L) return pos;
- }
- }
-
-
- /*
- * PRIMARY ROUTINES -----------------------------------------------------------
- *
- */
-
- mb_err
- mb_addfn (rel, rec, fIndex)
- relation *rel;
- dataptr rec;
- bool fIndex;
- {
- int idx;
- long rcd;
-
-
- if (_identify (rel) < 0) Error (MB_BAD_REL);
-
- if (rel->fReadOnly) Error (MB_NO_WRITE);
-
- if (_format (rel, rec, 1)) Error (mb_errno);
-
- if (_set_lck (rel)) Error (mb_errno);
-
- if (_chk_elck (rel, TRUE)) Error_2 (mb_errno);
-
-
- _encrypt (rel, rec);
-
- for (idx = 0; idx < rel->nIdx; idx++)
- {
- if (_check_dup (rel, rec, idx, 0L))
- {
- Error_3 (mb_errno);
- }
- if (_queue_dup (rel, rec, idx, 0L))
- {
- Error_3 (mb_errno);
- }
- }
-
-
- (void)_format (rel, rec, 2); /* Set serial number (if necessary) */
-
- if (! (rcd = _append (rel, rec, fIndex)))
- {
- Error_3 (mb_errno);
- }
-
- if (fIndex)
- {
- if (_link (rel, rcd) != MB_OKAY)
- {
- Error_3 (mb_errno);
- }
- }
-
- rel->pos = rcd;
-
- SetError (MB_OKAY);
-
- lblERROR_3:
- _decrypt (rel, rec);
-
- lblERROR_2:
- _clr_lck (rel);
-
- lblERROR:
- return mb_errno;
- }
-
- mb_err
- mb_upd (rel, rec)
- relation *rel;
- dataptr rec;
- {
- int idx;
- long rcd;
-
-
- if (_identify (rel) < 0) Error (MB_BAD_REL);
-
- if (rel->fReadOnly) Error (MB_NO_WRITE);
-
- if (_format (rel, rec, 1)) Error (mb_errno);
-
- if (_set_lck (rel)) Error (mb_errno);
-
- if (_chk_elck (rel, TRUE)) Error_2 (mb_errno);
-
- if ((rcd = rel->pos) == 0L) Error_2 (MB_NO_CURR);
-
-
- if (rel->iSerial < rel->nFld)
- {
- if (*(long *)((char *)rec + rel->cbStart [rel->iSerial]) != rel->serial)
- {
- Error_2 (MB_BAD_SERIAL);
- }
- }
-
- _encrypt (rel, rec);
-
- for (idx = 0; idx < rel->nIdx; idx++)
- {
- if (_check_dup (rel, rec, idx, rcd))
- {
- Error_3 (mb_errno);
- }
- if (_queue_dup (rel, rec, idx, rcd))
- {
- Error_3 (mb_errno);
- }
- }
-
- if (_delete (rel, rcd) != MB_OKAY)
- {
- Error_3 (mb_errno);
- }
-
- _recWrite (rel, rec, rcd);
-
- if (_link (rel, rcd))
- {
- Error_3 (mb_errno);
- }
-
- SetError (MB_OKAY);
-
- lblERROR_3:
- _decrypt (rel, rec);
-
- lblERROR_2:
- _clr_lck (rel);
-
- lblERROR:
- return mb_errno;
- }
-
- mb_err
- mb_del (rel)
- relation *rel;
- {
- if (_identify (rel) < 0) Error (MB_BAD_REL);
-
- if (rel->fReadOnly) Error (MB_NO_WRITE);
-
- if (rel->pos == 0L) Error (MB_NO_CURR);
-
- if (_set_lck (rel)) Error (mb_errno);
-
- if (_chk_elck (rel, TRUE)) Error_2 (mb_errno);
-
-
- if (_delete (rel, rel->pos) != MB_OKAY)
- {
- Error_2 (mb_errno);
- }
-
- if (_isqueue (rel))
- {
- if (_remove_q (rel, rel->pos) != MB_OKAY)
- {
- Error_2 (mb_errno);
- }
- }
- else
- {
- if (_remove (rel, rel->pos) != MB_OKAY)
- {
- Error_2 (mb_errno);
- }
- }
-
- rel->pos = 0L;
-
- SetError (MB_OKAY);
-
- lblERROR_2:
- _clr_lck (rel);
-
- lblERROR:
- return mb_errno;
- }
-
- mb_err
- mb_sel (rel, idx, buf, act, comp)
- relation *rel;
- int idx;
- mb_action act;
- dataptr buf, comp;
- {
- dataptr rec = NULL; /* Comparison record (==comp if comp!=NULL) */
- long off;
- bool fComplex = FALSE;
-
-
- if (_identify (rel) < 0) Error (MB_BAD_REL);
-
- if (idx < 0 || idx >= rel->nIdx) Error (MB_BAD_IDX);
-
- if (_set_lck (rel)) Error (mb_errno);
-
- if (_chk_elck (rel, FALSE)) Error_2 (mb_errno);
-
- /*
- * Determine the comparison record to use...
- *
- */
-
- if ( (act == GTEQ) || (act == GTHN) ||
- (act == LTEQ) || (act == LTHN) || (act == EQUL) )
- {
- fComplex = TRUE;
-
- if (comp != NULL)
- {
- rec = comp;
- }
- else
- {
- if ((rec = (dataptr)malloc (rel->cbRecord +1)) == (dataptr)0)
- {
- Error_2 (mb_errno);
- }
-
- numcpy (rec, buf, rel->cbRecord);
- }
- }
-
- if (fComplex)
- {
- _encrypt (rel, rec); /* The comparison buffer must be encrypted */
- }
-
-
- /*
- * And then determine the requested action.
- *
- */
-
- if (rel->pos == 0L)
- {
- if (act == NEXT) act = FRST;
- if (act == PREV) act = LAST;
- }
-
- _free_cache ();
-
- if (_isqueue (rel))
- {
- switch (act)
- {
- case NEXT: act = NQUE; break;
- case PREV: act = PQUE; break;
- }
- }
-
- switch (act)
- {
- case FRST:
- case LAST: off = _find_ends (rel, idx, (act == FRST) ? -1 : 1);
- break;
-
- case CURR: off = rel->pos;
- break;
-
- case NEXT:
- case PREV: off = _find_seq (rel, 0L, rel->pos, idx, (act == NEXT)?1:-1);
- break;
-
- case NQUE:
- case PQUE:
- case FQUE:
- case LQUE: off = _find_que (rel, act);
- break;
-
- case GTEQ:
- case GTHN:
- case LTEQ:
- case LTHN:
- case EQUL: off = _search (rel, idx, act, rec);
- break;
-
- default : Error_3 (MB_UNKNOWN);
- break;
- }
-
- if (mb_errno != MB_OKAY) Error_3 (mb_errno);
-
- if (off == 0L) Error_3 (MB_NO_SUCH);
-
-
- if (recClean (rel, buf) != MB_OKAY) /* Ensure we will have a place to */
- Error_3 (mb_errno); /* put multi-length fields */
-
-
- rel->pos = off;
-
- _memrec (rel, buf, rel->pos); /* Read in the output buffer, encrypted */
- _decrypt (rel, buf); /* Decrypt the output buffer */
-
- if (_recFill (rel, buf) != MB_OKAY)
- {
- Error_3 (mb_errno);
- }
-
- if (rel->pos && rel->iSerial < rel->nFld)
- {
- rel->serial = *(long *)((char *)buf + rel->cbStart[rel->iSerial]);
- }
-
- SetError (MB_OKAY);
-
-
- lblERROR_3:
- if (fComplex && comp != NULL)
- {
- _decrypt (rel, comp); /* Re-decrypt the compare buffer, if given one */
- }
-
- lblERROR_2:
- if (fComplex && comp == NULL && rec)
- {
- free (rec); /* otherwise, free the comp buffer we created */
- }
-
- _clr_lck (rel);
-
- lblERROR:
- return mb_errno;
- }
-
- long
- mb_num (rel)
- relation *rel;
- {
- long x, y;
-
- if (_identify (rel) < 0) Error (MB_BAD_REL);
-
- lseek (rel->fhRel, POS_NUMREC, 0);
- readx (rel->fhRel, &x, 4); /* Doesn't include non-indexed recs */
- lseek (rel->fhRel, POS_NUMQUE, 0);
- readx (rel->fhRel, &y, 4);
-
- SetError (MB_OKAY);
-
- lblERROR:
- return (mb_errno == MB_OKAY) ? (x+y) : -1L;
- }
-
-
- /*
- * DEFERRED-INDEXING ROUTINES -------------------------------------------------
- *
- */
-
- long
- mb_num_q (rel)
- relation *rel;
- {
- long x;
-
- if (_identify (rel) < 0) Error (MB_BAD_REL);
-
- lseek (rel->fhRel, POS_NUMQUE, 0);
- readx (rel->fhRel, &x, 4);
-
- SetError (MB_OKAY);
-
- lblERROR:
- return (mb_errno == MB_OKAY) ? x : -1L;
- }
-
- static long
- _find_que (rel, act)
- relation *rel;
- mb_action act;
- {
- long numrec, numque, targ;
-
- lseek (rel->fhRel, POS_NUMREC, 0);
- readx (rel->fhRel, &numrec, 4); /* Doesn't include non-indexed recs */
- lseek (rel->fhRel, POS_NUMQUE, 0);
- readx (rel->fhRel, &numque, 4);
-
- switch (act)
- {
- case FQUE: targ = numrec +1; break;
- case LQUE: targ = numrec + numque; break;
- case NQUE: targ = rel->pos +1; break;
- case PQUE: targ = rel->pos -1; break;
- }
-
- if ((targ <= numrec) || (targ > numrec+numque))
- return 0L;
-
- return targ;
- }
-
- static mb_err
- _remove_q (rel, trg)
- relation *rel;
- long trg;
- {
- dataptr dat;
- long numrec, numque, org;
-
- lseek (rel->fhRel, POS_NUMREC, 0);
- readx (rel->fhRel, &numrec, 4);
- lseek (rel->fhRel, POS_NUMQUE, 0);
- readx (rel->fhRel, &numque, 4);
-
- org = numrec +numque;
-
- numque--;
- lseek (rel->fhRel, POS_NUMQUE, 0);
- writx (rel->fhRel, &numque, 4);
-
- if ( (trg <= numrec) || (trg >= org) )
- {
- Error (MB_OKAY);
- }
-
- if (! (dat = (dataptr)malloc (rel->cbRecord + cbINDEX* rel->nIdx +1)) )
- {
- Error (MB_NO_MEMORY);
- }
-
- GO_START (rel, org);
- readx (rel->fhRel, dat, rel->cbRecord + cbINDEX* rel->nIdx);
- GO_START (rel, trg);
- writx (rel->fhRel, dat, rel->cbRecord + cbINDEX* rel->nIdx);
-
- free (dat);
-
- SetError (MB_OKAY);
-
- lblERROR:
- return mb_errno;
- }
-
- static bool
- _isqueue (rel)
- relation *rel;
- {
- long num;
-
- lseek (rel->fhRel, POS_NUMREC, 0);
- readx (rel->fhRel, &num, 4);
-
- return (rel->pos > num) ? TRUE : FALSE;
- }
-
- static mb_err
- _roll_queue (rel, fOutward)
- relation *rel;
- bool fOutward;
- {
- dataptr dat;
- long numrec, numque, org, trg;
-
- lseek (rel->fhRel, POS_NUMREC, 0);
- readx (rel->fhRel, &numrec, 4);
- lseek (rel->fhRel, POS_NUMQUE, 0);
- readx (rel->fhRel, &numque, 4);
-
- if (fOutward)
- {
- org = numrec +1;
- trg = numrec +numque +1;
- }
- else
- {
- org = numrec +numque;
- trg = numrec;
- }
-
- if (org != trg)
- {
- if (! (dat = (dataptr)malloc (rel->cbRecord + cbINDEX* rel->nIdx +1)) )
- {
- Error (MB_NO_MEMORY);
- }
-
- GO_START (rel, org);
- readx (rel->fhRel, dat, rel->cbRecord + cbINDEX* rel->nIdx);
-
- GO_START (rel, trg);
- writx (rel->fhRel, dat, rel->cbRecord + cbINDEX* rel->nIdx);
-
- free (dat);
- }
-
- SetError (MB_OKAY);
-
- lblERROR:
- return mb_errno;
- }
-
- static mb_err
- _queue_dup (rel, rec, idx, ign)
- relation *rel;
- dataptr rec;
- int idx;
- long ign;
- {
- dataptr mem;
- long pos, num;
-
-
- lseek (rel->fhRel, POS_NUMREC, 0);
- readx (rel->fhRel, &pos, 4);
- lseek (rel->fhRel, POS_NUMQUE, 0);
- readx (rel->fhRel, &num, 4);
-
- if (rel->fDups[idx] == TRUE || fSerialIdx(rel,idx))
- {
- Error (MB_OKAY);
- }
-
- if ((mem = (dataptr)malloc (rel->cbRecord +1)) == NULL)
- {
- Error (mb_errno);
- }
-
- for (pos++; num; num--,pos++)
- {
- if (_compare (rel, rec, _memrec(rel,mem,pos), idx) == 0)
- {
- if (pos == ign)
- break;
-
- Error_2 (MB_BAD_DUP);
- }
- }
-
- SetError (MB_OKAY);
-
- lblERROR_2:
- free (mem);
-
- lblERROR:
- return mb_errno;
- }
-
- mb_err
- mb_xfer (rel)
- relation *rel;
- {
- long num;
-
-
- if (_identify (rel) < 0) Error (MB_BAD_REL);
-
- if (rel->fReadOnly) Error (MB_NO_WRITE);
-
- if (_set_lck (rel)) Error (mb_errno);
-
- if (_chk_elck (rel, TRUE)) Error_2 (mb_errno);
-
-
- lseek (rel->fhRel, POS_NUMQUE, 0);
- readx (rel->fhRel, &num, 4);
-
- if (! num)
- {
- Error_2 (MB_NO_QUEUE);
- }
-
- lseek (rel->fhRel, POS_NUMREC, 0);
- readx (rel->fhRel, &num, 4);
- num++;
-
- if (_link (rel, num))
- {
- Error_2 (mb_errno);
- }
-
- rel->pos = num;
-
- lseek (rel->fhRel, POS_NUMREC, 0);
- writx (rel->fhRel, &num, 4);
- lseek (rel->fhRel, POS_NUMQUE, 0);
- readx (rel->fhRel, &num, 4); num--;
- lseek (rel->fhRel, POS_NUMQUE, 0);
- writx (rel->fhRel, &num, 4);
-
- SetError (MB_OKAY);
-
-
- lblERROR_2:
- _clr_lck (rel);
-
- lblERROR:
- return mb_errno;
- }
-
-