summaryrefslogtreecommitdiffstats
path: root/libnetdata/dictionary
diff options
context:
space:
mode:
Diffstat (limited to 'libnetdata/dictionary')
-rw-r--r--libnetdata/dictionary/dictionary.c122
-rw-r--r--libnetdata/dictionary/dictionary.h3
2 files changed, 59 insertions, 66 deletions
diff --git a/libnetdata/dictionary/dictionary.c b/libnetdata/dictionary/dictionary.c
index 42e4a99f..05da5534 100644
--- a/libnetdata/dictionary/dictionary.c
+++ b/libnetdata/dictionary/dictionary.c
@@ -147,14 +147,14 @@ struct dictionary {
struct { // support for multiple indexing engines
Pvoid_t JudyHSArray; // the hash table
- netdata_rwlock_t rwlock; // protect the index
+ RW_SPINLOCK rw_spinlock; // protect the index
} index;
struct {
DICTIONARY_ITEM *list; // the double linked list of all items in the dictionary
- netdata_rwlock_t rwlock; // protect the linked-list
+ RW_SPINLOCK rw_spinlock; // protect the linked-list
pid_t writer_pid; // the gettid() of the writer
- size_t writer_depth; // nesting of write locks
+ uint32_t writer_depth; // nesting of write locks
} items;
struct dictionary_hooks *hooks; // pointer to external function callbacks to be called at certain points
@@ -163,7 +163,7 @@ struct dictionary {
DICTIONARY *master; // the master dictionary
DICTIONARY *next; // linked list for delayed destruction (garbage collection of whole dictionaries)
- size_t version; // the current version of the dictionary
+ uint32_t version; // the current version of the dictionary
// it is incremented when:
// - item added
// - item removed
@@ -171,9 +171,9 @@ struct dictionary {
// - conflict callback returns true
// - function dictionary_version_increment() is called
- long int entries; // how many items are currently in the index (the linked list may have more)
- long int referenced_items; // how many items of the dictionary are currently being used by 3rd parties
- long int pending_deletion_items; // how many items of the dictionary have been deleted, but have not been removed yet
+ int32_t entries; // how many items are currently in the index (the linked list may have more)
+ int32_t referenced_items; // how many items of the dictionary are currently being used by 3rd parties
+ int32_t pending_deletion_items; // how many items of the dictionary have been deleted, but have not been removed yet
#ifdef NETDATA_DICTIONARY_VALIDATE_POINTERS
netdata_mutex_t global_pointer_registry_mutex;
@@ -369,10 +369,6 @@ size_t dictionary_referenced_items(DICTIONARY *dict) {
return referenced_items;
}
-long int dictionary_stats_for_registry(DICTIONARY *dict) {
- if(unlikely(!dict)) return 0;
- return (dict->stats->memory.index + dict->stats->memory.dict);
-}
void dictionary_version_increment(DICTIONARY *dict) {
__atomic_fetch_add(&dict->version, 1, __ATOMIC_RELAXED);
}
@@ -632,19 +628,14 @@ static void dictionary_execute_delete_callback(DICTIONARY *dict, DICTIONARY_ITEM
static inline size_t dictionary_locks_init(DICTIONARY *dict) {
if(likely(!is_dictionary_single_threaded(dict))) {
- netdata_rwlock_init(&dict->index.rwlock);
- netdata_rwlock_init(&dict->items.rwlock);
+ rw_spinlock_init(&dict->index.rw_spinlock);
+ rw_spinlock_init(&dict->items.rw_spinlock);
}
return 0;
}
-static inline size_t dictionary_locks_destroy(DICTIONARY *dict) {
- if(likely(!is_dictionary_single_threaded(dict))) {
- netdata_rwlock_destroy(&dict->index.rwlock);
- netdata_rwlock_destroy(&dict->items.rwlock);
- }
-
+static inline size_t dictionary_locks_destroy(DICTIONARY *dict __maybe_unused) {
return 0;
}
@@ -676,11 +667,11 @@ static inline void ll_recursive_lock(DICTIONARY *dict, char rw) {
if(rw == DICTIONARY_LOCK_READ || rw == DICTIONARY_LOCK_REENTRANT || rw == 'R') {
// read lock
- netdata_rwlock_rdlock(&dict->items.rwlock);
+ rw_spinlock_read_lock(&dict->items.rw_spinlock);
}
else {
// write lock
- netdata_rwlock_wrlock(&dict->items.rwlock);
+ rw_spinlock_write_lock(&dict->items.rw_spinlock);
ll_recursive_lock_set_thread_as_writer(dict);
}
}
@@ -697,14 +688,14 @@ static inline void ll_recursive_unlock(DICTIONARY *dict, char rw) {
if(rw == DICTIONARY_LOCK_READ || rw == DICTIONARY_LOCK_REENTRANT || rw == 'R') {
// read unlock
- netdata_rwlock_unlock(&dict->items.rwlock);
+ rw_spinlock_read_unlock(&dict->items.rw_spinlock);
}
else {
// write unlock
ll_recursive_unlock_unset_thread_writer(dict);
- netdata_rwlock_unlock(&dict->items.rwlock);
+ rw_spinlock_write_unlock(&dict->items.rw_spinlock);
}
}
@@ -719,27 +710,27 @@ static inline void dictionary_index_lock_rdlock(DICTIONARY *dict) {
if(unlikely(is_dictionary_single_threaded(dict)))
return;
- netdata_rwlock_rdlock(&dict->index.rwlock);
+ rw_spinlock_read_lock(&dict->index.rw_spinlock);
}
static inline void dictionary_index_rdlock_unlock(DICTIONARY *dict) {
if(unlikely(is_dictionary_single_threaded(dict)))
return;
- netdata_rwlock_unlock(&dict->index.rwlock);
+ rw_spinlock_read_unlock(&dict->index.rw_spinlock);
}
static inline void dictionary_index_lock_wrlock(DICTIONARY *dict) {
if(unlikely(is_dictionary_single_threaded(dict)))
return;
- netdata_rwlock_wrlock(&dict->index.rwlock);
+ rw_spinlock_write_lock(&dict->index.rw_spinlock);
}
static inline void dictionary_index_wrlock_unlock(DICTIONARY *dict) {
if(unlikely(is_dictionary_single_threaded(dict)))
return;
- netdata_rwlock_unlock(&dict->index.rwlock);
+ rw_spinlock_write_unlock(&dict->index.rw_spinlock);
}
// ----------------------------------------------------------------------------
@@ -957,7 +948,7 @@ static int item_check_and_acquire_advanced(DICTIONARY *dict, DICTIONARY_ITEM *it
if (having_index_lock) {
// delete it from the hashtable
if(hashtable_delete_unsafe(dict, item_get_name(item), item->key_len, item) == 0)
- error("DICTIONARY: INTERNAL ERROR VIEW: tried to delete item with name '%s', name_len %u that is not in the index", item_get_name(item), (KEY_LEN_TYPE)(item->key_len - 1));
+ netdata_log_error("DICTIONARY: INTERNAL ERROR VIEW: tried to delete item with name '%s', name_len %u that is not in the index", item_get_name(item), (KEY_LEN_TYPE)(item->key_len - 1));
else
pointer_del(dict, item);
@@ -1070,11 +1061,11 @@ static size_t hashtable_destroy_unsafe(DICTIONARY *dict) {
JError_t J_Error;
Word_t ret = JudyHSFreeArray(&dict->index.JudyHSArray, &J_Error);
if(unlikely(ret == (Word_t) JERR)) {
- error("DICTIONARY: Cannot destroy JudyHS, JU_ERRNO_* == %u, ID == %d",
- JU_ERRNO(&J_Error), JU_ERRID(&J_Error));
+ netdata_log_error("DICTIONARY: Cannot destroy JudyHS, JU_ERRNO_* == %u, ID == %d",
+ JU_ERRNO(&J_Error), JU_ERRID(&J_Error));
}
- debug(D_DICTIONARY, "Dictionary: hash table freed %lu bytes", ret);
+ netdata_log_debug(D_DICTIONARY, "Dictionary: hash table freed %lu bytes", ret);
dict->index.JudyHSArray = NULL;
return (size_t)ret;
@@ -1084,8 +1075,8 @@ static inline void **hashtable_insert_unsafe(DICTIONARY *dict, const char *name,
JError_t J_Error;
Pvoid_t *Rc = JudyHSIns(&dict->index.JudyHSArray, (void *)name, name_len, &J_Error);
if (unlikely(Rc == PJERR)) {
- error("DICTIONARY: Cannot insert entry with name '%s' to JudyHS, JU_ERRNO_* == %u, ID == %d",
- name, JU_ERRNO(&J_Error), JU_ERRID(&J_Error));
+ netdata_log_error("DICTIONARY: Cannot insert entry with name '%s' to JudyHS, JU_ERRNO_* == %u, ID == %d",
+ name, JU_ERRNO(&J_Error), JU_ERRID(&J_Error));
}
// if *Rc == 0, new item added to the array
@@ -1105,8 +1096,9 @@ static inline int hashtable_delete_unsafe(DICTIONARY *dict, const char *name, si
JError_t J_Error;
int ret = JudyHSDel(&dict->index.JudyHSArray, (void *)name, name_len, &J_Error);
if(unlikely(ret == JERR)) {
- error("DICTIONARY: Cannot delete entry with name '%s' from JudyHS, JU_ERRNO_* == %u, ID == %d", name,
- JU_ERRNO(&J_Error), JU_ERRID(&J_Error));
+ netdata_log_error("DICTIONARY: Cannot delete entry with name '%s' from JudyHS, JU_ERRNO_* == %u, ID == %d",
+ name,
+ JU_ERRNO(&J_Error), JU_ERRID(&J_Error));
return 0;
}
@@ -1232,7 +1224,7 @@ void dictionary_static_items_aral_init(void) {
static SPINLOCK spinlock;
if(unlikely(!dict_items_aral || !dict_shared_items_aral)) {
- netdata_spinlock_lock(&spinlock);
+ spinlock_lock(&spinlock);
// we have to check again
if(!dict_items_aral)
@@ -1254,7 +1246,7 @@ void dictionary_static_items_aral_init(void) {
aral_by_size_statistics(),
NULL, NULL, false, false);
- netdata_spinlock_unlock(&spinlock);
+ spinlock_unlock(&spinlock);
}
}
@@ -1384,7 +1376,7 @@ static void dict_item_reset_value_with_hooks(DICTIONARY *dict, DICTIONARY_ITEM *
if(unlikely(is_view_dictionary(dict)))
fatal("DICTIONARY: %s() should never be called on views.", __FUNCTION__ );
- debug(D_DICTIONARY, "Dictionary entry with name '%s' found. Changing its value.", item_get_name(item));
+ netdata_log_debug(D_DICTIONARY, "Dictionary entry with name '%s' found. Changing its value.", item_get_name(item));
DICTIONARY_VALUE_RESETS_PLUS1(dict);
@@ -1396,12 +1388,12 @@ static void dict_item_reset_value_with_hooks(DICTIONARY *dict, DICTIONARY_ITEM *
dictionary_execute_delete_callback(dict, item);
if(likely(dict->options & DICT_OPTION_VALUE_LINK_DONT_CLONE)) {
- debug(D_DICTIONARY, "Dictionary: linking value to '%s'", item_get_name(item));
+ netdata_log_debug(D_DICTIONARY, "Dictionary: linking value to '%s'", item_get_name(item));
item->shared->value = value;
item->shared->value_len = value_len;
}
else {
- debug(D_DICTIONARY, "Dictionary: cloning value to '%s'", item_get_name(item));
+ netdata_log_debug(D_DICTIONARY, "Dictionary: cloning value to '%s'", item_get_name(item));
void *old_value = item->shared->value;
void *new_value = NULL;
@@ -1413,7 +1405,7 @@ static void dict_item_reset_value_with_hooks(DICTIONARY *dict, DICTIONARY_ITEM *
item->shared->value = new_value;
item->shared->value_len = value_len;
- debug(D_DICTIONARY, "Dictionary: freeing old value of '%s'", item_get_name(item));
+ netdata_log_debug(D_DICTIONARY, "Dictionary: freeing old value of '%s'", item_get_name(item));
dict_item_value_freez(dict, old_value);
}
@@ -1421,7 +1413,7 @@ static void dict_item_reset_value_with_hooks(DICTIONARY *dict, DICTIONARY_ITEM *
}
static size_t dict_item_free_with_hooks(DICTIONARY *dict, DICTIONARY_ITEM *item) {
- debug(D_DICTIONARY, "Destroying name value entry for name '%s'.", item_get_name(item));
+ netdata_log_debug(D_DICTIONARY, "Destroying name value entry for name '%s'.", item_get_name(item));
if(!item_flag_check(item, ITEM_FLAG_DELETED))
DICTIONARY_ENTRIES_MINUS1(dict);
@@ -1436,7 +1428,7 @@ static size_t dict_item_free_with_hooks(DICTIONARY *dict, DICTIONARY_ITEM *item)
dictionary_execute_delete_callback(dict, item);
if(unlikely(!(dict->options & DICT_OPTION_VALUE_LINK_DONT_CLONE))) {
- debug(D_DICTIONARY, "Dictionary freeing value of '%s'", item_get_name(item));
+ netdata_log_debug(D_DICTIONARY, "Dictionary freeing value of '%s'", item_get_name(item));
dict_item_value_freez(dict, item->shared->value);
item->shared->value = NULL;
}
@@ -1562,7 +1554,7 @@ static bool dict_item_del(DICTIONARY *dict, const char *name, ssize_t name_len)
if(name_len == -1)
name_len = (ssize_t)strlen(name) + 1; // we need the terminating null too
- debug(D_DICTIONARY, "DEL dictionary entry with name '%s'.", name);
+ netdata_log_debug(D_DICTIONARY, "DEL dictionary entry with name '%s'.", name);
// Unfortunately, the JudyHSDel() does not return the value of the
// item that was deleted, so we have to find it before we delete it,
@@ -1578,7 +1570,9 @@ static bool dict_item_del(DICTIONARY *dict, const char *name, ssize_t name_len)
}
else {
if(hashtable_delete_unsafe(dict, name, name_len, item) == 0)
- error("DICTIONARY: INTERNAL ERROR: tried to delete item with name '%s', name_len %zd that is not in the index", name, name_len - 1);
+ netdata_log_error("DICTIONARY: INTERNAL ERROR: tried to delete item with name '%s', name_len %zd that is not in the index",
+ name,
+ name_len - 1);
else
pointer_del(dict, item);
@@ -1611,7 +1605,7 @@ static DICTIONARY_ITEM *dict_item_add_or_reset_value_and_acquire(DICTIONARY *dic
if(name_len == -1)
name_len = (ssize_t)strlen(name) + 1; // we need the terminating null too
- debug(D_DICTIONARY, "SET dictionary entry with name '%s'.", name);
+ netdata_log_debug(D_DICTIONARY, "SET dictionary entry with name '%s'.", name);
// DISCUSSION:
// Is it better to gain a read-lock and do a hashtable_get_unsafe()
@@ -1673,7 +1667,7 @@ static DICTIONARY_ITEM *dict_item_add_or_reset_value_and_acquire(DICTIONARY *dic
// view dictionary
// the item is already there and can be used
if(item->shared != master_item->shared)
- error("DICTIONARY: changing the master item on a view is not supported. The previous item will remain. To change the key of an item in a view, delete it and add it again.");
+ netdata_log_error("DICTIONARY: changing the master item on a view is not supported. The previous item will remain. To change the key of an item in a view, delete it and add it again.");
}
else {
// master dictionary
@@ -1730,7 +1724,7 @@ static DICTIONARY_ITEM *dict_item_find_and_acquire(DICTIONARY *dict, const char
if(name_len == -1)
name_len = (ssize_t)strlen(name) + 1; // we need the terminating null too
- debug(D_DICTIONARY, "GET dictionary entry with name '%s'.", name);
+ netdata_log_debug(D_DICTIONARY, "GET dictionary entry with name '%s'.", name);
dictionary_index_lock_rdlock(dict);
@@ -2096,7 +2090,7 @@ size_t dictionary_destroy(DICTIONARY *dict) {
internal_error(
true,
- "DICTIONARY: delaying destruction of dictionary created from %s() %zu@%s, because it has %ld referenced items in it (%ld total).",
+ "DICTIONARY: delaying destruction of dictionary created from %s() %zu@%s, because it has %d referenced items in it (%d total).",
dict->creation_function,
dict->creation_line,
dict->creation_file,
@@ -2560,8 +2554,8 @@ void thread_cache_destroy(void) {
JError_t J_Error;
Word_t ret = JudyHSFreeArray(&thread_cache_judy_array, &J_Error);
if(unlikely(ret == (Word_t) JERR)) {
- error("THREAD_CACHE: Cannot destroy JudyHS, JU_ERRNO_* == %u, ID == %d",
- JU_ERRNO(&J_Error), JU_ERRID(&J_Error));
+ netdata_log_error("THREAD_CACHE: Cannot destroy JudyHS, JU_ERRNO_* == %u, ID == %d",
+ JU_ERRNO(&J_Error), JU_ERRID(&J_Error));
}
internal_error(true, "THREAD_CACHE: hash table freed %lu bytes", ret);
@@ -2842,7 +2836,7 @@ static usec_t dictionary_unittest_run_and_measure_time(DICTIONARY *dict, char *m
}
}
- fprintf(stderr, " %zu errors, %ld (found %ld) items in dictionary, %ld (found %ld) referenced, %ld (found %ld) deleted, %llu usec \n",
+ fprintf(stderr, " %zu errors, %d (found %ld) items in dictionary, %d (found %ld) referenced, %d (found %ld) deleted, %llu usec \n",
errs, dict?dict->entries:0, found_ok, dict?dict->referenced_items:0, found_referenced, dict?dict->pending_deletion_items:0, found_deleted, dt);
*errors += errs;
return dt;
@@ -2984,7 +2978,7 @@ static size_t unittest_check_dictionary(const char *label, DICTIONARY *dict, siz
referenced++;
}
- fprintf(stderr, "DICT %-20s: dictionary active items reported %ld, counted %zu, expected %zu...\t\t\t",
+ fprintf(stderr, "DICT %-20s: dictionary active items reported %d, counted %zu, expected %zu...\t\t\t",
label, dict->entries, active, active_items);
if(active != active_items || active != (size_t)dict->entries) {
fprintf(stderr, "FAILED\n");
@@ -3002,7 +2996,7 @@ static size_t unittest_check_dictionary(const char *label, DICTIONARY *dict, siz
else
fprintf(stderr, "OK\n");
- fprintf(stderr, "DICT %-20s: dictionary referenced items reported %ld, counted %zu, expected %zu...\t\t",
+ fprintf(stderr, "DICT %-20s: dictionary referenced items reported %d, counted %zu, expected %zu...\t\t",
label, dict->referenced_items, referenced, referenced_items);
if(referenced != referenced_items || dict->referenced_items != (long int)referenced) {
fprintf(stderr, "FAILED\n");
@@ -3011,7 +3005,7 @@ static size_t unittest_check_dictionary(const char *label, DICTIONARY *dict, siz
else
fprintf(stderr, "OK\n");
- fprintf(stderr, "DICT %-20s: dictionary pending deletion items reported %ld, counted %zu, expected %zu...\t",
+ fprintf(stderr, "DICT %-20s: dictionary pending deletion items reported %d, counted %zu, expected %zu...\t",
label, dict->pending_deletion_items, pending, pending_deletion);
if(pending != pending_deletion || pending != (size_t)dict->pending_deletion_items) {
fprintf(stderr, "FAILED\n");
@@ -3257,9 +3251,9 @@ static int dictionary_unittest_threads() {
", searches %zu"
", resets %zu"
", flushes %zu"
- ", entries %ld"
- ", referenced_items %ld"
- ", pending deletions %ld"
+ ", entries %d"
+ ", referenced_items %d"
+ ", pending deletions %d"
", check spins %zu"
", insert spins %zu"
", delete spins %zu"
@@ -3418,9 +3412,9 @@ static int dictionary_unittest_view_threads() {
", deletes %zu"
", searches %zu"
", resets %zu"
- ", entries %ld"
- ", referenced_items %ld"
- ", pending deletions %ld"
+ ", entries %d"
+ ", referenced_items %d"
+ ", pending deletions %d"
", check spins %zu"
", insert spins %zu"
", delete spins %zu"
@@ -3443,9 +3437,9 @@ static int dictionary_unittest_view_threads() {
", deletes %zu"
", searches %zu"
", resets %zu"
- ", entries %ld"
- ", referenced_items %ld"
- ", pending deletions %ld"
+ ", entries %d"
+ ", referenced_items %d"
+ ", pending deletions %d"
", check spins %zu"
", insert spins %zu"
", delete spins %zu"
diff --git a/libnetdata/dictionary/dictionary.h b/libnetdata/dictionary/dictionary.h
index c13d784c..eea14d3f 100644
--- a/libnetdata/dictionary/dictionary.h
+++ b/libnetdata/dictionary/dictionary.h
@@ -46,7 +46,7 @@
typedef struct dictionary DICTIONARY;
typedef struct dictionary_item DICTIONARY_ITEM;
-typedef enum dictionary_options {
+typedef enum __attribute__((packed)) dictionary_options {
DICT_OPTION_NONE = 0, // the default is the opposite of all below
DICT_OPTION_SINGLE_THREADED = (1 << 0), // don't use any locks (default: use locks)
DICT_OPTION_VALUE_LINK_DONT_CLONE = (1 << 1), // don't copy the value, just point to the one provided (default: copy)
@@ -310,7 +310,6 @@ void dictionary_foreach_unlock(DICTFE *dfe);
size_t dictionary_version(DICTIONARY *dict);
size_t dictionary_entries(DICTIONARY *dict);
size_t dictionary_referenced_items(DICTIONARY *dict);
-long int dictionary_stats_for_registry(DICTIONARY *dict);
// for all cases that the caller does not provide a stats structure, this is where they are accumulated.
extern struct dictionary_stats dictionary_stats_category_other;