X-Git-Url: https://arthur.barton.de/gitweb/?a=blobdiff_plain;f=src%2Fadaptive_resortable_list.c;h=f74c53eae5e192845ae57ed7975eb3ee9d8d5034;hb=9dccc16d3763392f0b13349de18c3a838a667653;hp=a37c396fa89ea63e1446fbe80af5b153451558d3;hpb=b7bdfd8535b029f8aabc101575c00bb5885aa99b;p=netdata.git diff --git a/src/adaptive_resortable_list.c b/src/adaptive_resortable_list.c index a37c396f..f74c53ea 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;