QueryCache: Fix flushing on server list changes

The query cache wasn't properly flushing on server list changes
and was attempting to flush even when the server list didn't
actually change.

Fix By: Brad House (@bradh352)
v1.28
Brad House 6 months ago
parent 0f0674c42e
commit 0b25c7475c
  1. 8
      src/lib/ares_qcache.c
  2. 20
      src/lib/ares_update_servers.c

@ -147,7 +147,9 @@ static void ares__qcache_expire(ares__qcache_t *cache,
while ((node = ares__slist_node_first(cache->expire)) != NULL) { while ((node = ares__slist_node_first(cache->expire)) != NULL) {
const ares__qcache_entry_t *entry = ares__slist_node_val(node); const ares__qcache_entry_t *entry = ares__slist_node_val(node);
if (entry->expire_ts > now->tv_sec) {
/* If now is NULL, we're flushing everything, so don't break */
if (now != NULL && entry->expire_ts > now->tv_sec) {
break; break;
} }
@ -158,9 +160,7 @@ static void ares__qcache_expire(ares__qcache_t *cache,
void ares__qcache_flush(ares__qcache_t *cache) void ares__qcache_flush(ares__qcache_t *cache)
{ {
struct timeval now; ares__qcache_expire(cache, NULL /* flush all */);
memset(&now, 0, sizeof(now));
ares__qcache_expire(cache, &now);
} }
void ares__qcache_destroy(ares__qcache_t *cache) void ares__qcache_destroy(ares__qcache_t *cache)

@ -663,9 +663,10 @@ static ares_bool_t ares__server_in_newconfig(const struct server_state *server,
return ARES_FALSE; return ARES_FALSE;
} }
static void ares__servers_remove_stale(ares_channel_t *channel, static ares_bool_t ares__servers_remove_stale(ares_channel_t *channel,
ares__llist_t *srvlist) ares__llist_t *srvlist)
{ {
ares_bool_t stale_removed = ARES_FALSE;
ares__slist_node_t *snode = ares__slist_node_first(channel->servers); ares__slist_node_t *snode = ares__slist_node_first(channel->servers);
while (snode != NULL) { while (snode != NULL) {
@ -675,9 +676,11 @@ static void ares__servers_remove_stale(ares_channel_t *channel,
/* This will clean up all server state via the destruction callback and /* This will clean up all server state via the destruction callback and
* move any queries to new servers */ * move any queries to new servers */
ares__slist_node_destroy(snode); ares__slist_node_destroy(snode);
stale_removed = ARES_TRUE;
} }
snode = snext; snode = snext;
} }
return stale_removed;
} }
static void ares__servers_trim_single(ares_channel_t *channel) static void ares__servers_trim_single(ares_channel_t *channel)
@ -694,6 +697,7 @@ ares_status_t ares__servers_update(ares_channel_t *channel,
ares__llist_node_t *node; ares__llist_node_t *node;
size_t idx = 0; size_t idx = 0;
ares_status_t status; ares_status_t status;
ares_bool_t list_changed = ARES_FALSE;
if (channel == NULL) { if (channel == NULL) {
return ARES_EFORMERR; return ARES_EFORMERR;
@ -739,13 +743,17 @@ ares_status_t ares__servers_update(ares_channel_t *channel,
if (status != ARES_SUCCESS) { if (status != ARES_SUCCESS) {
goto done; goto done;
} }
list_changed = ARES_TRUE;
} }
idx++; idx++;
} }
/* Remove any servers that don't exist in the current configuration */ /* Remove any servers that don't exist in the current configuration */
ares__servers_remove_stale(channel, server_list); if (ares__servers_remove_stale(channel, server_list)) {
list_changed = ARES_TRUE;
}
/* Trim to one server if ARES_FLAG_PRIMARY is set. */ /* Trim to one server if ARES_FLAG_PRIMARY is set. */
if (channel->flags & ARES_FLAG_PRIMARY) { if (channel->flags & ARES_FLAG_PRIMARY) {
@ -757,8 +765,10 @@ ares_status_t ares__servers_update(ares_channel_t *channel,
channel->optmask |= ARES_OPT_SERVERS; channel->optmask |= ARES_OPT_SERVERS;
} }
/* Clear any cached query results */ /* Clear any cached query results only if the server list changed */
ares__qcache_flush(channel->qcache); if (list_changed) {
ares__qcache_flush(channel->qcache);
}
status = ARES_SUCCESS; status = ARES_SUCCESS;

Loading…
Cancel
Save