struct compact_slabtop {
dns_typepair_t typepair;
- dns_slabheader_t header;
+ dns_slabheader_t *header;
};
struct slabtop_array {
static void
slabtop_shrink_to_fit(isc_mem_t *mctx, slabtop_array_t *arr);
+/* Replacement for DNS_SLABTOP_FOREACH that works with slabtop_array */
+#define SLABTOP_ARRAY_FOREACH(arr, elt) \
+ for (compact_slabtop_t *elt = (arr)->data, \
+ *elt##_end = (arr)->data + (arr)->size; \
+ elt < elt##_end; \
+ elt++)
+
+/* Continue iteration on slabtop_array */
+#define SLABTOP_ARRAY_FOREACH_CONTINUE(arr, start, elt) \
+ for (compact_slabtop_t *elt = start, \
+ *elt##_end = (arr)->data + (arr)->size; \
+ elt < elt##_end; \
+ elt++)
+
struct qpznode {
DBNODE_FIELDS;
atomic_bool wild;
atomic_bool delegating;
atomic_bool dirty;
- dns_slabtop_t *data;
+ slabtop_array_t array;
};
struct qpzonedb {
typedef struct qpdb_rdatasetiter {
dns_rdatasetiter_t common;
- dns_slabtop_t *currenttop;
+ compact_slabtop_t *currenttop;
dns_slabheader_t *current;
} qpdb_rdatasetiter_t;
static compact_slabtop_t
slabtop_array_find(slabtop_array_t *arr, dns_typepair_t needle) {
- compact_slabtop_t result = { 0, { 0 } };
+ compact_slabtop_t result = { 0, NULL };
REQUIRE(arr != NULL);
/* Element not found, create new one */
compact_slabtop_t new_element = {
.typepair = needle,
- .header = { 0 }
+ .header = NULL
};
slabtop_array_push(mctx, arr, new_element);
};
isc_mem_attach(qpdb->common.mctx, &newdata->mctx);
+ slabtop_array_init(newdata->mctx, &newdata->array, 8);
dns_name_dup(name, qpdb->common.mctx, &newdata->name);
qpz_heap_ref(newdata->heap);
*/
REQUIRE(least_serial != 0);
- DNS_SLABTOP_FOREACH(top, node->data) {
+ SLABTOP_ARRAY_FOREACH(&node->array, top) {
INSIST(top->header != NULL);
/* Torvalds style */
}
}
- DNS_SLABTOP_FOREACH(top, node->data) {
+ SLABTOP_ARRAY_FOREACH(&node->array, top) {
if (top->header != NULL) {
/*
* We now try to find the first down node less than the least
}
}
- dns_slabtop_t *top_prev = NULL;
- DNS_SLABTOP_FOREACH(top, node->data) {
- if (top->header == NULL) {
- if (top_prev != NULL) {
- top_prev->next = top->next;
- } else {
- node->data = top->next;
- }
- dns_slabtop_destroy(node->mctx, &top);
- } else {
- top_prev = top;
- }
- }
+ // FIXME (ap): Erase empty nodes
+
+ // dns_slabtop_t *top_prev = NULL;
+ // DNS_SLABTOP_FOREACH(top, node->data) {
+ // if (top->header == NULL) {
+ // if (top_prev != NULL) {
+ // top_prev->next = top->next;
+ // } else {
+ // node->data = top->next;
+ // }
+ // dns_slabtop_destroy(node->mctx, &top);
+ // } else {
+ // top_prev = top;
+ // }
+ // }
if (!still_dirty) {
node->dirty = false;
goto unref;
}
+ // FIXME(ap): Implement slabtop_array_empty helper function
+
/* Handle easy and typical case first. */
- if (!node->dirty && node->data != NULL) {
+ if (!node->dirty && node->array.size != 0ul) {
goto unref;
}
}
}
-static dns_slabtop_t *
-find_slabtop_by_typepair(dns_slabtop_t *head, dns_typepair_t typepair) {
- dns_slabtop_t *top = head;
- while (top != NULL && top->typepair != typepair) {
- top = top->next;
- }
- return top;
-}
-
static void
setnsec3parameters(dns_db_t *db, qpz_version_t *version) {
qpznode_t *node = NULL;
dns_rdata_nsec3param_t nsec3param;
isc_region_t region;
isc_result_t result;
- dns_slabtop_t *top = NULL;
unsigned char *raw; /* RDATASLAB */
unsigned int count, length;
qpzonedb_t *qpdb = (qpzonedb_t *)db;
NODE_RDLOCK(nlock, &nlocktype);
- top = find_slabtop_by_typepair(node->data, dns_rdatatype_nsec3param);
+ // FIXME(ap): pointer on failure?
+ compact_slabtop_t top = slabtop_array_find(&node->array, dns_rdatatype_nsec3param);
- if (top != NULL) {
- SLABHEADER_FOREACH_SAFE(top->header, inner, down) {
+ if (top.header != NULL) {
+ SLABHEADER_FOREACH_SAFE(top.header, inner, down) {
if (inner->serial <= version->serial &&
!IGNORE(inner))
{
* 'serial'. When the reference count goes to zero, these rdatasets
* will be cleaned up; until that time, they will be ignored.
*/
- DNS_SLABTOP_FOREACH(top, node->data) {
+ SLABTOP_ARRAY_FOREACH(&node->array, top) {
SLABHEADER_FOREACH_SAFE(top->header, dcurrent, down) {
if (dcurrent->serial == serial) {
DNS_SLABHEADER_SETATTR(
sigpair = dns_typepair_none;
}
- DNS_SLABTOP_FOREACH(top, node->data) {
+ SLABTOP_ARRAY_FOREACH(&node->array, top) {
dns_slabheader_t * candidate = NULL;
SLABHEADER_FOREACH_SAFE(top->header, inner, down) {
* ("Other data" is any rdataset whose type is not KEY, NSEC, SIG
* or RRSIG.
*/
- DNS_SLABTOP_FOREACH(top, node->data) {
+ SLABTOP_ARRAY_FOREACH(&node->array, top) {
dns_slabheader_t *header = top->header;
rdtype = DNS_TYPEPAIR_TYPE(top->typepair);
bool loading, dns_rdataset_t *addedrdataset,
isc_stdtime_t now ISC_ATTR_UNUSED DNS__DB_FLARG) {
qpz_changed_t *changed = NULL;
- dns_slabtop_t *foundtop = NULL;
- dns_slabtop_t *priotop = NULL;
dns_slabheader_t *merged = NULL;
isc_result_t result;
bool merge = false;
}
ntypes = 0;
- DNS_SLABTOP_FOREACH(top, node->data) {
+ compact_slabtop_t *foundtop = NULL;
+ SLABTOP_ARRAY_FOREACH(&node->array, top) {
++ntypes;
- if (prio_type(top->typepair)) {
- priotop = top;
- }
if (top->typepair == newheader->typepair) {
foundtop = top;
break;
* Since we don't generate changed records when
* loading, we MUST clean up 'header' now.
*/
- newheader->top = foundtop;
foundtop->header = newheader;
maybe_update_recordsandsize(false, version, header,
nodename->length);
foundtop->header = newheader;
}
- newheader->top = foundtop;
newheader->down = header;
node->dirty = true;
*/
INSIST(!loading);
INSIST(version->serial >= foundtop->header->serial);
- newheader->top = foundtop;
newheader->down = foundtop->header;
foundtop->header = newheader;
if (changed != NULL) {
newheader->top = newtop;
newtop->header = newheader;
- if (prio_type(newheader->typepair)) {
- /* This is a priority type, prepend it */
- newtop->next = node->data;
- node->data = newtop;
- } else if (priotop != NULL) {
- /* Append after the priority headers */
- newtop->next = priotop->next;
- priotop->next = newtop;
- } else {
- /* There were no priority headers */
- newtop->next = node->data;
- node->data = newtop;
- }
+ slabtop_array_push(node->mctx, &node->array, (compact_slabtop_t){newheader->typepair, newheader});
}
}
NODE_RDLOCK(nlock, &nlocktype);
dns_slabheader_t *found = NULL;
- DNS_SLABTOP_FOREACH(top, node->data) {
+ SLABTOP_ARRAY_FOREACH(&node->array, top) {
SLABHEADER_FOREACH_SAFE(top->header, inner, down) {
if (inner->serial <= search->serial &&
!IGNORE(inner))
* may not need the information, because it simplifies the
* locking and code flow.
*/
- DNS_SLABTOP_FOREACH(top, node->data) {
+ SLABTOP_ARRAY_FOREACH(&node->array, top) {
dns_slabheader_t *header = top->header;
if (header->serial <= search->serial &&
!IGNORE(header) && EXISTS(header))
*/
nlock = qpzone_get_lock(wnode);
NODE_RDLOCK(nlock, &nlocktype);
- DNS_SLABTOP_FOREACH(top, wnode->data) {
+ SLABTOP_ARRAY_FOREACH(&wnode->array, top) {
dns_slabheader_t *header = top->header;
if (header->serial <= search->serial &&
!IGNORE(header) && EXISTS(header))
isc_rwlock_t *nlock = qpzone_get_lock(node);
NODE_RDLOCK(nlock, &nlocktype);
empty_node = true;
- DNS_SLABTOP_FOREACH(top, node->data) {
+ SLABTOP_ARRAY_FOREACH(&node->array, top) {
/*
* Look for an active, extant NSEC or RRSIG NSEC.
/*
* Look for an NS or DNAME rdataset active in our version.
*/
- DNS_SLABTOP_FOREACH(top, node->data) {
+ SLABTOP_ARRAY_FOREACH(&node->array, top) {
dns_slabheader_t *header = top->header;
if (top->typepair == DNS_TYPEPAIR(dns_rdatatype_ns) ||
top->typepair == DNS_TYPEPAIR(dns_rdatatype_dname) ||
sigpair = DNS_SIGTYPEPAIR(type);
empty_node = true;
- DNS_SLABTOP_FOREACH(top, node->data) {
+ SLABTOP_ARRAY_FOREACH(&node->array, top) {
dns_slabheader_t *header = top->header;
/*
* Look for an active, extant rdataset.
qrditer->currenttop = NULL;
qrditer->current = NULL;
- DNS_SLABTOP_FOREACH(top, node->data) {
+ SLABTOP_ARRAY_FOREACH(&node->array, top) {
SLABHEADER_FOREACH_SAFE(top->header, header, down) {
if (header->serial <= version->serial && !IGNORE(header)) {
if (EXISTS(header)) {
qpz_version_t *version = (qpz_version_t *)qrditer->common.version;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlock_t *nlock = qpzone_get_lock(node);
- dns_slabtop_t *next = NULL;
- if (qrditer->currenttop == NULL) {
+ // FIXME(ap): implement slabtop_array_end helper function
+ if (qrditer->currenttop == node->array.data + node->array.size) {
return ISC_R_NOMORE;
}
- next = qrditer->currenttop->next;
+ compact_slabtop_t *next = ++qrditer->currenttop;
qrditer->currenttop = NULL;
qrditer->current = NULL;
/*
* Find the start of the header chain for the next type.
*/
- DNS_SLABTOP_FOREACH(top, next) {
+ SLABTOP_ARRAY_FOREACH_CONTINUE(&node->array, next, top) {
SLABHEADER_FOREACH_SAFE(top->header, header, down) {
if (header->serial <= version->serial && !IGNORE(header)) {
if (EXISTS(header)) {
qpz_version_t *version = (qpz_version_t *)dbversion;
dns_fixedname_t fname;
dns_name_t *nodename = dns_fixedname_initname(&fname);
- dns_slabtop_t *foundtop = NULL;
dns_slabheader_t *newheader = NULL;
dns_slabheader_t *subresult = NULL;
isc_region_t region;
NODE_WRLOCK(nlock, &nlocktype);
changed = add_changed(qpdb, newheader, version DNS__DB_FLARG_PASS);
- DNS_SLABTOP_FOREACH(top, node->data) {
+
+ compact_slabtop_t *foundtop = NULL;
+ SLABTOP_ARRAY_FOREACH(&node->array, top) {
if (top->typepair == newheader->typepair) {
foundtop = top;
break;
maybe_update_recordsandsize(false, version, header,
nodename->length);
- newheader->top = foundtop;
newheader->down = foundtop->header;
foundtop->header = newheader;
static void
destroy_qpznode(qpznode_t *node) {
- DNS_SLABTOP_FOREACH(top, node->data) {
+ SLABTOP_ARRAY_FOREACH(&node->array, top) {
SLABHEADER_FOREACH_SAFE(top->header, header, down) {
dns_slabheader_destroy(&header);
}
top->header = NULL;
-
- dns_slabtop_destroy(node->mctx, &top);
}
+ // TODO(ap): destroy array
+
qpz_heap_unref(node->heap);
dns_name_free(&node->name, node->mctx);
isc_mem_putanddetach(&node->mctx, node, sizeof(qpznode_t));