mirror of
https://github.com/systemd/systemd.git
synced 2025-02-03 17:47:28 +03:00
resolved: wait to gc transactions if they might still give an answer
In some cases when a query completes there are still pending transactions that are no longer useful to answer the query. But if this query is repeated in the future and we don't have the answers cached, we're going to ask and ignore the answer again. Instead of purging these superfluous transactions, let's wait and see if they produce an answer, since we already asked the question, and use it to fill our cache.
This commit is contained in:
parent
48570c9273
commit
ce88017255
@ -57,6 +57,21 @@ static void dns_query_candidate_stop(DnsQueryCandidate *c) {
|
||||
}
|
||||
}
|
||||
|
||||
static void dns_query_candidate_abandon(DnsQueryCandidate *c) {
|
||||
DnsTransaction *t;
|
||||
|
||||
assert(c);
|
||||
|
||||
/* Abandon all the DnsTransactions attached to this query */
|
||||
|
||||
while ((t = set_steal_first(c->transactions))) {
|
||||
t->wait_for_answer = true;
|
||||
set_remove(t->notify_query_candidates, c);
|
||||
set_remove(t->notify_query_candidates_done, c);
|
||||
dns_transaction_gc(t);
|
||||
}
|
||||
}
|
||||
|
||||
static DnsQueryCandidate* dns_query_candidate_unlink(DnsQueryCandidate *c) {
|
||||
assert(c);
|
||||
|
||||
@ -354,6 +369,16 @@ static void dns_query_stop(DnsQuery *q) {
|
||||
dns_query_candidate_stop(c);
|
||||
}
|
||||
|
||||
static void dns_query_abandon(DnsQuery *q) {
|
||||
assert(q);
|
||||
|
||||
/* Thankfully transactions have their own timeouts */
|
||||
event_source_disable(q->timeout_event_source);
|
||||
|
||||
LIST_FOREACH(candidates_by_query, c, q->candidates)
|
||||
dns_query_candidate_abandon(c);
|
||||
}
|
||||
|
||||
static void dns_query_unlink_candidates(DnsQuery *q) {
|
||||
assert(q);
|
||||
|
||||
@ -591,7 +616,7 @@ void dns_query_complete(DnsQuery *q, DnsTransactionState state) {
|
||||
|
||||
(void) manager_monitor_send(q->manager, q);
|
||||
|
||||
dns_query_stop(q);
|
||||
dns_query_abandon(q);
|
||||
if (q->complete)
|
||||
q->complete(q);
|
||||
}
|
||||
|
@ -181,6 +181,9 @@ DnsTransaction* dns_transaction_gc(DnsTransaction *t) {
|
||||
if (t->block_gc > 0)
|
||||
return t;
|
||||
|
||||
if (t->wait_for_answer && IN_SET(t->state, DNS_TRANSACTION_PENDING, DNS_TRANSACTION_VALIDATING))
|
||||
return t;
|
||||
|
||||
if (set_isempty(t->notify_query_candidates) &&
|
||||
set_isempty(t->notify_query_candidates_done) &&
|
||||
set_isempty(t->notify_zone_items) &&
|
||||
|
@ -136,6 +136,11 @@ struct DnsTransaction {
|
||||
|
||||
unsigned block_gc;
|
||||
|
||||
/* Set when we're willing to let this transaction live beyond it's usefulness for the original query,
|
||||
* for caching purposes. This blocks gc while there is still a chance we might still receive an
|
||||
* answer. */
|
||||
bool wait_for_answer;
|
||||
|
||||
LIST_FIELDS(DnsTransaction, transactions_by_scope);
|
||||
LIST_FIELDS(DnsTransaction, transactions_by_stream);
|
||||
LIST_FIELDS(DnsTransaction, transactions_by_key);
|
||||
|
Loading…
x
Reference in New Issue
Block a user