#define QPDB_ATTR_LOADED 0x01
#define QPDB_ATTR_LOADING 0x02
-#ifndef DEFAULT_BUCKETS_COUNT
-#define DEFAULT_BUCKETS_COUNT 17 /*%< Should be prime. */
-#endif
-
#define QPDBITER_NSEC3_ORIGIN_NODE(qpdb, iterator) \
((iterator)->current == &(iterator)->nsec3iter && \
(iterator)->node == (qpdb)->nsec3_origin)
(sizeof(isc_rwlock_t)) % ISC_OS_CACHELINE_SIZE];
} qpzone_bucket_t;
+static qpzone_bucket_t qpzone_buckets_g[1024];
+
typedef struct qpz_changed {
qpznode_t *node;
bool dirty;
dns_qpmulti_t *tree; /* Main QP trie for data storage */
dns_qpmulti_t *nsec; /* NSEC nodes only */
dns_qpmulti_t *nsec3; /* NSEC3 nodes only */
-
- qpzone_bucket_t buckets[DEFAULT_BUCKETS_COUNT];
};
#ifdef DNS_DB_NODETRACE
* Failure to follow this hierarchy can result in deadlock.
*/
+void
+dns__qpzone_initialize(void) {
+ for (size_t idx = 0; idx < ARRAY_SIZE(qpzone_buckets_g); ++idx) {
+ NODE_INITLOCK(&qpzone_buckets_g[idx].lock);
+ }
+}
+
+void
+dns__qpzone_shutdown(void) {
+ for (size_t idx = 0; idx < ARRAY_SIZE(qpzone_buckets_g); ++idx) {
+ NODE_DESTROYLOCK(&qpzone_buckets_g[idx].lock);
+ }
+}
+
static isc_rwlock_t *
-qpzone_get_lock(qpzonedb_t *qpdb, qpznode_t *node) {
- return &qpdb->buckets[node->locknum].lock;
+qpzone_get_lock(qpznode_t *node) {
+ return &qpzone_buckets_g[node->locknum].lock;
}
static uint16_t
qpzone_get_locknum(void) {
- return isc_random_uniform(DEFAULT_BUCKETS_COUNT);
+ return isc_random_uniform(ARRAY_SIZE(qpzone_buckets_g));
}
/*%
dns_name_free(&qpdb->common.origin, qpdb->common.mctx);
}
- for (size_t i = 0; i < DEFAULT_BUCKETS_COUNT; i++) {
- NODE_DESTROYLOCK(&qpdb->buckets[i].lock);
- }
-
qpz_heap_detach(&qpdb->heap);
if (qpdb->gluecachestats != NULL) {
qpdb->heap = new_qpz_heap(mctx);
- for (size_t i = 0; i < DEFAULT_BUCKETS_COUNT; i++) {
- NODE_INITLOCK(&qpdb->buckets[i].lock);
- }
-
/*
* Attach to the mctx. The database will persist so long as there
* are references to it, and attaching to the mctx ensures that our
* erefs_increment. If another thread acquires reference it
* will be larger than 0, if it doesn't it is going to be 0.
*/
- isc_rwlock_t *nlock = qpzone_get_lock(qpdb, node);
+ isc_rwlock_t *nlock = qpzone_get_lock(node);
qpznode_erefs_increment(qpdb, node DNS__DB_FLARG_PASS);
NODE_FORCEUPGRADE(nlock, nlocktypep);
if (!qpznode_erefs_decrement(qpdb, node DNS__DB_FLARG_PASS)) {
version->havensec3 = false;
node = qpdb->origin;
- nlock = qpzone_get_lock(qpdb, node);
+ nlock = qpzone_get_lock(node);
NODE_RDLOCK(nlock, &nlocktype);
for (header = node->data; header != NULL; header = header_next) {
header_next = header->next;
ISC_LIST_UNLINK(resigned_list, header, link);
- nlock = qpzone_get_lock(qpdb, HEADERNODE(header));
+ nlock = qpzone_get_lock(HEADERNODE(header));
NODE_WRLOCK(nlock, &nlocktype);
if (rollback && !IGNORE(header)) {
resigninsert(header);
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
node = changed->node;
- nlock = qpzone_get_lock(qpdb, node);
+ nlock = qpzone_get_lock(node);
NODE_WRLOCK(nlock, &nlocktype);
if (rollback) {
}
serial = version->serial;
- nlock = qpzone_get_lock(qpdb, node);
+ nlock = qpzone_get_lock(node);
NODE_RDLOCK(nlock, &nlocktype);
matchtype = DNS_TYPEPAIR_VALUE(type, covers);
newheader->resign_lsb = rdataset->resign & 0x1;
}
- nlock = qpzone_get_lock(qpdb, node);
+ nlock = qpzone_get_lock(node);
NODE_WRLOCK(nlock, &nlocktype);
result = add(qpdb, node, name, qpdb->current_version, newheader,
DNS_DBADD_MERGE, true, NULL, 0 DNS__DB_FLARG_PASS);
header = dns_rdataset_getheader(rdataset);
- nlock = qpzone_get_lock(qpdb, HEADERNODE(header));
+ nlock = qpzone_get_lock(HEADERNODE(header));
NODE_WRLOCK(nlock, &nlocktype);
oldheader = *header;
UNLOCK(&qpdb->heap->lock);
return ISC_R_NOTFOUND;
}
- nlock = qpzone_get_lock(qpdb, HEADERNODE(header));
+ nlock = qpzone_get_lock(HEADERNODE(header));
UNLOCK(&qpdb->heap->lock);
again:
LOCK(&qpdb->heap->lock);
header = isc_heap_element(qpdb->heap->heap, 1);
- if (header != NULL &&
- qpzone_get_lock(qpdb, HEADERNODE(header)) != nlock)
- {
+ if (header != NULL && qpzone_get_lock(HEADERNODE(header)) != nlock) {
UNLOCK(&qpdb->heap->lock);
NODE_UNLOCK(nlock, &nlocktype);
- nlock = qpzone_get_lock(qpdb, HEADERNODE(header));
+ nlock = qpzone_get_lock(HEADERNODE(header));
goto again;
}
}
if (rdataset != NULL) {
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
- isc_rwlock_t *nlock = qpzone_get_lock(search->qpdb, node);
+ isc_rwlock_t *nlock = qpzone_get_lock(node);
NODE_RDLOCK(nlock, &nlocktype);
bindrdataset(search->qpdb, node, search->zonecut_header,
rdataset DNS__DB_FLARG_PASS);
dns_name_t *nextname) {
dns_fixedname_t fnodename;
dns_name_t *nodename = dns_fixedname_initname(&fnodename);
- qpzonedb_t *qpdb = NULL;
qpznode_t *node = NULL;
isc_result_t result = ISC_R_SUCCESS;
dns_slabheader_t *header = NULL;
- qpdb = search->qpdb;
-
result = dns_qpiter_current(it, nodename, (void **)&node, NULL);
while (result == ISC_R_SUCCESS) {
- isc_rwlock_t *nlock = qpzone_get_lock(qpdb, node);
+ isc_rwlock_t *nlock = qpzone_get_lock(node);
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
dns_slabheader_t *header_next = NULL;
const dns_name_t *qname) {
dns_slabheader_t *header = NULL;
isc_result_t result = ISC_R_NOTFOUND;
- qpzonedb_t *qpdb = search->qpdb;
/*
* Examine each ancestor level. If the level's wild bit
dns_qpchain_node(&search->chain, i, NULL, (void **)&node, NULL);
- nlock = qpzone_get_lock(qpdb, node);
+ nlock = qpzone_get_lock(node);
NODE_RDLOCK(nlock, &nlocktype);
/*
* First we try to figure out if this node is active in
* is active in the search's version, we're
* done.
*/
- nlock = qpzone_get_lock(qpdb, wnode);
+ nlock = qpzone_get_lock(wnode);
NODE_RDLOCK(nlock, &nlocktype);
for (header = wnode->data; header != NULL;
header = header->next)
do {
dns_slabheader_t *found = NULL, *foundsig = NULL;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
- isc_rwlock_t *nlock = qpzone_get_lock(search->qpdb, node);
+ isc_rwlock_t *nlock = qpzone_get_lock(node);
NODE_RDLOCK(nlock, &nlocktype);
empty_node = true;
for (header = node->data; header != NULL; header = header_next)
dns_slabheader_t *found = NULL;
isc_result_t result = DNS_R_CONTINUE;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
- isc_rwlock_t *nlock = qpzone_get_lock(search->qpdb, node);
+ isc_rwlock_t *nlock = qpzone_get_lock(node);
NODE_RDLOCK(nlock, &nlocktype);
* have matched a wildcard.
*/
- nlock = qpzone_get_lock(search.qpdb, node);
+ nlock = qpzone_get_lock(node);
NODE_RDLOCK(nlock, &nlocktype);
if (search.zonecut != NULL) {
if (search.need_cleanup) {
node = search.zonecut;
INSIST(node != NULL);
- nlock = qpzone_get_lock(search.qpdb, node);
+ nlock = qpzone_get_lock(node);
NODE_RDLOCK(nlock, &nlocktype);
qpznode_release(search.qpdb, node, 0,
node = (qpznode_t *)(*nodep);
*nodep = NULL;
- nlock = qpzone_get_lock(qpdb, node);
+ nlock = qpzone_get_lock(node);
/*
* qpzone_destroy() uses call_rcu() API to destroy the node locks, so it
}
static void
-locknode(dns_db_t *db, dns_dbnode_t *dbnode, isc_rwlocktype_t type) {
- qpzonedb_t *qpdb = (qpzonedb_t *)db;
+locknode(dns_db_t *db ISC_ATTR_UNUSED, dns_dbnode_t *dbnode,
+ isc_rwlocktype_t type) {
qpznode_t *node = (qpznode_t *)dbnode;
- RWLOCK(qpzone_get_lock(qpdb, node), type);
+ RWLOCK(qpzone_get_lock(node), type);
}
static void
-unlocknode(dns_db_t *db, dns_dbnode_t *dbnode, isc_rwlocktype_t type) {
- qpzonedb_t *qpdb = (qpzonedb_t *)db;
+unlocknode(dns_db_t *db ISC_ATTR_UNUSED, dns_dbnode_t *dbnode,
+ isc_rwlocktype_t type) {
qpznode_t *node = (qpznode_t *)dbnode;
- RWUNLOCK(qpzone_get_lock(qpdb, node), type);
+ RWUNLOCK(qpzone_get_lock(node), type);
}
static void
static isc_result_t
rdatasetiter_first(dns_rdatasetiter_t *iterator DNS__DB_FLARG) {
qpdb_rdatasetiter_t *qrditer = (qpdb_rdatasetiter_t *)iterator;
- qpzonedb_t *qpdb = (qpzonedb_t *)(qrditer->common.db);
qpznode_t *node = (qpznode_t *)qrditer->common.node;
qpz_version_t *version = (qpz_version_t *)qrditer->common.version;
dns_slabheader_t *header = NULL, *top_next = NULL;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
- isc_rwlock_t *nlock = qpzone_get_lock(qpdb, node);
+ isc_rwlock_t *nlock = qpzone_get_lock(node);
NODE_RDLOCK(nlock, &nlocktype);
static isc_result_t
rdatasetiter_next(dns_rdatasetiter_t *iterator DNS__DB_FLARG) {
qpdb_rdatasetiter_t *qrditer = (qpdb_rdatasetiter_t *)iterator;
- qpzonedb_t *qpdb = (qpzonedb_t *)(qrditer->common.db);
qpznode_t *node = (qpznode_t *)qrditer->common.node;
qpz_version_t *version = (qpz_version_t *)qrditer->common.version;
dns_slabheader_t *header = NULL;
dns_slabheader_t *topheader, *topheader_next = NULL;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
- isc_rwlock_t *nlock = qpzone_get_lock(qpdb, node);
+ isc_rwlock_t *nlock = qpzone_get_lock(node);
header = qrditer->current;
if (header == NULL) {
qpznode_t *node = (qpznode_t *)qrditer->common.node;
dns_slabheader_t *header = NULL;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
- isc_rwlock_t *nlock = qpzone_get_lock(qpdb, node);
+ isc_rwlock_t *nlock = qpzone_get_lock(node);
header = qrditer->current;
REQUIRE(header != NULL);
}
iter->node = NULL;
- nlock = qpzone_get_lock(qpdb, node);
+ nlock = qpzone_get_lock(node);
NODE_RDLOCK(nlock, &nlocktype);
qpznode_release(qpdb, node, 0, &nlocktype DNS__DB_FLARG_PASS);
* (Note: node lock must be acquired after starting
* the QPDB transaction and released before committing.)
*/
- nlock = qpzone_get_lock(qpdb, node);
+ nlock = qpzone_get_lock(node);
NODE_WRLOCK(nlock, &nlocktype);
newheader->resign_lsb = rdataset->resign & 0x1;
}
- nlock = qpzone_get_lock(qpdb, node);
+ nlock = qpzone_get_lock(node);
NODE_WRLOCK(nlock, &nlocktype);
changed = add_changed(newheader, version DNS__DB_FLARG_PASS);
dns_name_copy(&node->name, nodename);
- nlock = qpzone_get_lock(qpdb, node);
+ nlock = qpzone_get_lock(node);
NODE_WRLOCK(nlock, &nlocktype);
result = add(qpdb, node, nodename, version, newheader, DNS_DBADD_FORCE,
false, NULL, 0 DNS__DB_FLARG_PASS);
REQUIRE(node != NULL);
REQUIRE(name != NULL);
- nlock = qpzone_get_lock(qpdb, qpnode);
+ nlock = qpzone_get_lock(qpnode);
NODE_RDLOCK(nlock, &nlocktype);
dns_name_copy(&qpnode->name, name);