resolved: replace transaction list by hashmap
Right now we keep track of ongoing transactions in a linked listed for each scope. Replace this by a hashmap that is indexed by the RR key. Given that all ongoing transactions will be placed in pretty much the same scopes usually this should optimize behaviour. We used to require a list here, since we wanted to do "superset" query checks, but this became obsolete since transactions are now single-key instead of multi-key.
This commit is contained in:
parent
53496ca9ad
commit
da0c630e14
|
@ -78,8 +78,7 @@ DnsScope* dns_scope_free(DnsScope *s) {
|
||||||
|
|
||||||
dns_scope_llmnr_membership(s, false);
|
dns_scope_llmnr_membership(s, false);
|
||||||
|
|
||||||
while ((t = s->transactions)) {
|
while ((t = hashmap_steal_first(s->transactions))) {
|
||||||
|
|
||||||
/* Abort the transaction, but make sure it is not
|
/* Abort the transaction, but make sure it is not
|
||||||
* freed while we still look at it */
|
* freed while we still look at it */
|
||||||
|
|
||||||
|
@ -90,6 +89,8 @@ DnsScope* dns_scope_free(DnsScope *s) {
|
||||||
dns_transaction_free(t);
|
dns_transaction_free(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hashmap_free(s->transactions);
|
||||||
|
|
||||||
while ((rr = ordered_hashmap_steal_first(s->conflict_queue)))
|
while ((rr = ordered_hashmap_steal_first(s->conflict_queue)))
|
||||||
dns_resource_record_unref(rr);
|
dns_resource_record_unref(rr);
|
||||||
|
|
||||||
|
@ -623,24 +624,20 @@ DnsTransaction *dns_scope_find_transaction(DnsScope *scope, DnsResourceKey *key,
|
||||||
assert(scope);
|
assert(scope);
|
||||||
assert(key);
|
assert(key);
|
||||||
|
|
||||||
/* Try to find an ongoing transaction that is a equal or a
|
/* Try to find an ongoing transaction that is a equal to the
|
||||||
* superset of the specified question */
|
* specified question */
|
||||||
|
t = hashmap_get(scope->transactions, key);
|
||||||
|
if (!t)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
LIST_FOREACH(transactions_by_scope, t, scope->transactions) {
|
/* Refuse reusing transactions that completed based on cached
|
||||||
|
* data instead of a real packet, if that's requested. */
|
||||||
/* Refuse reusing transactions that completed based on
|
|
||||||
* cached data instead of a real packet, if that's
|
|
||||||
* requested. */
|
|
||||||
if (!cache_ok &&
|
if (!cache_ok &&
|
||||||
IN_SET(t->state, DNS_TRANSACTION_SUCCESS, DNS_TRANSACTION_FAILURE) &&
|
IN_SET(t->state, DNS_TRANSACTION_SUCCESS, DNS_TRANSACTION_FAILURE) &&
|
||||||
!t->received)
|
!t->received)
|
||||||
continue;
|
|
||||||
|
|
||||||
if (dns_resource_key_equal(t->key, key) > 0)
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dns_scope_make_conflict_packet(
|
static int dns_scope_make_conflict_packet(
|
||||||
|
|
|
@ -60,7 +60,7 @@ struct DnsScope {
|
||||||
usec_t resend_timeout;
|
usec_t resend_timeout;
|
||||||
usec_t max_rtt;
|
usec_t max_rtt;
|
||||||
|
|
||||||
LIST_HEAD(DnsTransaction, transactions);
|
Hashmap *transactions;
|
||||||
|
|
||||||
LIST_FIELDS(DnsScope, scopes);
|
LIST_FIELDS(DnsScope, scopes);
|
||||||
};
|
};
|
||||||
|
|
|
@ -35,7 +35,6 @@ DnsTransaction* dns_transaction_free(DnsTransaction *t) {
|
||||||
|
|
||||||
sd_event_source_unref(t->timeout_event_source);
|
sd_event_source_unref(t->timeout_event_source);
|
||||||
|
|
||||||
dns_resource_key_unref(t->key);
|
|
||||||
dns_packet_unref(t->sent);
|
dns_packet_unref(t->sent);
|
||||||
dns_packet_unref(t->received);
|
dns_packet_unref(t->received);
|
||||||
dns_answer_unref(t->cached);
|
dns_answer_unref(t->cached);
|
||||||
|
@ -47,12 +46,14 @@ DnsTransaction* dns_transaction_free(DnsTransaction *t) {
|
||||||
dns_stream_free(t->stream);
|
dns_stream_free(t->stream);
|
||||||
|
|
||||||
if (t->scope) {
|
if (t->scope) {
|
||||||
LIST_REMOVE(transactions_by_scope, t->scope->transactions, t);
|
hashmap_remove(t->scope->transactions, t->key);
|
||||||
|
|
||||||
if (t->id != 0)
|
if (t->id != 0)
|
||||||
hashmap_remove(t->scope->manager->dns_transactions, UINT_TO_PTR(t->id));
|
hashmap_remove(t->scope->manager->dns_transactions, UINT_TO_PTR(t->id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dns_resource_key_unref(t->key);
|
||||||
|
|
||||||
while ((q = set_steal_first(t->queries)))
|
while ((q = set_steal_first(t->queries)))
|
||||||
set_remove(q->transactions, t);
|
set_remove(q->transactions, t);
|
||||||
set_free(t->queries);
|
set_free(t->queries);
|
||||||
|
@ -89,14 +90,18 @@ int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsResourceKey *key)
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
r = hashmap_ensure_allocated(&s->transactions, &dns_resource_key_hash_ops);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
t = new0(DnsTransaction, 1);
|
t = new0(DnsTransaction, 1);
|
||||||
if (!t)
|
if (!t)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
t->dns_fd = -1;
|
t->dns_fd = -1;
|
||||||
|
|
||||||
t->key = dns_resource_key_ref(key);
|
t->key = dns_resource_key_ref(key);
|
||||||
|
|
||||||
|
/* Find a fresh, unused transaction id */
|
||||||
do
|
do
|
||||||
random_bytes(&t->id, sizeof(t->id));
|
random_bytes(&t->id, sizeof(t->id));
|
||||||
while (t->id == 0 ||
|
while (t->id == 0 ||
|
||||||
|
@ -108,7 +113,12 @@ int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsResourceKey *key)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
LIST_PREPEND(transactions_by_scope, s->transactions, t);
|
r = hashmap_put(s->transactions, t->key, t);
|
||||||
|
if (r < 0) {
|
||||||
|
hashmap_remove(s->manager->dns_transactions, UINT_TO_PTR(t->id));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
t->scope = s;
|
t->scope = s;
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
|
|
Loading…
Reference in a new issue