summaryrefslogtreecommitdiffstats
path: root/libnetdata/dictionary/dictionary.h
diff options
context:
space:
mode:
Diffstat (limited to 'libnetdata/dictionary/dictionary.h')
-rw-r--r--libnetdata/dictionary/dictionary.h108
1 files changed, 85 insertions, 23 deletions
diff --git a/libnetdata/dictionary/dictionary.h b/libnetdata/dictionary/dictionary.h
index 356bf1895..fdb2088c0 100644
--- a/libnetdata/dictionary/dictionary.h
+++ b/libnetdata/dictionary/dictionary.h
@@ -35,23 +35,34 @@
*
*/
-#ifndef DICTIONARY_INTERNALS
-typedef void DICTIONARY;
-#endif
+typedef struct dictionary DICTIONARY;
+typedef struct dictionary_item DICTIONARY_ITEM;
typedef enum dictionary_flags {
- DICTIONARY_FLAG_NONE = 0, // the default is the opposite of all below
- DICTIONARY_FLAG_SINGLE_THREADED = (1 << 0), // don't use any locks (default: use locks)
- DICTIONARY_FLAG_VALUE_LINK_DONT_CLONE = (1 << 1), // don't copy the value, just point to the one provided (default: copy)
- DICTIONARY_FLAG_NAME_LINK_DONT_CLONE = (1 << 2), // don't copy the name, just point to the one provided (default: copy)
- DICTIONARY_FLAG_WITH_STATISTICS = (1 << 3), // maintain statistics about dictionary operations (default: disabled)
- DICTIONARY_FLAG_DONT_OVERWRITE_VALUE = (1 << 4), // don't overwrite values of dictionary items (default: overwrite)
- DICTIONARY_FLAG_ADD_IN_FRONT = (1 << 5), // add dictionary items at the front of the linked list (default: at the end)
- DICTIONARY_FLAG_RESERVED1 = (1 << 6), // this is reserved for DICTIONARY_FLAG_REFERENCE_COUNTERS
+ DICTIONARY_FLAG_NONE = 0, // the default is the opposite of all below
+ DICTIONARY_FLAG_SINGLE_THREADED = (1 << 0), // don't use any locks (default: use locks)
+ DICTIONARY_FLAG_VALUE_LINK_DONT_CLONE = (1 << 1), // don't copy the value, just point to the one provided (default: copy)
+ DICTIONARY_FLAG_NAME_LINK_DONT_CLONE = (1 << 2), // don't copy the name, just point to the one provided (default: copy)
+ DICTIONARY_FLAG_DONT_OVERWRITE_VALUE = (1 << 3), // don't overwrite values of dictionary items (default: overwrite)
+ DICTIONARY_FLAG_ADD_IN_FRONT = (1 << 4), // add dictionary items at the front of the linked list (default: at the end)
+
+ // to change the value of the following, you also need to change the corresponding #defines in dictionary.c
+ DICTIONARY_FLAG_RESERVED1 = (1 << 29), // reserved for DICTIONARY_FLAG_EXCLUSIVE_ACCESS
+ DICTIONARY_FLAG_RESERVED2 = (1 << 30), // reserved for DICTIONARY_FLAG_DESTROYED
+ DICTIONARY_FLAG_RESERVED3 = (1 << 31), // reserved for DICTIONARY_FLAG_DEFER_ALL_DELETIONS
} DICTIONARY_FLAGS;
// Create a dictionary
-extern DICTIONARY *dictionary_create(DICTIONARY_FLAGS flags);
+#ifdef NETDATA_INTERNAL_CHECKS
+#define dictionary_create(flags) dictionary_create_advanced_with_trace(flags, 0, __FUNCTION__, __LINE__, __FILE__);
+#define dictionary_create_advanced(flags) dictionary_create_advanced_with_trace(flags, 0, __FUNCTION__, __LINE__, __FILE__);
+extern DICTIONARY *dictionary_create_advanced_with_trace(DICTIONARY_FLAGS flags, size_t scratchpad_size, const char *function, size_t line, const char *file);
+#else
+#define dictionary_create(flags) dictionary_create_advanced(flags, 0);
+extern DICTIONARY *dictionary_create_advanced(DICTIONARY_FLAGS flags, size_t scratchpad_size);
+#endif
+
+extern void *dictionary_scratchpad(DICTIONARY *dict);
// an insert callback to be called just after an item is added to the dictionary
// this callback is called while the dictionary is write locked!
@@ -66,6 +77,11 @@ extern void dictionary_register_delete_callback(DICTIONARY *dict, void (*del_cal
// the old_value will remain in the dictionary - the new_value is ignored
extern void dictionary_register_conflict_callback(DICTIONARY *dict, void (*conflict_callback)(const char *name, void *old_value, void *new_value, void *data), void *data);
+// a reaction callback to be called after every item insertion or conflict
+// after the constructors have finished and the items are fully available for use
+// and the dictionary is not write locked anymore
+extern void dictionary_register_react_callback(DICTIONARY *dict, void (*react_callback)(const char *name, void *value, void *data), void *data);
+
// Destroy a dictionary
// returns the number of bytes freed
// the returned value will not include name and value sizes if DICTIONARY_FLAG_WITH_STATISTICS is not set
@@ -85,7 +101,7 @@ extern size_t dictionary_destroy(DICTIONARY *dict);
//
// Passing NULL as value, the dictionary will callocz() the newly allocated value, otherwise it will copy it.
// Passing 0 as value_len, the dictionary will set the value to NULL (no allocations for value will be made).
-extern void *dictionary_set(DICTIONARY *dict, const char *name, void *value, size_t value_len) NEVERNULL;
+extern void *dictionary_set(DICTIONARY *dict, const char *name, void *value, size_t value_len);
// Get an item from the dictionary
// If it returns NULL, the item is not found
@@ -96,6 +112,19 @@ extern void *dictionary_get(DICTIONARY *dict, const char *name);
// returns -1 if the item was not found in the index
extern int dictionary_del(DICTIONARY *dict, const char *name);
+extern DICTIONARY_ITEM *dictionary_get_and_acquire_item_unsafe(DICTIONARY *dict, const char *name);
+extern DICTIONARY_ITEM *dictionary_get_and_acquire_item(DICTIONARY *dict, const char *name);
+
+extern DICTIONARY_ITEM *dictionary_set_and_acquire_item_unsafe(DICTIONARY *dict, const char *name, void *value, size_t value_len);
+extern DICTIONARY_ITEM *dictionary_set_and_acquire_item(DICTIONARY *dict, const char *name, void *value, size_t value_len);
+
+extern void dictionary_acquired_item_release_unsafe(DICTIONARY *dict, DICTIONARY_ITEM *item);
+extern void dictionary_acquired_item_release(DICTIONARY *dict, DICTIONARY_ITEM *item);
+
+extern DICTIONARY_ITEM *dictionary_acquired_item_dup(DICTIONARY_ITEM *item);
+extern const char *dictionary_acquired_item_name(DICTIONARY_ITEM *item);
+extern void *dictionary_acquired_item_value(DICTIONARY_ITEM *item);
+
// UNSAFE functions, without locks
// to be used when the user is traversing with the right lock type
// Read lock is acquired by dictionary_walktrhough_read() and dfe_start_read()
@@ -126,6 +155,10 @@ extern int dictionary_del_unsafe(DICTIONARY *dict, const char *name);
#define dictionary_walkthrough_write(dict, callback, data) dictionary_walkthrough_rw(dict, 'w', callback, data)
extern int dictionary_walkthrough_rw(DICTIONARY *dict, char rw, int (*callback)(const char *name, void *value, void *data), void *data);
+#define dictionary_sorted_walkthrough_read(dict, callback, data) dictionary_sorted_walkthrough_rw(dict, 'r', callback, data)
+#define dictionary_sorted_walkthrough_write(dict, callback, data) dictionary_sorted_walkthrough_rw(dict, 'w', callback, data)
+int dictionary_sorted_walkthrough_rw(DICTIONARY *dict, char rw, int (*callback)(const char *name, void *entry, void *data), void *data);
+
// Traverse with foreach
//
// Use like this:
@@ -146,29 +179,35 @@ extern int dictionary_walkthrough_rw(DICTIONARY *dict, char rw, int (*callback)(
#define DICTFE_CONST const
#endif
+#define DICTIONARY_LOCK_READ 'r'
+#define DICTIONARY_LOCK_WRITE 'w'
+#define DICTIONARY_LOCK_NONE 'u'
+
typedef DICTFE_CONST struct dictionary_foreach {
DICTFE_CONST char *name; // the dictionary name of the last item used
void *value; // the dictionary value of the last item used
// same as the return value of dictfe_start() and dictfe_next()
// the following are for internal use only - to keep track of the point we are
+ char rw; // the lock mode 'r' or 'w'
usec_t started_ut; // the time the caller started iterating (now_realtime_usec())
DICTIONARY *dict; // the dictionary upon we work
- void *last_position_index; // the internal position index, to remember the position we are at
- void *next_position_index; // the internal position index, of the next item
+ void *last_item; // the item we work on, to remember the position we are at
} DICTFE;
-#define dfe_start_read(dict, value) dfe_start_rw(dict, value, 'r')
-#define dfe_start_write(dict, value) dfe_start_rw(dict, value, 'w')
+#define dfe_start_read(dict, value) dfe_start_rw(dict, value, DICTIONARY_LOCK_READ)
+#define dfe_start_write(dict, value) dfe_start_rw(dict, value, DICTIONARY_LOCK_WRITE)
#define dfe_start_rw(dict, value, mode) \
do { \
DICTFE value ## _dfe = {}; \
- const char *value ## _name; (void)(value ## _name); \
+ const char *value ## _name; (void)(value ## _name); (void)value; \
for((value) = dictionary_foreach_start_rw(&value ## _dfe, (dict), (mode)), ( value ## _name ) = value ## _dfe.name; \
- (value) ;\
- (value) = dictionary_foreach_next(&value ## _dfe), ( value ## _name ) = value ## _dfe.name)
+ (value ## _dfe.name) ;\
+ (value) = dictionary_foreach_next(&value ## _dfe), ( value ## _name ) = value ## _dfe.name) \
+ {
#define dfe_done(value) \
+ } \
dictionary_foreach_done(&value ## _dfe); \
} while(0)
@@ -177,14 +216,37 @@ extern void * dictionary_foreach_next(DICTFE *dfe);
extern usec_t dictionary_foreach_done(DICTFE *dfe);
// Get statistics about the dictionary
-// If DICTIONARY_FLAG_WITH_STATISTICS is not set, these return zero
-extern size_t dictionary_stats_allocated_memory(DICTIONARY *dict);
-extern size_t dictionary_stats_entries(DICTIONARY *dict);
+extern long int dictionary_stats_allocated_memory(DICTIONARY *dict);
+extern long int dictionary_stats_entries(DICTIONARY *dict);
+extern size_t dictionary_stats_version(DICTIONARY *dict);
extern size_t dictionary_stats_inserts(DICTIONARY *dict);
extern size_t dictionary_stats_searches(DICTIONARY *dict);
extern size_t dictionary_stats_deletes(DICTIONARY *dict);
extern size_t dictionary_stats_resets(DICTIONARY *dict);
+extern size_t dictionary_stats_walkthroughs(DICTIONARY *dict);
+extern size_t dictionary_stats_referenced_items(DICTIONARY *dict);
extern int dictionary_unittest(size_t entries);
+// ----------------------------------------------------------------------------
+// STRING implementation
+
+typedef struct netdata_string STRING;
+extern STRING *string_strdupz(const char *str);
+extern STRING *string_dup(STRING *string);
+extern void string_freez(STRING *string);
+extern size_t string_length(STRING *string);
+extern const char *string2str(STRING *string) NEVERNULL;
+
+// keep common prefix/suffix and replace everything else with [x]
+extern STRING *string_2way_merge(STRING *a, STRING *b);
+
+static inline int string_cmp(STRING *s1, STRING *s2) {
+ // STRINGs are deduplicated, so the same strings have the same pointer
+ if(unlikely(s1 == s2)) return 0;
+
+ // they differ, do the typical comparison
+ return strcmp(string2str(s1), string2str(s2));
+}
+
#endif /* NETDATA_DICTIONARY_H */