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"
-
-
- /*
- * VARIABLES ------------------------------------------------------------------
- *
- */
-
- static int ncache = 0; /* Number of cache slots used */
- static cache mb_ctop; /* Cache of top-of-index pointer */
- static cache mb_cache[MAX_CACHE]; /* Cache of index pointers */
- static cache *mb_hash[MAX_CACHE]; /* Hash table/updated after a collision */
-
-
- /*
- * PROTOTYPES -----------------------------------------------------------------
- *
- */
-
- static cache *_new_cache XARGS( (relation *, int) );
-
-
- /*
- * ROUTINES -------------------------------------------------------------------
- *
- */
-
- static cache *
- _new_cache (rel, idx)
- relation *rel;
- int idx;
- {
- if (ncache >= MAX_CACHE) /* If this happens, expand cache for performance */
- {
- _flush_cache (rel, idx);
- }
- ncache ++;
-
- return &mb_cache[ncache-1];
- }
-
-
- /******************************************************************************
- *
- * Since this isn't a client/server model, we can't cache data between
- * requests... instead, we cache it during the slowest operation: rebalancing.
- *
- * This is a pretty basic cache--rebalancing doesn't require that the actual
- * records be checked, just the pointers for the indices. So we keep track
- * of every record that we read, and service any requests we get for further
- * queries or updates from the cache. If we run out of space in the cache,
- * the whole thing is flushed and zeroed before servicing the request.
- *
- * There's a hashtable so that when the system requests the pointers for a
- * record number, we don't have to scan the entire cache table to find out
- * which entry in the array is required.
- *
- * Updates are done through macros in internal.h, that write to the cache
- * directly. Any update sets a flag within the cache array, saying that the
- * record's indices have changed and need to be written.
- *
- */
-
- cache *
- _read_cache (rel, rcd, idx)
- relation *rel;
- long rcd;
- int idx;
- {
- byte buf[cbINDEX];
- cache *ptr, *end;
- long n;
-
- end = &mb_cache[ncache]; /* Can't check when ptr==end */
-
- if (rcd == 0L)
- {
- if (mb_ctop.num != 0L)
- {
- return (&mb_ctop);
- }
-
- GO_TOP (rel, idx);
- readx (rel->fhRel, &(mb_ctop.num), 4);
- mb_ctop.changed = 0;
- return (&mb_ctop);
- }
-
- if ((ptr = mb_hash[ n=(rcd % MAX_CACHE) ]) != NULL && ptr->num == rcd)
- {
- return (ptr);
- }
-
- for (ptr = mb_cache; ptr < end; ptr++)
- if (ptr->num == rcd)
- {
- return (mb_hash[n] = ptr);
- }
-
- ptr = _new_cache (rel, idx);
-
- GO_INDEX (rel, rcd, idx);
- readx (rel->fhRel, buf, cbINDEX);
-
- ptr->left = *(long *)( 0+ buf);
- ptr->right = *(long *)( 4+ buf);
- ptr->parent = *(long *)( 8+ buf);
- ptr->parbal = *(char *)(12+ buf);
- ptr->num = rcd;
- ptr->changed = 0;
-
- return (mb_hash[n] = ptr);
- }
-
- void
- _flush_cache (rel, idx)
- relation *rel;
- int idx;
- {
- byte buf[cbINDEX];
- cache *ptr, *end;
-
- if (mb_ctop.changed)
- {
- GO_TOP (rel, idx);
- writx (rel->fhRel, &(mb_ctop.num), 4);
- }
-
- end = &mb_cache[ncache]; /* Can't check when ptr==end */
-
- for (ptr = mb_cache; ptr < end; ptr++)
- if (ptr->changed)
- {
- *(long *)( 0+ buf) = ptr->left;
- *(long *)( 4+ buf) = ptr->right;
- *(long *)( 8+ buf) = ptr->parent;
- *(char *)(12+ buf) = ptr->parbal;
-
- GO_INDEX (rel, ptr->num, idx);
- writx (rel->fhRel, buf, cbINDEX);
- }
-
- _free_cache ();
- }
-
- void
- _free_cache ()
- {
- register int i;
-
- for (i = 0; i < MAX_CACHE; i++)
- mb_hash[i] = NULL;
-
- ncache = 0;
- mb_ctop.num = 0L;
- mb_ctop.changed = 0;
- }
-
-