@cryptotaxi247 / netdata-1 / commits / 446ac867e

add the ability to merge dictionary items (#13054)

* add the ability to merge old value and new value * docs * merge to conflict

Costa Tsaousis committed Jun 2, 2022 at 16:10 UTC 446ac867e414da2c920e8ea7dbc9f7c9a7faebd1
3 files changed +28 -4
libnetdata/dictionary/README.md
+4 -3
@@ -31,10 +31,11 @@ Dictionaries come with 2 memory management options:
31 - **Clone** (copy) the name and/or the value to memory allocated by the dictionary.
32 - **Link** the name and/or the value, without allocating any memory about them.
33
34 -In **clone** mode, the dictionary guarantees that all operations on the dictionary items will automatically take care of the memory used by the name and/or the value. In case the value is an object needs to have user allocated memory, two callback functions can be registered:
34 +In **clone** mode, the dictionary guarantees that all operations on the dictionary items will automatically take care of the memory used by the name and/or the value. In case the value is an object needs to have user allocated memory, the following callback functions can be registered:
35
36 - 1.`dictionary_register_insert_callback()` that will be called just after the insertion of an item to the dictionary (but while the dictionary is write-locked - if locking is enabled).
37 - 2. `dictionary_register_delete_callback()` that will be called just prior to the deletion of an item from the dictionary (but while the dictionary is write-locked - if locking is enabled).
36 + 1.`dictionary_register_insert_callback()` that will be called just after the insertion of an item to the dictionary, or after the replacement of the value of a dictionary item (but while the dictionary is write-locked - if locking is enabled).
37 + 2. `dictionary_register_delete_callback()` that will be called just prior to the deletion of an item from the dictionary, or prior to the replacement of the value of a dictionary item (but while the dictionary is write-locked - if locking is enabled).
38 + 3. `dictionary_register_conflict_callback()` that will be called when `DICTIONARY_FLAG_DONT_OVERWRITE_VALUE` is set and another value is attempted to be inserted for the same key.
39
40 In **link** mode, the name and/or the value are just linked to the dictionary item, and it is the user's responsibility to free the memory used after an item is deleted from the dictionary.
41
libnetdata/dictionary/dictionary.c
+19 -1
@@ -134,6 +134,9 @@ struct dictionary {
134 void (*del_callback)(const char *name, void *value, void *data);
135 void *del_callback_data;
136
137 + void (*conflict_callback)(const char *name, void *old_value, void *new_value, void *data);
138 + void *conflict_callback_data;
139 +
140 struct dictionary_stats *stats; // the statistics when DICTIONARY_FLAG_WITH_STATISTICS is set
141 };
142
@@ -147,6 +150,11 @@ void dictionary_register_delete_callback(DICTIONARY *dict, void (*del_callback)(
150 dict->del_callback_data = data;
151 }
152
153 +void dictionary_register_conflict_callback(DICTIONARY *dict, void (*conflict_callback)(const char *name, void *old_value, void *new_value, void *data), void *data) {
154 + dict->conflict_callback = conflict_callback;
155 + dict->conflict_callback_data = data;
156 +}
157 +
158 // ----------------------------------------------------------------------------
159 // dictionary statistics maintenance
160
@@ -724,8 +732,18 @@ void *dictionary_set_unsafe(DICTIONARY *dict, const char *name, void *value, siz
732 // or overwrite the value, depending on dictionary flags
733
734 nv = *pnv;
727 - if(!(dict->flags & DICTIONARY_FLAG_DONT_OVERWRITE_VALUE))
735 + if(!(dict->flags & DICTIONARY_FLAG_DONT_OVERWRITE_VALUE)) {
736 +
737 + if(dict->del_callback)
738 + dict->del_callback(nv->name, nv->value, dict->del_callback_data);
739 +
740 namevalue_reset_unsafe(dict, nv, value, value_len);
741 +
742 + if(dict->ins_callback)
743 + dict->ins_callback(nv->name, nv->value, dict->ins_callback_data);
744 + }
745 + else if(dict->conflict_callback)
746 + dict->conflict_callback(nv->name, nv->value, value, dict->conflict_callback_data);
747 }
748
749 return nv->value;
libnetdata/dictionary/dictionary.h
+5
@@ -61,6 +61,11 @@ extern void dictionary_register_insert_callback(DICTIONARY *dict, void (*ins_cal
61 // this callback is called while the dictionary is write locked!
62 extern void dictionary_register_delete_callback(DICTIONARY *dict, void (*del_callback)(const char *name, void *value, void *data), void *data);
63
64 +// a merge callback to be called when DICTIONARY_FLAG_DONT_OVERWRITE_VALUE
65 +// and an item is already found in the dictionary - the dictionary does nothing else in this case
66 +// the old_value will remain in the dictionary - the new_value is ignored
67 +extern void dictionary_register_conflict_callback(DICTIONARY *dict, void (*conflict_callback)(const char *name, void *old_value, void *new_value, void *data), void *data);
68 +
69 // Destroy a dictionary
70 // returns the number of bytes freed
71 // the returned value will not include name and value sizes if DICTIONARY_FLAG_WITH_STATISTICS is not set