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.
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;
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) {
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];
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. */
};
/**
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. */
* 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);
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)