]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
lib/resolve: deferred zone cut lookup
authorMarek Vavruša <marek.vavrusa@nic.cz>
Wed, 27 May 2015 23:23:47 +0000 (01:23 +0200)
committerMarek Vavruša <marek.vavrusa@nic.cz>
Wed, 27 May 2015 23:23:47 +0000 (01:23 +0200)
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
lib/rplan.c
lib/rplan.h
lib/zonecut.c
lib/zonecut.h
tests/test_zonecut.c

index ec50f7c129b96732fa1bbc899c5836156846e900..7b25e846e737a69e44ba2a880b49267bdc07b8a6 100644 (file)
@@ -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) {
index d98b6e5bcb55124bd9f968e0198d33d6d90aa747..4065bfb4eac3157b0df08bad4a5e91de28a3ff1c 100644 (file)
@@ -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];
index c3a84383d4b119f12700c989c237f32b02d4b302..e5afd9bbae7aacdf507d62d2e7748ee2e70b78e6 100644 (file)
@@ -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. */
 };
 
 /**
index 51ede9b151323a79dd2dac199ee0ef3cb53d57d0..f45b1ef078164905187c29a7c1e6ff68d650fd7b 100644 (file)
@@ -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. */
index 0c4670699454c02f23aa498ca3ef2510a53492ca..545098d32cad716d16d90009b2bf61b540178e50 100644 (file)
@@ -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);
index 18452749aa76f8252f59a5a8c80d592066484033..a9401cbffcde3a61fd7cc537d4936a1374edb946 100644 (file)
@@ -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)