rbtdb.c revision e851ea826066ac5a5b01c2c23218faa0273a12e8
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * Copyright (C) 2004-2013 Internet Systems Consortium, Inc. ("ISC")
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * Copyright (C) 1999-2003 Internet Software Consortium.
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * Permission to use, copy, modify, and/or distribute this software for any
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * purpose with or without fee is hereby granted, provided that the above
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * copyright notice and this permission notice appear in all copies.
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * PERFORMANCE OF THIS SOFTWARE.
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * Principal Author: Bob Halley
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff/* #define inline */
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff#define RBTDB_MAGIC ISC_MAGIC('R', 'B', 'D', '8')
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff#define RBTDB_MAGIC ISC_MAGIC('R', 'B', 'D', '4')
213973a334f92d4aef4ef62b4538fc2e4d0e8082Michael Graff * This is the map file header for RBTDB images. It is populated, and then
213973a334f92d4aef4ef62b4538fc2e4d0e8082Michael Graff * written, as the LAST thing done to the file. Writing this last (with
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * zeros in the header area initially) will ensure that the header is only
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * valid when the RBTDB image is also valid.
213973a334f92d4aef4ef62b4538fc2e4d0e8082Michael Grafftypedef struct rbtdb_file_header rbtdb_file_header_t;
213973a334f92d4aef4ef62b4538fc2e4d0e8082Michael Graff/* Pad to 32 bytes */
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff/* Header length, always the same size regardless of structure size */
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff char version2[32]; /* repeated; must match version1 */
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff * Note that "impmagic" is not the first four bytes of the struct, so
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff * ISC_MAGIC_VALID cannot be used.
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff#define VALID_RBTDB(rbtdb) ((rbtdb) != NULL && \
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * Make casting easier in symbolic debuggers by using different names
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff * for the 64 bit version.
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff#define RBTDB_RDATATYPE_BASE(type) ((dns_rdatatype_t)((type) & 0xFFFF))
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff#define RBTDB_RDATATYPE_EXT(type) ((dns_rdatatype_t)((type) >> 16))
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff#define RBTDB_RDATATYPE_VALUE(b, e) ((rbtdb_rdatatype_t)((e) << 16) | (b))
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_nsec)
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_nsec3)
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_ns)
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_cname)
439c0011e642fb1d26011116144af698125262dbMichael Graff RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_dname)
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_ds)
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff * We use rwlock for DB lock only when ISC_RWLOCK_USEATOMIC is non 0.
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff * Using rwlock is effective with regard to lookup performance only when
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * it is implemented in an efficient way.
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * Otherwise, it is generally wise to stick to the simple locking since rwlock
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * would require more memory or can even make lookups slower due to its own
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff * overhead (when it internally calls mutex locks).
439c0011e642fb1d26011116144af698125262dbMichael Graff#define RBTDB_INITLOCK(l) isc_rwlock_init((l), 0, 0)
439c0011e642fb1d26011116144af698125262dbMichael Graff#define RBTDB_DESTROYLOCK(l) isc_rwlock_destroy(l)
439c0011e642fb1d26011116144af698125262dbMichael Graff * Since node locking is sensitive to both performance and memory footprint,
439c0011e642fb1d26011116144af698125262dbMichael Graff * we need some trick here. If we have both high-performance rwlock and
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff * high performance and small-memory reference counters, we use rwlock for
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * node lock and isc_refcount for node references. In this case, we don't have
a385f150bb21b8b81f70ed7df545357a83f1da82Michael Graff * to protect the access to the counters by locks.
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * Otherwise, we simply use ordinary mutex lock for node locking, and use
a385f150bb21b8b81f70ed7df545357a83f1da82Michael Graff * simple integers as reference counters which is protected by the lock.
439c0011e642fb1d26011116144af698125262dbMichael Graff * In most cases, we can simply use wrapper macros such as NODE_LOCK and
439c0011e642fb1d26011116144af698125262dbMichael Graff * NODE_UNLOCK. In some other cases, however, we need to protect reference
439c0011e642fb1d26011116144af698125262dbMichael Graff * counters first and then protect other parts of a node as read-only data.
439c0011e642fb1d26011116144af698125262dbMichael Graff * Special additional macros, NODE_STRONGLOCK(), NODE_WEAKLOCK(), etc, are also
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff * provided for these special cases. When we can use the efficient backend
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * routines, we should only protect the "other members" by NODE_WEAKLOCK(read).
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * Otherwise, we should use NODE_STRONGLOCK() to protect the entire critical
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff * section including the access to the reference counter.
29f28fe573d4b3b318b3b026d567c1eb86738015Michael Graff * Note that we cannot use NODE_LOCK()/NODE_UNLOCK() wherever the protected
29f28fe573d4b3b318b3b026d567c1eb86738015Michael Graff * section is also protected by NODE_STRONGLOCK().
a385f150bb21b8b81f70ed7df545357a83f1da82Michael Graff#if defined(ISC_RWLOCK_USEATOMIC) && defined(DNS_RBT_USEISCREFCOUNT)
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff#define NODE_INITLOCK(l) isc_rwlock_init((l), 0, 0)
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff#define NODE_DESTROYLOCK(l) isc_rwlock_destroy(l)
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff#define NODE_TRYUPGRADE(l) isc_rwlock_tryupgrade(l)
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff#define NODE_STRONGLOCK(l) ((void)0)
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff#define NODE_STRONGUNLOCK(l) ((void)0)
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff#define NODE_WEAKUNLOCK(l, t) NODE_UNLOCK(l, t)
a385f150bb21b8b81f70ed7df545357a83f1da82Michael Graff#define NODE_WEAKDOWNGRADE(l) isc_rwlock_downgrade(l)
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff#define NODE_WEAKLOCK(l, t) ((void)0)
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff#define NODE_WEAKUNLOCK(l, t) ((void)0)
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff#define NODE_WEAKDOWNGRADE(l) ((void)0)
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * Whether to rate-limit updating the LRU to avoid possible thread contention.
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * Our performance measurement has shown the cost is marginal, so it's defined
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * to be 0 by default either with or without threads.
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * Allow clients with a virtual time of up to 5 minutes in the past to see
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * records that would have otherwise have expired.
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Grafftypedef struct rdatasetheader {
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * Locked by the owning node's lock.
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * We don't use the LIST macros, because the LIST structure has
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * both head and tail pointers, and is doubly linked.
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * If this is the top header for an rdataset, 'next' points
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * to the top header for the next rdataset (i.e., the next type).
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * Otherwise, it points up to the header whose down pointer points
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * at this header.
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * Points to the header for the next older version of
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * this rdataset.
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * Monotonously increased every time this rdataset is bound so that
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * it is used as the base of the starting point in DNS responses
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * when the "cyclic" rrset-order is required. Since the ordering
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * should not be so crucial, no lock is set for the counter for
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * performance reasons.
f181f94ec8da8b1dbcc6353e8be965ea4a5ea282Michael Graff * Used for TTL-based cache cleaning.
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Grafftypedef ISC_LIST(rdatasetheader_t) rdatasetheaderlist_t;
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Grafftypedef struct acache_cbarg {
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff unsigned int count;
a385f150bb21b8b81f70ed7df545357a83f1da82Michael Graff * When the cache will pre-expire data (due to memory low or other
a385f150bb21b8b81f70ed7df545357a83f1da82Michael Graff * situations) before the rdataset's TTL has expired, it MUST
a385f150bb21b8b81f70ed7df545357a83f1da82Michael Graff * respect the RETAIN bit and not expire the data until its TTL is
a385f150bb21b8b81f70ed7df545357a83f1da82Michael Graff#undef IGNORE /* WIN32 winbase.h defines this. */
a385f150bb21b8b81f70ed7df545357a83f1da82Michael Graff (((header)->attributes & RDATASET_ATTR_NONEXISTENT) == 0)
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff (((header)->attributes & RDATASET_ATTR_NONEXISTENT) != 0)
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff (((header)->attributes & RDATASET_ATTR_IGNORE) != 0)
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff (((header)->attributes & RDATASET_ATTR_RETAIN) != 0)
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff (((header)->attributes & RDATASET_ATTR_NXDOMAIN) != 0)
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff (((header)->attributes & RDATASET_ATTR_RESIGN) != 0)
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff (((header)->attributes & RDATASET_ATTR_OPTOUT) != 0)
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff (((header)->attributes & RDATASET_ATTR_NEGATIVE) != 0)
a385f150bb21b8b81f70ed7df545357a83f1da82Michael Graff#define DEFAULT_NODE_LOCK_COUNT 7 /*%< Should be prime. */
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * Number of buckets for cache DB entries (locks, LRU lists, TTL heaps).
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * There is a tradeoff issue about configuring this value: if this is too
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * small, it may cause heavier contention between threads; if this is too large,
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * LRU purge algorithm won't work well (entries tend to be purged prematurely).
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * The default value should work well for most environments, but this can
a385f150bb21b8b81f70ed7df545357a83f1da82Michael Graff * also be configurable at compilation time via the
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * DNS_RBTDB_CACHE_NODE_LOCK_COUNT variable. This value must be larger than
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * 1 due to the assumption of overmem_purge().
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff#error "DNS_RBTDB_CACHE_NODE_LOCK_COUNT must be larger than 1"
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff#define DEFAULT_CACHE_NODE_LOCK_COUNT DNS_RBTDB_CACHE_NODE_LOCK_COUNT
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff#endif /* DNS_RBTDB_CACHE_NODE_LOCK_COUNT */
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Grafftypedef struct {
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff /* Protected in the refcount routines. */
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff /* Locked by lock. */
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Grafftypedef struct rbtdb_changed {
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Grafftypedef ISC_LIST(rbtdb_changed_t) rbtdb_changedlist_t;
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Grafftypedef enum {
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff/* Reason for expiring a record from cache */
439c0011e642fb1d26011116144af698125262dbMichael Grafftypedef enum {
439c0011e642fb1d26011116144af698125262dbMichael Grafftypedef struct rbtdb_version {
439c0011e642fb1d26011116144af698125262dbMichael Graff /* Not locked */
439c0011e642fb1d26011116144af698125262dbMichael Graff * Protected in the refcount routines.
439c0011e642fb1d26011116144af698125262dbMichael Graff * XXXJT: should we change the lock policy based on the refcount
439c0011e642fb1d26011116144af698125262dbMichael Graff * performance?
439c0011e642fb1d26011116144af698125262dbMichael Graff /* Locked by database lock. */
439c0011e642fb1d26011116144af698125262dbMichael Graff /* NSEC3 parameters */
439c0011e642fb1d26011116144af698125262dbMichael Grafftypedef ISC_LIST(rbtdb_version_t) rbtdb_versionlist_t;
439c0011e642fb1d26011116144af698125262dbMichael Graff /* Unlocked. */
439c0011e642fb1d26011116144af698125262dbMichael Graff /* Locks the data in this struct */
439c0011e642fb1d26011116144af698125262dbMichael Graff /* Locks the tree structure (prevents nodes appearing/disappearing) */
439c0011e642fb1d26011116144af698125262dbMichael Graff /* Locks for individual tree nodes */
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff /* Locked by lock. */
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff unsigned int active;
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff * This is a linked list used to implement the LRU cache. There will
439c0011e642fb1d26011116144af698125262dbMichael Graff * be node_lock_count linked lists here. Nodes in bucket 1 will be
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * placed on the linked list rdatasets[1].
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff * Temporary storage for stale cache nodes and dynamically deleted
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff * nodes that await being cleaned up.
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff * Heaps. These are used for TTL based expiry in a cache,
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff * or for zone resigning in a zone DB. hmctx is the memory
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff * context to use for the heap (which differs from the main
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff * database memory context in the case of a cache).
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff * Base values for the mmap() code.
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff /* Locked by tree_lock. */
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff /* Unlocked */
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff unsigned int quantum;
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff * Search Context
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Grafftypedef struct {
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff unsigned int options;
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * Load Context
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Grafftypedef struct {
f36a81c88493985ee2d1c53cc6fe88f4b00dbbc8Michael Graffstatic void delete_callback(void *data, void *arg);
f36a81c88493985ee2d1c53cc6fe88f4b00dbbc8Michael Graffstatic void rdataset_disassociate(dns_rdataset_t *rdataset);
f36a81c88493985ee2d1c53cc6fe88f4b00dbbc8Michael Graffstatic isc_result_t rdataset_first(dns_rdataset_t *rdataset);
f36a81c88493985ee2d1c53cc6fe88f4b00dbbc8Michael Graffstatic isc_result_t rdataset_next(dns_rdataset_t *rdataset);
f36a81c88493985ee2d1c53cc6fe88f4b00dbbc8Michael Graffstatic void rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata);
f36a81c88493985ee2d1c53cc6fe88f4b00dbbc8Michael Graffstatic void rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target);
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graffstatic unsigned int rdataset_count(dns_rdataset_t *rdataset);
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graffstatic isc_result_t rdataset_getnoqname(dns_rdataset_t *rdataset,
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graffstatic isc_result_t rdataset_getclosest(dns_rdataset_t *rdataset,
439c0011e642fb1d26011116144af698125262dbMichael Graffstatic isc_result_t rdataset_getadditional(dns_rdataset_t *rdataset,
439c0011e642fb1d26011116144af698125262dbMichael Graffstatic isc_result_t rdataset_setadditional(dns_rdataset_t *rdataset,
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graffstatic isc_result_t rdataset_putadditional(dns_acache_t *acache,
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graffstatic inline isc_boolean_t need_headerupdate(rdatasetheader_t *header,
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graffstatic void update_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header,
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graffstatic void expire_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header,
f181f94ec8da8b1dbcc6353e8be965ea4a5ea282Michael Graffstatic void overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start,
f181f94ec8da8b1dbcc6353e8be965ea4a5ea282Michael Graff isc_stdtime_t now, isc_boolean_t tree_locked);
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graffstatic isc_result_t resign_insert(dns_rbtdb_t *rbtdb, int idx,
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graffstatic void prune_tree(isc_task_t *task, isc_event_t *event);
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graffstatic void rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust);
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graffstatic void rdataset_expire(dns_rdataset_t *rdataset);
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graffstatic dns_rdatasetmethods_t rdataset_methods = {
3f6a66689410910ef601a4d26f10a24f331ef83cMichael Graffstatic void rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp);
3f6a66689410910ef601a4d26f10a24f331ef83cMichael Graffstatic isc_result_t rdatasetiter_first(dns_rdatasetiter_t *iterator);
3f6a66689410910ef601a4d26f10a24f331ef83cMichael Graffstatic isc_result_t rdatasetiter_next(dns_rdatasetiter_t *iterator);
3f6a66689410910ef601a4d26f10a24f331ef83cMichael Graffstatic void rdatasetiter_current(dns_rdatasetiter_t *iterator,
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graffstatic dns_rdatasetitermethods_t rdatasetiter_methods = {
519b4a1a27c8b767a57a981dda69a3c6394bd49dMichael Graffstatic void dbiterator_destroy(dns_dbiterator_t **iteratorp);
519b4a1a27c8b767a57a981dda69a3c6394bd49dMichael Graffstatic isc_result_t dbiterator_first(dns_dbiterator_t *iterator);
519b4a1a27c8b767a57a981dda69a3c6394bd49dMichael Graffstatic isc_result_t dbiterator_last(dns_dbiterator_t *iterator);
519b4a1a27c8b767a57a981dda69a3c6394bd49dMichael Graffstatic isc_result_t dbiterator_seek(dns_dbiterator_t *iterator,
439c0011e642fb1d26011116144af698125262dbMichael Graffstatic isc_result_t dbiterator_prev(dns_dbiterator_t *iterator);
29f28fe573d4b3b318b3b026d567c1eb86738015Michael Graffstatic isc_result_t dbiterator_next(dns_dbiterator_t *iterator);
439c0011e642fb1d26011116144af698125262dbMichael Graffstatic isc_result_t dbiterator_current(dns_dbiterator_t *iterator,
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graffstatic isc_result_t dbiterator_pause(dns_dbiterator_t *iterator);
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graffstatic isc_result_t dbiterator_origin(dns_dbiterator_t *iterator,
519b4a1a27c8b767a57a981dda69a3c6394bd49dMichael Graffstatic dns_dbiteratormethods_t dbiterator_methods = {
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * If 'paused' is ISC_TRUE, then the tree lock is not being held.
439c0011e642fb1d26011116144af698125262dbMichael Graff#define IS_STUB(rbtdb) (((rbtdb)->common.attributes & DNS_DBATTR_STUB) != 0)
439c0011e642fb1d26011116144af698125262dbMichael Graff#define IS_CACHE(rbtdb) (((rbtdb)->common.attributes & DNS_DBATTR_CACHE) != 0)
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graffstatic void free_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t log,
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graffstatic void overmem(dns_db_t *db, isc_boolean_t overmem);
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graffstatic void setnsec3parameters(dns_db_t *db, rbtdb_version_t *version);
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * 'init_count' is used to initialize 'newheader->count' which inturn
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * is used to determine where in the cycle rrset-order cyclic starts.
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * We don't lock this as we don't care about simultaneous updates.
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * Both init_count and header->count can be ISC_UINT32_MAX.
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * The count on the returned rdataset however can't be as
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * that indicates that the database does not implement cyclic
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * processing.
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graffstatic unsigned int init_count;
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * If a routine is going to lock more than one lock in this module, then
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * the locking must be done in the following order:
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff * Node Lock (Only one from the set may be locked at one time by
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff * any caller)
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff * Database Lock
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff * Failure to follow this hierarchy can result in deadlock.
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff * Deleting Nodes
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff * For zone databases the node for the origin of the zone MUST NOT be deleted.
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff * Debugging routines
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graffhexdump(const char *desc, unsigned char *data, size_t size) {
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff isc_buffer_init(&b, hexdump, sizeof(hexdump));
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff * DB Routines
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff isc_refcount_increment(&rbtdb->references, NULL);
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Grafffree_rbtdb_callback(isc_task_t *task, isc_event_t *event) {
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graffupdate_cachestats(dns_rbtdb_t *rbtdb, isc_result_t result) {
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graffupdate_rrsetstats(dns_rbtdb_t *rbtdb, rdatasetheader_t *header,
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff /* At the moment we count statistics only for cache DB */
f181f94ec8da8b1dbcc6353e8be965ea4a5ea282Michael Graff statattributes = DNS_RDATASTATSTYPE_ATTR_NXDOMAIN;
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff statattributes = DNS_RDATASTATSTYPE_ATTR_NXRRSET;
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff type = DNS_RDATASTATSTYPE_VALUE(base, statattributes);
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff dns_rdatasetstats_increment(rbtdb->rrsetstats, type);
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff dns_rdatasetstats_decrement(rbtdb->rrsetstats, type);
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graffset_ttl(dns_rbtdb_t *rbtdb, rdatasetheader_t *header, dns_ttl_t newttl) {
f181f94ec8da8b1dbcc6353e8be965ea4a5ea282Michael Graff * It's possible the rbtdb is not a cache. If this is the case,
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff * we will not have a heap, and we move on. If we do, though,
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff * we might need to adjust things.
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff if (header->heap_index == 0 || newttl == oldttl)
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff if (rbtdb->heaps == NULL || rbtdb->heaps[idx] == NULL)
439c0011e642fb1d26011116144af698125262dbMichael Graff * These functions allow the heap code to rank the priority of each
439c0011e642fb1d26011116144af698125262dbMichael Graff * element. It returns ISC_TRUE if v1 happens "sooner" than v2.
439c0011e642fb1d26011116144af698125262dbMichael Graff * This function sets the heap index into the header.
3024dbecbac365171bc6de0f3fa04951d6558be3Michael Graff * Work out how many nodes can be deleted in the time between two
3024dbecbac365171bc6de0f3fa04951d6558be3Michael Graff * requests to the nameserver. Smooth the resulting number and use it
3024dbecbac365171bc6de0f3fa04951d6558be3Michael Graff * as a estimate for the number of nodes to be deleted in the next
3024dbecbac365171bc6de0f3fa04951d6558be3Michael Graffstatic unsigned int
3024dbecbac365171bc6de0f3fa04951d6558be3Michael Graffadjust_quantum(unsigned int old, isc_time_t *start) {
3024dbecbac365171bc6de0f3fa04951d6558be3Michael Graff unsigned int pps = dns_pps; /* packets per second */
3024dbecbac365171bc6de0f3fa04951d6558be3Michael Graff unsigned int new;
3024dbecbac365171bc6de0f3fa04951d6558be3Michael Graff interval = 1000000 / pps; /* interval in usec */
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff * We were unable to measure the amount of time taken.
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff * Double the nodes deleted next time.
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_CACHE,
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff ISC_LOG_DEBUG(1), "adjust_quantum -> %d", new);
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Grafffree_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t log, isc_event_t *event) {
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff unsigned int i;
f181f94ec8da8b1dbcc6353e8be965ea4a5ea282Michael Graff if (IS_CACHE(rbtdb) && rbtdb->common.rdclass == dns_rdataclass_in)
f181f94ec8da8b1dbcc6353e8be965ea4a5ea282Michael Graff overmem((dns_db_t *)rbtdb, (isc_boolean_t)-1);
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff REQUIRE(rbtdb->current_version != NULL || EMPTY(rbtdb->open_versions));
f181f94ec8da8b1dbcc6353e8be965ea4a5ea282Michael Graff unsigned int refs;
f181f94ec8da8b1dbcc6353e8be965ea4a5ea282Michael Graff isc_refcount_decrement(&rbtdb->current_version->references,
3024dbecbac365171bc6de0f3fa04951d6558be3Michael Graff UNLINK(rbtdb->open_versions, rbtdb->current_version, link);
3024dbecbac365171bc6de0f3fa04951d6558be3Michael Graff isc_refcount_destroy(&rbtdb->current_version->references);
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff isc_mem_put(rbtdb->common.mctx, rbtdb->current_version,
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * We assume the number of remaining dead nodes is reasonably small;
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * the overhead of unlinking all nodes here should be negligible.
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff for (i = 0; i < rbtdb->node_lock_count; i++) {
3024dbecbac365171bc6de0f3fa04951d6558be3Michael Graff ISC_LIST_UNLINK(rbtdb->deadnodes[i], node, deadlink);
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff rbtdb->quantum = (rbtdb->task != NULL) ? 100 : 0;
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * pick the next tree to (start to) destroy
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * we're finished after clear cutting
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff result = dns_rbt_destroy2(treep, rbtdb->quantum);
439c0011e642fb1d26011116144af698125262dbMichael Graff rbtdb->quantum = adjust_quantum(rbtdb->quantum,
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff event = isc_event_allocate(rbtdb->common.mctx,
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff INSIST(result == ISC_R_SUCCESS && *treep == NULL);
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
f181f94ec8da8b1dbcc6353e8be965ea4a5ea282Michael Graff dns_name_free(&rbtdb->common.origin, rbtdb->common.mctx);
f181f94ec8da8b1dbcc6353e8be965ea4a5ea282Michael Graff for (i = 0; i < rbtdb->node_lock_count; i++) {
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff isc_refcount_destroy(&rbtdb->node_locks[i].references);
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff * Clean up LRU / re-signing order lists.
a385f150bb21b8b81f70ed7df545357a83f1da82Michael Graff isc_mem_put(rbtdb->common.mctx, rbtdb->rdatasets,
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * Clean up dead node buckets.
a385f150bb21b8b81f70ed7df545357a83f1da82Michael Graff isc_mem_put(rbtdb->common.mctx, rbtdb->deadnodes,
a385f150bb21b8b81f70ed7df545357a83f1da82Michael Graff rbtdb->node_lock_count * sizeof(rbtnodelist_t));
a385f150bb21b8b81f70ed7df545357a83f1da82Michael Graff * Clean up heap objects.
439c0011e642fb1d26011116144af698125262dbMichael Graff rbtdb->node_lock_count * sizeof(isc_heap_t *));
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graff * We must be cleaning up after a failed zone loading.
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff REQUIRE(rbtdb->rpz_num < rbtdb->rpzs->p.num_zones);
f181f94ec8da8b1dbcc6353e8be965ea4a5ea282Michael Graff isc_mem_put(rbtdb->common.mctx, rbtdb->node_locks,
f181f94ec8da8b1dbcc6353e8be965ea4a5ea282Michael Graff rbtdb->node_lock_count * sizeof(rbtdb_nodelock_t));
50b5857f1ad137624a18ce67b26b9941e316b007Michael Graff isc_mem_putanddetach(&rbtdb->common.mctx, rbtdb, sizeof(*rbtdb));
50b5857f1ad137624a18ce67b26b9941e316b007Michael Graffstatic inline void
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff unsigned int i;
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff unsigned int inactive = 0;
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff /* XXX check for open versions here */
439c0011e642fb1d26011116144af698125262dbMichael Graff dns_db_detachnode((dns_db_t *)rbtdb, &rbtdb->soanode);
439c0011e642fb1d26011116144af698125262dbMichael Graff dns_db_detachnode((dns_db_t *)rbtdb, &rbtdb->nsnode);
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * Even though there are no external direct references, there still
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff * may be nodes in use.
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff for (i = 0; i < rbtdb->node_lock_count; i++) {
439c0011e642fb1d26011116144af698125262dbMichael Graff NODE_LOCK(&rbtdb->node_locks[i].lock, isc_rwlocktype_write);
439c0011e642fb1d26011116144af698125262dbMichael Graff NODE_UNLOCK(&rbtdb->node_locks[i].lock, isc_rwlocktype_write);
439c0011e642fb1d26011116144af698125262dbMichael Graff if (isc_refcount_current(&rbtdb->node_locks[i].references)
439c0011e642fb1d26011116144af698125262dbMichael Graff RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_write);
439c0011e642fb1d26011116144af698125262dbMichael Graff RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_write);
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
439c0011e642fb1d26011116144af698125262dbMichael Graff unsigned int refs;
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff isc_refcount_decrement(&rbtdb->references, &refs);
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graffcurrentversion(dns_db_t *db, dns_dbversion_t **versionp) {
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff unsigned int refs;
29f28fe573d4b3b318b3b026d567c1eb86738015Michael Graff RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_read);
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff isc_refcount_increment(&version->references, &refs);
439c0011e642fb1d26011116144af698125262dbMichael Graff RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_read);
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graffallocate_version(isc_mem_t *mctx, rbtdb_serial_t serial,
439c0011e642fb1d26011116144af698125262dbMichael Graff unsigned int references, isc_boolean_t writer)
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff version = isc_mem_get(mctx, sizeof(*version));
dec90b6caef758fe2890ee50db148cff6acffb90Michael Graff result = isc_refcount_init(&version->references, references);
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graffnewversion(dns_db_t *db, dns_dbversion_t **versionp) {
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff REQUIRE(versionp != NULL && *versionp == NULL);
439c0011e642fb1d26011116144af698125262dbMichael Graff RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_write);
439c0011e642fb1d26011116144af698125262dbMichael Graff RUNTIME_CHECK(rbtdb->next_serial != 0); /* XXX Error? */
439c0011e642fb1d26011116144af698125262dbMichael Graff version = allocate_version(rbtdb->common.mctx, rbtdb->next_serial, 1,
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff version->secure = rbtdb->current_version->secure;
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff version->havensec3 = rbtdb->current_version->havensec3;
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff version->flags = rbtdb->current_version->flags;
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff memmove(version->salt, rbtdb->current_version->salt,
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff memset(version->salt, 0, sizeof(version->salt));
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_write);
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graffattachversion(dns_db_t *db, dns_dbversion_t *source,
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff unsigned int refs;
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff INSIST(rbtversion != NULL && rbtversion->rbtdb == rbtdb);
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graff isc_refcount_increment(&rbtversion->references, &refs);
30251e07d1705d1a85b0e1d5a969496e1aed612eMichael Graffadd_changed(dns_rbtdb_t *rbtdb, rbtdb_version_t *version,
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff unsigned int refs;
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * Caller must be holding the node lock if its reference must be
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * protected by the lock.
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff changed = isc_mem_get(rbtdb->common.mctx, sizeof(*changed));
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_write);
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff ISC_LIST_INITANDAPPEND(version->changed_list, changed, link);
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_write);
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Grafffree_acachearray(isc_mem_t *mctx, rdatasetheader_t *header,
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff unsigned int count;
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff unsigned int i;
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * The caller must be holding the corresponding node lock.
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff raw = (unsigned char *)header + sizeof(*header);
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * Sanity check: since an additional cache entry has a reference to
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * the original DB node (in the callback arg), there should be no
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * acache entries when the node can be freed.
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff for (i = 0; i < count; i++)
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff INSIST(array[i].entry == NULL && array[i].cbarg == NULL);
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff isc_mem_put(mctx, array, count * sizeof(acachectl_t));
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graffstatic inline void
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Grafffree_noqname(isc_mem_t *mctx, struct noqname **noqname) {
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff isc_mem_put(mctx, *noqname, sizeof(**noqname));
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graffstatic inline void
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graffinit_rdataset(dns_rbtdb_t *rbtdb, rdatasetheader_t *h) {
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff if (IS_CACHE(rbtdb) && rbtdb->common.rdclass == dns_rdataclass_in)
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff fprintf(stderr, "initialized header: %p\n", h);
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff * Update the copied values of 'next' and 'node' if they are relative.
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graffupdate_newheader(rdatasetheader_t *new, rdatasetheader_t *old) {
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff p = (char *) old;
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff p = (char *) old;
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graffnew_rdataset(dns_rbtdb_t *rbtdb, isc_mem_t *mctx) {
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graff if (IS_CACHE(rbtdb) && rbtdb->common.rdclass == dns_rdataclass_in)
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Graffstatic inline void
ad3a5c4b7e21af04d1b872f933c2e19e5c0a135bMichael Grafffree_rdataset(dns_rbtdb_t *rbtdb, isc_mem_t *mctx, rdatasetheader_t *rdataset) {
66bd3b3c6b171271c705b897823dcdcf29464698Michael Graff unsigned int size;
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff (rdataset->attributes & RDATASET_ATTR_STATCOUNT) != 0) {
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff update_rrsetstats(rbtdb, rdataset, ISC_FALSE);
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff ISC_LIST_UNLINK(rbtdb->rdatasets[idx], rdataset, link);
a385f150bb21b8b81f70ed7df545357a83f1da82Michael Graff isc_heap_delete(rbtdb->heaps[idx], rdataset->heap_index);
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff free_acachearray(mctx, rdataset, rdataset->additional_auth);
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff free_acachearray(mctx, rdataset, rdataset->additional_glue);
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff if ((rdataset->attributes & RDATASET_ATTR_NONEXISTENT) != 0)
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff size = dns_rdataslab_size((unsigned char *)rdataset,
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graffstatic inline void
11fcc67616fac1bc6a28b3d4fed24641137888e7Michael Graffrollback_node(dns_rbtnode_t *node, rbtdb_serial_t serial) {
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff * Caller must hold the node lock.
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff * We set the IGNORE attribute on rdatasets with serial number
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff * 'serial'. When the reference count goes to zero, these rdatasets
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff * will be cleaned up; until that time, they will be ignored.
6d14fe95e9ea5bbc5e863e5aab4618f7b3dbcc0fMichael Graff for (header = node->data; header != NULL; header = header->next) {
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graffstatic inline void
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graffmark_stale_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header) {
e51511aa3281f8dc384eb1283115c7f8d5c402aeMichael Graff * If we are already stale there is nothing to do.
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff if ((header->attributes & RDATASET_ATTR_STALE) != 0)
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff * If we have not been counted then there is nothing to do.
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff if ((header->attributes & RDATASET_ATTR_STATCOUNT) == 0)
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graffstatic inline void
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graffclean_stale_headers(dns_rbtdb_t *rbtdb, isc_mem_t *mctx, rdatasetheader_t *top)
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff for (d = top->down; d != NULL; d = down_next) {
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graffstatic inline void
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graffclean_cache_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node) {
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff rdatasetheader_t *current, *top_prev, *top_next;
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff * Caller must be holding the node lock.
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff for (current = node->data; current != NULL; current = top_next) {
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff * If current is nonexistent or stale, we can clean it up.
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff (RDATASET_ATTR_NONEXISTENT|RDATASET_ATTR_STALE)) != 0) {
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graffstatic inline void
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graffclean_zone_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
a9ece9973c35d4d780338e89e288fb6a59575324Michael Graff rdatasetheader_t *current, *dcurrent, *down_next, *dparent;
a9ece9973c35d4d780338e89e288fb6a59575324Michael Graff * Caller must be holding the node lock.
a9ece9973c35d4d780338e89e288fb6a59575324Michael Graff for (current = node->data; current != NULL; current = top_next) {
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff * First, we clean up any instances of multiple rdatasets
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff * with the same serial number, or that have the IGNORE
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff * We've now eliminated all IGNORE datasets with the possible
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff * exception of current, which we now check.
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff * current no longer exists, so we can
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff * just continue with the loop.
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff * Pull up current->down, making it the new
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff * We now try to find the first down node less than the
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff * least serial.
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graff * If there is a such an rdataset, delete it and any older
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff * Note. The serial number of 'current' might be less than
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff * least_serial too, but we cannot delete it because it is
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff * the most recent version, unless it is a NONEXISTENT
64828244e04e86dfa40f0a4f0c05f27923da499dMichael Graff * If this is a NONEXISTENT rdataset, we can delete it.
86944a4c8002e80ae9b6eb5a5e29b797879be45fMichael Graffdelete_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node)
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff dns_rpz_delete(rbtdb->rpzs, rbtdb->rpz_num, name);
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff result = dns_rbt_deletenode(rbtdb->tree, node, ISC_FALSE);
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff * Delete the corresponding node from the auxiliary NSEC
29f28fe573d4b3b318b3b026d567c1eb86738015Michael Graff * tree before deleting from the main tree.
29f28fe573d4b3b318b3b026d567c1eb86738015Michael Graff result = dns_rbt_findnode(rbtdb->nsec, name, NULL, &nsecnode,
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff "delete_node: "
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff "dns_rbt_findnode(nsec): %s",
29f28fe573d4b3b318b3b026d567c1eb86738015Michael Graff result = dns_rbt_deletenode(rbtdb->nsec, nsecnode,
29f28fe573d4b3b318b3b026d567c1eb86738015Michael Graff "delete_node(): "
29f28fe573d4b3b318b3b026d567c1eb86738015Michael Graff "dns_rbt_deletenode(nsecnode): %s",
29f28fe573d4b3b318b3b026d567c1eb86738015Michael Graff result = dns_rbt_deletenode(rbtdb->tree, node, ISC_FALSE);
29f28fe573d4b3b318b3b026d567c1eb86738015Michael Graff dns_rpz_delete(rbtdb->rpzs, rbtdb->rpz_num, name);
4d727d86b245063f00c5bfd98d138a63e0b7de6dMichael Graff result = dns_rbt_deletenode(rbtdb->nsec, node, ISC_FALSE);
29f28fe573d4b3b318b3b026d567c1eb86738015Michael Graff result = dns_rbt_deletenode(rbtdb->nsec3, node, ISC_FALSE);
29f28fe573d4b3b318b3b026d567c1eb86738015Michael Graff "delete_node(): "
29f28fe573d4b3b318b3b026d567c1eb86738015Michael Graff "dns_rbt_deletenode: %s",
4d727d86b245063f00c5bfd98d138a63e0b7de6dMichael Graff * Clean up dead nodes. These are nodes which have no references, and
4d727d86b245063f00c5bfd98d138a63e0b7de6dMichael Graff * have no data. They are dead but we could not or chose not to delete
4d727d86b245063f00c5bfd98d138a63e0b7de6dMichael Graff * them when we deleted all the data at that node because we did not want
4d727d86b245063f00c5bfd98d138a63e0b7de6dMichael Graff * to wait for the tree write lock.
4d727d86b245063f00c5bfd98d138a63e0b7de6dMichael Graff * The caller must hold a tree write lock and bucketnum'th node (write) lock.
4d727d86b245063f00c5bfd98d138a63e0b7de6dMichael Graffcleanup_dead_nodes(dns_rbtdb_t *rbtdb, int bucketnum) {
4d727d86b245063f00c5bfd98d138a63e0b7de6dMichael Graff int count = 10; /* XXXJT: should be adjustable */
4d727d86b245063f00c5bfd98d138a63e0b7de6dMichael Graff node = ISC_LIST_HEAD(rbtdb->deadnodes[bucketnum]);
4d727d86b245063f00c5bfd98d138a63e0b7de6dMichael Graff ISC_LIST_UNLINK(rbtdb->deadnodes[bucketnum], node, deadlink);
4d727d86b245063f00c5bfd98d138a63e0b7de6dMichael Graff * Since we're holding a tree write lock, it should be
4d727d86b245063f00c5bfd98d138a63e0b7de6dMichael Graff * impossible for this node to be referenced by others.
29f28fe573d4b3b318b3b026d567c1eb86738015Michael Graff node = ISC_LIST_HEAD(rbtdb->deadnodes[bucketnum]);
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff * Caller must be holding the node lock.
29f28fe573d4b3b318b3b026d567c1eb86738015Michael Graffstatic inline void
4d727d86b245063f00c5bfd98d138a63e0b7de6dMichael Graffnew_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node) {
4d727d86b245063f00c5bfd98d138a63e0b7de6dMichael Graff if (noderefs == 1) { /* this is the first reference to the node */
d8590892d10fc9528b0dde7e2781935e7b8d7a87Michael Graff lockref = &rbtdb->node_locks[node->locknum].references;
f36a81c88493985ee2d1c53cc6fe88f4b00dbbc8Michael Graff * This function is assumed to be called when a node is newly referenced
f36a81c88493985ee2d1c53cc6fe88f4b00dbbc8Michael Graff * and can be in the deadnode list. In that case the node must be retrieved
f00d96a15cdd11e764437f9359e67328631caaeaMichael Graff * from the list because it is going to be used. In addition, if the caller
f36a81c88493985ee2d1c53cc6fe88f4b00dbbc8Michael Graff * happens to hold a write lock on the tree, it's a good chance to purge dead
f36a81c88493985ee2d1c53cc6fe88f4b00dbbc8Michael Graff * Note: while a new reference is gained in multiple places, there are only very
f36a81c88493985ee2d1c53cc6fe88f4b00dbbc8Michael Graff * few cases where the node can be in the deadnode list (only empty nodes can
f36a81c88493985ee2d1c53cc6fe88f4b00dbbc8Michael Graff * have been added to the list).
f36a81c88493985ee2d1c53cc6fe88f4b00dbbc8Michael Graffstatic inline void
f36a81c88493985ee2d1c53cc6fe88f4b00dbbc8Michael Graffreactivate_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
f00d96a15cdd11e764437f9359e67328631caaeaMichael Graff isc_rwlocktype_t locktype = isc_rwlocktype_read;
f00d96a15cdd11e764437f9359e67328631caaeaMichael Graff nodelock_t *nodelock = &rbtdb->node_locks[node->locknum].lock;
ca924f706b53b895a662de8345d88437b23b8f01Michael Graff * Check if we can possibly cleanup the dead node. If so, upgrade
ca924f706b53b895a662de8345d88437b23b8f01Michael Graff * the node lock below to perform the cleanup.
ca924f706b53b895a662de8345d88437b23b8f01Michael Graff if (!ISC_LIST_EMPTY(rbtdb->deadnodes[node->locknum]) &&
ca924f706b53b895a662de8345d88437b23b8f01Michael Graff if (ISC_LINK_LINKED(node, deadlink) || maybe_cleanup) {
ca924f706b53b895a662de8345d88437b23b8f01Michael Graff * Upgrade the lock and test if we still need to unlink.
ca924f706b53b895a662de8345d88437b23b8f01Michael Graff ISC_LIST_UNLINK(rbtdb->deadnodes[node->locknum],
beb2b4f19624af46230a8e3df97e54d6c596573eMichael Graff * Caller must be holding the node lock; either the "strong", read or write
ca924f706b53b895a662de8345d88437b23b8f01Michael Graff * lock. Note that the lock must be held even when node references are
ca924f706b53b895a662de8345d88437b23b8f01Michael Graff * atomically modified; in that case the decrement operation itself does not
ca924f706b53b895a662de8345d88437b23b8f01Michael Graff * have to be protected, but we must avoid a race condition where multiple
ca924f706b53b895a662de8345d88437b23b8f01Michael Graff * threads are decreasing the reference to zero simultaneously and at least
beb2b4f19624af46230a8e3df97e54d6c596573eMichael Graff * one of them is going to free the node.
beb2b4f19624af46230a8e3df97e54d6c596573eMichael Graff * This function returns ISC_TRUE if and only if the node reference decreases
beb2b4f19624af46230a8e3df97e54d6c596573eMichael Graffdecrement_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
beb2b4f19624af46230a8e3df97e54d6c596573eMichael Graff isc_rwlocktype_t nlock, isc_rwlocktype_t tlock,
beb2b4f19624af46230a8e3df97e54d6c596573eMichael Graff#define KEEP_NODE(n, r) \
beb2b4f19624af46230a8e3df97e54d6c596573eMichael Graff ((n)->data != NULL || (n)->down != NULL || (n) == (r)->origin_node)
if (nrefs == 0) {
if (nrefs > 0) {
return (ISC_FALSE);
if (least_serial == 0) {
goto restore_locks;
if (write_locked) {
sizeof(isc_event_t));
deadlink);
node,
sizeof(printname)));
if (write_locked)
if (write_locked)
return (no_reference);
unsigned int locknum;
if (!haszonekey) {
while (count-- > 0U) {
®ion);
NULL);
goto unlock;
unsigned int locknum;
unsigned int refs;
if (again)
if (refs == 0)
unsigned int refs;
if (commit) {
goto end;
if (commit) {
unsigned cur_ref;
&cur_ref);
if (cur_ref == 0) {
&cleanup_list);
if (cur_ref == 0) {
link);
&cur_ref);
&cleanup_list);
link);
sizeof(*cleanup_version));
if (rollback)
if (rollback)
sizeof(*changed));
end:
static isc_result_t
return (result);
return (ISC_R_SUCCESS);
static isc_result_t
return (result);
&node);
return (result);
return (ISC_R_SUCCESS);
static isc_result_t
if (!create) {
return (result);
return (result);
#ifdef DNS_RBT_USEHASH
return (result);
return (result);
return (ISC_R_SUCCESS);
static isc_result_t
static isc_result_t
static isc_result_t
return (DNS_R_CONTINUE);
return (result);
static inline isc_result_t
return (result);
return (DNS_R_DNAME);
return (DNS_R_DELEGATION);
static inline isc_boolean_t
return (ISC_FALSE);
return (ISC_FALSE);
while (count > 0) {
count--;
return (valid);
static inline isc_boolean_t
return (answer);
static inline isc_boolean_t
return (answer);
static inline isc_result_t
if (wild) {
&name,
NULL);
wname)) {
return (ISC_R_NOTFOUND);
if (active) {
} while (!done);
return (result);
static isc_boolean_t
while (count-- > 0) {
return (ISC_TRUE);
return (ISC_FALSE);
static inline isc_result_t
return (result);
nodep);
return (result);
if (*firstp) {
return (result);
return (result);
return (result);
return (result);
return (DNS_R_BADDB);
static inline isc_result_t
return (result);
if (!empty_node) {
NULL);
node);
rdataset);
node,
&prevnode,
&first);
if (!first)
goto again;
return (result);
static isc_result_t
goto tree_exit;
goto tree_exit;
goto found;
goto tree_exit;
goto tree_exit;
goto tree_exit;
if (maybe_zonecut &&
goto partial_match;
cname_ok)) {
cname_ok) {
sigtype =
} else if (cname_ok &&
if (empty_node) {
if (!wild) {
goto partial_match;
goto tree_exit;
if (!wild) {
goto node_exit;
goto tree_exit;
goto node_exit;
0, rdataset);
if (wild)
goto node_exit;
goto tree_exit;
if (!at_zonecut)
if (wild)
if (close_version)
return (result);
static isc_result_t
return (ISC_R_NOTIMPLEMENTED);
static isc_result_t
mctx,
header);
header);
header);
return (result);
static inline isc_result_t
RBTDB_VIRTUAL) &&
isc_mem_t *m;
m, header);
header);
header);
&name);
result =
&name,
NULL);
goto node_exit;
rdataset);
} while (!done);
return (result);
static isc_result_t
return (result);
isc_mem_t *m;
m, header);
header);
header);
goto unlock_node;
} else if (!empty_node) {
NULL);
return (result);
static isc_result_t
return (result);
static isc_result_t
if (now == 0)
goto tree_exit;
goto tree_exit;
goto tree_exit;
goto tree_exit;
header);
header);
cname_ok &&
} else if (cname_ok &&
if (empty_node) {
goto find_ns;
rdataset);
goto node_exit;
goto find_ns;
rdataset);
return (result);
static isc_result_t
if (now == 0)
goto tree_exit;
goto tree_exit;
header);
header);
goto find_ns;
return (result);
unsigned int refs;
if (inactive) {
if (want_free) {
sizeof(buf));
static isc_result_t
if (now == 0)
if (log)
sizeof(printname)));
if (log)
} else if (force_expire) {
} else if (log) {
return (ISC_R_SUCCESS);
/* This is an empty callback. See adb.c:water() */
if (!first)
static isc_result_t
return (ISC_R_NOMEMORY);
return (ISC_R_SUCCESS);
static isc_result_t
now = 0;
if (covers == 0)
sigmatchtype = 0;
if (close_version)
return (ISC_R_NOTFOUND);
return (ISC_R_SUCCESS);
static isc_result_t
if (now == 0)
if (covers == 0)
sigmatchtype = 0;
return (ISC_R_NOTFOUND);
return (result);
static isc_result_t
unsigned int refs;
return (ISC_R_NOMEMORY);
now = 0;
unsigned int refs;
&refs);
if (now == 0)
return (ISC_R_SUCCESS);
static isc_boolean_t
return (ISC_TRUE);
return (ISC_FALSE);
static isc_result_t
return (result);
static isc_result_t
unsigned char *merged;
int idx;
return (ISC_R_NOMEMORY);
negtype = 0;
goto find_header;
return (DNS_R_UNCHANGED);
goto find_header;
return (DNS_R_UNCHANGED);
return (DNS_R_UNCHANGED);
if (merge) {
unsigned int flags = 0;
(unsigned char *)header,
(unsigned char *)newheader,
(unsigned int)(sizeof(*newheader)),
return (result);
(unsigned char *)newheader,
(unsigned int)(sizeof(*newheader)),
return (ISC_R_SUCCESS);
(unsigned char *)newheader,
(unsigned int)(sizeof(*newheader)))) {
return (ISC_R_SUCCESS);
if (loading) {
if (newheader_nx) {
return (DNS_R_UNCHANGED);
return (DNS_R_CNAMEANDOTHER);
return (ISC_R_SUCCESS);
static inline isc_boolean_t
return (ISC_TRUE);
return (ISC_FALSE);
return (ISC_TRUE);
return (ISC_FALSE);
static inline isc_result_t
isc_region_t r;
goto cleanup;
goto cleanup;
goto cleanup;
goto cleanup;
return (ISC_R_SUCCESS);
return(result);
static inline isc_result_t
isc_region_t r;
goto cleanup;
goto cleanup;
goto cleanup;
goto cleanup;
return (ISC_R_SUCCESS);
return(result);
static isc_result_t
if (now == 0)
now = 0;
return (result);
now = 0;
return (result);
return (result);
if (cache_is_overmem)
if (tree_locked)
if (newnsec) {
if (tree_locked)
return (result);
static isc_result_t
unsigned char *subresult;
®ion,
sizeof(rdatasetheader_t));
return (result);
return (ISC_R_NOMEMORY);
unsigned int flags = 0;
(unsigned char *)header,
(unsigned char *)newheader,
(unsigned int)(sizeof(*newheader)),
goto unlock;
goto unlock;
return (result);
static isc_result_t
return (ISC_R_NOTIMPLEMENTED);
return (ISC_R_NOTIMPLEMENTED);
return (ISC_R_NOMEMORY);
return (result);
static isc_result_t
name);
if (!hasnsec)
goto done;
goto done;
goto done;
goto done;
goto done;
done:
return (noderesult);
static isc_result_t
return (DNS_R_NOTZONETOP);
return (DNS_R_INVALIDNS);
return (DNS_R_INVALIDNSEC3);
return (result);
return (result);
#ifdef DNS_RBT_USEHASH
®ion,
sizeof(rdatasetheader_t));
return (result);
return (result);
static isc_result_t
p = (unsigned char *) header;
#ifdef DEBUG
return (result);
return (ISC_R_INVALIDFILE);
return (ISC_R_INVALIDFILE);
return (ISC_R_SUCCESS);
static isc_result_t
int fd;
char *base;
#ifdef MAP_FILE
return (ISC_R_FAILURE);
return (result);
return (result);
return (result);
return (ISC_R_SUCCESS);
static isc_result_t
return (ISC_R_NOMEMORY);
sizeof(*loadctx));
return (result);
return (ISC_R_SUCCESS);
static isc_result_t
return (ISC_R_SUCCESS);
static isc_result_t
char pad[sizeof(char *)];
sizeof(rdatasetheader_t));
p = (unsigned char *) header;
return (ISC_R_RANGE);
#ifdef DEBUG
sizeof(rdatasetheader_t));
sizeof(rdatasetheader_t));
return (result);
static isc_result_t
return (result);
static isc_result_t
return (result);
static isc_result_t
return (result);
static isc_result_t
unsigned int locknum;
static isc_boolean_t
return (secure);
static isc_boolean_t
return (dnssec);
unsigned int count;
return (count);
unsigned int count;
return (count);
static isc_boolean_t
return (ISC_FALSE);
static isc_result_t
return (result);
static isc_result_t
return (result);
static isc_result_t
header--;
if (resign == 0) {
return (result);
static isc_result_t
unsigned int locknum;
goto unlock;
return (result);
header--;
static isc_result_t
return (ISC_R_SUCCESS);
static dns_stats_t *
dump,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
dump,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
#ifdef DNS_RBTDB_VERSION64
return (ISC_R_NOMEMORY);
if (argc != 0)
goto cleanup_rbtdb;
goto cleanup_lock;
goto cleanup_tree_lock;
sizeof(rbtdb_nodelock_t));
goto cleanup_tree_lock;
goto cleanup_node_locks;
sizeof(rdatasetheaderlist_t));
goto cleanup_rrsetstats;
sizeof(isc_heap_t *));
goto cleanup_rdatasets;
goto cleanup_heaps;
sizeof(rbtnodelist_t));
goto cleanup_heaps;
goto cleanup_deadnodes;
return (result);
return (result);
return (result);
return (result);
return (result);
#ifdef DNS_RBT_USEHASH
&nsec3node);
return (result);
#ifdef DNS_RBT_USEHASH
return (result);
return (ISC_R_NOMEMORY);
return (ISC_R_SUCCESS);
sizeof(rdatasetheaderlist_t));
return (result);
static isc_result_t
unsigned int count;
if (count == 0) {
return (ISC_R_NOMORE);
count--;
return (ISC_R_SUCCESS);
static isc_result_t
unsigned int count;
unsigned int length;
if (count == 0)
return (ISC_R_NOMORE);
count--;
return (ISC_R_SUCCESS);
unsigned int offset;
unsigned int length;
isc_region_t r;
unsigned int flags = 0;
length--;
raw++;
unsigned int count;
return (count);
static isc_result_t
return (ISC_R_SUCCESS);
static isc_result_t
return (ISC_R_SUCCESS);
header--;
header--;
sizeof(*rbtiterator));
static isc_result_t
now = 0;
return (ISC_R_NOMORE);
return (ISC_R_SUCCESS);
static isc_result_t
return (ISC_R_NOMORE);
now = 0;
RDATASET_ATTR_NONEXISTENT) != 0 ||
return (ISC_R_NOMORE);
return (ISC_R_SUCCESS);
rdataset);
if (was_read_locked) {
static isc_result_t
origin);
return (result);
static isc_result_t
return (result);
static isc_result_t
return (result);
static isc_result_t
return (result);
static isc_result_t
return (result);
static isc_result_t
return (result);
unsigned int refs;
return (result);
static isc_result_t
return (ISC_R_SUCCESS);
return (ISC_R_SUCCESS);
static isc_result_t
static isc_result_t
unsigned int count;
unsigned int total_count;
switch (type) {
INSIST(0);
return (ISC_R_NOTFOUND);
return (ISC_R_NOTFOUND);
return (result);
unsigned int count;
INSIST(0);
static isc_result_t
return (ISC_R_SUCCESS);
return (ISC_R_NOMEMORY);
goto fail;
goto fail;
switch (type) {
INSIST(0);
sizeof(acachectl_t));
goto fail;
for (i = 0; i < total_count; i++) {
switch (type) {
INSIST(0);
return (ISC_R_SUCCESS);
fail:
&newcbarg);
sizeof(*newcbarg));
return (result);
static isc_result_t
return (ISC_R_SUCCESS);
switch (type) {
INSIST(0);
return (ISC_R_NOTFOUND);
return (ISC_R_NOTFOUND);
return (ISC_R_SUCCESS);
static inline isc_boolean_t
return (ISC_FALSE);
return (ISC_TRUE);
unsigned int locknum;
purgecount--;
link);
purgecount--;
switch (reason) {
case expire_ttl:
case expire_lru: