dovecot-1.2: Berkeley DB fixes and cleanups. Don't leak memory/b...
dovecot at dovecot.org
dovecot at dovecot.org
Fri Jan 9 20:14:30 EET 2009
details: http://hg.dovecot.org/dovecot-1.2/rev/04816f18bf18
changeset: 8607:04816f18bf18
user: Timo Sirainen <tss at iki.fi>
date: Fri Jan 09 13:14:04 2009 -0500
description:
Berkeley DB fixes and cleanups. Don't leak memory/bdb resources.
diffstat:
1 file changed, 97 insertions(+), 77 deletions(-)
src/lib-dict/dict-db.c | 174 ++++++++++++++++++++++++++----------------------
diffs (222 lines):
diff -r c1fea9e157c8 -r 04816f18bf18 src/lib-dict/dict-db.c
--- a/src/lib-dict/dict-db.c Fri Jan 09 11:17:20 2009 -0500
+++ b/src/lib-dict/dict-db.c Fri Jan 09 13:14:04 2009 -0500
@@ -15,6 +15,7 @@ struct db_dict {
DB_ENV *db_env;
DB *pdb;
DB *sdb;
+ DB_TXN *tid;
};
struct db_dict_iterate_context {
@@ -60,103 +61,119 @@ static int uint32_t_compare(DB *db ATTR_
(*ua < *ub ? -1 : 0);
}
+static int db_dict_open(struct db_dict *dict, const char *uri,
+ const char *username)
+{
+ const char *dir;
+ int ret;
+
+ dict->db_env->set_errfile(dict->db_env, stderr);
+ dict->db_env->set_errpfx(dict->db_env,
+ p_strdup_printf(dict->pool, "db_env(%s)", username));
+
+ dir = strrchr(uri, '/');
+ if (dir != NULL)
+ dir = t_strdup_until(uri, dir);
+ else
+ dir = ".";
+
+ ret = dict->db_env->open(dict->db_env, dir, DB_CREATE |
+ DB_INIT_MPOOL | DB_INIT_TXN, 0);
+ if (ret != 0) {
+ i_error("db_env.open(%s) failed: %s\n", dir, db_strerror(ret));
+ return -1;
+ }
+
+ ret = dict->db_env->txn_begin(dict->db_env, NULL, &dict->tid, 0);
+ if (ret != 0) {
+ i_error("db_env.txn_begin() failed: %s\n", db_strerror(ret));
+ return -1;
+ }
+
+ /* create both primary and secondary databases */
+ ret = db_create(&dict->pdb, dict->db_env, 0);
+ if (ret != 0) {
+ i_error("db_create(primary) failed: %s\n", db_strerror(ret));
+ return -1;
+ }
+ dict->pdb->set_errfile(dict->pdb, stderr);
+ dict->pdb->set_errpfx(dict->pdb,
+ p_strdup_printf(dict->pool, "db(primary, %s)", username));
+
+ ret = db_create(&dict->sdb, dict->db_env, 0);
+ if (ret != 0) {
+ i_error("db_create(secondary) failed: %s\n", db_strerror(ret));
+ return -1;
+ }
+ dict->sdb->set_errfile(dict->sdb, stderr);
+ dict->sdb->set_errpfx(dict->sdb,
+ p_strdup_printf(dict->pool, "db(secondary, %s)", username));
+
+ if ((ret = dict->pdb->open(dict->pdb, dict->tid, uri, NULL,
+ DB_BTREE, DB_CREATE, 0)) != 0) {
+ i_error("pdb.open() failed: %s\n", db_strerror(ret));
+ return -1;
+ }
+ if (dict->sdb->set_flags(dict->sdb, DB_DUP) != 0)
+ return -1;
+
+ /* by default keys are compared as strings. if we store uint32_t,
+ we need a customized compare function */
+ if (dict->value_type == DICT_DATA_TYPE_UINT32) {
+ if (dict->sdb->set_bt_compare(dict->sdb, uint32_t_compare) != 0)
+ return -1;
+ }
+
+ if ((ret = dict->sdb->open(dict->sdb, dict->tid, NULL, NULL,
+ DB_BTREE, DB_CREATE, 0)) != 0) {
+ i_error("sdb.open() failed: %s\n", db_strerror(ret));
+ return -1;
+ }
+ if ((ret = dict->pdb->associate(dict->pdb, dict->tid, dict->sdb,
+ associate_key, DB_CREATE)) != 0) {
+ i_error("pdb.associate() failed: %s\n", db_strerror(ret));
+ return -1;
+ }
+ return 0;
+}
+
static struct dict *db_dict_init(struct dict *driver, const char *uri,
enum dict_data_type value_type,
- const char *username ATTR_UNUSED)
+ const char *username)
{
struct db_dict *dict;
- const char *hdir;
- DB_TXN *tid = NULL;
pool_t pool;
- int ret;
-
+ int ret, major, minor, patch;
+
+ (void)db_version(&major, &minor, &patch);
+ if (major != DB_VERSION_MAJOR || minor != DB_VERSION_MINOR) {
+ i_error("Berkeley DB version mismatch: "
+ "Compiled against %d.%d.%d headers, "
+ "run-time linked against %d.%d.%d library",
+ DB_VERSION_MAJOR, DB_VERSION_MINOR, DB_VERSION_PATCH,
+ major, minor, patch);
+ return NULL;
+ }
+
pool = pool_alloconly_create("db dict", 1024);
dict = p_new(pool, struct db_dict, 1);
dict->pool = pool;
dict->dict = *driver;
+ dict->value_type = value_type;
/* prepare the environment */
ret = db_env_create(&dict->db_env, 0);
if (ret != 0) {
- i_error("db_env:%s\n", db_strerror(ret));
+ i_error("db_env_create() failed: %s\n", db_strerror(ret));
pool_unref(&pool);
return NULL;
}
- dict->db_env->set_errfile(dict->db_env, stderr);
- dict->db_env->set_errpfx(dict->db_env, "db_env");
-
- hdir = strrchr(uri, '/');
- if (hdir != NULL)
- hdir = t_strndup(uri, hdir - uri);
-
- ret = dict->db_env->open(dict->db_env, hdir, DB_CREATE |
- DB_INIT_MPOOL | DB_INIT_TXN, 0);
- if (ret != 0) {
- pool_unref(&pool);
- return NULL;
- }
-
- ret = dict->db_env->txn_begin(dict->db_env, NULL, &tid, 0);
- if (ret != 0) {
- pool_unref(&pool);
- return NULL;
- }
-
- /* create both primary and secondary databases */
- ret = db_create(&dict->pdb, dict->db_env, 0);
- if (ret != 0) {
- i_error("primary db:%s\n", db_strerror(ret));
+ if (db_dict_open(dict, uri, username) < 0) {
+ i_error("db(%s) open failed", uri);
db_dict_deinit(&dict->dict);
return NULL;
}
- dict->pdb->set_errfile(dict->pdb, stderr);
- dict->pdb->set_errpfx(dict->pdb, "primary db");
-
- ret = db_create(&dict->sdb, dict->db_env, 0);
- if (ret != 0) {
- i_error("secondary db:%s\n", db_strerror(ret));
- db_dict_deinit(&dict->dict);
- return NULL;
- }
- dict->pdb->set_errfile(dict->pdb, stderr);
- dict->pdb->set_errpfx(dict->pdb, "secondary db");
-
- if (dict->pdb->open(dict->pdb, tid, uri, NULL,
- DB_BTREE, DB_CREATE, 0) != 0) {
- db_dict_deinit(&dict->dict);
- return NULL;
- }
-
- if (dict->sdb->set_flags(dict->sdb, DB_DUP) != 0) {
- db_dict_deinit(&dict->dict);
- return NULL;
- }
-
- /* by default db compare keys as if they are strings.
- if we store uint32_t, then we need a customized
- compare function */
- dict->value_type = value_type;
- if (value_type == DICT_DATA_TYPE_UINT32) {
- if (dict->sdb->set_bt_compare(dict->sdb,
- uint32_t_compare) != 0) {
- db_dict_deinit(&dict->dict);
- return NULL;
- }
- }
-
- if (dict->sdb->open(dict->sdb, tid, NULL, NULL,
- DB_BTREE, DB_CREATE, 0) != 0) {
- db_dict_deinit(&dict->dict);
- return NULL;
- }
-
- if (dict->pdb->associate(dict->pdb, tid, dict->sdb,
- associate_key, DB_CREATE) != 0) {
- db_dict_deinit(&dict->dict);
- return NULL;
- }
-
return &dict->dict;
}
@@ -164,10 +181,13 @@ static void db_dict_deinit(struct dict *
{
struct db_dict *dict = (struct db_dict *)_dict;
+ if (dict->tid != NULL)
+ (void)dict->tid->commit(dict->tid, 0);
if (dict->pdb != NULL)
dict->pdb->close(dict->pdb, 0);
if (dict->sdb != NULL)
dict->sdb->close(dict->sdb, 0);
+ dict->db_env->close(dict->db_env, 0);
pool_unref(&dict->pool);
}
More information about the dovecot-cvs
mailing list