* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rbtdb.c,v 1.261 2008/06/04 01:11:05 jinmei Exp $ */
+/* $Id: rbtdb.c,v 1.262 2008/08/13 02:28:45 jinmei Exp $ */
/*! \file */
INSIST(noderefs != 0);
}
+/*
+ * This function is assumed to be called when a node is newly referenced
+ * and can be in the deadnode list. In that case the node must be retrieved
+ * from the list because the it is going to be used. In addition, if the caller
+ * happens to hold a write lock on the tree, it's a good chance to purge dead
+ * nodes.
+ * Note: while a new reference is gained in multiple places, there are only very
+ * few cases where the node can be in the deadnode list (only empty nodes can
+ * have been added to the list).
+ */
+static inline void
+reactivate_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
+ isc_rwlocktype_t treelocktype)
+{
+ isc_boolean_t need_relock = ISC_FALSE;
+
+ NODE_STRONGLOCK(&rbtdb->node_locks[node->locknum].lock);
+ new_reference(rbtdb, node);
+
+ NODE_WEAKLOCK(&rbtdb->node_locks[node->locknum].lock,
+ isc_rwlocktype_read);
+ if (ISC_LINK_LINKED(node, deadlink))
+ need_relock = ISC_TRUE;
+ else if (!ISC_LIST_EMPTY(rbtdb->deadnodes[node->locknum]) &&
+ treelocktype == isc_rwlocktype_write)
+ need_relock = ISC_TRUE;
+ NODE_WEAKUNLOCK(&rbtdb->node_locks[node->locknum].lock,
+ isc_rwlocktype_read);
+ if (need_relock) {
+ NODE_WEAKLOCK(&rbtdb->node_locks[node->locknum].lock,
+ isc_rwlocktype_write);
+ if (ISC_LINK_LINKED(node, deadlink))
+ ISC_LIST_UNLINK(rbtdb->deadnodes[node->locknum],
+ node, deadlink);
+ if (treelocktype == isc_rwlocktype_write)
+ cleanup_dead_nodes(rbtdb, node->locknum);
+ NODE_WEAKUNLOCK(&rbtdb->node_locks[node->locknum].lock,
+ isc_rwlocktype_write);
+ }
+
+ NODE_STRONGUNLOCK(&rbtdb->node_locks[node->locknum].lock);
+}
+
/*
* Caller must be holding the node lock; either the "strong", read or write
* lock. Note that the lock must be held even when node references are
sizeof(printname)));
}
+ INSIST(!ISC_LINK_LINKED(node, deadlink));
result = dns_rbt_deletenode(rbtdb->tree, node, ISC_FALSE);
if (result != ISC_R_SUCCESS)
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
dns_name_t nodename;
isc_result_t result;
isc_rwlocktype_t locktype = isc_rwlocktype_read;
- isc_boolean_t need_relock;
REQUIRE(VALID_RBTDB(rbtdb));
return (result);
}
}
- NODE_STRONGLOCK(&rbtdb->node_locks[node->locknum].lock);
- new_reference(rbtdb, node);
-
- /*
- * If the node just found is in the deadnode list, we need to retrieve
- * it from the list because we are going to use the node. There are
- * other cases where a node is newly referenced, but this should be
- * the only case where it can be in the deadnode list. Also, if we
- * happen to hold a write lock on the tree, it's a good chance to purge
- * dead nodes.
- */
- need_relock = ISC_FALSE;
- NODE_WEAKLOCK(&rbtdb->node_locks[node->locknum].lock,
- isc_rwlocktype_read);
- if (ISC_LINK_LINKED(node, deadlink))
- need_relock = ISC_TRUE;
- else if (!ISC_LIST_EMPTY(rbtdb->deadnodes[node->locknum]) &&
- locktype == isc_rwlocktype_write)
- need_relock = ISC_TRUE;
- NODE_WEAKUNLOCK(&rbtdb->node_locks[node->locknum].lock,
- isc_rwlocktype_read);
- if (need_relock) {
- NODE_WEAKLOCK(&rbtdb->node_locks[node->locknum].lock,
- isc_rwlocktype_write);
- if (ISC_LINK_LINKED(node, deadlink))
- ISC_LIST_UNLINK(rbtdb->deadnodes[node->locknum],
- node, deadlink);
- if (locktype == isc_rwlocktype_write)
- cleanup_dead_nodes(rbtdb, node->locknum);
- NODE_WEAKUNLOCK(&rbtdb->node_locks[node->locknum].lock,
- isc_rwlocktype_write);
- }
-
- NODE_STRONGUNLOCK(&rbtdb->node_locks[node->locknum].lock);
+ reactivate_node(rbtdb, node, locktype);
RWUNLOCK(&rbtdb->tree_lock, locktype);
*nodep = (dns_dbnode_t *)node;
* search->zonecut_rdataset will still be valid later.
*/
new_reference(search->rbtdb, node);
+ INSIST(!ISC_LINK_LINKED(node, deadlink));
search->zonecut = node;
search->zonecut_rdataset = dname_header;
search->zonecut_sigrdataset = sigdname_header;
if (nsheader != NULL) {
if (nodep != NULL) {
new_reference(search.rbtdb, node);
+ INSIST(!ISC_LINK_LINKED(node, deadlink));
*nodep = node;
}
bind_rdataset(search.rbtdb, node, nsheader, search.now,
if (nodep != NULL) {
new_reference(search.rbtdb, node);
+ INSIST(!ISC_LINK_LINKED(node, deadlink));
*nodep = node;
}
if (nodep != NULL) {
new_reference(search.rbtdb, node);
+ INSIST(!ISC_LINK_LINKED(node, deadlink));
*nodep = node;
}
return;
INSIST(rbtdbiter->tree_locked != isc_rwlocktype_none);
- NODE_STRONGLOCK(&rbtdb->node_locks[node->locknum].lock);
- new_reference(rbtdb, node);
- NODE_STRONGUNLOCK(&rbtdb->node_locks[node->locknum].lock);
+ reactivate_node(rbtdb, node, rbtdbiter->tree_locked);
}
static inline void