]> andersk Git - moira.git/commitdiff
*** empty log message ***
authorgenoa <genoa>
Mon, 22 Jun 1992 23:05:25 +0000 (23:05 +0000)
committergenoa <genoa>
Mon, 22 Jun 1992 23:05:25 +0000 (23:05 +0000)
server/cache.dc [new file with mode: 0644]

diff --git a/server/cache.dc b/server/cache.dc
new file mode 100644 (file)
index 0000000..23087ad
--- /dev/null
@@ -0,0 +1,342 @@
+/*
+ *     $Header$
+ *
+ *     Copyright (C) 1989, 1990 by the Massachusetts Institute of Technology
+ *     For copying and distribution information, please see the file
+ *     <mit-copyright.h>.
+ */
+
+#ifndef lint
+static char *rcsid_cache_dc = "$Header$";
+#endif lint
+
+#include <mit-copyright.h>
+#include "query.h"
+#include "mr_server.h"
+EXEC SQL INCLUDE sqlca;
+
+extern char *whoami, *strsave();
+extern int ingres_errno, mr_errcode;
+
+
+/*** NOTE **************************************************************
+ *
+ *    This code depends on each type starting with a unique letter.  If
+ *    any new types are added to the system that begin with the same
+ *    letter as one of the existing types:
+ *             User
+ *             List
+ *             String
+ *             Machine
+ *             Cluster
+ *             Filesystem
+ *    then we will have to rework the code that only looks at the first
+ *    letter of the types.
+ *
+ ***********************************************************************
+ */
+
+/* Cache parameters: */
+#define CACHESIZE 101          /* number of cache slots */
+#define NAMESZ 257             /* max size of a name */
+
+struct item {
+    char name[NAMESZ];
+    char type[9];
+    int nhash;
+    int id;
+    struct item *next;
+    struct item *prev;
+};
+
+static struct item cachehead;
+static int cachesize;
+
+/* statistics counters */
+int cachehits = 0, cachemisses = 0;
+
+
+/* Name hash function. */
+
+int hashname(name, type)
+register char *name;
+char *type;
+{
+    register int val = *type;
+
+    while (*name)
+      val = val<<5 - val + *name++ - '`';
+    return(val);
+}
+
+
+/* Initialize the cache, flushing any old data, and report the statistics
+ * if the cache was previously in use.
+ */
+
+flush_cache()
+{
+    register struct item *i;
+
+    if (cachehits + cachemisses != 0)
+      com_err(whoami, 0, "Flushing cache; %d hits, %d misses, %d%% hit rate",
+             cachehits, cachemisses,
+             (100 * cachehits) / (cachehits + cachemisses));
+    else
+      cachehead.next = cachehead.prev = &cachehead;
+    cachehits = cachemisses = cachesize = 0;
+    for (i = cachehead.next; i != &cachehead; i = i->next) {
+       if (i->prev != &cachehead)
+         free(i->prev);
+    }
+    if (cachehead.prev != &cachehead)
+      free(cachehead.prev);
+    cachehead.next = cachehead.prev = &cachehead;
+}
+
+
+/* Do a name to ID translation.  id will be updated with the answer if
+ * it is available, and as a side effect the cache is updated.
+ */
+
+int name_to_id(name, type, id)
+char *name;
+char *type;
+int *id;
+{
+    register struct item *i;
+    EXEC SQL BEGIN DECLARE SECTION;
+    char *iname;
+    int j, rowcount;
+    EXEC SQL END DECLARE SECTION;
+    int h, ctr;
+
+    h = hashname(name, type);
+    for (i = cachehead.next; i != &cachehead; i = i->next) {
+       if (i->nhash != h ||
+           strcmp(name, i->name) ||
+           strcasecmp(type, i->type))
+         continue;
+       *id = i->id;
+       cachehits++;
+       i->next->prev = i->prev;
+       i->prev->next = i->next;
+       i->next = cachehead.next;
+       i->prev = &cachehead;
+       cachehead.next->prev = i;
+       cachehead.next = i;
+       return(MR_SUCCESS);
+    }
+
+    cachemisses++;
+    iname = name;
+
+    switch (*type) {
+    case 'U':
+    case 'u':
+       EXEC SQL SELECT users_id INTO :j FROM users WHERE login=:iname;
+       break;
+    case 'L':
+    case 'l':
+       EXEC SQL SELECT list_id INTO :j FROM list WHERE name=:iname;
+       break;
+    case 'M':
+    case 'm':
+       uppercase(iname);
+       EXEC SQL SELECT mach_id INTO :j FROM machine WHERE name=:iname;
+       break;
+    case 'C':
+    case 'c':
+       EXEC SQL SELECT clu_id INTO :j FROM cluster WHERE name=:iname;
+       break;
+    case 'F':
+    case 'f':
+       EXEC SQL SELECT filsys_id INTO :j FROM filesys WHERE label=:iname;
+       break;
+    case 'S':
+    case 's':
+       EXEC SQL SELECT string_id INTO :j FROM strings WHERE string=:iname;
+       break;
+    default:
+       return(MR_INTERNAL);
+    }
+    if (sqlca.sqlcode == 100)
+      return(MR_NO_MATCH);
+    if (sqlca.sqlerrd[2] > 1)
+      return(MR_NOT_UNIQUE);
+    if (sqlca.sqlcode != 0)
+      return(MR_INGRES_ERR);
+    *id = j;
+    if (name[0] == '#' && !strcasecmp(type, "USER"))
+      return(MR_SUCCESS);
+    if (cachesize < CACHESIZE) {
+       i = (struct item *) malloc(sizeof(struct item));
+       cachesize++;
+    } else {
+       i = cachehead.prev;
+       cachehead.prev = i->prev;
+       i->prev->next = &cachehead;
+    }
+    strcpy(i->name, name);
+    strcpy(i->type, type);
+    i->nhash = h;
+    i->id = j;
+    i->next = cachehead.next;
+    i->prev = &cachehead;
+    cachehead.next->prev = i;
+    cachehead.next = i;
+    return(MR_SUCCESS);
+}
+
+
+/* Perform an ID to name mapping.  name should be a pointer to a pointer to
+ * malloc'ed data.  The buffer it refers to will be freed, and a new buffer
+ * allocated with the answer.
+ */
+
+int id_to_name(id, type, name)
+int id;
+char *type;
+char **name;
+{
+    register struct item *i;
+    EXEC SQL BEGIN DECLARE SECTION;
+    char iname[NAMESZ];
+    int j, rowcount;
+    EXEC SQL END DECLARE SECTION;
+    int ctr;
+
+    for (i = cachehead.next; i != &cachehead; i = i->next) {
+       if (i->id != id || strcasecmp(type, i->type)) continue;
+       free(*name);
+       *name = strsave(i->name);
+       cachehits++;
+       i->next->prev = i->prev;
+       i->prev->next = i->next;
+       i->next = cachehead.next;
+       i->prev = &cachehead;
+       cachehead.next->prev = i;
+       cachehead.next = i;
+       return(MR_SUCCESS);
+    }
+
+    cachemisses++;
+    j = id;
+
+    switch (*type) {
+    case 'U':
+    case 'u':
+       EXEC SQL SELECT login INTO :iname FROM users WHERE users_id=:j;
+       break;
+    case 'L':
+    case 'l':
+       EXEC SQL SELECT name INTO :iname FROM list WHERE list_id=:j;
+       break;
+    case 'M':
+    case 'm':
+       EXEC SQL SELECT name INTO :iname FROM machine WHERE mach_id=:j;
+       break;
+    case 'C':
+    case 'c':
+       EXEC SQL SELECT name INTO :iname FROM cluster WHERE clu_id=:j;
+       break;
+    case 'F':
+    case 'f':
+       EXEC SQL SELECT label INTO :iname FROM filesys WHERE filsys_id=:j;
+       break;
+    case 'S':
+    case 's':
+       EXEC SQL SELECT string INTO :iname FROM strings WHERE string_id=:j;
+       break;
+    default:
+       return(MR_INTERNAL);
+    }
+    if (sqlca.sqlcode == 100) {
+       free(*name);
+       sprintf(iname, "#%d", j);
+       *name = strsave(iname);
+       return(MR_NO_MATCH);
+    }
+    if (sqlca.sqlerrd[2] > 1)
+      return(MR_INTERNAL);
+    if (sqlca.sqlcode != 0)
+      return(MR_INGRES_ERR);
+    free(*name);
+    *name = strsave(strtrim(iname));
+    if (**name == '#' && !strcasecmp(type, "USER"))
+      return(MR_SUCCESS);
+    if (cachesize < CACHESIZE) {
+       i = (struct item *) malloc(sizeof(struct item));
+       cachesize++;
+    } else {
+       i = cachehead.prev;
+       cachehead.prev = i->prev;
+       i->prev->next = &cachehead;
+    }
+    strcpy(i->name, *name);
+    strcpy(i->type, type);
+    i->nhash = hashname(*name, type);
+    i->id = id;
+    i->next = cachehead.next;
+    i->prev = &cachehead;
+    cachehead.next->prev = i;
+    cachehead.next = i;
+    return(MR_SUCCESS);
+}
+
+
+/* Explicitly add something to the cache without doing a lookup in the
+ * database.
+ */
+
+cache_entry(name, type, id)
+char *name;
+char *type;
+int id;
+{
+    register struct item *i;
+
+    for (i = cachehead.next; i != &cachehead; i = i->next)
+      if (i->id == id && !strcmp(i->type, type))
+       return(MR_SUCCESS);
+    if (cachesize < CACHESIZE) {
+       i = (struct item *) malloc(sizeof(struct item));
+       cachesize++;
+    } else {
+       i = cachehead.prev;
+       cachehead.prev = i->prev;
+       i->prev->next = &cachehead;
+    }
+    strcpy(i->name, name);
+    strcpy(i->type, type);
+    i->nhash = hashname(name, type);
+    i->id = id;
+    i->next = cachehead.next;
+    i->prev = &cachehead;
+    cachehead.next->prev = i;
+    cachehead.next = i;
+    return(MR_SUCCESS);
+}
+
+
+/* Flush something that may or may not already be in the cache. */
+
+flush_name(name, type)
+char *name;
+char *type;
+{
+    int h;
+    register struct item *i;
+
+    h = hashname(name, type);
+
+    for (i = cachehead.next; i != &cachehead; i = i->next) {
+       if (!strcmp(name, i->name) && !strcasecmp(type, i->type)) {
+           cachesize--;
+           i->next->prev = i->prev;
+           i->prev->next = i->next;
+           free(i);
+           return(MR_SUCCESS);
+       }
+    }
+}
This page took 0.310939 seconds and 5 git commands to generate.