2 $Id: cache.c,v 1.6 2010-04-23 11:37:05 franklahm Exp $
3 Copyright (c) 2008,2009 Frank Lahm <franklahm@gmail.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
18 #endif /* HAVE_CONFIG_H */
26 #include <atalk/logger.h>
27 #include <atalk/afp.h>
28 #include <atalk/uuid.h>
31 typedef struct cacheduser {
32 unsigned long uid; /* for future use */
37 struct cacheduser *prev;
38 struct cacheduser *next;
41 cacheduser_t *namecache[256]; /* indexed by hash of name */
42 cacheduser_t *uuidcache[256]; /* indexed by hash of uuid */
44 /********************************************************
46 ********************************************************/
48 static int dumpcache() {
52 char *uuidstring = NULL;
54 struct tm *tmp = NULL;
56 for ( i=0 ; i<256; i++) {
57 if ((entry = namecache[i]) != NULL) {
59 uuid_bin2string(entry->uuid, &uuidstring);
60 tmp = localtime(&entry->creationtime);
63 if (strftime(timestr, 200, "%c", tmp) == 0)
65 LOG(log_debug9, logtype_default, "namecache{%d}: name:%s, uuid:%s, type: %s, cached: %s",
66 i, entry->name, uuidstring, uuidtype[entry->type], timestr);
68 } while ((entry = entry->next) != NULL);
72 for ( i=0; i<256; i++) {
73 if ((entry = uuidcache[i]) != NULL) {
75 uuid_bin2string(entry->uuid, &uuidstring);
76 tmp = localtime(&entry->creationtime);
79 if (strftime(timestr, 200, "%c", tmp) == 0)
81 LOG(log_debug9, logtype_default, "uuidcache{%d}: uuid:%s, name:%s, type: %s, cached: %s",
82 i, uuidstring, entry->name, uuidtype[entry->type], timestr);
84 } while ((entry = entry->next) != NULL);
91 /* hash string it into unsigned char */
92 static unsigned char hashstring(unsigned char *str) {
93 unsigned long hash = 5381;
96 while ((c = *str++) != 0)
97 hash = ((hash << 5) + hash) ^ c; /* (hash * 33) ^ c */
99 index = 85 ^ (hash & 0xff);
100 while ((hash = hash >> 8) != 0)
101 index ^= (hash & 0xff);
106 /* hash uuid_t into unsigned char */
107 static unsigned char hashuuid(uuidp_t uuid) {
108 unsigned char index = 83;
111 for (i=0; i<16; i++) {
118 /********************************************************
120 ********************************************************/
122 int add_cachebyname( const char *inname, const uuidp_t inuuid, const uuidtype_t type, const unsigned long uid _U_) {
126 cacheduser_t *cacheduser = NULL;
134 /* allocate mem and copy values */
135 name = malloc(strlen(inname)+1);
137 LOG(log_error, logtype_default, "add_cachebyname: mallor error");
142 uuid = malloc(UUID_BINSIZE);
144 LOG(log_error, logtype_default, "add_cachebyname: mallor error");
149 cacheduser = malloc(sizeof(cacheduser_t));
151 LOG(log_error, logtype_default, "add_cachebyname: mallor error");
156 strcpy(name, inname);
157 memcpy(uuid, inuuid, UUID_BINSIZE);
159 /* fill in the cacheduser */
160 cacheduser->name = name;
161 cacheduser->uuid = uuid;
162 cacheduser->type = type;
163 cacheduser->creationtime = time(NULL);
164 cacheduser->prev = NULL;
165 cacheduser->next = NULL;
168 hash = hashstring((unsigned char *)name);
170 /* insert cache entry into cache array */
171 if (namecache[hash] == NULL) { /* this queue is empty */
172 namecache[hash] = cacheduser;
173 } else { /* queue is not empty, search end of queue*/
174 entry = namecache[hash];
175 while( entry->next != NULL)
177 cacheduser->prev = entry;
178 entry->next = cacheduser;
199 * Caller provides buffer uuid for result
201 int search_cachebyname( const char *name, uuidtype_t type, uuidp_t uuid) {
211 hash = hashstring((unsigned char *)name);
213 if (! namecache[hash])
216 entry = namecache[hash];
218 ret = strcmp(entry->name, name);
219 if (ret == 0 && type == entry->type) {
220 /* found, now check if expired */
222 if ((tim - entry->creationtime) > CACHESECONDS) {
223 LOG(log_debug, logtype_default, "search_cachebyname: expired: name:\'%s\' in queue {%d}", entry->name, hash);
225 if (entry->prev) /* 2nd to last in queue */
226 entry->prev->next = entry->next;
227 else { /* queue head */
228 if ((namecache[hash] = entry->next) != NULL)
229 namecache[hash]->prev = NULL;
239 memcpy(uuid, entry->uuid, UUID_BINSIZE);
255 * Caller must free allocated name
257 int search_cachebyuuid( uuidp_t uuidp, char **name, uuidtype_t *type) {
267 hash = hashuuid(uuidp);
269 if (! uuidcache[hash])
272 entry = uuidcache[hash];
274 ret = memcmp(entry->uuid, uuidp, UUID_BINSIZE);
277 if ((tim - entry->creationtime) > CACHESECONDS) {
278 LOG(log_debug, logtype_default, "search_cachebyuuid: expired: name:\'%s\' in queue {%d}", entry->name, hash);
279 if (entry->prev) /* 2nd to last in queue */
280 entry->prev->next = entry->next;
281 else { /* queue head */
282 if ((uuidcache[hash] = entry->next) != NULL)
283 uuidcache[hash]->prev = NULL;
293 *name = malloc(strlen(entry->name)+1);
294 strcpy(*name, entry->name);
312 int add_cachebyuuid( uuidp_t inuuid, const char *inname, uuidtype_t type, const unsigned long uid _U_) {
316 cacheduser_t *cacheduser = NULL;
324 /* allocate mem and copy values */
325 name = malloc(strlen(inname)+1);
327 LOG(log_error, logtype_default, "add_cachebyuuid: mallor error");
332 uuid = malloc(UUID_BINSIZE);
334 LOG(log_error, logtype_default, "add_cachebyuuid: mallor error");
339 cacheduser = malloc(sizeof(cacheduser_t));
341 LOG(log_error, logtype_default, "add_cachebyuuid: mallor error");
346 strcpy(name, inname);
347 memcpy(uuid, inuuid, UUID_BINSIZE);
349 /* fill in the cacheduser */
350 cacheduser->name = name;
351 cacheduser->type = type;
352 cacheduser->uuid = uuid;
353 cacheduser->creationtime = time(NULL);
354 cacheduser->prev = NULL;
355 cacheduser->next = NULL;
358 hash = hashuuid(uuid);
360 /* insert cache entry into cache array */
361 if (uuidcache[hash] == NULL) { /* this queue is empty */
362 uuidcache[hash] = cacheduser;
363 } else { /* queue is not empty, search end of queue*/
364 entry = uuidcache[hash];
365 while( entry->next != NULL)
367 cacheduser->prev = entry;
368 entry->next = cacheduser;