Signed-off-by: Angus Salkeld <asalkeld(a)redhat.com>
---
include/qb/qbmap.h | 4 +++-
lib/hashtable.c | 17 +++++++++--------
lib/map.c | 4 ++--
lib/map_int.h | 4 +++-
lib/skiplist.c | 13 +++++++------
lib/trie.c | 15 ++++++++-------
tests/check_map.c | 30 +++++++++++++++++++++++++-----
7 files changed, 57 insertions(+), 30 deletions(-)
diff --git a/include/qb/qbmap.h b/include/qb/qbmap.h
index 9ebd2c0..364c483 100644
--- a/include/qb/qbmap.h
+++ b/include/qb/qbmap.h
@@ -89,6 +89,7 @@ qb_map_t* qb_trie_create(void);
* @param key the key (or prefix) to attach the notification to.
* @param fn the callback
* @param events the type of events to register for.
+ * @param user_data a pointer to be passed into the callback
*
* @note QB_MAP_NOTIFY_INSERTED is only valid on tries.
* @note you can use key prefixes with trie maps.
@@ -97,7 +98,8 @@ qb_map_t* qb_trie_create(void);
* @retval -errno failure
*/
int32_t qb_map_notify_add(qb_map_t* m, const char* key,
- qb_map_notify_fn fn, int32_t events);
+ qb_map_notify_fn fn, int32_t events,
+ void *user_data);
/**
* Delete a notifier from the map.
diff --git a/lib/hashtable.c b/lib/hashtable.c
index 3f83c37..835e318 100644
--- a/lib/hashtable.c
+++ b/lib/hashtable.c
@@ -56,7 +56,7 @@ struct hashtable_iter {
static void hashtable_notify(struct hash_table *t, struct hash_node *n,
uint32_t event, const char *key,
- void *old_value, void *value, void *user_data);
+ void *old_value, void *value);
static uint32_t
hash_fnv(const void *value, uint32_t valuelen, uint32_t order)
@@ -126,7 +126,7 @@ hashtable_node_deref(struct qb_map *map, struct hash_node *hash_node)
}
hashtable_notify(t, hash_node,
QB_MAP_NOTIFY_DELETED,
- hash_node->key, hash_node->value, NULL, NULL);
+ hash_node->key, hash_node->value, NULL);
qb_list_del(&hash_node->list);
free(hash_node);
}
@@ -204,7 +204,7 @@ hashtable_put(struct qb_map *map, const char *key, const void *value)
hashtable_notify(hash_table, hash_node,
QB_MAP_NOTIFY_INSERTED,
- hash_node->key, hash_node->value, NULL, NULL);
+ hash_node->key, hash_node->value, NULL);
} else {
char *old_k = (char *)hash_node->key;
char *old_v = (void *)hash_node->value;
@@ -213,14 +213,14 @@ hashtable_put(struct qb_map *map, const char *key, const void
*value)
hashtable_notify(hash_table, hash_node,
QB_MAP_NOTIFY_REPLACED,
- old_k, old_v, hash_node->value, NULL);
+ old_k, old_v, hash_node->value);
}
}
static void
hashtable_notify(struct hash_table *t, struct hash_node *n,
uint32_t event, const char *key,
- void *old_value, void *value, void *user_data)
+ void *old_value, void *value)
{
struct qb_list_head *list;
struct qb_map_notifier *tn;
@@ -231,7 +231,7 @@ hashtable_notify(struct hash_table *t, struct hash_node *n,
if (tn->events & event) {
tn->callback(event, (char *)key, old_value, value,
- user_data);
+ tn->user_data);
}
}
for (list = t->notifier_head.next;
@@ -240,14 +240,14 @@ hashtable_notify(struct hash_table *t, struct hash_node *n,
if (tn->events & event) {
tn->callback(event, (char *)key, old_value, value,
- user_data);
+ tn->user_data);
}
}
}
static int32_t
hashtable_notify_add(qb_map_t * m, const char *key,
- qb_map_notify_fn fn, int32_t events)
+ qb_map_notify_fn fn, int32_t events, void *user_data)
{
struct hash_table *t = (struct hash_table *)m;
struct qb_map_notifier *f;
@@ -276,6 +276,7 @@ hashtable_notify_add(qb_map_t * m, const char *key,
f = malloc(sizeof(struct qb_map_notifier));
f->events = events;
+ f->user_data = user_data;
f->callback = fn;
qb_list_init(&f->list);
qb_list_add(&f->list, head);
diff --git a/lib/map.c b/lib/map.c
index 5e92906..43f665e 100644
--- a/lib/map.c
+++ b/lib/map.c
@@ -90,10 +90,10 @@ qb_map_iter_free(qb_map_iter_t * i)
int32_t
qb_map_notify_add(qb_map_t * m, const char *key, qb_map_notify_fn fn,
- int32_t events)
+ int32_t events, void *user_data)
{
if (m->notify_add) {
- return m->notify_add(m, key, fn, events);
+ return m->notify_add(m, key, fn, events, user_data);
} else {
return -ENOSYS;
}
diff --git a/lib/map_int.h b/lib/map_int.h
index 5e670e2..2b262e8 100644
--- a/lib/map_int.h
+++ b/lib/map_int.h
@@ -37,7 +37,8 @@ typedef const char* (*qb_map_iter_next_func)(qb_map_iter_t* i, void**
value);
typedef void (*qb_map_iter_free_func)(qb_map_iter_t* i);
typedef int32_t (*qb_map_notify_add_func)(qb_map_t* m, const char* key,
- qb_map_notify_fn fn, int32_t events);
+ qb_map_notify_fn fn, int32_t events,
+ void *user_data);
typedef int32_t (*qb_map_notify_del_func)(qb_map_t* m, const char* key,
qb_map_notify_fn fn, int32_t events);
@@ -62,6 +63,7 @@ struct qb_map_notifier {
struct qb_list_head list;
qb_map_notify_fn callback;
int32_t events;
+ void *user_data;
};
diff --git a/lib/skiplist.c b/lib/skiplist.c
index bf1c567..60e962d 100644
--- a/lib/skiplist.c
+++ b/lib/skiplist.c
@@ -185,7 +185,7 @@ skiplist_lookup(struct skiplist *list, const char *key)
static void
skiplist_notify(struct skiplist *l, struct skiplist_node *n,
uint32_t event,
- char *key, void *old_value, void *value, void *user_data)
+ char *key, void *old_value, void *value)
{
struct qb_list_head *list;
struct qb_map_notifier *tn;
@@ -197,7 +197,7 @@ skiplist_notify(struct skiplist *l, struct skiplist_node *n,
tn = qb_list_entry(list, struct qb_map_notifier, list);
if (tn->events & event) {
- tn->callback(event, key, old_value, value, user_data);
+ tn->callback(event, key, old_value, value, tn->user_data);
}
}
/* global callbacks
@@ -207,7 +207,7 @@ skiplist_notify(struct skiplist *l, struct skiplist_node *n,
tn = qb_list_entry(list, struct qb_map_notifier, list);
if (tn->events & event) {
- tn->callback(event, key, old_value, value, user_data);
+ tn->callback(event, key, old_value, value, tn->user_data);
}
}
@@ -218,7 +218,7 @@ skiplist_node_destroy(struct skiplist_node *node, struct skiplist
*list)
{
skiplist_notify(list, node,
QB_MAP_NOTIFY_DELETED,
- (char *)node->key, node->value, NULL, NULL);
+ (char *)node->key, node->value, NULL);
free(node->forward);
free(node);
@@ -235,7 +235,7 @@ skiplist_node_deref(struct skiplist_node *node, struct skiplist
*list)
static int32_t
skiplist_notify_add(qb_map_t * m, const char *key,
- qb_map_notify_fn fn, int32_t events)
+ qb_map_notify_fn fn, int32_t events, void *user_data)
{
struct skiplist *t = (struct skiplist *)m;
struct qb_map_notifier *f;
@@ -249,6 +249,7 @@ skiplist_notify_add(qb_map_t * m, const char *key,
if (n) {
f = malloc(sizeof(struct qb_map_notifier));
f->events = events;
+ f->user_data = user_data;
f->callback = fn;
qb_list_init(&f->list);
qb_list_add(&f->list, &n->notifier_head);
@@ -308,7 +309,7 @@ skiplist_put(struct qb_map *map, const char *key, const void *value)
fwd_node->key = (void *)key;
skiplist_notify(list, fwd_node,
QB_MAP_NOTIFY_REPLACED,
- old_k, old_v, fwd_node->value, NULL);
+ old_k, old_v, fwd_node->value);
return;
case OP_GOTO_NEXT_NODE:
diff --git a/lib/trie.c b/lib/trie.c
index 888f3bc..19521ce 100644
--- a/lib/trie.c
+++ b/lib/trie.c
@@ -52,7 +52,7 @@ struct trie {
};
static void trie_notify(struct trie_node *n, uint32_t event, const char *key,
- void *old_value, void *value, void *user_data);
+ void *old_value, void *value);
/*
* characters are stored in reverse to make accessing the
@@ -122,7 +122,7 @@ keep_going:
static void
trie_node_destroy(struct trie *t, struct trie_node *n)
{
- trie_notify(n, QB_MAP_NOTIFY_DELETED, n->key, n->value, NULL, NULL);
+ trie_notify(n, QB_MAP_NOTIFY_DELETED, n->key, n->value, NULL);
n->key = NULL;
n->value = NULL;
@@ -233,11 +233,11 @@ trie_put(struct qb_map *map, const char *key, const void *value)
n->refcount++;
t->length++;
trie_notify(n, QB_MAP_NOTIFY_INSERTED,
- n->key, NULL, n->value, NULL);
+ n->key, NULL, n->value);
} else {
trie_notify(n, QB_MAP_NOTIFY_REPLACED,
(char *)old_key, (void *)old_value,
- (void *)value, NULL);
+ (void *)value);
}
}
}
@@ -271,7 +271,7 @@ trie_get(struct qb_map *map, const char *key)
static void
trie_notify(struct trie_node *n,
uint32_t event,
- const char *key, void *old_value, void *value, void *user_data)
+ const char *key, void *old_value, void *value)
{
struct trie_node *c = n;
struct qb_list_head *list;
@@ -286,7 +286,7 @@ trie_notify(struct trie_node *n,
((tn->events & QB_MAP_NOTIFY_RECURSIVE) ||
(n == c))) {
tn->callback(event, (char *)key, old_value,
- value, user_data);
+ value, tn->user_data);
}
}
c = c->parent;
@@ -295,7 +295,7 @@ trie_notify(struct trie_node *n,
static int32_t
trie_notify_add(qb_map_t * m, const char *key,
- qb_map_notify_fn fn, int32_t events)
+ qb_map_notify_fn fn, int32_t events, void *user_data)
{
struct trie *t = (struct trie *)m;
struct qb_map_notifier *f;
@@ -309,6 +309,7 @@ trie_notify_add(qb_map_t * m, const char *key,
if (n) {
f = malloc(sizeof(struct qb_map_notifier));
f->events = events;
+ f->user_data = user_data;
f->callback = fn;
qb_list_init(&f->list);
if (events & QB_MAP_NOTIFY_RECURSIVE) {
diff --git a/tests/check_map.c b/tests/check_map.c
index d3ea622..95a7a12 100644
--- a/tests/check_map.c
+++ b/tests/check_map.c
@@ -42,6 +42,7 @@ const char *chars2[] = {
static char *notified_key = NULL;
static void *notified_value = NULL;
static void *notified_new_value = NULL;
+static void *notified_user_data = NULL;
static void
test_map_simple(qb_map_t *m, const char *name)
@@ -188,6 +189,7 @@ my_map_notification(uint32_t event,
notified_key = key;
notified_value = old_value;
notified_new_value = value;
+ notified_user_data = user_data;
}
static void
@@ -201,7 +203,8 @@ test_map_remove(qb_map_t *m)
i = qb_map_notify_add(m, NULL, my_map_notification,
(QB_MAP_NOTIFY_DELETED|
QB_MAP_NOTIFY_REPLACED|
- QB_MAP_NOTIFY_RECURSIVE));
+ QB_MAP_NOTIFY_RECURSIVE),
+ m);
ck_assert_int_eq(i, 0);
for (i = 0; chars[i]; i++) {
@@ -212,21 +215,26 @@ test_map_remove(qb_map_t *m)
qb_map_put(m, a, a);
ck_assert(notified_key == chars[0]);
ck_assert(notified_value == chars[0]);
+ ck_assert(notified_user_data == m);
notified_key = NULL;
notified_value = NULL;
+ notified_user_data = NULL;
b = "5";
removed = qb_map_rm(m, b);
ck_assert(removed);
ck_assert(notified_key == chars[5]);
ck_assert(notified_value == chars[5]);
+ ck_assert(notified_user_data == m);
notified_key = NULL;
notified_value = NULL;
+ notified_user_data = NULL;
d = "1";
qb_map_put(m, d, d);
ck_assert(notified_key == chars[1]);
ck_assert(notified_value == chars[1]);
+ ck_assert(notified_user_data == m);
notified_key = NULL;
notified_value = NULL;
@@ -257,24 +265,28 @@ test_map_notifications(qb_map_t *m)
(QB_MAP_NOTIFY_INSERTED|
QB_MAP_NOTIFY_DELETED|
QB_MAP_NOTIFY_REPLACED|
- QB_MAP_NOTIFY_RECURSIVE));
+ QB_MAP_NOTIFY_RECURSIVE),
+ m);
ck_assert_int_eq(i, 0);
/* insert */
qb_map_put(m, "garden", "grow");
ck_assert_str_eq(notified_key, "garden");
ck_assert_str_eq(notified_new_value, "grow");
+ ck_assert(notified_user_data == m);
/* update */
qb_map_put(m, "garden", "green");
ck_assert_str_eq(notified_key, "garden");
ck_assert_str_eq(notified_value, "grow");
ck_assert_str_eq(notified_new_value, "green");
+ ck_assert(notified_user_data == m);
/* delete */
qb_map_rm(m, "garden");
ck_assert_str_eq(notified_key, "garden");
ck_assert_str_eq(notified_value, "green");
+ ck_assert(notified_user_data == m);
/* no event with notifier removed */
i = qb_map_notify_del(m, NULL, my_map_notification,
@@ -292,19 +304,20 @@ test_map_notifications(qb_map_t *m)
ck_assert(notified_new_value == NULL);
-/* with prefic notifier */
-
+/* with prefix notifier */
i = qb_map_notify_add(m, "add", my_map_notification,
(QB_MAP_NOTIFY_INSERTED|
QB_MAP_NOTIFY_DELETED|
QB_MAP_NOTIFY_REPLACED|
- QB_MAP_NOTIFY_RECURSIVE));
+ QB_MAP_NOTIFY_RECURSIVE),
+ &i);
ck_assert_int_eq(i, 0);
/* insert */
qb_map_put(m, "adder", "snake");
ck_assert_str_eq(notified_key, "adder");
ck_assert_str_eq(notified_new_value, "snake");
+ ck_assert(notified_user_data == &i);
/* insert (no match) */
notified_key = NULL;
@@ -326,6 +339,13 @@ test_map_notifications(qb_map_t *m)
ck_assert_str_eq(notified_key, "adder");
ck_assert_str_eq(notified_value, "+++");
+/* deleting a non-existing notification */
+ i = qb_map_notify_del(m, "a", my_map_notification,
+ (QB_MAP_NOTIFY_INSERTED|
+ QB_MAP_NOTIFY_DELETED|
+ QB_MAP_NOTIFY_REPLACED|
+ QB_MAP_NOTIFY_RECURSIVE));
+ ck_assert_int_eq(i, -ENOENT);
}
static void
--
1.7.6