char *bufmem;
dns_name_t *name;
dns_fixedname_t fixname;
+ unsigned int options = DNS_DB_STALEOK;
+
+ if ((dctx->tctx.style.flags & DNS_STYLEFLAG_EXPIRED) != 0) {
+ options |= DNS_DB_EXPIREDOK;
+ }
bufmem = isc_mem_get(dctx->mctx, initial_buffer_length);
result = dns_dbiterator_pause(dctx->dbiter);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
- result = dns_db_allrdatasets(dctx->db, node, dctx->version, 0,
- dctx->now, &rdsiter);
+ result = dns_db_allrdatasets(dctx->db, node, dctx->version,
+ options, dctx->now, &rdsiter);
if (result != ISC_R_SUCCESS) {
dns_db_detachnode(dctx->db, &node);
goto cleanup;
isc_stdtime_t now;
dns_totext_ctx_t ctx;
dns_rdatasetiter_t *rdsiter = NULL;
+ unsigned int options = DNS_DB_STALEOK;
+
+ if ((style->flags & DNS_STYLEFLAG_EXPIRED) != 0) {
+ options |= DNS_DB_EXPIREDOK;
+ }
result = totext_ctx_init(style, NULL, &ctx);
if (result != ISC_R_SUCCESS) {
isc_buffer_init(&buffer, bufmem, initial_buffer_length);
- result = dns_db_allrdatasets(db, node, version, 0, now, &rdsiter);
+ result = dns_db_allrdatasets(db, node, version, options, now, &rdsiter);
if (result != ISC_R_SUCCESS) {
goto failure;
}
#define DEFAULT_NODE_LOCK_COUNT 7 /*%< Should be prime. */
+#define EXPIREDOK(rbtiterator) \
+ (((rbtiterator)->common.options & DNS_DB_EXPIREDOK) != 0)
+
+#define STALEOK(rbtiterator) \
+ (((rbtiterator)->common.options & DNS_DB_STALEOK) != 0)
+
/*%
* Number of buckets for cache DB entries (locks, LRU lists, TTL heaps).
* There is a tradeoff issue about configuring this value: if this is too
for (header = rbtnode->data; header != NULL; header = top_next) {
top_next = header->next;
do {
- if (header->serial <= serial && !IGNORE(header)) {
+ dns_ttl_t stale_ttl = header->rdh_ttl;
+ if (STALEOK(rbtiterator)) {
+ stale_ttl += STALE_TTL(header, rbtdb);
+ }
+ if (EXPIREDOK(rbtiterator)) {
+ if (!NONEXISTENT(header)) {
+ break;
+ }
+ header = header->down;
+ } else if (header->serial <= serial && !IGNORE(header))
+ {
/*
* Is this a "this rdataset doesn't exist"
* record? Or is it too old in the cache?
* queries for 0 TTL rdatasets to work.
*/
if (NONEXISTENT(header) ||
- (now != 0 && now > header->rdh_ttl))
- {
+ (now != 0 && now > stale_ttl)) {
header = NULL;
}
break;
rbtdb_rdatatype_t type, negtype;
dns_rdatatype_t rdtype, covers;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
+ bool expiredok = EXPIREDOK(rbtiterator);
header = rbtiterator->current;
if (header == NULL) {
} else {
negtype = RBTDB_RDATATYPE_VALUE(0, rdtype);
}
- for (header = header->next; header != NULL; header = top_next) {
- top_next = header->next;
+
+ /*
+ * Find the start of the header chain for the next type
+ * by walking back up the list.
+ */
+ top_next = header->next;
+ while (top_next != NULL &&
+ (top_next->type == type || top_next->type == negtype))
+ {
+ top_next = top_next->next;
+ }
+ if (expiredok) {
/*
- * If not walking back up the down list.
+ * Keep walking down the list if possible or
+ * start the next type.
*/
- if (header->type != type && header->type != negtype) {
- do {
- if (header->serial <= serial && !IGNORE(header))
- {
- /*
- * Is this a "this rdataset doesn't
- * exist" record?
- *
- * Note: unlike everywhere else, we
- * check for now > header->ttl instead
- * of ">=". This allows ANY and RRSIG
- * queries for 0 TTL rdatasets to work.
- */
- if (NONEXISTENT(header) ||
- (now != 0 && now > header->rdh_ttl))
- {
- header = NULL;
- }
+ header = header->down != NULL ? header->down : top_next;
+ } else {
+ header = top_next;
+ }
+ for (; header != NULL; header = top_next) {
+ top_next = header->next;
+ do {
+ dns_ttl_t stale_ttl = header->rdh_ttl;
+ if (STALEOK(rbtiterator)) {
+ stale_ttl += STALE_TTL(header, rbtdb);
+ }
+ if (expiredok) {
+ if (!NONEXISTENT(header)) {
break;
- } else {
- header = header->down;
}
- } while (header != NULL);
- if (header != NULL) {
+ header = header->down;
+ } else if (header->serial <= serial && !IGNORE(header))
+ {
+ /*
+ * Is this a "this rdataset doesn't
+ * exist" record?
+ *
+ * Note: unlike everywhere else, we
+ * check for now > header->ttl instead
+ * of ">=". This allows ANY and RRSIG
+ * queries for 0 TTL rdatasets to work.
+ */
+ if (NONEXISTENT(header) ||
+ (now != 0 && now > stale_ttl)) {
+ header = NULL;
+ }
break;
+ } else {
+ header = header->down;
}
+ } while (header != NULL);
+ if (header != NULL) {
+ break;
+ }
+ /*
+ * Find the start of the header chain for the next type
+ * by walking back up the list.
+ */
+ while (top_next != NULL &&
+ (top_next->type == type || top_next->type == negtype))
+ {
+ top_next = top_next->next;
}
}