home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / CONTRIB / MBASE / MBASE51.TAR / mbase51 / src / mb_cache.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-09-04  |  3.9 KB  |  167 lines

  1. /*
  2.  * METALBASE 5.1
  3.  *
  4.  * Released January 1st, 1993 by Huan-Ti [ t-richj@microsoft.com ]
  5.  *
  6.  */
  7.  
  8. #include <mbase.h>
  9. #include "internal.h"
  10.  
  11.  
  12. /*
  13.  * VARIABLES ------------------------------------------------------------------
  14.  *
  15.  */
  16.  
  17. static int    ncache = 0;           /* Number of cache slots used           */
  18. static cache  mb_ctop;              /* Cache of top-of-index pointer        */
  19. static cache  mb_cache[MAX_CACHE];  /* Cache of index pointers              */
  20. static cache *mb_hash[MAX_CACHE];   /* Hash table/updated after a collision */
  21.  
  22.  
  23. /*
  24.  * PROTOTYPES -----------------------------------------------------------------
  25.  *
  26.  */
  27.  
  28.    static cache *_new_cache  XARGS( (relation *, int) );
  29.  
  30.  
  31. /*
  32.  * ROUTINES -------------------------------------------------------------------
  33.  *
  34.  */
  35.  
  36. static cache *
  37. _new_cache (rel, idx)
  38. relation   *rel;
  39. int              idx;
  40. {
  41.    if (ncache >= MAX_CACHE) /* If this happens, expand cache for performance */
  42.       {
  43.       _flush_cache (rel, idx);
  44.       }
  45.    ncache ++;
  46.  
  47.    return &mb_cache[ncache-1];
  48. }
  49.  
  50.  
  51. /******************************************************************************
  52.  *
  53.  * Since this isn't a client/server model, we can't cache data between
  54.  * requests... instead, we cache it during the slowest operation: rebalancing.
  55.  *
  56.  * This is a pretty basic cache--rebalancing doesn't require that the actual
  57.  * records be checked, just the pointers for the indices.  So we keep track
  58.  * of every record that we read, and service any requests we get for further
  59.  * queries or updates from the cache.  If we run out of space in the cache,
  60.  * the whole thing is flushed and zeroed before servicing the request.
  61.  *
  62.  * There's a hashtable so that when the system requests the pointers for a
  63.  * record number, we don't have to scan the entire cache table to find out
  64.  * which entry in the array is required.
  65.  *
  66.  * Updates are done through macros in internal.h, that write to the cache
  67.  * directly.  Any update sets a flag within the cache array, saying that the
  68.  * record's indices have changed and need to be written.
  69.  *
  70.  */
  71.  
  72. cache *
  73. _read_cache (rel, rcd, idx)
  74. relation    *rel;
  75. long              rcd;
  76. int                    idx;
  77. {
  78.    byte   buf[cbINDEX];
  79.    cache *ptr, *end;
  80.    long   n;
  81.  
  82.    end = &mb_cache[ncache];                  /* Can't check when ptr==end   */
  83.  
  84.    if (rcd == 0L)
  85.       {
  86.       if (mb_ctop.num != 0L)
  87.          {
  88.          return (&mb_ctop);
  89.          }
  90.  
  91.       GO_TOP (rel, idx);
  92.       readx  (rel->fhRel, &(mb_ctop.num), 4);
  93.       mb_ctop.changed = 0;
  94.       return (&mb_ctop);
  95.       }
  96.  
  97.    if ((ptr = mb_hash[ n=(rcd % MAX_CACHE) ]) != NULL && ptr->num == rcd)
  98.       {
  99.       return (ptr);
  100.       }
  101.  
  102.    for (ptr = mb_cache; ptr < end; ptr++)
  103.       if (ptr->num == rcd)
  104.          {
  105.          return (mb_hash[n] = ptr);
  106.          }
  107.  
  108.    ptr = _new_cache (rel, idx);
  109.  
  110.    GO_INDEX (rel, rcd, idx);
  111.    readx (rel->fhRel, buf, cbINDEX);
  112.  
  113.    ptr->left    = *(long *)( 0+ buf);
  114.    ptr->right   = *(long *)( 4+ buf);
  115.    ptr->parent  = *(long *)( 8+ buf);
  116.    ptr->parbal  = *(char *)(12+ buf);
  117.    ptr->num     = rcd;
  118.    ptr->changed = 0;
  119.  
  120.    return (mb_hash[n] = ptr);
  121. }
  122.  
  123. void
  124. _flush_cache (rel, idx)
  125. relation     *rel;
  126. int                idx;
  127. {
  128.    byte   buf[cbINDEX];
  129.    cache *ptr, *end;
  130.  
  131.    if (mb_ctop.changed)
  132.       {
  133.       GO_TOP (rel, idx);
  134.       writx  (rel->fhRel, &(mb_ctop.num), 4);
  135.       }
  136.  
  137.    end = &mb_cache[ncache];  /* Can't check when ptr==end */
  138.  
  139.    for (ptr = mb_cache; ptr < end; ptr++)
  140.       if (ptr->changed)
  141.          {
  142.          *(long *)( 0+ buf) = ptr->left;
  143.          *(long *)( 4+ buf) = ptr->right;
  144.          *(long *)( 8+ buf) = ptr->parent;
  145.          *(char *)(12+ buf) = ptr->parbal;
  146.  
  147.          GO_INDEX (rel, ptr->num, idx);
  148.          writx (rel->fhRel, buf, cbINDEX);
  149.          }
  150.  
  151.    _free_cache ();
  152. }
  153.  
  154. void
  155. _free_cache ()
  156. {
  157.    register int  i;
  158.  
  159.    for (i = 0; i < MAX_CACHE; i++)
  160.       mb_hash[i] = NULL;
  161.  
  162.    ncache = 0;
  163.    mb_ctop.num = 0L;
  164.    mb_ctop.changed = 0;
  165. }
  166.  
  167.