static void
bdbhpt_destroy(void *driverarg, void *dbdata)
{
	UNUSED(driverarg);

	bdbhpt_cleanup((bdbhpt_instance_t *) dbdata);
}
/*
 * Shut down the backend
 */
void
dlz_destroy(void *dbdata) {
  struct bdbhpt_instance *db = (struct bdbhpt_instance *)dbdata;
  
  db->log(ISC_LOG_INFO,
          "dlz_bdbhpt_dynamic (%s): shutting down", dlz_bdbhpt_dynamic_version);
  bdbhpt_cleanup((bdbhpt_instance_t *) dbdata);
  free (db);
}
/*
 * Called to initialize the driver
 */
isc_result_t
dlz_create(const char *dlzname, unsigned int argc, char *argv[],
		 void **dbdata, ...)
{
	isc_result_t result;
	int bdbhptres;
	int bdbFlags = 0;
	bdbhpt_instance_t *db = NULL;
	
	const char *helper_name;
	va_list ap;

	UNUSED(dlzname);

	/* Allocate memory for our db structures and helper functions */
	db = calloc(1, sizeof(struct bdbhpt_instance));
	if (db == NULL)
		return (ISC_R_NOMEMORY);

	/* Fill in the helper functions */
	va_start(ap, dbdata);
	while ((helper_name = va_arg(ap, const char *)) != NULL)
		b9_add_helper(db, helper_name, va_arg(ap, void*));
	va_end(ap);

	/* verify we have 4 arg's passed to the driver */
	if (argc != 4) {
		db->log(ISC_LOG_ERROR,
			"bdbhpt_dynamic: please supply 3 command line args. "
			"You supplied: %s", argc);
		return (ISC_R_FAILURE);
	}

	switch((char) *argv[1]) {
		/*
		 * Transactional mode.	Highest safety - lowest speed.
		 */
	case 'T':
	case 't':
		bdbFlags = DB_INIT_MPOOL | DB_INIT_LOCK |
			DB_INIT_LOG | DB_INIT_TXN;
		db->log(ISC_LOG_INFO,
			"bdbhpt_dynamic: using transactional mode.");
		break;

		/*
		 * Concurrent mode.	 Lower safety (no rollback) -
		 * higher speed.
		 */
	case 'C':
	case 'c':
		bdbFlags = DB_INIT_CDB | DB_INIT_MPOOL;
		db->log(ISC_LOG_INFO,
			"bdbhpt_dynamic: using concurrent mode.");
		break;

		/*
		 * Private mode. No inter-process communication & no locking.
		 * Lowest saftey - highest speed.
		 */
	case 'P':
	case 'p':
		bdbFlags = DB_PRIVATE | DB_INIT_MPOOL;
		db->log(ISC_LOG_INFO,
			"bdbhpt_dynamic: using private mode.");
		break;
	default:
		db->log(ISC_LOG_ERROR,
			"bdbhpt_dynamic: "
			"operating mode must be set to P or C or T. "
			"You specified '%s'", argv[1]);
		return (ISC_R_FAILURE);
	}
	
	/*
	 * create bdbhpt environment
	 * Basically bdbhpt allocates and assigns memory to db->dbenv
	 */
	bdbhptres = db_env_create(&db->dbenv, 0);
	if (bdbhptres != 0) {
		db->log(ISC_LOG_ERROR,
			"bdbhpt_dynamic: db environment could not be created. "
			"BerkeleyDB error: %s", db_strerror(bdbhptres));
		result = ISC_R_FAILURE;
		goto init_cleanup;
	}
	
	/* open bdbhpt environment */
	bdbhptres = db->dbenv->open(db->dbenv, argv[2],
				    bdbFlags | bdbhpt_threads | DB_CREATE, 0);
	if (bdbhptres != 0) {
		db->log(ISC_LOG_ERROR,
			"bdbhpt_dynamic: "
			"db environment at '%s' could not be opened. "
			"BerkeleyDB error: %s",
			argv[2], db_strerror(bdbhptres));
		result = ISC_R_FAILURE;
		goto init_cleanup;
	}

	/* open dlz_data database. */
	result = bdbhpt_opendb(db->log, db->dbenv, DB_UNKNOWN, &db->data,
			       dlz_data, argv[3], DB_DUP | DB_DUPSORT);
	if (result != ISC_R_SUCCESS)
		goto init_cleanup;

	/* open dlz_xfr database. */
	result = bdbhpt_opendb(db->log, db->dbenv, DB_UNKNOWN, &db->xfr,
			       dlz_xfr, argv[3], DB_DUP | DB_DUPSORT);
	if (result != ISC_R_SUCCESS)
		goto init_cleanup;
	
	/* open dlz_zone database. */
	result = bdbhpt_opendb(db->log, db->dbenv, DB_UNKNOWN, &db->zone,
			       dlz_zone, argv[3], 0);
	if (result != ISC_R_SUCCESS)
		goto init_cleanup;
	
	/* open dlz_client database. */
	result = bdbhpt_opendb(db->log, db->dbenv, DB_UNKNOWN, &db->client,
			       dlz_client, argv[3], DB_DUP | DB_DUPSORT);
	if (result != ISC_R_SUCCESS)
		goto init_cleanup;
	
	*dbdata = db;

	db->log(ISC_LOG_INFO,
		"bdbhpt_dynamic: version %s, started",
		dlz_bdbhpt_dynamic_version);
	return(ISC_R_SUCCESS);
	
 init_cleanup:
	bdbhpt_cleanup(db);
	return result;
}
static isc_result_t
bdbhpt_create(const char *dlzname, unsigned int argc, char *argv[],
	      void *driverarg, void **dbdata)
{
	isc_result_t result;
	int bdbhptres;
	int bdbFlags = 0;
	bdbhpt_instance_t *db = NULL;

	UNUSED(dlzname);
	UNUSED(driverarg);

	/* verify we have 4 arg's passed to the driver */
	if (argc != 4) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "bdbhpt driver requires at least "
			      "3 command line args.");
		return (ISC_R_FAILURE);
	}

	switch((char) *argv[1]) {
		/*
		 * Transactional mode.  Highest safety - lowest speed.
		 */
	case 'T':
	case 't':
		bdbFlags = DB_INIT_MPOOL | DB_INIT_LOCK |
			   DB_INIT_LOG | DB_INIT_TXN;
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
			      "bdbhpt driver using transactional mode.");
		break;
		/*
		 * Concurrent mode.  Lower safety (no rollback) -
		 * higher speed.
		 */
	case 'C':
	case 'c':
		bdbFlags = DB_INIT_CDB | DB_INIT_MPOOL;
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
			      "bdbhpt driver using concurrent mode.");
		break;
		/*
		 * Private mode. No inter-process communication & no locking.
		 * Lowest saftey - highest speed.
		 */
	case 'P':
	case 'p':
		bdbFlags = DB_PRIVATE | DB_INIT_MPOOL;
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
			      "bdbhpt driver using private mode.");
		break;
	default:
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "bdbhpt driver requires the operating mode "
			      "be set to P or C or T.  You specified '%s'",
			      argv[1]);
		return (ISC_R_FAILURE);
	}

	/* allocate and zero memory for driver structure */
	db = isc_mem_get(ns_g_mctx, sizeof(bdbhpt_instance_t));
	if (db == NULL) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "Could not allocate memory for "
			      "database instance object.");
		return (ISC_R_NOMEMORY);
	}
	memset(db, 0, sizeof(bdbhpt_instance_t));

	/* attach to the memory context */
	isc_mem_attach(ns_g_mctx, &db->mctx);

	/*
	 * create bdbhpt environment
	 * Basically bdbhpt allocates and assigns memory to db->dbenv
	 */
	bdbhptres = db_env_create(&db->dbenv, 0);
	if (bdbhptres != 0) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "bdbhpt environment could not be created. "
			      "bdbhpt error: %s",
			      db_strerror(bdbhptres));
		result = ISC_R_FAILURE;
		goto init_cleanup;
	}

	/* open bdbhpt environment */
	bdbhptres = db->dbenv->open(db->dbenv, argv[2],
				    bdbFlags | bdbhpt_threads | DB_CREATE, 0);
	if (bdbhptres != 0) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "bdbhpt environment at '%s' could not be opened."
			      " bdbhpt error: %s",
			      argv[2], db_strerror(bdbhptres));
		result = ISC_R_FAILURE;
		goto init_cleanup;
	}

	/* open dlz_data database. */
	result = bdbhpt_opendb(db->dbenv, DB_UNKNOWN, &db->data,
			       dlz_data, argv[3], DB_DUP | DB_DUPSORT);
	if (result != ISC_R_SUCCESS)
		goto init_cleanup;

	/* open dlz_xfr database. */
	result = bdbhpt_opendb(db->dbenv, DB_UNKNOWN, &db->xfr,
			       dlz_xfr, argv[3], DB_DUP | DB_DUPSORT);
	if (result != ISC_R_SUCCESS)
		goto init_cleanup;

	/* open dlz_zone database. */
	result = bdbhpt_opendb(db->dbenv, DB_UNKNOWN, &db->zone,
			       dlz_zone, argv[3], 0);
	if (result != ISC_R_SUCCESS)
		goto init_cleanup;

	/* open dlz_client database. */
	result = bdbhpt_opendb(db->dbenv, DB_UNKNOWN, &db->client,
			       dlz_client, argv[3], DB_DUP | DB_DUPSORT);
	if (result != ISC_R_SUCCESS)
		goto init_cleanup;

	*dbdata = db;

	return(ISC_R_SUCCESS);

 init_cleanup:

	bdbhpt_cleanup(db);
	return result;
}