summaryrefslogtreecommitdiffstats
path: root/src/adaptive_resortable_list.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/adaptive_resortable_list.c')
-rw-r--r--src/adaptive_resortable_list.c40
1 files changed, 35 insertions, 5 deletions
diff --git a/src/adaptive_resortable_list.c b/src/adaptive_resortable_list.c
index a37c396fa..f74c53eae 100644
--- a/src/adaptive_resortable_list.c
+++ b/src/adaptive_resortable_list.c
@@ -52,7 +52,6 @@ void arl_free(ARL_BASE *arl_base) {
}
void arl_begin(ARL_BASE *base) {
- ARL_ENTRY *e;
#ifdef NETDATA_INTERNAL_CHECKS
if(likely(base->iteration > 10)) {
@@ -66,6 +65,7 @@ void arl_begin(ARL_BASE *base) {
info("ARL '%s' has %zu fast searches and %zu slow searches. Is the source really changing so fast?"
, base->name, base->fast, base->slow);
+ /*
if(unlikely(base->iteration % 60 == 0)) {
info("ARL '%s' statistics: iteration %zu, expected %zu, wanted %zu, allocated %zu, fred %zu, relinkings %zu, found %zu, added %zu, fast %zu, slow %zu"
, base->name
@@ -83,13 +83,15 @@ void arl_begin(ARL_BASE *base) {
// for(e = base->head; e; e = e->next) fprintf(stderr, "%s ", e->name);
// fprintf(stderr, "\n");
}
+ */
}
#endif
if(unlikely(base->added || base->iteration % base->rechecks) == 1) {
base->added = 0;
base->wanted = 0;
- for(e = base->head; e ; e = e->next) {
+ ARL_ENTRY *e = base->head;
+ while(e) {
if(e->flags & ARL_ENTRY_FLAG_FOUND) {
// remove the found flag
@@ -98,25 +100,48 @@ void arl_begin(ARL_BASE *base) {
// count it in wanted
if(e->flags & ARL_ENTRY_FLAG_EXPECTED)
base->wanted++;
+
}
- else if(e->flags & ARL_ENTRY_FLAG_DYNAMIC) {
+ else if(e->flags & ARL_ENTRY_FLAG_DYNAMIC && !(base->head == e && !e->next)) { // not last entry
// we can remove this entry
// it is not found, and it was created because
// it was found in the source file
+
+ // remember the next one
+ ARL_ENTRY *t = e->next;
+
+ // remove it from the list
if(e->next) e->next->prev = e->prev;
if(e->prev) e->prev->next = e->next;
if(base->head == e) base->head = e->next;
+
+ // free it
freez(e->name);
freez(e);
+ // count it
base->fred++;
+
+ // continue
+ e = t;
+ continue;
}
+
+ e = e->next;
}
}
+ if(unlikely(!base->head)) {
+ // hm... no nodes at all in the list #1700
+ // add a fake one to prevent a crash
+ // this is better than checking for the existence of nodes all the time
+ arl_expect(base, "a-really-not-existing-source-keyword", NULL);
+ }
+
base->iteration++;
base->next_keyword = base->head;
base->found = 0;
+
}
// register an expected keyword to the ARL
@@ -153,7 +178,7 @@ int arl_find_or_create_and_relink(ARL_BASE *base, const char *s, const char *val
break;
#ifdef NETDATA_INTERNAL_CHECKS
- if(unlikely(e == base->next_keyword))
+ if(unlikely(base->next_keyword && e == base->next_keyword))
fatal("Internal Error: e == base->last");
#endif
@@ -208,9 +233,14 @@ int arl_find_or_create_and_relink(ARL_BASE *base, const char *s, const char *val
if(base->head == base->next_keyword)
base->head = e;
}
- else
+ else {
e->prev = NULL;
+ if(!base->head)
+ base->head = e;
+ }
+
+ // prepare the next iteration
base->next_keyword = e->next;
if(unlikely(!base->next_keyword))
base->next_keyword = base->head;