]> arthur.barton.de Git - netdata.git/blobdiff - src/avl.c
locks error handling
[netdata.git] / src / avl.c
index cf9705e257d01fbe8809e042caffa98d2ef968a2..f6a997884efc5eb06c688881bd6dffddcf962ce9 100644 (file)
--- a/src/avl.c
+++ b/src/avl.c
@@ -1,10 +1,4 @@
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-// #include <assert.h>
-
-#include "avl.h"
-#include "log.h"
+#include "common.h"
 
 /* ------------------------------------------------------------------------- */
 /*
@@ -21,7 +15,7 @@
 
 
 /* Search |tree| for an item matching |item|, and return it if found.
-        Otherwise return |NULL|. */
+     Otherwise return |NULL|. */
 avl *avl_search(avl_tree *tree, avl *item) {
     avl *p;
 
@@ -42,8 +36,8 @@ avl *avl_search(avl_tree *tree, avl *item) {
 }
 
 /* Inserts |item| into |tree| and returns a pointer to |item|'s address.
-        If a duplicate item is found in the tree,
-        returns a pointer to the duplicate without inserting |item|.
+     If a duplicate item is found in the tree,
+     returns a pointer to the duplicate without inserting |item|.
  */
 avl *avl_insert(avl_tree *tree, avl *item) {
     avl *y, *z; /* Top node to update balance factor, and parent. */
@@ -140,7 +134,7 @@ avl *avl_insert(avl_tree *tree, avl *item) {
 }
 
 /* Deletes from |tree| and returns an item matching |item|.
-        Returns a null pointer if no matching item found. */
+     Returns a null pointer if no matching item found. */
 avl *avl_remove(avl_tree *tree, avl *item) {
     /* Stack of nodes. */
     avl *pa[AVL_MAX_HEIGHT]; /* Nodes. */
@@ -284,14 +278,48 @@ avl *avl_remove(avl_tree *tree, avl *item) {
 }
 
 /* ------------------------------------------------------------------------- */
-// these functions are (C) Costa Tsaousis
+// below are functions by (C) Costa Tsaousis
+
+// ---------------------------
+// traversing
+
+int avl_walker(avl *node, int (*callback)(void *entry, void *data), void *data) {
+    int total = 0, ret = 0;
+
+    if(node->avl_link[0]) {
+        ret = avl_walker(node->avl_link[0], callback, data);
+        if(ret < 0) return ret;
+        total += ret;
+    }
+
+    ret = callback(node, data);
+    if(ret < 0) return ret;
+    total += ret;
+
+    if(node->avl_link[1]) {
+        ret = avl_walker(node->avl_link[1], callback, data);
+        if (ret < 0) return ret;
+        total += ret;
+    }
+
+    return total;
+}
+
+int avl_traverse(avl_tree *t, int (*callback)(void *entry, void *data), void *data) {
+    return avl_walker(t->root, callback, data);
+}
+
+// ---------------------------
+// locks
 
 void avl_read_lock(avl_tree_lock *t) {
 #ifndef AVL_WITHOUT_PTHREADS
 #ifdef AVL_LOCK_WITH_MUTEX
-       pthread_mutex_lock(&t->mutex);
+    if(unlikely(pthread_mutex_lock(&t->mutex) != 0))
+        error("Cannot get mutex of an AVL");
 #else
-       pthread_rwlock_rdlock(&t->rwlock);
+    if(unlikely(pthread_rwlock_rdlock(&t->rwlock) != 0))
+        error("Cannot get read lock of an AVL");
 #endif
 #endif /* AVL_WITHOUT_PTHREADS */
 }
@@ -299,9 +327,11 @@ void avl_read_lock(avl_tree_lock *t) {
 void avl_write_lock(avl_tree_lock *t) {
 #ifndef AVL_WITHOUT_PTHREADS
 #ifdef AVL_LOCK_WITH_MUTEX
-       pthread_mutex_lock(&t->mutex);
+    if(unlikely(pthread_mutex_lock(&t->mutex) != 0)
+        error("Cannot get mutex of an AVL");
 #else
-       pthread_rwlock_wrlock(&t->rwlock);
+    if(unlikely(pthread_rwlock_wrlock(&t->rwlock) != 0))
+        error("Cannot write lock an AVL.");
 #endif
 #endif /* AVL_WITHOUT_PTHREADS */
 }
@@ -309,52 +339,63 @@ void avl_write_lock(avl_tree_lock *t) {
 void avl_unlock(avl_tree_lock *t) {
 #ifndef AVL_WITHOUT_PTHREADS
 #ifdef AVL_LOCK_WITH_MUTEX
-       pthread_mutex_unlock(&t->mutex);
+    if(unlikely(pthread_mutex_unlock(&t->mutex) != 0))
+        error("Cannot unlock mutex of an AVL");
 #else
-       pthread_rwlock_unlock(&t->rwlock);
+    if(unlikely(pthread_rwlock_unlock(&t->rwlock) != 0))
+        error("Cannot unlock an AVL");
 #endif
 #endif /* AVL_WITHOUT_PTHREADS */
 }
 
-/* ------------------------------------------------------------------------- */
+// ---------------------------
+// operations with locking
 
 void avl_init_lock(avl_tree_lock *t, int (*compar)(void *a, void *b)) {
-       avl_init(&t->avl_tree, compar);
+    avl_init(&t->avl_tree, compar);
 
 #ifndef AVL_WITHOUT_PTHREADS
-       int lock;
+    int lock;
 
 #ifdef AVL_LOCK_WITH_MUTEX
-       lock = pthread_mutex_init(&t->mutex, NULL);
+    lock = pthread_mutex_init(&t->mutex, NULL);
 #else
-       lock = pthread_rwlock_init(&t->rwlock, NULL);
+    lock = pthread_rwlock_init(&t->rwlock, NULL);
 #endif
 
-       if(lock != 0)
-               fatal("Failed to initialize AVL mutex/rwlock, error: %d", lock);
+    if(lock != 0)
+        fatal("Failed to initialize AVL mutex/rwlock, error: %d", lock);
 
 #endif /* AVL_WITHOUT_PTHREADS */
 }
 
 avl *avl_search_lock(avl_tree_lock *t, avl *a) {
-       avl_read_lock(t);
-       avl *ret = avl_search(&t->avl_tree, a);
-       avl_unlock(t);
-       return ret;
+    avl_read_lock(t);
+    avl *ret = avl_search(&t->avl_tree, a);
+    avl_unlock(t);
+    return ret;
 }
 
 avl * avl_remove_lock(avl_tree_lock *t, avl *a) {
-       avl_write_lock(t);
-       avl *ret = avl_remove(&t->avl_tree, a);
-       avl_unlock(t);
-       return ret;
+    avl_write_lock(t);
+    avl *ret = avl_remove(&t->avl_tree, a);
+    avl_unlock(t);
+    return ret;
 }
 
 avl *avl_insert_lock(avl_tree_lock *t, avl *a) {
-       avl_write_lock(t);
+    avl_write_lock(t);
     avl * ret = avl_insert(&t->avl_tree, a);
-       avl_unlock(t);
-       return ret;
+    avl_unlock(t);
+    return ret;
+}
+
+int avl_traverse_lock(avl_tree_lock *t, int (*callback)(void *entry, void *data), void *data) {
+    int ret;
+    avl_read_lock(t);
+    ret = avl_traverse(&t->avl_tree, callback, data);
+    avl_unlock(t);
+    return ret;
 }
 
 void avl_init(avl_tree *t, int (*compar)(void *a, void *b)) {
@@ -362,3 +403,4 @@ void avl_init(avl_tree *t, int (*compar)(void *a, void *b)) {
     t->compar = compar;
 }
 
+// ------------------
\ No newline at end of file