]> arthur.barton.de Git - netdata.git/blobdiff - src/dictionary.c
dns_query_time plugin: replace "." with "_" in dimensions
[netdata.git] / src / dictionary.c
index 8bc048276b45e7667cacf4a4af27af863e5c7657..512b4bbe6c182bf92d3161c488d3e1b89c5b9d28 100644 (file)
@@ -1,39 +1,27 @@
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <pthread.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "avl.h"
 #include "common.h"
-#include "log.h"
-
-#include "dictionary.h"
 
 // ----------------------------------------------------------------------------
 // dictionary statistics
 
 static inline void NETDATA_DICTIONARY_STATS_INSERTS_PLUS1(DICTIONARY *dict) {
-       if(likely(dict->stats))
-               dict->stats->inserts++;
+    if(likely(dict->stats))
+        dict->stats->inserts++;
 }
 static inline void NETDATA_DICTIONARY_STATS_DELETES_PLUS1(DICTIONARY *dict) {
-       if(likely(dict->stats))
-               dict->stats->deletes++;
+    if(likely(dict->stats))
+        dict->stats->deletes++;
 }
 static inline void NETDATA_DICTIONARY_STATS_SEARCHES_PLUS1(DICTIONARY *dict) {
-       if(likely(dict->stats))
-               dict->stats->searches++;
+    if(likely(dict->stats))
+        dict->stats->searches++;
 }
 static inline void NETDATA_DICTIONARY_STATS_ENTRIES_PLUS1(DICTIONARY *dict) {
-       if(likely(dict->stats))
-               dict->stats->entries++;
+    if(likely(dict->stats))
+        dict->stats->entries++;
 }
 static inline void NETDATA_DICTIONARY_STATS_ENTRIES_MINUS1(DICTIONARY *dict) {
-       if(likely(dict->stats))
-               dict->stats->entries--;
+    if(likely(dict->stats))
+        dict->stats->entries--;
 }
 
 
@@ -41,24 +29,24 @@ static inline void NETDATA_DICTIONARY_STATS_ENTRIES_MINUS1(DICTIONARY *dict) {
 // dictionary locks
 
 static inline void dictionary_read_lock(DICTIONARY *dict) {
-       if(likely(dict->rwlock)) {
-               // debug(D_DICTIONARY, "Dictionary READ lock");
-               pthread_rwlock_rdlock(dict->rwlock);
-       }
+    if(likely(dict->rwlock)) {
+        // debug(D_DICTIONARY, "Dictionary READ lock");
+        netdata_rwlock_rdlock(dict->rwlock);
+    }
 }
 
 static inline void dictionary_write_lock(DICTIONARY *dict) {
-       if(likely(dict->rwlock)) {
-               // debug(D_DICTIONARY, "Dictionary WRITE lock");
-               pthread_rwlock_wrlock(dict->rwlock);
-       }
+    if(likely(dict->rwlock)) {
+        // debug(D_DICTIONARY, "Dictionary WRITE lock");
+        netdata_rwlock_wrlock(dict->rwlock);
+    }
 }
 
 static inline void dictionary_unlock(DICTIONARY *dict) {
-       if(likely(dict->rwlock)) {
-               // debug(D_DICTIONARY, "Dictionary UNLOCK lock");
-               pthread_rwlock_unlock(dict->rwlock);
-       }
+    if(likely(dict->rwlock)) {
+        // debug(D_DICTIONARY, "Dictionary UNLOCK lock");
+        netdata_rwlock_unlock(dict->rwlock);
+    }
 }
 
 
@@ -66,209 +54,200 @@ static inline void dictionary_unlock(DICTIONARY *dict) {
 // avl index
 
 static int name_value_compare(void* a, void* b) {
-       if(((NAME_VALUE *)a)->hash < ((NAME_VALUE *)b)->hash) return -1;
-       else if(((NAME_VALUE *)a)->hash > ((NAME_VALUE *)b)->hash) return 1;
-       else return strcmp(((NAME_VALUE *)a)->name, ((NAME_VALUE *)b)->name);
+    if(((NAME_VALUE *)a)->hash < ((NAME_VALUE *)b)->hash) return -1;
+    else if(((NAME_VALUE *)a)->hash > ((NAME_VALUE *)b)->hash) return 1;
+    else return strcmp(((NAME_VALUE *)a)->name, ((NAME_VALUE *)b)->name);
 }
 
-#define dictionary_name_value_index_add_nolock(dict, nv) do { NETDATA_DICTIONARY_STATS_INSERTS_PLUS1(dict); avl_insert(&((dict)->values_index), (avl *)(nv)); } while(0)
-#define dictionary_name_value_index_del_nolock(dict, nv) do { NETDATA_DICTIONARY_STATS_DELETES_PLUS1(dict); avl_remove(&(dict->values_index), (avl *)(nv)); } while(0)
-
 static inline NAME_VALUE *dictionary_name_value_index_find_nolock(DICTIONARY *dict, const char *name, uint32_t hash) {
-       NAME_VALUE tmp;
-       tmp.hash = (hash)?hash:simple_hash(name);
-       tmp.name = (char *)name;
+    NAME_VALUE tmp;
+    tmp.hash = (hash)?hash:simple_hash(name);
+    tmp.name = (char *)name;
 
-       NETDATA_DICTIONARY_STATS_SEARCHES_PLUS1(dict);
-       return (NAME_VALUE *)avl_search(&(dict->values_index), (avl *) &tmp);
+    NETDATA_DICTIONARY_STATS_SEARCHES_PLUS1(dict);
+    return (NAME_VALUE *)avl_search(&(dict->values_index), (avl *) &tmp);
 }
 
 // ----------------------------------------------------------------------------
 // internal methods
 
 static NAME_VALUE *dictionary_name_value_create_nolock(DICTIONARY *dict, const char *name, void *value, size_t value_len, uint32_t hash) {
-       debug(D_DICTIONARY, "Creating name value entry for name '%s'.", name);
+    debug(D_DICTIONARY, "Creating name value entry for name '%s'.", name);
 
-       NAME_VALUE *nv = calloc(1, sizeof(NAME_VALUE));
-       if(unlikely(!nv)) fatal("Cannot allocate name_value of size %zu", sizeof(NAME_VALUE));
+    NAME_VALUE *nv = callocz(1, sizeof(NAME_VALUE));
 
-       if(dict->flags & DICTIONARY_FLAG_NAME_LINK_DONT_CLONE)
-               nv->name = (char *)name;
-       else {
-               nv->name = strdup(name);
-               if (unlikely(!nv->name))
-                       fatal("Cannot allocate name_value.name of size %zu", strlen(name));
-       }
+    if(dict->flags & DICTIONARY_FLAG_NAME_LINK_DONT_CLONE)
+        nv->name = (char *)name;
+    else {
+        nv->name = strdupz(name);
+    }
 
-       nv->hash = (hash)?hash:simple_hash(nv->name);
+    nv->hash = (hash)?hash:simple_hash(nv->name);
 
-       if(dict->flags & DICTIONARY_FLAG_VALUE_LINK_DONT_CLONE)
-               nv->value = value;
-       else {
-               nv->value = malloc(value_len);
-               if (unlikely(!nv->value))
-                       fatal("Cannot allocate name_value.value of size %zu", value_len);
+    if(dict->flags & DICTIONARY_FLAG_VALUE_LINK_DONT_CLONE)
+        nv->value = value;
+    else {
+        nv->value = mallocz(value_len);
+        memcpy(nv->value, value, value_len);
+    }
 
-               memcpy(nv->value, value, value_len);
-       }
+    // index it
+    NETDATA_DICTIONARY_STATS_INSERTS_PLUS1(dict);
+    if(unlikely(avl_insert(&((dict)->values_index), (avl *)(nv)) != (avl *)nv))
+        error("dictionary: INTERNAL ERROR: duplicate insertion to dictionary.");
 
-       // index it
-       dictionary_name_value_index_add_nolock(dict, nv);
-       NETDATA_DICTIONARY_STATS_ENTRIES_PLUS1(dict);
+    NETDATA_DICTIONARY_STATS_ENTRIES_PLUS1(dict);
 
-       return nv;
+    return nv;
 }
 
 static void dictionary_name_value_destroy_nolock(DICTIONARY *dict, NAME_VALUE *nv) {
-       debug(D_DICTIONARY, "Destroying name value entry for name '%s'.", nv->name);
+    debug(D_DICTIONARY, "Destroying name value entry for name '%s'.", nv->name);
 
-       dictionary_name_value_index_del_nolock(dict, nv);
+    NETDATA_DICTIONARY_STATS_DELETES_PLUS1(dict);
+    if(unlikely(avl_remove(&(dict->values_index), (avl *)(nv)) != (avl *)nv))
+        error("dictionary: INTERNAL ERROR: dictionary invalid removal of node.");
 
-       NETDATA_DICTIONARY_STATS_ENTRIES_MINUS1(dict);
+    NETDATA_DICTIONARY_STATS_ENTRIES_MINUS1(dict);
 
-       if(!(dict->flags & DICTIONARY_FLAG_VALUE_LINK_DONT_CLONE)) {
-               debug(D_REGISTRY, "Dictionary freeing value of '%s'", nv->name);
-               free(nv->value);
-       }
+    if(!(dict->flags & DICTIONARY_FLAG_VALUE_LINK_DONT_CLONE)) {
+        debug(D_REGISTRY, "Dictionary freeing value of '%s'", nv->name);
+        freez(nv->value);
+    }
 
-       if(!(dict->flags & DICTIONARY_FLAG_NAME_LINK_DONT_CLONE)) {
-               debug(D_REGISTRY, "Dictionary freeing name '%s'", nv->name);
-               free(nv->name);
-       }
+    if(!(dict->flags & DICTIONARY_FLAG_NAME_LINK_DONT_CLONE)) {
+        debug(D_REGISTRY, "Dictionary freeing name '%s'", nv->name);
+        freez(nv->name);
+    }
 
-       free(nv);
+    freez(nv);
 }
 
 // ----------------------------------------------------------------------------
 // API - basic methods
 
-DICTIONARY *dictionary_create(uint32_t flags) {
-       debug(D_DICTIONARY, "Creating dictionary.");
+DICTIONARY *dictionary_create(uint8_t flags) {
+    debug(D_DICTIONARY, "Creating dictionary.");
 
-       DICTIONARY *dict = calloc(1, sizeof(DICTIONARY));
-       if(unlikely(!dict)) fatal("Cannot allocate DICTIONARY");
+    DICTIONARY *dict = callocz(1, sizeof(DICTIONARY));
 
-       if(flags & DICTIONARY_FLAG_WITH_STATISTICS) {
-               dict->stats = calloc(1, sizeof(struct dictionary_stats));
-               if(!dict->stats) fatal("Cannot allocate statistics for DICTIONARY");
-       }
+    if(flags & DICTIONARY_FLAG_WITH_STATISTICS)
+        dict->stats = callocz(1, sizeof(struct dictionary_stats));
 
-       if(!(flags & DICTIONARY_FLAG_SINGLE_THREADED)) {
-               dict->rwlock = calloc(1, sizeof(pthread_rwlock_t));
-               if(!dict->rwlock) fatal("Cannot allocate pthread_rwlock_t for DICTIONARY");
-               pthread_rwlock_init(dict->rwlock, NULL);
-       }
+    if(!(flags & DICTIONARY_FLAG_SINGLE_THREADED)) {
+        dict->rwlock = callocz(1, sizeof(netdata_rwlock_t));
+        netdata_rwlock_init(dict->rwlock);
+    }
 
-       avl_init(&dict->values_index, name_value_compare);
-       dict->flags = flags;
+    avl_init(&dict->values_index, name_value_compare);
+    dict->flags = flags;
 
-       return dict;
+    return dict;
 }
 
 void dictionary_destroy(DICTIONARY *dict) {
-       debug(D_DICTIONARY, "Destroying dictionary.");
+    debug(D_DICTIONARY, "Destroying dictionary.");
 
-       dictionary_write_lock(dict);
+    dictionary_write_lock(dict);
 
-       while(dict->values_index.root)
-               dictionary_name_value_destroy_nolock(dict, (NAME_VALUE *)dict->values_index.root);
+    while(dict->values_index.root)
+        dictionary_name_value_destroy_nolock(dict, (NAME_VALUE *)dict->values_index.root);
 
-       dictionary_unlock(dict);
+    dictionary_unlock(dict);
 
-       if(dict->stats)
-               free(dict->stats);
+    if(dict->stats)
+        freez(dict->stats);
 
-       if(dict->rwlock)
-               free(dict->rwlock);
+    if(dict->rwlock) {
+        netdata_rwlock_destroy(dict->rwlock);
+        freez(dict->rwlock);
+    }
 
-       free(dict);
+    freez(dict);
 }
 
 // ----------------------------------------------------------------------------
 
 void *dictionary_set(DICTIONARY *dict, const char *name, void *value, size_t value_len) {
-       debug(D_DICTIONARY, "SET dictionary entry with name '%s'.", name);
-
-       uint32_t hash = simple_hash(name);
+    debug(D_DICTIONARY, "SET dictionary entry with name '%s'.", name);
 
-       dictionary_write_lock(dict);
+    uint32_t hash = simple_hash(name);
 
-       NAME_VALUE *nv = dictionary_name_value_index_find_nolock(dict, name, hash);
-       if(unlikely(!nv)) {
-               debug(D_DICTIONARY, "Dictionary entry with name '%s' not found. Creating a new one.", name);
+    dictionary_write_lock(dict);
 
-               nv = dictionary_name_value_create_nolock(dict, name, value, value_len, hash);
-               if(unlikely(!nv))
-                       fatal("Cannot create name_value.");
-       }
-       else {
-               debug(D_DICTIONARY, "Dictionary entry with name '%s' found. Changing its value.", name);
+    NAME_VALUE *nv = dictionary_name_value_index_find_nolock(dict, name, hash);
+    if(unlikely(!nv)) {
+        debug(D_DICTIONARY, "Dictionary entry with name '%s' not found. Creating a new one.", name);
 
-               if(dict->flags & DICTIONARY_FLAG_VALUE_LINK_DONT_CLONE) {
-                       debug(D_REGISTRY, "Dictionary: linking value to '%s'", name);
-                       nv->value = value;
-               }
-               else {
-                       debug(D_REGISTRY, "Dictionary: cloning value to '%s'", name);
+        nv = dictionary_name_value_create_nolock(dict, name, value, value_len, hash);
+        if(unlikely(!nv))
+            fatal("Cannot create name_value.");
+    }
+    else {
+        debug(D_DICTIONARY, "Dictionary entry with name '%s' found. Changing its value.", name);
 
-                       // copy the new value without breaking
-                       // any other thread accessing the same entry
-                       void *new = malloc(value_len),
-                                       *old = nv->value;
+        if(dict->flags & DICTIONARY_FLAG_VALUE_LINK_DONT_CLONE) {
+            debug(D_REGISTRY, "Dictionary: linking value to '%s'", name);
+            nv->value = value;
+        }
+        else {
+            debug(D_REGISTRY, "Dictionary: cloning value to '%s'", name);
 
-                       if(unlikely(!new))
-                               fatal("Cannot allocate value of size %zu", value_len);
+            // copy the new value without breaking
+            // any other thread accessing the same entry
+            void *new = mallocz(value_len),
+                    *old = nv->value;
 
-                       memcpy(new, value, value_len);
-                       nv->value = new;
+            memcpy(new, value, value_len);
+            nv->value = new;
 
-                       debug(D_REGISTRY, "Dictionary: freeing old value of '%s'", name);
-                       free(old);
-               }
-       }
+            debug(D_REGISTRY, "Dictionary: freeing old value of '%s'", name);
+            freez(old);
+        }
+    }
 
-       dictionary_unlock(dict);
+    dictionary_unlock(dict);
 
-       return nv->value;
+    return nv->value;
 }
 
 void *dictionary_get(DICTIONARY *dict, const char *name) {
-       debug(D_DICTIONARY, "GET dictionary entry with name '%s'.", name);
+    debug(D_DICTIONARY, "GET dictionary entry with name '%s'.", name);
 
-       dictionary_read_lock(dict);
-       NAME_VALUE *nv = dictionary_name_value_index_find_nolock(dict, name, 0);
-       dictionary_unlock(dict);
+    dictionary_read_lock(dict);
+    NAME_VALUE *nv = dictionary_name_value_index_find_nolock(dict, name, 0);
+    dictionary_unlock(dict);
 
-       if(unlikely(!nv)) {
-               debug(D_DICTIONARY, "Not found dictionary entry with name '%s'.", name);
-               return NULL;
-       }
+    if(unlikely(!nv)) {
+        debug(D_DICTIONARY, "Not found dictionary entry with name '%s'.", name);
+        return NULL;
+    }
 
-       debug(D_DICTIONARY, "Found dictionary entry with name '%s'.", name);
-       return nv->value;
+    debug(D_DICTIONARY, "Found dictionary entry with name '%s'.", name);
+    return nv->value;
 }
 
 int dictionary_del(DICTIONARY *dict, const char *name) {
-       int ret;
+    int ret;
 
-       debug(D_DICTIONARY, "DEL dictionary entry with name '%s'.", name);
+    debug(D_DICTIONARY, "DEL dictionary entry with name '%s'.", name);
 
-       dictionary_write_lock(dict);
+    dictionary_write_lock(dict);
 
-       NAME_VALUE *nv = dictionary_name_value_index_find_nolock(dict, name, 0);
-       if(unlikely(!nv)) {
-               debug(D_DICTIONARY, "Not found dictionary entry with name '%s'.", name);
-               ret = -1;
-       }
-       else {
-               debug(D_DICTIONARY, "Found dictionary entry with name '%s'.", name);
-               dictionary_name_value_destroy_nolock(dict, nv);
-               ret = 0;
-       }
+    NAME_VALUE *nv = dictionary_name_value_index_find_nolock(dict, name, 0);
+    if(unlikely(!nv)) {
+        debug(D_DICTIONARY, "Not found dictionary entry with name '%s'.", name);
+        ret = -1;
+    }
+    else {
+        debug(D_DICTIONARY, "Found dictionary entry with name '%s'.", name);
+        dictionary_name_value_destroy_nolock(dict, nv);
+        ret = 0;
+    }
 
-       dictionary_unlock(dict);
+    dictionary_unlock(dict);
 
-       return ret;
+    return ret;
 }
 
 
@@ -278,36 +257,36 @@ int dictionary_del(DICTIONARY *dict, const char *name) {
 // do not user other dictionary calls while walking the dictionary - deadlock!
 
 static int dictionary_walker(avl *a, int (*callback)(void *entry, void *data), void *data) {
-       int total = 0, ret = 0;
+    int total = 0, ret = 0;
 
-       if(a->avl_link[0]) {
-               ret = dictionary_walker(a->avl_link[0], callback, data);
-               if(ret < 0) return ret;
-               total += ret;
-       }
+    if(a->avl_link[0]) {
+        ret = dictionary_walker(a->avl_link[0], callback, data);
+        if(ret < 0) return ret;
+        total += ret;
+    }
 
-       ret = callback(((NAME_VALUE *)a)->value, data);
-       if(ret < 0) return ret;
-       total += ret;
+    ret = callback(((NAME_VALUE *)a)->value, data);
+    if(ret < 0) return ret;
+    total += ret;
 
-       if(a->avl_link[1]) {
-               ret = dictionary_walker(a->avl_link[1], callback, data);
-               if (ret < 0) return ret;
-               total += ret;
-       }
+    if(a->avl_link[1]) {
+        ret = dictionary_walker(a->avl_link[1], callback, data);
+        if (ret < 0) return ret;
+        total += ret;
+    }
 
-       return total;
+    return total;
 }
 
 int dictionary_get_all(DICTIONARY *dict, int (*callback)(void *entry, void *data), void *data) {
-       int ret = 0;
+    int ret = 0;
 
-       dictionary_read_lock(dict);
+    dictionary_read_lock(dict);
 
-       if(likely(dict->values_index.root))
-               ret = dictionary_walker(dict->values_index.root, callback, data);
+    if(likely(dict->values_index.root))
+        ret = dictionary_walker(dict->values_index.root, callback, data);
 
-       dictionary_unlock(dict);
+    dictionary_unlock(dict);
 
-       return ret;
+    return ret;
 }