#include <mit-copyright.h>
#include "query.h"
-#include "sms_server.h"
+#include "mr_server.h"
extern char *whoami, *strsave();
-extern int ingres_errno, sms_errcode;
+extern int ingres_errno, mr_errcode;
/*** NOTE **************************************************************
*
- * This code depends each type starting with a unique letter. If
+ * 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
struct item {
char name[NAMESZ];
char type[9];
+ int nhash;
int id;
- int use;
+ struct item *next;
+ struct item *prev;
};
-static struct item cache[CACHESIZE];
-static struct item *ncache[CACHESIZE];
-static struct item *icache[CACHESIZE];
+static struct item cachehead;
+static int cachesize;
-/* use counter for implementing LRU */
-static int use = 1;
/* statistics counters */
int cachehits = 0, cachemisses = 0;
-/* ID hash function */
-#define hashid(id, type) (((id) + *(type)) % CACHESIZE)
-
/* Name hash function. */
while (*name)
val = val<<5 - val + *name++ - '`';
- return(val % CACHESIZE);
+ return(val);
}
flush_cache()
{
- int i;
+ 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));
- cachehits = cachemisses = 0;
- for (i = 0; i < CACHESIZE; i++) {
- cache[i].use = 0;
- ncache[i] = NULL;
- icache[i] = NULL;
+ 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;
}
char *type;
int *id;
##{
- struct item *i, *mini;
+ register struct item *i;
## char *iname;
## int j, rowcount;
- int ctr, minv;
-
- i = ncache[hashname(name, type)];
- if (i && !strcmp(name, i->name) && !strcasecmp(type, i->type)) {
+ 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;
- i->use = use++;
cachehits++;
- return(SMS_SUCCESS);
+ 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++;
## repeat retrieve (j = strings.string_id) where strings.#string=@iname
break;
default:
- return(SMS_INTERNAL);
+ return(MR_INTERNAL);
}
## inquire_equel(rowcount = "rowcount")
- if (ingres_errno) return(sms_errcode);
+ if (ingres_errno) return(mr_errcode);
if (rowcount == 0)
- return(SMS_NO_MATCH);
+ return(MR_NO_MATCH);
if (rowcount > 1)
- return(SMS_NOT_UNIQUE);
+ return(MR_NOT_UNIQUE);
*id = j;
if (name[0] == '#' && !strcasecmp(type, "USER"))
- return(SMS_SUCCESS);
- minv = use;
- for (i = &cache[0]; i < &cache[CACHESIZE]; i++) {
- if (i->use < minv) {
- minv = i->use;
- mini = i;
- if (minv == 0)
- break;
- }
+ 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;
}
- mini->id = j;
- mini->use = use++;
- strcpy(mini->name, name);
- strcpy(mini->type, type);
- ncache[hashname(name, type)] = icache[hashid(j, type)] = mini;
- return(SMS_SUCCESS);
+ 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);
##}
char *type;
char **name;
##{
- struct item *i, *mini;
+ register struct item *i;
## char iname[NAMESZ];
## int j, rowcount;
- int ctr, minv;
+ int ctr;
- i = icache[hashid(id, type)];
- if (i && id == i->id && !strcasecmp(type, i->type)) {
+ for (i = cachehead.next; i != &cachehead; i = i->next) {
+ if (i->id != id || strcasecmp(type, i->type)) continue;
free(*name);
*name = strsave(i->name);
- i->use = use++;
cachehits++;
- return(SMS_SUCCESS);
+ 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++;
## repeat retrieve (iname = strings.string) where strings.string_id=@j
break;
default:
- return(SMS_INTERNAL);
+ return(MR_INTERNAL);
}
## inquire_equel(rowcount = "rowcount")
- if (ingres_errno) return(sms_errcode);
+ if (ingres_errno) return(mr_errcode);
if (rowcount == 0) {
free(*name);
sprintf(iname, "#%d", j);
*name = strsave(iname);
- return(SMS_NO_MATCH);
+ return(MR_NO_MATCH);
}
if (rowcount != 1)
- return(SMS_INTERNAL);
+ return(MR_INTERNAL);
free(*name);
*name = strsave(strtrim(iname));
if (**name == '#' && !strcasecmp(type, "USER"))
- return(SMS_SUCCESS);
- minv = use;
- for (i = &cache[0]; i < &cache[CACHESIZE]; i++) {
- if (i->use < minv) {
- minv = i->use;
- mini = i;
- if (minv == 0)
- break;
- }
+ 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;
}
- mini->id = id;
- mini->use = use++;
- strcpy(mini->name, *name);
- strcpy(mini->type, type);
- ncache[hashname(name, type)] = icache[hashid(id, type)] = mini;
- return(SMS_SUCCESS);
+ 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);
##}
char *type;
int id;
{
- int minv;
- struct item *i, *mini;
-
- i = icache[hashid(id, type)];
- if (i->id == id &&
- !strcasecmp(i->type, type) &&
- !strcmp(i->name, name))
- return(SMS_SUCCESS);
- minv = use;
- if (i)
- mini = i;
- else
- for (i = &cache[0]; i < &cache[CACHESIZE]; i++) {
- if (i->use < minv) {
- minv = i->use;
- mini = i;
- if (minv == 0)
- break;
- }
- }
- mini->id = id;
- mini->use = use++;
- strcpy(mini->name, name);
- strcpy(mini->type, type);
- ncache[hashname(name, type)] = icache[hashid(id, type)] = mini;
+ 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);
}
char *name;
char *type;
{
- struct item *i;
-
- i = ncache[hashname(name, type)];
- if (i && !strcmp(name, i->name) && !strcasecmp(type, i->type)) {
- ncache[hashname(name, type)] = NULL;
- icache[hashid(i->id, type)] = NULL;
- i->use = 0;
- return(SMS_SUCCESS);
+ 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);
+ }
}
}