From a7e6c06ef7fb197f0ec928159720f0abbd655f4d Mon Sep 17 00:00:00 2001 From: Evan Hunt Date: Sat, 4 May 2024 01:35:30 -0700 Subject: [PATCH] in findnode, use a read transaction when possible when findnode() is called with the 'create' flag set, instead of automatically opening a write transaction, we will now try to look up the name with a read transaction, and only open a write transaction if that failed. --- lib/dns/qpcache.c | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/lib/dns/qpcache.c b/lib/dns/qpcache.c index c01b668188..6f7ba766d6 100644 --- a/lib/dns/qpcache.c +++ b/lib/dns/qpcache.c @@ -2601,13 +2601,9 @@ findnode(dns_db_t *db, const dns_name_t *name, bool create, isc_result_t result; dbmod_t modctx; - modctx = (dbmod_t){ .writing = create }; - if (create) { - dns_qpmulti_write(qpdb->tree, &modctx.tree); - } else { - dns_qpmulti_query(qpdb->tree, &modctx.qpr); - modctx.tree = (dns_qp_t *)&modctx.qpr; - } + modctx = (dbmod_t){ .writing = false }; + dns_qpmulti_query(qpdb->tree, &modctx.qpr); + modctx.tree = (dns_qp_t *)&modctx.qpr; result = dns_qp_getname(modctx.tree, name, (void **)&node, NULL); if (result != ISC_R_SUCCESS) { @@ -2615,11 +2611,26 @@ findnode(dns_db_t *db, const dns_name_t *name, bool create, goto cleanup; } + /* Switch to a write transaction */ + modctx.writing = true; + modctx.tree = NULL; + dns_qpread_destroy(qpdb->tree, &modctx.qpr); + dns_qpmulti_write(qpdb->tree, &modctx.tree); + + /* Insert a new node, if we still need to */ node = new_qpcnode(qpdb, name); result = dns_qp_insert(modctx.tree, node, 0); - INSIST(result == ISC_R_SUCCESS); - qpcnode_unref(node); - modctx.compact = true; + if (result == ISC_R_SUCCESS) { + /* Insertion succeeded; compact the DB. */ + qpcnode_unref(node); + modctx.compact = true; + } else { + /* Some other thread added the node already */ + qpcnode_detach(&node); + result = dns_qp_getname(modctx.tree, name, + (void **)&node, NULL); + INSIST(result == ISC_R_SUCCESS); + } } reactivate_node(qpdb, node, &modctx DNS__DB_FLARG_PASS); @@ -2627,7 +2638,7 @@ findnode(dns_db_t *db, const dns_name_t *name, bool create, *nodep = (dns_dbnode_t *)node; cleanup: - if (create) { + if (modctx.writing) { if (modctx.compact) { dns_qp_compact(modctx.tree, DNS_QPGC_MAYBE); }