1582. [bug] rrset-order failed to work on RRsets with more
than 32 elements. [RT #10381]
+1580. [bug] Zone destuction on final detach takes a long time.
+ [RT #3746]
+
+1579. [bug] Multiple task managers could not be created.
+
1578. [bug] Don't use CLASS E IPv4 addresses when resolving.
[RT #10346]
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: db.c,v 1.69.2.3 2003/10/09 07:32:36 marka Exp $ */
+/* $Id: db.c,v 1.69.2.4 2004/03/04 06:56:26 marka Exp $ */
/***
*** Imports
return ((db->methods->nodecount)(db));
}
+void
+dns_db_settask(dns_db_t *db, isc_task_t *task) {
+ REQUIRE(DNS_DB_VALID(db));
+
+ (db->methods->settask)(db, task);
+}
+
isc_result_t
dns_db_register(const char *name, dns_dbcreatefunc_t create, void *driverarg,
isc_mem_t *mctx, dns_dbimplementation_t **dbimp)
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: db.h,v 1.67.2.2 2003/10/09 07:32:39 marka Exp $ */
+/* $Id: db.h,v 1.67.2.3 2004/03/04 06:56:27 marka Exp $ */
#ifndef DNS_DB_H
#define DNS_DB_H 1
unsigned int (*nodecount)(dns_db_t *db);
isc_boolean_t (*ispersistent)(dns_db_t *db);
void (*overmem)(dns_db_t *db, isc_boolean_t overmem);
+ void (*settask)(dns_db_t *db, isc_task_t *);
} dns_dbmethods_t;
typedef isc_result_t
* The number of nodes in the database
*/
+void
+dns_db_settask(dns_db_t *db, isc_task_t *task);
+/*
+ * If task is set then the final detach maybe performed asynchronously.
+ *
+ * Requires:
+ * 'db' is a valid database.
+ * 'task' to be valid or NULL.
+ */
+
isc_boolean_t
dns_db_ispersistent(dns_db_t *db);
/*
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: events.h,v 1.37.2.1 2002/09/04 02:47:08 jinmei Exp $ */
+/* $Id: events.h,v 1.37.2.2 2004/03/04 06:56:28 marka Exp $ */
#ifndef DNS_EVENTS_H
#define DNS_EVENTS_H 1
#define DNS_EVENT_DISPATCHCONTROL (ISC_EVENTCLASS_DNS + 32)
#define DNS_EVENT_REQUESTCONTROL (ISC_EVENTCLASS_DNS + 33)
#define DNS_EVENT_IMPORTRECVDONE (ISC_EVENTCLASS_DNS + 35)
+#define DNS_EVENT_FREESTORAGE (ISC_EVENTCLASS_DNS + 36)
#define DNS_EVENT_FIRSTEVENT (ISC_EVENTCLASS_DNS + 0)
#define DNS_EVENT_LASTEVENT (ISC_EVENTCLASS_DNS + 65535)
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rbt.h,v 1.55 2001/06/01 03:07:54 halley Exp $ */
+/* $Id: rbt.h,v 1.55.2.1 2004/03/04 06:56:28 marka Exp $ */
#ifndef DNS_RBT_H
#define DNS_RBT_H 1
void
dns_rbt_destroy(dns_rbt_t **rbtp);
+isc_result_t
+dns_rbt_destroy2(dns_rbt_t **rbtp, unsigned int quantum);
/*
- * Stop working with a red-black tree of trees.
+ * Stop working with a red-black tree of trees. Once dns_rbt_destroy2()
+ * has been called on a 'rbt' only dns_rbt_destroy() or dns_rbt_destroy2()
+ * may be used on the tree. If 'quantum' is zero then the entire tree will
+ * be destroyed.
*
* Requires:
* *rbt is a valid rbt manager.
* All space allocated by the RBT library has been returned.
*
* *rbt is invalidated as an rbt manager.
+ *
+ * Returns:
+ * ISC_R_SUCCESS
+ * ISC_R_QUOTA if 'quantum' nodes have been destroyed.
*/
void
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rbt.c,v 1.115.2.3 2004/03/03 22:38:20 marka Exp $ */
+/* $Id: rbt.c,v 1.115.2.4 2004/03/04 06:56:26 marka Exp $ */
/* Principal Authors: DCL */
#include <config.h>
#include <isc/mem.h>
+#include <isc/platform.h>
#include <isc/print.h>
#include <isc/string.h>
#include <isc/util.h>
unsigned int nodecount;
unsigned int hashsize;
dns_rbtnode_t ** hashtable;
+ unsigned int quantum;
};
#define RED 0
static void
dns_rbt_deletefromlevel(dns_rbtnode_t *delete, dns_rbtnode_t **rootp);
-static void
+static isc_result_t
dns_rbt_deletetree(dns_rbt_t *rbt, dns_rbtnode_t *node);
+static void
+dns_rbt_deletetreeflat(dns_rbt_t *rbt, dns_rbtnode_t **nodep);
+
/*
* Initialize a red/black tree of trees.
*/
return (result);
}
#endif
+ rbt->quantum = 0;
rbt->magic = RBT_MAGIC;
*rbtp = rbt;
*/
void
dns_rbt_destroy(dns_rbt_t **rbtp) {
+ RUNTIME_CHECK(dns_rbt_destroy2(rbtp, 0) == ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_rbt_destroy2(dns_rbt_t **rbtp, unsigned int quantum) {
dns_rbt_t *rbt;
REQUIRE(rbtp != NULL && VALID_RBT(*rbtp));
rbt = *rbtp;
- dns_rbt_deletetree(rbt, rbt->root);
+ rbt->quantum = quantum;
+
+ dns_rbt_deletetreeflat(rbt, &rbt->root);
+ if (rbt->root != NULL)
+ return (ISC_R_QUOTA);
INSIST(rbt->nodecount == 0);
rbt->magic = 0;
isc_mem_put(rbt->mctx, rbt, sizeof(*rbt));
-
*rbtp = NULL;
+ return (ISC_R_SUCCESS);
}
unsigned int
if (DOWN(node) != NULL) {
if (recurse)
- dns_rbt_deletetree(rbt, DOWN(node));
-
+ RUNTIME_CHECK(dns_rbt_deletetree(rbt, DOWN(node))
+ == ISC_R_SUCCESS);
else {
if (DATA(node) != NULL && rbt->data_deleter != NULL)
rbt->data_deleter(DATA(node),
static inline void
hash_node(dns_rbt_t *rbt, dns_rbtnode_t *node) {
- if (rbt->nodecount >= rbt->hashsize)
+ if (rbt->nodecount >= (rbt->hashsize * 3))
rehash(rbt);
hash_add_node(rbt, node);
* a pointer needs to be told that this tree no longer exists,
* this function would need to adjusted accordingly.
*/
-static void
+static isc_result_t
dns_rbt_deletetree(dns_rbt_t *rbt, dns_rbtnode_t *node) {
+ isc_result_t result = ISC_R_SUCCESS;
REQUIRE(VALID_RBT(rbt));
if (node == NULL)
+ return (result);
+
+ if (LEFT(node) != NULL) {
+ result = dns_rbt_deletetree(rbt, LEFT(node));
+ if (result != ISC_R_SUCCESS)
+ goto done;
+ LEFT(node) = NULL;
+ }
+ if (RIGHT(node) != NULL) {
+ result = dns_rbt_deletetree(rbt, RIGHT(node));
+ if (result != ISC_R_SUCCESS)
+ goto done;
+ RIGHT(node) = NULL;
+ }
+ if (DOWN(node) != NULL) {
+ result = dns_rbt_deletetree(rbt, DOWN(node));
+ if (result != ISC_R_SUCCESS)
+ goto done;
+ DOWN(node) = NULL;
+ }
+ done:
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ if (rbt->quantum != 0 && --rbt->quantum == 0)
+ return (ISC_R_QUOTA);
+
+ if (DATA(node) != NULL && rbt->data_deleter != NULL)
+ rbt->data_deleter(DATA(node), rbt->deleter_arg);
+
+ unhash_node(rbt, node);
+#if DNS_RBT_USEMAGIC
+ node->magic = 0;
+#endif
+ isc_mem_put(rbt->mctx, node, NODE_SIZE(node));
+ rbt->nodecount--;
+ return (result);
+}
+
+static void
+dns_rbt_deletetreeflat(dns_rbt_t *rbt, dns_rbtnode_t **nodep) {
+ dns_rbtnode_t *parent;
+ dns_rbtnode_t *node = *nodep;
+ REQUIRE(VALID_RBT(rbt));
+
+ again:
+ if (node == NULL) {
+ *nodep = NULL;
return;
+ }
- if (LEFT(node) != NULL)
- dns_rbt_deletetree(rbt, LEFT(node));
- if (RIGHT(node) != NULL)
- dns_rbt_deletetree(rbt, RIGHT(node));
- if (DOWN(node) != NULL)
- dns_rbt_deletetree(rbt, DOWN(node));
+ traverse:
+ if (LEFT(node) != NULL) {
+ node = LEFT(node);
+ goto traverse;
+ }
+ if (RIGHT(node) != NULL) {
+ node = RIGHT(node);
+ goto traverse;
+ }
+ if (DOWN(node) != NULL) {
+ node = DOWN(node);
+ goto traverse;
+ }
if (DATA(node) != NULL && rbt->data_deleter != NULL)
rbt->data_deleter(DATA(node), rbt->deleter_arg);
unhash_node(rbt, node);
+ parent = PARENT(node);
+ if (parent != NULL) {
+ if (LEFT(parent) == node)
+ LEFT(parent) = NULL;
+ else if (DOWN(parent) == node)
+ DOWN(parent) = NULL;
+ else if (RIGHT(parent) == node)
+ RIGHT(parent) = NULL;
+ }
isc_mem_put(rbt->mctx, node, NODE_SIZE(node));
rbt->nodecount--;
+ node = parent;
+ if (rbt->quantum != 0 && --rbt->quantum == 0) {
+ *nodep = node;
+ return;
+ }
+ goto again;
}
static void
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rbtdb.c,v 1.168.2.14 2004/03/04 02:46:24 marka Exp $ */
+/* $Id: rbtdb.c,v 1.168.2.15 2004/03/04 06:56:26 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/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>
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;
#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
*
}
static void
-free_rbtdb(dns_rbtdb_t *rbtdb) {
+free_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 void
+free_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t log, isc_event_t *event) {
unsigned int i;
isc_ondestroy_t ondest;
- isc_mem_t *mctx;
+ 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);
- if (rbtdb->tree != NULL)
- dns_rbt_destroy(&rbtdb->tree);
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;
- mctx = rbtdb->common.mctx;
- isc_mem_put(mctx, rbtdb, sizeof *rbtdb);
- isc_mem_detach(&mctx);
+ isc_mem_putanddetach(&rbtdb->common.mctx, rbtdb, sizeof(*rbtdb));
isc_ondestroy_notify(&ondest, rbtdb);
}
if (rbtdb->active == 0)
want_free = ISC_TRUE;
UNLOCK(&rbtdb->lock);
- if (want_free)
- free_rbtdb(rbtdb);
+ 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);
+ }
}
}
if (rbtdb->active == 0)
want_free = ISC_TRUE;
UNLOCK(&rbtdb->lock);
- if (want_free)
- free_rbtdb(rbtdb);
+ 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);
+ }
}
}
return (count);
}
+static void
+settask(dns_db_t *db, isc_task_t *task) {
+ dns_rbtdb_t *rbtdb;
+
+ rbtdb = (dns_rbtdb_t *)db;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+
+ LOCK(&rbtdb->lock);
+ if (rbtdb->task != NULL)
+ isc_task_detach(&rbtdb->task);
+ if (task != NULL)
+ isc_task_attach(task, &rbtdb->task);
+ UNLOCK(&rbtdb->lock);
+}
+
static isc_boolean_t
ispersistent(dns_db_t *db) {
UNUSED(db);
issecure,
nodecount,
ispersistent,
- overmem
+ overmem,
+ settask
};
static dns_dbmethods_t cache_methods = {
issecure,
nodecount,
ispersistent,
- overmem
+ overmem,
+ settask
};
isc_result_t
*/
result = dns_name_dupwithoffsets(origin, mctx, &rbtdb->common.origin);
if (result != ISC_R_SUCCESS) {
- free_rbtdb(rbtdb);
+ free_rbtdb(rbtdb, ISC_FALSE, NULL);
return (result);
}
*/
result = dns_rbt_create(mctx, delete_callback, rbtdb, &rbtdb->tree);
if (result != ISC_R_SUCCESS) {
- free_rbtdb(rbtdb);
+ free_rbtdb(rbtdb, ISC_FALSE, NULL);
return (result);
}
/*
&rbtdb->origin_node);
if (result != ISC_R_SUCCESS) {
INSIST(result != ISC_R_EXISTS);
- free_rbtdb(rbtdb);
+ free_rbtdb(rbtdb, ISC_FALSE, NULL);
return (result);
}
/*
rbtdb->attributes = 0;
rbtdb->secure = ISC_FALSE;
rbtdb->overmem = ISC_FALSE;
+ rbtdb->task = NULL;
/*
* Version Initialization.
rbtdb->next_serial = 2;
rbtdb->current_version = allocate_version(mctx, 1, 0, ISC_FALSE);
if (rbtdb->current_version == NULL) {
- free_rbtdb(rbtdb);
+ free_rbtdb(rbtdb, ISC_FALSE, NULL);
return (ISC_R_NOMEMORY);
}
rbtdb->future_version = NULL;
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: sdb.c,v 1.35.2.2 2003/10/09 07:32:38 marka Exp $ */
+/* $Id: sdb.c,v 1.35.2.3 2004/03/04 06:56:26 marka Exp $ */
#include <config.h>
UNUSED(overmem);
}
+static void
+settask(dns_db_t *db, isc_task_t *task) {
+ UNUSED(db);
+ UNUSED(task);
+}
+
static dns_dbmethods_t sdb_methods = {
attach,
issecure,
nodecount,
ispersistent,
- overmem
+ overmem,
+ settask
};
static isc_result_t
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: zone.c,v 1.333.2.29 2004/03/02 02:36:41 marka Exp $ */
+/* $Id: zone.c,v 1.333.2.30 2004/03/04 06:56:27 marka Exp $ */
#include <config.h>
isc_result_totext(result));
goto cleanup;
}
+ dns_db_settask(db, zone->task);
if (! dns_db_ispersistent(db)) {
if (zone->masterfile != NULL) {
dns_result_totext(result));
goto cleanup;
}
+ dns_db_settask(stub->db, zone->task);
}
dns_db_newversion(stub->db, &stub->version);
if (zone->task != NULL)
isc_task_detach(&zone->task);
isc_task_attach(task, &zone->task);
+ if (zone->db != NULL)
+ dns_db_settask(zone->db, zone->task);
UNLOCK_ZONE(zone);
}
if (zone->db != NULL)
dns_db_detach(&zone->db);
dns_db_attach(db, &zone->db);
+ dns_db_settask(zone->db, zone->task);
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
return (ISC_R_SUCCESS);
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: task.c,v 1.85.2.3 2002/08/06 02:20:39 marka Exp $ */
+/* $Id: task.c,v 1.85.2.4 2004/03/04 06:56:28 marka Exp $ */
/*
* Principal Author: Bob Halley
}
isc_thread_setconcurrency(workers);
#else /* ISC_PLATFORM_USETHREADS */
- manager->refs = 0;
+ manager->refs = 1;
taskmgr = manager;
#endif /* ISC_PLATFORM_USETHREADS */