1 #include "adaptive_resortable_list.h"
3 // the default processor() of the ARL
4 // can be overwritten at arl_create()
5 static inline void arl_callback_str2ull(const char *name, uint32_t hash, const char *value, void *dst) {
9 register unsigned long long *d = dst;
11 // fprintf(stderr, "name '%s' with hash %u and value '%s' is %llu\n", name, hash, value, *d);
15 ARL_BASE *arl_create(void (*processor)(const char *, uint32_t, const char *, void *), size_t rechecks) {
16 ARL_BASE *base = callocz(1, sizeof(ARL_BASE));
19 base->processor = arl_callback_str2ull;
21 base->processor = processor;
23 base->rechecks = rechecks;
28 void arl_free(ARL_BASE *arl_base) {
29 if(unlikely(!arl_base))
32 while(arl_base->head) {
33 ARL_ENTRY *e = arl_base->head;
34 arl_base->head = e->next;
37 #ifdef NETDATA_INTERNAL_CHECKS
38 memset(e, 0, sizeof(ARL_ENTRY));
43 #ifdef NETDATA_INTERNAL_CHECKS
44 memset(arl_base, 0, sizeof(ARL_BASE));
50 void arl_begin(ARL_BASE *base) {
54 info("iteration %zu, expected %zu, wanted %zu, allocated %zu, relinkings %zu, found %zu, added %zu"
63 for(e = base->head; e ; e = e->next) fprintf(stderr, "%s ", e->name);
64 fprintf(stderr, "\n");
67 if(unlikely(base->added || base->iteration % base->rechecks) == 1) {
70 for(e = base->head; e ; e = e->next)
71 if(e->flags & ARL_ENTRY_FLAG_FOUND && e->flags & ARL_ENTRY_FLAG_EXPECTED)
76 base->next_keyword = base->head;
80 // register an expected keyword to the ARL
81 // together with its destination ( i.e. the output of the processor() )
82 ARL_ENTRY *arl_expect(ARL_BASE *base, const char *keyword, void *dst) {
83 ARL_ENTRY *e = callocz(1, sizeof(ARL_ENTRY));
84 e->name = strdupz(keyword);
85 e->hash = simple_hash(e->name);
87 e->flags = ARL_ENTRY_FLAG_EXPECTED;
91 if(base->head) base->head->prev = e;
92 else base->next_keyword = e;
98 base->wanted = base->expected;
103 int arl_find_or_create_and_relink(ARL_BASE *base, const char *s, uint32_t hash, const char *value) {
106 // find if it already exists in the data
107 for(e = base->head; e ; e = e->next)
108 if(e->hash == hash && !strcmp(e->name, s))
111 #ifdef NETDATA_INTERNAL_CHECKS
112 if(unlikely(e == base->next_keyword))
113 fatal("Internal Error: e == base->last");
117 // found it in the keywords
120 // run the processor for it
121 if(unlikely(e->dst)) {
122 base->processor(e->name, hash, value, e->dst);
126 // unlink it - we will relink it below
127 if(e->next) e->next->prev = e->prev;
128 if(e->prev) e->prev->next = e->next;
130 // make sure the head is properly linked
132 base->head = e->next;
138 e = callocz(1, sizeof(ARL_ENTRY));
139 e->name = strdupz(s);
141 e->flags = ARL_ENTRY_FLAG_DYNAMIC;
147 e->flags |= ARL_ENTRY_FLAG_FOUND;
150 e->next = base->next_keyword;
151 if(base->next_keyword) {
152 e->prev = base->next_keyword->prev;
153 base->next_keyword->prev = e;
155 if(base->head == base->next_keyword)
164 base->next_keyword = e->next;
165 if(unlikely(!base->next_keyword))
166 base->next_keyword = base->head;
168 if(unlikely(base->found == base->wanted))