modifying the cache head/tail pointers. Therefore, the process of
flushing old files may perturb the cache_queue_head pointer. This caused
some nodes with CI_FLAGS_IN_QUEUE to be un-linked from the queue list.
Thereafter, they would not be flushed by any periodic process (although
they could be revived with FLUSH or UPDATE). This caused a slow memory
leak for files that are no longer updated. Pending updates for these
"abandoned" files would remain in memory ad infinitum.
With this patch, remove_from_queue() will check that the item is queued
before modifying the head/tail pointers. This restores the intended
behavior.
--kevin
git-svn-id: svn://svn.oetiker.ch/rrdtool/trunk/program@1626
a5681a0c-68f1-0310-ab6d-
d61299d08faa
static void remove_from_queue(cache_item_t *ci) /* {{{ */
{
if (ci == NULL) return;
static void remove_from_queue(cache_item_t *ci) /* {{{ */
{
if (ci == NULL) return;
+ if ((ci->flags & CI_FLAGS_IN_QUEUE) == 0) return; /* not queued */
if (ci->prev == NULL)
cache_queue_head = ci->next; /* reset head */
if (ci->prev == NULL)
cache_queue_head = ci->next; /* reset head */
if (cache_queue_head == ci)
return 0;
if (cache_queue_head == ci)
return 0;
- /* remove from the double linked list */
- if (ci->flags & CI_FLAGS_IN_QUEUE)
- remove_from_queue(ci);
+ /* remove if further down in queue */
+ remove_from_queue(ci);
ci->prev = NULL;
ci->next = cache_queue_head;
ci->prev = NULL;
ci->next = cache_queue_head;
ci = (cache_item_t *) value;
cfd = (callback_flush_data_t *) data;
ci = (cache_item_t *) value;
cfd = (callback_flush_data_t *) data;
+ if (ci->flags & CI_FLAGS_IN_QUEUE)
+ return FALSE;
+
if ((ci->last_flush_time <= cfd->abs_timeout)
if ((ci->last_flush_time <= cfd->abs_timeout)
- && ((ci->flags & CI_FLAGS_IN_QUEUE) == 0)
&& (ci->values_num > 0))
{
enqueue_cache_item (ci, TAIL);
}
else if ((do_shutdown != 0)
&& (ci->values_num > 0))
{
enqueue_cache_item (ci, TAIL);
}
else if ((do_shutdown != 0)
- && ((ci->flags & CI_FLAGS_IN_QUEUE) == 0)
&& (ci->values_num > 0))
{
enqueue_cache_item (ci, TAIL);
}
else if (((cfd->now - ci->last_flush_time) >= config_flush_interval)
&& (ci->values_num > 0))
{
enqueue_cache_item (ci, TAIL);
}
else if (((cfd->now - ci->last_flush_time) >= config_flush_interval)
- && ((ci->flags & CI_FLAGS_IN_QUEUE) == 0)
&& (ci->values_num <= 0))
{
char **temp;
&& (ci->values_num <= 0))
{
char **temp;