From 3f3b38f70ac29923f4368a9deb6ef204e29f9aed Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Vavru=C5=A1a?= Date: Thu, 28 May 2015 01:23:47 +0200 Subject: [PATCH] lib/resolve: deferred zone cut lookup MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit if the query is satisfied from cache, it doesn’t need a zone cut lookup, so it may be deferred until an outbound query is about the be issued. --- lib/resolve.c | 24 ++++++++++++++++-------- lib/rplan.c | 2 +- lib/rplan.h | 5 +++-- lib/zonecut.c | 10 +++++----- lib/zonecut.h | 3 ++- tests/test_zonecut.c | 2 +- 6 files changed, 28 insertions(+), 18 deletions(-) diff --git a/lib/resolve.c b/lib/resolve.c index ec50f7c12..7b25e846e 100644 --- a/lib/resolve.c +++ b/lib/resolve.c @@ -289,14 +289,8 @@ int kr_resolve_query(struct kr_request *request, const knot_dname_t *qname, uint return KNOT_STATE_FAIL; } - /* Find closest zone cut for this query. */ - struct kr_cache_txn txn; - if (kr_cache_txn_begin(&rplan->context->cache, &txn, NAMEDB_RDONLY) != 0) { - kr_zonecut_set_sbelt(&qry->zone_cut); - } else { - kr_zonecut_find_cached(&qry->zone_cut, &txn, qry->timestamp.tv_sec); - kr_cache_txn_abort(&txn); - } + /* Deferred zone cut lookup for this query. */ + qry->flags |= QUERY_AWAIT_CUT; /* Initialize answer packet */ knot_pkt_t *answer = request->answer; @@ -395,6 +389,20 @@ int kr_resolve_produce(struct kr_request *request, struct sockaddr **dst, int *t return kr_rplan_empty(rplan) ? KNOT_STATE_DONE : KNOT_STATE_PRODUCE; } + /* The query wasn't resolved from cache, + * now it's the time to look up closest zone cut from cache. + */ + if (qry->flags & QUERY_AWAIT_CUT) { + struct kr_cache_txn txn; + if (kr_cache_txn_begin(&rplan->context->cache, &txn, NAMEDB_RDONLY) != 0) { + kr_zonecut_set_sbelt(&qry->zone_cut); + } else { + kr_zonecut_find_cached(&qry->zone_cut, qry->sname, &txn, qry->timestamp.tv_sec); + kr_cache_txn_abort(&txn); + } + qry->flags &= ~QUERY_AWAIT_CUT; + } + /* Elect best nameserver candidate */ kr_nsrep_elect(&qry->ns, &qry->zone_cut.nsset); if (qry->ns.score < KR_NS_VALID) { diff --git a/lib/rplan.c b/lib/rplan.c index d98b6e5bc..4065bfb4e 100644 --- a/lib/rplan.c +++ b/lib/rplan.c @@ -112,7 +112,7 @@ struct kr_query *kr_rplan_push(struct kr_rplan *rplan, struct kr_query *parent, qry->parent = parent; gettimeofday(&qry->timestamp, NULL); add_tail(&rplan->pending, &qry->node); - kr_zonecut_init(&qry->zone_cut, name, rplan->pool); + kr_zonecut_init(&qry->zone_cut, (const uint8_t *)"", rplan->pool); #ifndef NDEBUG char name_str[KNOT_DNAME_MAXLEN], type_str[16]; diff --git a/lib/rplan.h b/lib/rplan.h index c3a84383d..e5afd9bba 100644 --- a/lib/rplan.h +++ b/lib/rplan.h @@ -33,8 +33,9 @@ enum kr_query_flag { QUERY_RESOLVED = 1 << 2, /**< Query is resolved. */ QUERY_AWAIT_IPV4 = 1 << 3, /**< Query is waiting for A address. */ QUERY_AWAIT_IPV6 = 1 << 4, /**< Query is waiting for AAAA address. */ - QUERY_SAFEMODE = 1 << 5, /**< Don't use fancy stuff (EDNS...) */ - QUERY_CACHED = 1 << 6 /**< Query response is cached. */ + QUERY_AWAIT_CUT = 1 << 5, /**< Query is waiting for zone cut lookup */ + QUERY_SAFEMODE = 1 << 6, /**< Don't use fancy stuff (EDNS...) */ + QUERY_CACHED = 1 << 7 /**< Query response is cached. */ }; /** diff --git a/lib/zonecut.c b/lib/zonecut.c index 51ede9b15..f45b1ef07 100644 --- a/lib/zonecut.c +++ b/lib/zonecut.c @@ -209,24 +209,24 @@ static int fetch_ns(struct kr_zonecut *cut, const knot_dname_t *name, struct kr_ return kr_ok(); } -int kr_zonecut_find_cached(struct kr_zonecut *cut, struct kr_cache_txn *txn, uint32_t timestamp) +int kr_zonecut_find_cached(struct kr_zonecut *cut, const knot_dname_t *name, struct kr_cache_txn *txn, uint32_t timestamp) { if (cut == NULL) { return kr_error(EINVAL); } - /* Start at QNAME. */ - const knot_dname_t *name = cut->name; + /* Start at QNAME parent. */ + name = knot_wire_next_label(name, NULL); while (txn) { if (fetch_ns(cut, name, txn, timestamp) == 0) { update_cut_name(cut, name); return kr_ok(); } - name = knot_wire_next_label(name, NULL); - /* Subtract label from QNAME. */ if (name[0] == '\0') { break; } + /* Subtract label from QNAME. */ + name = knot_wire_next_label(name, NULL); } /* Name server not found, start with SBELT. */ diff --git a/lib/zonecut.h b/lib/zonecut.h index 0c4670699..545098d32 100644 --- a/lib/zonecut.h +++ b/lib/zonecut.h @@ -100,8 +100,9 @@ int kr_zonecut_set_sbelt(struct kr_zonecut *cut); * Populate zone cut address set from cache. * * @param cut zone cut to be populated + * @param name QNAME to start finding zone cut for * @param txn cache transaction (read) * @param timestamp transaction timestamp * @return 0 or error code */ -int kr_zonecut_find_cached(struct kr_zonecut *cut, struct kr_cache_txn *txn, uint32_t timestamp); +int kr_zonecut_find_cached(struct kr_zonecut *cut, const knot_dname_t *name, struct kr_cache_txn *txn, uint32_t timestamp); diff --git a/tests/test_zonecut.c b/tests/test_zonecut.c index 18452749a..a9401cbff 100644 --- a/tests/test_zonecut.c +++ b/tests/test_zonecut.c @@ -30,7 +30,7 @@ static void test_zonecut_params(void **state) assert_null((void *)kr_zonecut_find(NULL, NULL)); assert_null((void *)kr_zonecut_find(&cut, NULL)); assert_int_not_equal(kr_zonecut_set_sbelt(NULL), 0); - assert_int_not_equal(kr_zonecut_find_cached(NULL, NULL, 0), 0); + assert_int_not_equal(kr_zonecut_find_cached(NULL, NULL, NULL, 0), 0); } int main(void) -- 2.47.3