return ctx->state;
}
- namedb_txn_t *txn = kr_rplan_txn_acquire(rplan, NAMEDB_RDONLY);
+ namedb_txn_t txn;
+ struct kr_cache *cache = req->ctx->cache;
+ if (kr_cache_txn_begin(cache, &txn, NAMEDB_RDONLY) != 0) {
+ return KNOT_STATE_CONSUME;
+ }
uint32_t timestamp = cur->timestamp.tv_sec;
knot_rrset_t cache_rr;
knot_rrset_init(&cache_rr, cur->sname, cur->stype, cur->sclass);
}
/* Try to find expected record first. */
- int state = read_cache_rr(txn, &cache_rr, timestamp, callback, req);
+ int state = read_cache_rr(&txn, &cache_rr, timestamp, callback, req);
if (state == KNOT_STATE_DONE) {
DEBUG_MSG("=> satisfied from cache\n");
cur->flags |= QUERY_RESOLVED;
+ kr_cache_txn_abort(&txn);
return state;
}
/* Check if CNAME chain exists. */
cache_rr.type = KNOT_RRTYPE_CNAME;
- state = read_cache_rr(txn, &cache_rr, timestamp, callback, req);
+ state = read_cache_rr(&txn, &cache_rr, timestamp, callback, req);
if (state != KNOT_STATE_NOOP) {
if (cur->stype != KNOT_RRTYPE_CNAME) {
const knot_dname_t *cname = knot_cname_name(&cache_rr.rrs);
if (kr_rplan_push(rplan, cur->parent, cname, cur->sclass, cur->stype) == NULL) {
+ kr_cache_txn_abort(&txn);
return KNOT_STATE_FAIL;
}
}
cur->flags |= QUERY_RESOLVED;
+ kr_cache_txn_abort(&txn);
return KNOT_STATE_DONE;
}
/* Not resolved. */
+ kr_cache_txn_abort(&txn);
return KNOT_STATE_CONSUME;
}
return ctx->state;
}
- /* Open write transaction */
- mm_ctx_t *pool = rplan->pool;
- uint32_t timestamp = query->timestamp.tv_sec;
- namedb_txn_t *txn = kr_rplan_txn_acquire(rplan, 0);
- if (txn == NULL) {
- return ctx->state; /* Couldn't acquire cache, ignore. */
- }
-
/* Cache only positive answers. */
/** \todo Negative answers cache support */
if (knot_wire_get_rcode(pkt->wire) != KNOT_RCODE_NOERROR) {
return ctx->state;
}
+ /* Open write transaction */
+ mm_ctx_t *pool = rplan->pool;
+ uint32_t timestamp = query->timestamp.tv_sec;
+ struct kr_cache *cache = req->ctx->cache;
+ namedb_txn_t txn;
+ if (kr_cache_txn_begin(cache, &txn, 0) != 0) {
+ return ctx->state; /* Couldn't acquire cache, ignore. */
+ }
+
/* If authoritative, cache answer for current query. */
int ret = KNOT_EOK;
if (knot_wire_get_aa(pkt->wire)) {
- ret = write_cache_answer(pkt, txn, pool, timestamp);
+ ret = write_cache_answer(pkt, &txn, pool, timestamp);
}
if (ret == KNOT_EOK) {
- ret = write_cache_authority(pkt, txn, pool, timestamp);
+ ret = write_cache_authority(pkt, &txn, pool, timestamp);
}
/* Cache full, do what we must. */
if (ret == KNOT_ESPACE) {
- kr_cache_clear(txn);
+ kr_cache_clear(&txn);
+ } else {
+ kr_cache_txn_commit(&txn);
}
return ctx->state;
int kr_resolve_finish(struct kr_request *request, int state)
{
+#ifndef NDEBUG
struct kr_rplan *rplan = &request->rplan;
DEBUG_MSG("finished: %d, mempool: %zu B\n", state, (size_t) mp_total_size(request->pool.ctx));
-
- /* Resolution success, commit cache transaction. */
- if (state == KNOT_STATE_DONE) {
- kr_rplan_txn_commit(rplan);
- } else {
- /* Error during procesing, internal failure */
+#endif
+ /* Error during procesing, internal failure */
+ if (state != KNOT_STATE_DONE) {
knot_pkt_t *answer = request->answer;
if (knot_wire_get_rcode(answer->wire) == KNOT_RCODE_NOERROR) {
knot_wire_set_rcode(answer->wire, KNOT_RCODE_SERVFAIL);
WALK_LIST_DELSAFE(qry, next, rplan->resolved) {
query_free(rplan->pool, qry);
}
-
- /* Abort any pending transactions. */
- if (rplan->txn.db != NULL) {
- kr_cache_txn_abort(&rplan->txn);
- }
}
bool kr_rplan_empty(struct kr_rplan *rplan)
add_tail(&rplan->pending, &qry->node);
/* Find closest zone cut for this query. */
- namedb_txn_t *txn = kr_rplan_txn_acquire(rplan, NAMEDB_RDONLY);
+ namedb_txn_t txn;
kr_zonecut_init(&qry->zone_cut, name, rplan->pool);
- kr_zonecut_find_cached(&qry->zone_cut, txn, qry->timestamp.tv_sec);
+ 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);
+ }
#ifndef NDEBUG
char name_str[KNOT_DNAME_MAXLEN], type_str[16];
return TAIL(rplan->pending);
}
-namedb_txn_t *kr_rplan_txn_acquire(struct kr_rplan *rplan, unsigned flags)
-{
- if (rplan == NULL || rplan->context == NULL) {
- return NULL;
- }
-
- /* Discard current transaction if RDONLY, but WR is requested. */
- if ((rplan->txn_flags & NAMEDB_RDONLY) && !(flags & NAMEDB_RDONLY)) {
- kr_cache_txn_abort(&rplan->txn);
- rplan->txn.db = NULL;
- }
-
- /* Reuse transaction if exists. */
- if (rplan->txn.db != NULL) {
- return &rplan->txn;
- }
-
- /* Transaction doesn't exist, start new one. */
- int ret = kr_cache_txn_begin(rplan->context->cache, &rplan->txn, flags);
- if (ret != KNOT_EOK) {
- rplan->txn.db = NULL;
- return NULL;
- }
-
- rplan->txn_flags = flags;
- return &rplan->txn;
-}
-
-int kr_rplan_txn_commit(struct kr_rplan *rplan)
-{
- if (rplan == NULL || rplan->context == NULL) {
- return KNOT_EINVAL;
- }
-
- /* Just discard RDONLY transactions. */
- int ret = KNOT_EOK;
- if (rplan->txn_flags & NAMEDB_RDONLY) {
- kr_cache_txn_abort(&rplan->txn);
- } else {
- /* Commit write transactions. */
- ret = kr_cache_txn_commit(&rplan->txn);
- }
-
- rplan->txn.db = NULL;
- return ret;
-}
-
bool kr_rplan_satisfies(struct kr_query *closure, const knot_dname_t *name, uint16_t cls, uint16_t type)
{
while (closure != NULL) {
* It also keeps a notion of current zone cut.
*/
struct kr_rplan {
- unsigned txn_flags; /**< Current transaction flags. */
- namedb_txn_t txn; /**< Current transaction (may be r/o). */
list_t pending; /**< List of pending queries. */
list_t resolved; /**< List of resolved queries. */
struct kr_context *context; /**< Parent resolution context. */
*/
bool kr_rplan_empty(struct kr_rplan *rplan);
-/**
- * Acquire rplan transaction (read or write only).
- * @note The transaction is shared during the whole resolution, read only transactions
- * may be promoted to write-enabled transactions if requested, but never demoted.
- * @param rplan plan instance
- * @param flags transaction flags
- * @return transaction instance or NULL
- */
-namedb_txn_t *kr_rplan_txn_acquire(struct kr_rplan *rplan, unsigned flags);
-
-/**
- * Commit any existing transaction, read-only transactions may be just aborted.
- * @param rplan plan instance
- * @return KNOT_E*
- */
-int kr_rplan_txn_commit(struct kr_rplan *rplan);
-
/**
* Push a query to the top of the resolution plan.
* @note This means that this query takes precedence before all pending queries.
assert_int_equal(kr_rplan_pop(NULL, NULL), KNOT_EINVAL);
assert_true(kr_rplan_empty(NULL));
assert_null(kr_rplan_current(NULL));
- assert_null(kr_rplan_txn_acquire(NULL, 0));
- assert_int_equal(kr_rplan_txn_commit(NULL), KNOT_EINVAL);
kr_rplan_deinit(NULL);
/* NULL mandatory parameters */
assert_int_equal(kr_rplan_pop(&rplan, NULL), KNOT_EINVAL);
assert_true(kr_rplan_empty(&rplan));
assert_null(kr_rplan_current(&rplan));
- assert_null(kr_rplan_txn_acquire(&rplan, 0));
- assert_int_equal(kr_rplan_txn_commit(&rplan), KNOT_EINVAL);
kr_rplan_deinit(&rplan);
}
SECTION ANSWER
www.example.com. IN CNAME www.next.com.
SECTION AUTHORITY
-next.com. IN SOA next.com. next.com. 2007090400 28800 7200 604800 18000
+;next.com. IN SOA next.com. next.com. 2007090400 28800 7200 604800 18000
SECTION ADDITIONAL
ENTRY_END