From 6dcaf2ad4b1ef15c76f7f880326ef09fdc54aea9 Mon Sep 17 00:00:00 2001 From: John Kohl Date: Thu, 19 Mar 1987 09:08:44 +0000 Subject: All functions, minimal testing establishes it works for at least some cases --- server/class.c | 157 +++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 108 insertions(+), 49 deletions(-) (limited to 'server/class.c') diff --git a/server/class.c b/server/class.c index 43246ce..48d7d65 100644 --- a/server/class.c +++ b/server/class.c @@ -1,55 +1,60 @@ -/* Copyright (c) 1987 Massachusetts Institute of Technology */ - -/* +/* This file is part of the Project Athena Zephyr Notification System. + * It contains functions for the Zephyr server class manager subsystem. + * + * Created by: John T. Kohl + * * $Source$ - * $Header$ + * $Author$ + * + * Copyright (c) 1987 by the Massachusetts Institute of Technology. + * For copying and distribution information, see the file + * "mit-copyright.h". */ +#include + #ifndef lint -static char *rcsid_cm_c = "$Header$"; +static char rcsid_cm_c[] = "$Header$"; #endif lint -#include #include #include "zserver.h" /* * Class manager subsystem. + * + * * external functions are: + * * Code_t cm_register(client, class) + * * Code_t cm_deregister(client, class) - * struct qelem *cm_lookup(class) + * + * ZClientList_t *cm_lookup(class) * ZClientDesc_t *client; * char *class; */ /* Private variables */ -typedef struct _ZClientList_t { - struct _ZClientList_t *q_forw; - struct _ZClientList_t *q_back; - ZClientDesc_t *client; -} ZClientList_t; - -typedef struct _ZClass_t { - struct _ZClass_t *q_forw; - struct _ZClass_t *q_back; - char *classname; - ZClientList_t *clientlist; -} ZClass_t; - - -#define NULLZCT ((ZClass_t *) 0) -#define NULLZCDT ((ZClientDesc_t *) 0) -#define NULLZCLT ((ZClientList_t *) 0) - #define EMPTY_CLASS 2000 -#define HSHSIZ 8192 -#define HSHMUL 243 +#define HASHSIZE 511 +#define HASHMUL 243 static ZClass_t *class_bucket[511]; /* private routines */ +static int hash(string) +char *string; +{ + register int hval = 0; + register char *cp = string; + + while (*cp) + hval = (hval + (*cp++) * HASHMUL) % HASHSIZE; + return(hval); +} + static ZClass_t *class_alloc(class) char *class; { @@ -64,6 +69,13 @@ char *class; return(ptr); } +static void free_class(ptr) +ZClass_t *ptr; +{ + free(ptr->classname); + free(ptr); +} + static ZClientList_t *client_alloc(client) ZClientDesc_t *client; { @@ -83,9 +95,12 @@ ZClientDesc_t *client; if ((listp = client_alloc(client)) == NULLZCLT) return(ZERR_UNIX); - if (ptr->clientlist == NULLZCLT) - ptr->clientlist = listp; - else + + if (ptr->clientlist == NULLZCLT) { + listp->q_forw = listp; + listp->q_back = listp; + ptr->clientlist = listp; + } else insque(listp, ptr->clientlist); return(ZERR_NONE); } @@ -98,7 +113,7 @@ ZClientDesc_t *client; register ZClientList_t *listp2; if (listp->client == client) { /* found him */ - if (listp->q_forw = listp) { /* this is the only elem on this queue */ + if (listp->q_forw == listp) { /* this is the only elem on this queue */ ptr->clientlist = NULLZCLT; free(listp); return(EMPTY_CLASS); @@ -112,7 +127,7 @@ ZClientDesc_t *client; for (listp2 = listp->q_forw; listp2 != listp; listp2 = listp2->q_forw) /* walk down list, looking for him */ if (listp2->client == client) { - reqmue(listp); + remque(listp); free(listp); return(ZERR_NONE); } @@ -135,23 +150,24 @@ char *class; if ((ptr = class_alloc(class)) == NULLZCT) return(ZERR_UNIX); + ptr->q_forw = ptr; + ptr->q_back = ptr; class_bucket[hashval] = ptr; return(insert_client(ptr, client)); } else if (!strcmp(ptr->classname, class)) /* match! */ return(insert_client(ptr, client)); else { - for (ptr2 = ptr->q_forw; ptr2 != ptr; ptr2 = ptr2->q_forw) { - /* walk down the list, looking for a match */ - if (!strcmp(ptr2->classname, class)) - return(insert_client(ptr2, client)); - } - if (ptr2 = ptr) { /* fell off the end, no match */ - if ((ptr2 = class_alloc(class)) == NULLZCT) - return(ZERR_UNIX); - insque(ptr2, ptr); /* insert new class into hash bucket */ + for (ptr2 = ptr->q_forw; ptr2 != ptr; ptr2 = ptr2->q_forw) + /* walk down the list, looking for a match */ + if (!strcmp(ptr2->classname, class)) return(insert_client(ptr2, client)); - } + + /* fell off the end, no match */ + if ((ptr2 = class_alloc(class)) == NULLZCT) + return(ZERR_UNIX); + insque(ptr2, ptr); /* insert new class into hash bucket */ + return(insert_client(ptr2, client)); } } @@ -167,20 +183,63 @@ char *class; /* no such class to deregister */ return(ZERR_S_BADASSOC); if (!strcmp(ptr->classname, class)) { /* match! */ - retval = remove_client(ptr, client); - /* handle retval here*/ - ptr2 = ptr; + if (remove_client(ptr, client) == EMPTY_CLASS) { + /* careful here, we need to remove it and adjust the pointer to + the next element unless this is the only one */ + if (ptr = ptr->q_forw) { + /* garbage collect this bucket */ + free_class(ptr); + class_bucket[hashval] = NULLZCT; + } else { + /* adjust pointer and garbage collect */ + class_bucket[hashval] = ptr->q_forw; + remque(ptr); + free_class(ptr); + } + } + return(ZERR_NONE); } else { for (ptr2 = ptr->q_forw; ptr2 != ptr; ptr2 = ptr2->q_forw) { /* walk down the list, looking for a match */ if (!strcmp(ptr2->classname, class)) { - retval = remove_client(ptr2, client); - /* handle it here too */ + if ((retval = remove_client(ptr2, client)) == EMPTY_CLASS) { + /* here ptr2 is never pointing to class_bucket[hashval], + so we don't worry about freeing the bucket */ + remque(ptr2); + free_class(ptr2); + return(ZERR_NONE); + } + /* if not EMPTY_CLASS, it's either ZERR_S_BADASSOC (not found) + or ZERR_NONE (found and removed), so break */ break; } } - /* fell off, error */ - return(ZERR_S_BADASSOC); + + /* fell off: either client not found or client found + and removed, retval contains the result */ + + return(retval); + } +} + +ZClientList_t *cm_lookup(class) +char *class; +{ + register ZClass_t *ptr, *ptr2; + int hashval = hash(class); + + if ((ptr = class_bucket[hashval]) == NULLZCT) + return(NULLZCLT); /* no such class */ + else if (!strcmp(ptr->classname, class)) + return(ptr->clientlist); + else { /* go search the list for the class */ + for (ptr2 = ptr->q_forw; ptr2 != ptr; ptr2 = ptr2->q_forw) { + /* walk down the list, looking for a match */ + if (!strcmp(ptr2->classname, class)) + return(ptr2->clientlist); + } + /* fell off the end */ + return(NULLZCLT); } } -- cgit v1.2.3