From d505e229a7fd2997b6a50047b857ec90ee68d611 Mon Sep 17 00:00:00 2001 From: Lon Hohberger Date: Mon, 14 Sep 2009 15:05:16 -0400 Subject: [PATCH] Make history functions generic Signed-off-by: Lon Hohberger --- include/history.h | 25 ++++++++++ server/history.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 147 insertions(+) create mode 100644 include/history.h create mode 100644 server/history.c diff --git a/include/history.h b/include/history.h new file mode 100644 index 0000000..3d28518 --- /dev/null +++ b/include/history.h @@ -0,0 +1,25 @@ +#ifndef _HISTORY_H +#define _HISTORY_H + +typedef struct _history_node { + list_head(); + void *data; + time_t when; +} history_node; + +typedef int (*history_compare_fn)(void *, void *); + +typedef struct _history_info { + history_node *hist; + history_compare_fn compare_func; + time_t timeout; + size_t element_size; +} history_info_t; + +history_info_t *history_init(history_compare_fn func, + time_t expiration, size_t element_size); +int history_check(history_info_t *hinfo, void *stuff); +int history_record(history_info_t *hinfo, void *data); +int history_wipe(history_info_t *hinfo); + +#endif diff --git a/server/history.c b/server/history.c new file mode 100644 index 0000000..4c37214 --- /dev/null +++ b/server/history.c @@ -0,0 +1,122 @@ +#include +#include +#include +#include +#include +#include +#include +#include + + +history_info_t * +history_init(history_compare_fn func, time_t expiration, size_t element_size) +{ + history_info_t *hist; + + errno = EINVAL; + if (!func || !expiration || !element_size) + return NULL; + + hist = malloc(sizeof(*hist)); + if (!hist) + return NULL; + memset(hist, 0, sizeof(*hist)); + + hist->timeout = expiration; + hist->element_size = element_size; + hist->compare_func = func; + + return hist; +} + + +/* + * Purge our history when the entries time out. + * + * Returns 1 if a matching history node was found, or 0 + * if not. + */ +int +history_check(history_info_t *hinfo, void *stuff) +{ + history_node *entry = NULL; + time_t now; + int x; + + if (!hinfo) + return 0; /* XXX */ + + if (!hinfo->hist) + return 0; + + now = time(NULL); + +loop_again: + list_for((&hinfo->hist), entry, x) { + if (entry->when < (now - hinfo->timeout)) { + list_remove((&hinfo->hist), entry); + free(entry->data); + free(entry); + goto loop_again; + } + + if (hinfo->compare_func(entry->data, stuff)) { + return 1; + } + } + return 0; +} + + +int +history_record(history_info_t *hinfo, void *data) +{ + history_node *entry = NULL; + + errno = EINVAL; + if (!data || !hinfo) + return -1; + + if (history_check(hinfo, data) == 1) { + errno = EEXIST; + return -1; + } + + entry = malloc(sizeof(*entry)); + if (!entry) { + return -1; + } + memset(entry, 0, sizeof(*entry)); + + entry->data = malloc(hinfo->element_size); + if (!entry->data) { + free(entry); + errno = ENOMEM; + return -1; + } + + memcpy(entry->data, data, hinfo->element_size); + entry->when = time(NULL); + list_insert((&hinfo->hist), entry); + return 0; +} + + +int +history_wipe(history_info_t *hinfo) +{ + history_node *entry = NULL; + + if (!hinfo) + return -1; + + while (hinfo->hist) { + entry = hinfo->hist; + list_remove((&hinfo->hist), entry); + free(entry->data); + free(entry); + } + + /* User must free(hinfo); */ + return 0; +}