⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rbtdb.c

📁 bind 9.3结合mysql数据库
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Copyright (C) 2004  Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003  Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. *//* $Id: rbtdb.c,v 1.168.2.11.2.16 2004/05/23 11:07:23 marka Exp $ *//* * Principal Author: Bob Halley */#include <config.h>#include <isc/event.h>#include <isc/mem.h>#include <isc/print.h>#include <isc/mutex.h>#include <isc/random.h>#include <isc/refcount.h>#include <isc/rwlock.h>#include <isc/string.h>#include <isc/task.h>#include <isc/util.h>#include <dns/db.h>#include <dns/dbiterator.h>#include <dns/events.h>#include <dns/fixedname.h>#include <dns/log.h>#include <dns/masterdump.h>#include <dns/rbt.h>#include <dns/rdata.h>#include <dns/rdataset.h>#include <dns/rdatasetiter.h>#include <dns/rdataslab.h>#include <dns/result.h>#include <dns/zonekey.h>#ifdef DNS_RBTDB_VERSION64#include "rbtdb64.h"#else#include "rbtdb.h"#endif#ifdef DNS_RBTDB_VERSION64#define RBTDB_MAGIC			ISC_MAGIC('R', 'B', 'D', '8')#else#define RBTDB_MAGIC			ISC_MAGIC('R', 'B', 'D', '4')#endif/* * Note that "impmagic" is not the first four bytes of the struct, so * ISC_MAGIC_VALID cannot be used. */#define VALID_RBTDB(rbtdb)	((rbtdb) != NULL && \				 (rbtdb)->common.impmagic == RBTDB_MAGIC)#ifdef DNS_RBTDB_VERSION64typedef isc_uint64_t			rbtdb_serial_t;/* * Make casting easier in symbolic debuggers by using different names * for the 64 bit version. */#define dns_rbtdb_t dns_rbtdb64_t#define rdatasetheader_t rdatasetheader64_t#define rbtdb_version_t rbtdb_version64_t#elsetypedef isc_uint32_t			rbtdb_serial_t;#endiftypedef isc_uint32_t			rbtdb_rdatatype_t;#define RBTDB_RDATATYPE_BASE(type)	((dns_rdatatype_t)((type) & 0xFFFF))#define RBTDB_RDATATYPE_EXT(type)	((dns_rdatatype_t)((type) >> 16))#define RBTDB_RDATATYPE_VALUE(b, e)	(((e) << 16) | (b))#define RBTDB_RDATATYPE_SIGNSEC \		RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_nsec)#define RBTDB_RDATATYPE_SIGNS \		RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_ns)#define RBTDB_RDATATYPE_SIGCNAME \		RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_cname)#define RBTDB_RDATATYPE_SIGDNAME \		RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_dname)#define RBTDB_RDATATYPE_NCACHEANY \		RBTDB_RDATATYPE_VALUE(0, dns_rdatatype_any)struct noqname {	dns_name_t name;	void *	   nsec;	void *	   nsecsig;};typedef struct rdatasetheader {	/*	 * Locked by the owning node's lock.	 */	rbtdb_serial_t			serial;	dns_ttl_t			ttl;	rbtdb_rdatatype_t		type;	isc_uint16_t			attributes;	dns_trust_t			trust;	struct noqname			*noqname;	/*	 * We don't use the LIST macros, because the LIST structure has	 * both head and tail pointers, and is doubly linked.	 */	struct rdatasetheader		*next;	/*	 * If this is the top header for an rdataset, 'next' points	 * to the top header for the next rdataset (i.e., the next type).	 * Otherwise, it points up to the header whose down pointer points	 * at this header.	 */	  	struct rdatasetheader		*down;	/*	 * Points to the header for the next older version of	 * this rdataset.	 */	isc_uint32_t			count;	/*	 * Monotonously increased every time this rdataset is bound so that	 * it is used as the base of the starting point in DNS responses	 * when the "cyclic" rrset-order is required.  Since the ordering	 * should not be so crucial, no lock is set for the counter for	 * performance reasons.	 */} rdatasetheader_t;#define RDATASET_ATTR_NONEXISTENT	0x0001#define RDATASET_ATTR_STALE		0x0002#define RDATASET_ATTR_IGNORE		0x0004#define RDATASET_ATTR_RETAIN		0x0008#define RDATASET_ATTR_NXDOMAIN		0x0010/* * XXX * When the cache will pre-expire data (due to memory low or other * situations) before the rdataset's TTL has expired, it MUST * respect the RETAIN bit and not expire the data until its TTL is * expired. */#undef IGNORE			/* WIN32 winbase.h defines this. */#define EXISTS(header) \	(((header)->attributes & RDATASET_ATTR_NONEXISTENT) == 0)#define NONEXISTENT(header) \	(((header)->attributes & RDATASET_ATTR_NONEXISTENT) != 0)#define IGNORE(header) \	(((header)->attributes & RDATASET_ATTR_IGNORE) != 0)#define RETAIN(header) \	(((header)->attributes & RDATASET_ATTR_RETAIN) != 0)#define NXDOMAIN(header) \	(((header)->attributes & RDATASET_ATTR_NXDOMAIN) != 0)#define DEFAULT_NODE_LOCK_COUNT		7		/* Should be prime. */typedef struct {	isc_mutex_t			lock;	/* Locked by lock. */	unsigned int			references;	isc_boolean_t			exiting;} rbtdb_nodelock_t;typedef struct rbtdb_changed {	dns_rbtnode_t *			node;	isc_boolean_t			dirty;	ISC_LINK(struct rbtdb_changed)	link;} rbtdb_changed_t;typedef ISC_LIST(rbtdb_changed_t)	rbtdb_changedlist_t;typedef struct rbtdb_version {	/* Not locked */	rbtdb_serial_t			serial;	/* Locked by database lock. */	isc_boolean_t			writer;	unsigned int			references;	isc_boolean_t			commit_ok;	rbtdb_changedlist_t		changed_list;	ISC_LINK(struct rbtdb_version)	link;} rbtdb_version_t;typedef ISC_LIST(rbtdb_version_t)	rbtdb_versionlist_t;typedef struct {	/* Unlocked. */	dns_db_t			common;	isc_mutex_t			lock;	isc_rwlock_t			tree_lock;	unsigned int			node_lock_count;	rbtdb_nodelock_t *	       	node_locks;	dns_rbtnode_t *			origin_node;	/* Locked by lock. */	unsigned int			active;	isc_refcount_t			references;	unsigned int			attributes;	rbtdb_serial_t			current_serial;	rbtdb_serial_t			least_serial;	rbtdb_serial_t			next_serial;	rbtdb_version_t *		current_version;	rbtdb_version_t *		future_version;	rbtdb_versionlist_t		open_versions;	isc_boolean_t			overmem;	isc_task_t *			task;	/* Locked by tree_lock. */	dns_rbt_t *			tree;	isc_boolean_t			secure;} dns_rbtdb_t;#define RBTDB_ATTR_LOADED		0x01#define RBTDB_ATTR_LOADING		0x02/* * Search Context */typedef struct {	dns_rbtdb_t *		rbtdb;	rbtdb_version_t *	rbtversion;	rbtdb_serial_t		serial;	unsigned int		options;	dns_rbtnodechain_t	chain;	isc_boolean_t		copy_name;	isc_boolean_t		need_cleanup;	isc_boolean_t		wild;	dns_rbtnode_t *	       	zonecut;	rdatasetheader_t *	zonecut_rdataset;	rdatasetheader_t *	zonecut_sigrdataset;	dns_fixedname_t		zonecut_name;	isc_stdtime_t		now;} rbtdb_search_t;/* * Load Context */typedef struct {	dns_rbtdb_t *		rbtdb;	isc_stdtime_t		now;} rbtdb_load_t;static void rdataset_disassociate(dns_rdataset_t *rdataset);static isc_result_t rdataset_first(dns_rdataset_t *rdataset);static isc_result_t rdataset_next(dns_rdataset_t *rdataset);static void rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata);static void rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target);static unsigned int rdataset_count(dns_rdataset_t *rdataset);static isc_result_t rdataset_getnoqname(dns_rdataset_t *rdataset,				        dns_name_t *name,					dns_rdataset_t *nsec,					dns_rdataset_t *nsecsig);static dns_rdatasetmethods_t rdataset_methods = {	rdataset_disassociate,	rdataset_first,	rdataset_next,	rdataset_current,	rdataset_clone,	rdataset_count,	NULL,	rdataset_getnoqname};static void rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp);static isc_result_t rdatasetiter_first(dns_rdatasetiter_t *iterator);static isc_result_t rdatasetiter_next(dns_rdatasetiter_t *iterator);static void rdatasetiter_current(dns_rdatasetiter_t *iterator,				 dns_rdataset_t *rdataset);static dns_rdatasetitermethods_t rdatasetiter_methods = {	rdatasetiter_destroy,	rdatasetiter_first,	rdatasetiter_next,	rdatasetiter_current};typedef struct rbtdb_rdatasetiter {	dns_rdatasetiter_t		common;	rdatasetheader_t *		current;} rbtdb_rdatasetiter_t;static void		dbiterator_destroy(dns_dbiterator_t **iteratorp);static isc_result_t	dbiterator_first(dns_dbiterator_t *iterator);static isc_result_t	dbiterator_last(dns_dbiterator_t *iterator);static isc_result_t	dbiterator_seek(dns_dbiterator_t *iterator,					dns_name_t *name);static isc_result_t	dbiterator_prev(dns_dbiterator_t *iterator);static isc_result_t	dbiterator_next(dns_dbiterator_t *iterator);static isc_result_t	dbiterator_current(dns_dbiterator_t *iterator,					   dns_dbnode_t **nodep,					   dns_name_t *name);static isc_result_t	dbiterator_pause(dns_dbiterator_t *iterator);static isc_result_t	dbiterator_origin(dns_dbiterator_t *iterator,					  dns_name_t *name);static dns_dbiteratormethods_t dbiterator_methods = {	dbiterator_destroy,	dbiterator_first,	dbiterator_last,	dbiterator_seek,	dbiterator_prev,	dbiterator_next,	dbiterator_current,	dbiterator_pause,	dbiterator_origin};#define DELETION_BATCH_MAX 64/* * If 'paused' is ISC_TRUE, then the tree lock is not being held. */typedef struct rbtdb_dbiterator {	dns_dbiterator_t		common;	isc_boolean_t			paused;	isc_boolean_t			new_origin;	isc_rwlocktype_t		tree_locked;	isc_result_t			result;	dns_fixedname_t			name;	dns_fixedname_t			origin;	dns_rbtnodechain_t		chain;	dns_rbtnode_t			*node;	dns_rbtnode_t			*deletions[DELETION_BATCH_MAX];	int				delete;} rbtdb_dbiterator_t;#define IS_STUB(rbtdb)  (((rbtdb)->common.attributes & DNS_DBATTR_STUB)  != 0)#define IS_CACHE(rbtdb) (((rbtdb)->common.attributes & DNS_DBATTR_CACHE) != 0)static void free_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t log,		       isc_event_t *event);/* * Locking * * If a routine is going to lock more than one lock in this module, then * the locking must be done in the following order: * *	Tree Lock * *	Node Lock	(Only one from the set may be locked at one time by *			 any caller) * *	Database Lock * * Failure to follow this hierarchy can result in deadlock. *//* * Deleting Nodes * * Currently there is no deletion of nodes from the database, except when * the database is being destroyed. * * If node deletion is added in the future, then for zone databases the node * for the origin of the zone MUST NOT be deleted. *//* * DB Routines */static voidattach(dns_db_t *source, dns_db_t **targetp) {	dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)source;	REQUIRE(VALID_RBTDB(rbtdb));	isc_refcount_increment(&rbtdb->references, NULL);	*targetp = source;}static voidfree_rbtdb_callback(isc_task_t *task, isc_event_t *event) {	dns_rbtdb_t *rbtdb = event->ev_arg;	UNUSED(task);	free_rbtdb(rbtdb, ISC_TRUE, event);}static voidfree_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t log, isc_event_t *event) {	unsigned int i;	isc_ondestroy_t ondest;	isc_result_t result;	char buf[DNS_NAME_FORMATSIZE];	REQUIRE(EMPTY(rbtdb->open_versions));	REQUIRE(rbtdb->future_version == NULL);	if (rbtdb->current_version != NULL)		isc_mem_put(rbtdb->common.mctx, rbtdb->current_version,			    sizeof(rbtdb_version_t)); again:	if (rbtdb->tree != NULL) {		result = dns_rbt_destroy2(&rbtdb->tree,					  (rbtdb->task != NULL) ? 5 : 0);		if (result == ISC_R_QUOTA) {			INSIST(rbtdb->task != NULL);			if (event == NULL)				event = isc_event_allocate(rbtdb->common.mctx,							   NULL,						         DNS_EVENT_FREESTORAGE,							   free_rbtdb_callback,							   rbtdb,							   sizeof(isc_event_t));			if (event == NULL)				goto again;			isc_task_send(rbtdb->task, &event);			return;		}		INSIST(result == ISC_R_SUCCESS && rbtdb->tree == NULL);	}	if (event != NULL)		isc_event_free(&event);	if (log) {		if (dns_name_dynamic(&rbtdb->common.origin))			dns_name_format(&rbtdb->common.origin, buf,					sizeof(buf));		else			strcpy(buf, "<UNKNOWN>");		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,			      DNS_LOGMODULE_CACHE, ISC_LOG_DEBUG(1),			      "done free_rbtdb(%s)", buf);	}	if (dns_name_dynamic(&rbtdb->common.origin))		dns_name_free(&rbtdb->common.origin, rbtdb->common.mctx);	for (i = 0; i < rbtdb->node_lock_count; i++)		DESTROYLOCK(&rbtdb->node_locks[i].lock);	isc_mem_put(rbtdb->common.mctx, rbtdb->node_locks,		    rbtdb->node_lock_count * sizeof(rbtdb_nodelock_t));	isc_rwlock_destroy(&rbtdb->tree_lock);	isc_refcount_destroy(&rbtdb->references);	if (rbtdb->task != NULL)		isc_task_detach(&rbtdb->task);	DESTROYLOCK(&rbtdb->lock);	rbtdb->common.magic = 0;	rbtdb->common.impmagic = 0;	ondest = rbtdb->common.ondest;	isc_mem_putanddetach(&rbtdb->common.mctx, rbtdb, sizeof(*rbtdb));	isc_ondestroy_notify(&ondest, rbtdb);}static inline voidmaybe_free_rbtdb(dns_rbtdb_t *rbtdb) {	isc_boolean_t want_free = ISC_FALSE;	unsigned int i;	unsigned int inactive = 0;	/* XXX check for open versions here */	/*	 * Even though there are no external direct references, there still	 * may be nodes in use.	 */	for (i = 0; i < rbtdb->node_lock_count; i++) {		LOCK(&rbtdb->node_locks[i].lock);		rbtdb->node_locks[i].exiting = ISC_TRUE;		if (rbtdb->node_locks[i].references == 0)			inactive++;		UNLOCK(&rbtdb->node_locks[i].lock);	}	if (inactive != 0) {		LOCK(&rbtdb->lock);		rbtdb->active -= inactive;		if (rbtdb->active == 0)			want_free = ISC_TRUE;		UNLOCK(&rbtdb->lock);		if (want_free) {			char buf[DNS_NAME_FORMATSIZE];			if (dns_name_dynamic(&rbtdb->common.origin))				dns_name_format(&rbtdb->common.origin, buf,						sizeof(buf));			else				strcpy(buf, "<UNKNOWN>");			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,				      DNS_LOGMODULE_CACHE, ISC_LOG_DEBUG(1),				      "calling free_rbtdb(%s)", buf);			free_rbtdb(rbtdb, ISC_TRUE, NULL);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -