Files
smmapdfw/smmapdfw/libsmmapdfw/htcache.c
2005-02-25 14:21:07 +00:00

178 lines
4.6 KiB
C

/*
Copyright (C) 2004,2005 Wolfgang Hottgenroth
This file is part of smmapdfw.
smmapdfw is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
smmapdfw is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with smmapdfw. If not, write to the Free Software Foundation, 59
Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include <syslog.h>
#include <pthread.h>
#include <errno.h>
#include <time.h>
#include <string.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdio.h>
#if ENABLE_CACHE == 1
#define DB_DBM_HSEARCH 1
#include <db.h>
#endif
#include "htcache.h"
#include "htmalloc.h"
struct mydata_s {
time_t timestamp;
int value_size;
char value[1];
};
typedef struct mydata_s mydata_t;
htcache_t *htcache_init(const char *file, int expiry) {
#if ENABLE_CACHE == 1
htcache_t *handle = (htcache_t*) htmalloc(sizeof(htcache_t));
handle->mutex = (pthread_mutex_t*) htmalloc(sizeof(pthread_mutex_t));
pthread_mutex_init(handle->mutex, NULL);
pthread_mutex_unlock(handle->mutex);
handle->file = file;
handle->expiry = expiry;
return handle;
#else
return NULL;
#endif
}
void htcache_destroy(htcache_t *handle) {
#if ENABLE_CACHE == 1
pthread_mutex_destroy(handle->mutex);
free(handle->mutex);
free(handle);
#endif
}
void htcache_insert(htcache_t *handle, const char *key, const char *value, int value_size) {
#if ENABLE_CACHE == 1
DBM *cache;
datum data, dkey;
int ret;
mydata_t *mydata;
syslog(LOG_DEBUG, "cache_insert: inserting %s -> %s (size %d)", key, (char*) value, value_size);
dkey.dsize = strlen(key) + 1; /* one more for the terminating \0 */
dkey.dptr = (char*) key;
data.dsize = (sizeof(mydata_t) + value_size + 1);
mydata = (mydata_t *) htmalloc(data.dsize);
mydata->timestamp = time(NULL);
mydata->value_size = value_size;
memcpy(mydata->value, value, value_size);
data.dptr = (char*) mydata;
pthread_mutex_lock(handle->mutex);
if (NULL != (cache = dbm_open(handle->file, O_RDWR | O_CREAT, 0644))) {
ret = dbm_store(cache, dkey, data, DBM_INSERT);
if (ret != 0) {
syslog(LOG_DEBUG, "cache_insert: couldn't insert record");
} else {
syslog(LOG_DEBUG, "cache_insert: record inserted");
}
dbm_close(cache);
}
pthread_mutex_unlock(handle->mutex);
free(mydata);
#else
syslog(LOG_DEBUG, "cache_insert: cache disabled");
#endif /* ENABLE_CACHE */
}
int htcache_lookup(htcache_t *handle, const char* key, char** value, int* value_size2) {
#if ENABLE_CACHE == 1
DBM *cache;
datum data, dkey;
char *output;
mydata_t *mydata;
int value_size, ret, res = -1;
syslog(LOG_DEBUG, "cache_lookup: looking up %s, expiry %d",
key, handle->expiry);
if (NULL != (cache = dbm_open(handle->file, O_RDONLY, 0644))) {
dkey.dsize = strlen(key) + 1; /* one more for the terminating \0 */
dkey.dptr = (char*) key;
data = dbm_fetch(cache, dkey);
if (NULL == data.dptr) {
syslog(LOG_DEBUG, "cache_lookup: nothing found");
dbm_close(cache);
} else {
mydata = (mydata_t *) data.dptr;
syslog(LOG_DEBUG, "cache_lookup: found: %s %d %d %s (size %d)",
key, mydata->timestamp, mydata->value_size, mydata->value, data.dsize);
if ((mydata->timestamp + handle->expiry) > time(NULL)) {
syslog(LOG_DEBUG, "cache_lookup: not yet expired");
value_size = mydata->value_size;
output = (char*) htmalloc(value_size+5);
memcpy(output, mydata->value, value_size);
*value_size2 = value_size;
*value = output;
/* Berkeley DB frees on its own! */
/* free(data.dptr); */
dbm_close(cache);
res = 0;
} else {
syslog(LOG_DEBUG, "cache_lookup: expired, will be deleted from cache");
/* free(data.dptr); --- Berkeley DB frees on its own */
dbm_close(cache);
pthread_mutex_lock(handle->mutex);
if (NULL != (cache = dbm_open(handle->file, O_RDWR, 0644))) {
ret = dbm_delete(cache, dkey);
if (ret != 0) {
syslog(LOG_DEBUG, "cache_insert: couldn't delete record");
} else {
syslog(LOG_DEBUG, "cache_insert: record deleted");
}
dbm_close(cache);
res = -2;
}
pthread_mutex_unlock(handle->mutex);
}
}
}
return res;
#else
return -1;
#endif /* ENABLE_CACHE */
}