/*
lock the database for read - use by ltdb_search and ltdb_sequence_number
*/
-int ltdb_lock_read(struct ldb_module *module)
+static int ltdb_lock_read(struct ldb_module *module)
{
void *data = ldb_module_get_private(module);
struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
/*
unlock the database after a ltdb_lock_read()
*/
-int ltdb_unlock_read(struct ldb_module *module)
+static int ltdb_unlock_read(struct ldb_module *module)
{
void *data = ldb_module_get_private(module);
struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
note that the key for a record can depend on whether the
dn refers to a case sensitive index record or not
*/
-TDB_DATA ltdb_key_dn(struct ldb_module *module, struct ldb_dn *dn)
+TDB_DATA ltdb_key_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx,
+ struct ldb_dn *dn)
{
- struct ldb_context *ldb = ldb_module_get_ctx(module);
TDB_DATA key;
char *key_str = NULL;
const char *dn_folded = NULL;
goto failed;
}
- key_str = talloc_strdup(ldb, "DN=");
+ key_str = talloc_strdup(mem_ctx, "DN=");
if (!key_str) {
goto failed;
}
return key;
}
+/* The caller is to provide a correctly sized key */
+int ltdb_guid_to_key(struct ldb_module *module,
+ struct ltdb_private *ltdb,
+ const struct ldb_val *GUID_val,
+ TDB_DATA *key)
+{
+ const char *GUID_prefix = LTDB_GUID_KEY_PREFIX;
+ const int GUID_prefix_len = sizeof(LTDB_GUID_KEY_PREFIX) - 1;
+
+ if (key->dsize != (GUID_val->length+GUID_prefix_len)) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ memcpy(key->dptr, GUID_prefix, GUID_prefix_len);
+ memcpy(&key->dptr[GUID_prefix_len],
+ GUID_val->data, GUID_val->length);
+ return LDB_SUCCESS;
+}
+
+/*
+ * The caller is to provide a correctly sized key, used only in
+ * the GUID index mode
+ */
+int ltdb_idx_to_key(struct ldb_module *module,
+ struct ltdb_private *ltdb,
+ TALLOC_CTX *mem_ctx,
+ const struct ldb_val *idx_val,
+ TDB_DATA *key)
+{
+ struct ldb_context *ldb = ldb_module_get_ctx(module);
+ struct ldb_dn *dn;
+
+ if (ltdb->cache->GUID_index_attribute != NULL) {
+ return ltdb_guid_to_key(module, ltdb,
+ idx_val, key);
+ }
+
+ dn = ldb_dn_from_ldb_val(mem_ctx, ldb, idx_val);
+ if (dn == NULL) {
+ /*
+ * LDB_ERR_INVALID_DN_SYNTAX would just be confusing
+ * to the caller, as this in an invalid index value
+ */
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ /* form the key */
+ *key = ltdb_key_dn(module, mem_ctx, dn);
+ TALLOC_FREE(dn);
+ if (!key->dptr) {
+ return ldb_module_oom(module);
+ }
+ return LDB_SUCCESS;
+}
+
/*
form a TDB_DATA for a record key
- caller frees
+ caller frees mem_ctx, which may or may not have the key
+ as a child.
- note that the key for a record can depend on whether the
- dn refers to a case sensitive index record or not
+ note that the key for a record can depend on whether a
+ GUID index is in use, or the DN is used as the key
*/
-TDB_DATA ltdb_key_msg(struct ldb_module *module,
+TDB_DATA ltdb_key_msg(struct ldb_module *module, TALLOC_CTX *mem_ctx,
const struct ldb_message *msg)
{
- return ltdb_key_dn(module, msg->dn);
+ void *data = ldb_module_get_private(module);
+ struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
+ TDB_DATA key;
+ const struct ldb_val *guid_val;
+ int ret;
+
+ if (ltdb->cache->GUID_index_attribute == NULL) {
+ return ltdb_key_dn(module, mem_ctx, msg->dn);
+ }
+
+ if (ldb_dn_is_special(msg->dn)) {
+ return ltdb_key_dn(module, mem_ctx, msg->dn);
+ }
+
+ guid_val = ldb_msg_find_ldb_val(msg,
+ ltdb->cache->GUID_index_attribute);
+ if (guid_val == NULL) {
+ ldb_asprintf_errstring(ldb_module_get_ctx(module),
+ "Did not find GUID attribute %s "
+ "in %s, required for TDB record "
+ "key in " LTDB_IDXGUID " mode.",
+ ltdb->cache->GUID_index_attribute,
+ ldb_dn_get_linearized(msg->dn));
+ errno = EINVAL;
+ key.dptr = NULL;
+ key.dsize = 0;
+ return key;
+ }
+
+ /* In this case, allocate with talloc */
+ key.dptr = talloc_size(mem_ctx, LTDB_GUID_KEY_SIZE);
+ if (key.dptr == NULL) {
+ errno = ENOMEM;
+ key.dptr = NULL;
+ key.dsize = 0;
+ return key;
+ }
+ key.dsize = talloc_get_size(key.dptr);
+
+ ret = ltdb_guid_to_key(module, ltdb, guid_val, &key);
+
+ if (ret != LDB_SUCCESS) {
+ errno = EINVAL;
+ key.dptr = NULL;
+ key.dsize = 0;
+ return key;
+ }
+ return key;
}
/*
if (ltdb->warn_reindex) {
ldb_debug(ldb_module_get_ctx(module),
LDB_DEBUG_ERROR, "Reindexing %s due to modification on %s",
- tdb_name(ltdb->tdb), ldb_dn_get_linearized(dn));
+ ltdb->kv_ops->name(ltdb), ldb_dn_get_linearized(dn));
}
ret = ltdb_reindex(module);
}
ret = ltdb_cache_reload(module);
}
+ if (ret != LDB_SUCCESS) {
+ ltdb->reindex_failed = true;
+ }
+
return ret;
}
+static int ltdb_tdb_store(struct ltdb_private *ltdb, TDB_DATA key, TDB_DATA data, int flags)
+{
+ return tdb_store(ltdb->tdb, key, data, flags);
+}
+
+static int ltdb_error(struct ltdb_private *ltdb)
+{
+ return ltdb_err_map(tdb_error(ltdb->tdb));
+}
+
+static const char *ltdb_errorstr(struct ltdb_private *ltdb)
+{
+ return tdb_errorstr(ltdb->tdb);
+}
+
/*
store a record into the db
*/
TDB_DATA tdb_key, tdb_data;
struct ldb_val ldb_data;
int ret = LDB_SUCCESS;
+ TALLOC_CTX *tdb_key_ctx = talloc_new(module);
+
+ if (tdb_key_ctx == NULL) {
+ return ldb_module_oom(module);
+ }
if (ltdb->read_only) {
return LDB_ERR_UNWILLING_TO_PERFORM;
}
- tdb_key = ltdb_key_msg(module, msg);
+ tdb_key = ltdb_key_msg(module, tdb_key_ctx, msg);
if (tdb_key.dptr == NULL) {
+ TALLOC_FREE(tdb_key_ctx);
return LDB_ERR_OTHER;
}
ret = ldb_pack_data(ldb_module_get_ctx(module),
msg, &ldb_data);
if (ret == -1) {
- talloc_free(tdb_key.dptr);
+ TALLOC_FREE(tdb_key_ctx);
return LDB_ERR_OTHER;
}
tdb_data.dptr = ldb_data.data;
tdb_data.dsize = ldb_data.length;
- ret = tdb_store(ltdb->tdb, tdb_key, tdb_data, flgs);
+ ret = ltdb->kv_ops->store(ltdb, tdb_key, tdb_data, flgs);
if (ret != 0) {
bool is_special = ldb_dn_is_special(msg->dn);
- ret = ltdb_err_map(tdb_error(ltdb->tdb));
+ ret = ltdb->kv_ops->error(ltdb);
/*
* LDB_ERR_ENTRY_ALREADY_EXISTS means the DN, not
}
done:
- talloc_free(tdb_key.dptr);
+ TALLOC_FREE(tdb_key_ctx);
talloc_free(ldb_data.data);
return ret;
ret = ltdb_store(module, msg, TDB_INSERT);
if (ret != LDB_SUCCESS) {
+ /*
+ * Try really hard to get the right error code for
+ * a re-add situation, as this can matter!
+ */
+ if (ret == LDB_ERR_CONSTRAINT_VIOLATION) {
+ int ret2;
+ struct ldb_dn *dn2 = NULL;
+ TALLOC_CTX *mem_ctx = talloc_new(module);
+ if (mem_ctx == NULL) {
+ return ldb_module_operr(module);
+ }
+ ret2 = ltdb_search_base(module, module,
+ msg->dn, &dn2);
+ TALLOC_FREE(mem_ctx);
+ if (ret2 == LDB_SUCCESS) {
+ ret = LDB_ERR_ENTRY_ALREADY_EXISTS;
+ }
+ }
if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
ldb_asprintf_errstring(ldb,
"Entry %s already exists",
return ret;
}
+static int ltdb_tdb_delete(struct ltdb_private *ltdb, TDB_DATA tdb_key)
+{
+ return tdb_delete(ltdb->tdb, tdb_key);
+}
+
/*
delete a record from the database, not updating indexes (used for deleting
index records)
struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
TDB_DATA tdb_key;
int ret;
+ TALLOC_CTX *tdb_key_ctx = talloc_new(module);
+
+ if (tdb_key_ctx == NULL) {
+ return ldb_module_oom(module);
+ }
if (ltdb->read_only) {
return LDB_ERR_UNWILLING_TO_PERFORM;
}
- tdb_key = ltdb_key_dn(module, msg->dn);
+ tdb_key = ltdb_key_msg(module, tdb_key_ctx, msg);
if (!tdb_key.dptr) {
+ TALLOC_FREE(tdb_key_ctx);
return LDB_ERR_OTHER;
}
- ret = tdb_delete(ltdb->tdb, tdb_key);
- talloc_free(tdb_key.dptr);
+ ret = ltdb->kv_ops->delete(ltdb, tdb_key);
+ TALLOC_FREE(tdb_key_ctx);
if (ret != 0) {
- ret = ltdb_err_map(tdb_error(ltdb->tdb));
+ ret = ltdb->kv_ops->error(ltdb);
}
return ret;
return LDB_ERR_NO_SUCH_ATTRIBUTE;
}
-
/*
modify a record - internal interface
struct ldb_message *msg;
int ret = LDB_SUCCESS;
TDB_DATA tdb_key, tdb_key_old;
+ struct ldb_dn *db_dn;
ldb_request_set_state(req, LDB_ASYNC_PENDING);
* Even in GUID index mode we use ltdb_key_dn() as we are
* trying to figure out if this is just a case rename
*/
- tdb_key = ltdb_key_dn(module, req->op.rename.newdn);
+ tdb_key = ltdb_key_dn(module, msg, req->op.rename.newdn);
if (!tdb_key.dptr) {
talloc_free(msg);
return LDB_ERR_OPERATIONS_ERROR;
}
- tdb_key_old = ltdb_key_dn(module, req->op.rename.olddn);
+ tdb_key_old = ltdb_key_dn(module, msg, req->op.rename.olddn);
if (!tdb_key_old.dptr) {
talloc_free(msg);
talloc_free(tdb_key.dptr);
*/
if (tdb_key_old.dsize != tdb_key.dsize
|| memcmp(tdb_key.dptr, tdb_key_old.dptr, tdb_key.dsize) != 0) {
- ret = ltdb_search_base(module,
- req->op.rename.newdn);
+ ret = ltdb_search_base(module, msg,
+ req->op.rename.newdn,
+ &db_dn);
if (ret == LDB_SUCCESS) {
ret = LDB_ERR_ENTRY_ALREADY_EXISTS;
} else if (ret == LDB_ERR_NO_SUCH_OBJECT) {
return ret;
}
+static int ltdb_tdb_transaction_start(struct ltdb_private *ltdb)
+{
+ return tdb_transaction_start(ltdb->tdb);
+}
+
+static int ltdb_tdb_transaction_cancel(struct ltdb_private *ltdb)
+{
+ return tdb_transaction_cancel(ltdb->tdb);
+}
+
+static int ltdb_tdb_transaction_prepare_commit(struct ltdb_private *ltdb)
+{
+ return tdb_transaction_prepare_commit(ltdb->tdb);
+}
+
+static int ltdb_tdb_transaction_commit(struct ltdb_private *ltdb)
+{
+ return tdb_transaction_commit(ltdb->tdb);
+}
+
static int ltdb_start_trans(struct ldb_module *module)
{
void *data = ldb_module_get_private(module);
return LDB_ERR_UNWILLING_TO_PERFORM;
}
- if (tdb_transaction_start(ltdb->tdb) != 0) {
- return ltdb_err_map(tdb_error(ltdb->tdb));
+ if (ltdb->kv_ops->begin_write(ltdb) != 0) {
+ return ltdb->kv_ops->error(ltdb);
}
ltdb->in_transaction++;
ltdb_index_transaction_start(module);
+ ltdb->reindex_failed = false;
+
return LDB_SUCCESS;
}
+/*
+ * Forward declaration to allow prepare_commit to in fact abort the
+ * transaction
+ */
+static int ltdb_del_trans(struct ldb_module *module);
+
static int ltdb_prepare_commit(struct ldb_module *module)
{
int ret;
return LDB_SUCCESS;
}
+ /*
+ * Check if the last re-index failed.
+ *
+ * This can happen if for example a duplicate value was marked
+ * unique. We must not write a partial re-index into the DB.
+ */
+ if (ltdb->reindex_failed) {
+ /*
+ * We must instead abort the transaction so we get the
+ * old values and old index back
+ */
+ ltdb_del_trans(module);
+ ldb_set_errstring(ldb_module_get_ctx(module),
+ "Failure during re-index, so "
+ "transaction must be aborted.");
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
ret = ltdb_index_transaction_commit(module);
if (ret != LDB_SUCCESS) {
- tdb_transaction_cancel(ltdb->tdb);
+ ltdb->kv_ops->abort_write(ltdb);
ltdb->in_transaction--;
return ret;
}
- if (tdb_transaction_prepare_commit(ltdb->tdb) != 0) {
- ret = ltdb_err_map(tdb_error(ltdb->tdb));
+ if (ltdb->kv_ops->prepare_write(ltdb) != 0) {
+ ret = ltdb->kv_ops->error(ltdb);
ltdb->in_transaction--;
ldb_debug_set(ldb_module_get_ctx(module),
LDB_DEBUG_FATAL,
"Failure during "
- "tdb_transaction_prepare_commit(): %s -> %s",
- tdb_errorstr(ltdb->tdb),
+ "prepare_write): %s -> %s",
+ ltdb->kv_ops->errorstr(ltdb),
ldb_strerror(ret));
return ret;
}
ltdb->in_transaction--;
ltdb->prepared_commit = false;
- if (tdb_transaction_commit(ltdb->tdb) != 0) {
- ret = ltdb_err_map(tdb_error(ltdb->tdb));
+ if (ltdb->kv_ops->finish_write(ltdb) != 0) {
+ ret = ltdb->kv_ops->error(ltdb);
ldb_asprintf_errstring(ldb_module_get_ctx(module),
"Failure during tdb_transaction_commit(): %s -> %s",
- tdb_errorstr(ltdb->tdb),
+ ltdb->kv_ops->errorstr(ltdb),
ldb_strerror(ret));
return ret;
}
ltdb->in_transaction--;
if (ltdb_index_transaction_cancel(module) != 0) {
- tdb_transaction_cancel(ltdb->tdb);
- return ltdb_err_map(tdb_error(ltdb->tdb));
+ ltdb->kv_ops->abort_write(ltdb);
+ return ltdb->kv_ops->error(ltdb);
}
- tdb_transaction_cancel(ltdb->tdb);
+ ltdb->kv_ops->abort_write(ltdb);
return LDB_SUCCESS;
}
struct ldb_context *ldb;
struct ldb_module *module = ctx->module;
struct ldb_request *req = ctx->req;
+ void *data = ldb_module_get_private(module);
+ struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
TALLOC_CTX *tmp_ctx = NULL;
struct ldb_seqnum_request *seq;
struct ldb_seqnum_result *res;
ldb_request_set_state(req, LDB_ASYNC_PENDING);
- if (ltdb_lock_read(module) != 0) {
+ if (ltdb->kv_ops->lock_read(module) != 0) {
return LDB_ERR_OPERATIONS_ERROR;
}
done:
talloc_free(tmp_ctx);
- ltdb_unlock_read(module);
+
+ ltdb->kv_ops->unlock_read(module);
return ret;
}
ltdb_request_extended_done(ctx, ext, ret);
}
+struct kv_ctx {
+ ldb_kv_traverse_fn kv_traverse_fn;
+ void *ctx;
+ struct ltdb_private *ltdb;
+};
+
+static int ldb_tdb_traverse_fn_wrapper(struct tdb_context *tdb, TDB_DATA tdb_key, TDB_DATA tdb_data, void *ctx)
+{
+ struct kv_ctx *kv_ctx = ctx;
+ struct ldb_val key = {
+ .length = tdb_key.dsize,
+ .data = tdb_key.dptr,
+ };
+ struct ldb_val data = {
+ .length = tdb_data.dsize,
+ .data = tdb_data.dptr,
+ };
+ return kv_ctx->kv_traverse_fn(kv_ctx->ltdb, key, data, kv_ctx->ctx);
+}
+
+static int ltdb_tdb_traverse_fn(struct ltdb_private *ltdb, ldb_kv_traverse_fn fn, void *ctx)
+{
+ struct kv_ctx kv_ctx = {
+ .kv_traverse_fn = fn,
+ .ctx = ctx,
+ .ltdb = ltdb
+ };
+ if (ltdb->in_transaction != 0) {
+ return tdb_traverse(ltdb->tdb, ldb_tdb_traverse_fn_wrapper, &kv_ctx);
+ } else {
+ return tdb_traverse_read(ltdb->tdb, ldb_tdb_traverse_fn_wrapper, &kv_ctx);
+ }
+}
+
+static int ltdb_tdb_update_in_iterate(struct ltdb_private *ltdb, TDB_DATA key, TDB_DATA key2, TDB_DATA data, void *state)
+{
+ int tdb_ret;
+ struct ldb_context *ldb;
+ struct ltdb_reindex_context *ctx = (struct ltdb_reindex_context *)state;
+ struct ldb_module *module = ctx->module;
+
+ ldb = ldb_module_get_ctx(module);
+
+ tdb_ret = tdb_delete(ltdb->tdb, key);
+ if (tdb_ret != 0) {
+ ldb_debug(ldb, LDB_DEBUG_ERROR,
+ "Failed to delete %*.*s "
+ "for rekey as %*.*s: %s",
+ (int)key.dsize, (int)key.dsize,
+ (const char *)key.dptr,
+ (int)key2.dsize, (int)key2.dsize,
+ (const char *)key.dptr,
+ tdb_errorstr(ltdb->tdb));
+ ctx->error = ltdb_err_map(tdb_error(ltdb->tdb));
+ return -1;
+ }
+ tdb_ret = tdb_store(ltdb->tdb, key2, data, 0);
+ if (tdb_ret != 0) {
+ ldb_debug(ldb, LDB_DEBUG_ERROR,
+ "Failed to rekey %*.*s as %*.*s: %s",
+ (int)key.dsize, (int)key.dsize,
+ (const char *)key.dptr,
+ (int)key2.dsize, (int)key2.dsize,
+ (const char *)key.dptr,
+ tdb_errorstr(ltdb->tdb));
+ ctx->error = ltdb_err_map(tdb_error(ltdb->tdb));
+ return -1;
+ }
+ return tdb_ret;
+}
+
+static int ltdb_tdb_parse_record(struct ltdb_private *ltdb, TDB_DATA key,
+ int (*parser)(TDB_DATA key, TDB_DATA data,
+ void *private_data),
+ void *ctx)
+{
+ return tdb_parse_record(ltdb->tdb, key, parser, ctx);
+}
+
+static const char * ltdb_tdb_name(struct ltdb_private *ltdb)
+{
+ return tdb_name(ltdb->tdb);
+}
+
+static bool ltdb_tdb_changed(struct ltdb_private *ltdb)
+{
+ int seq = tdb_get_seqnum(ltdb->tdb);
+ bool has_changed = (seq != ltdb->tdb_seqnum);
+
+ ltdb->tdb_seqnum = seq;
+
+ return has_changed;
+}
+
+static const struct kv_db_ops key_value_ops = {
+ .store = ltdb_tdb_store,
+ .delete = ltdb_tdb_delete,
+ .iterate = ltdb_tdb_traverse_fn,
+ .update_in_iterate = ltdb_tdb_update_in_iterate,
+ .fetch_and_parse = ltdb_tdb_parse_record,
+ .lock_read = ltdb_lock_read,
+ .unlock_read = ltdb_unlock_read,
+ .begin_write = ltdb_tdb_transaction_start,
+ .prepare_write = ltdb_tdb_transaction_prepare_commit,
+ .finish_write = ltdb_tdb_transaction_commit,
+ .abort_write = ltdb_tdb_transaction_cancel,
+ .error = ltdb_error,
+ .errorstr = ltdb_errorstr,
+ .name = ltdb_tdb_name,
+ .has_changed = ltdb_tdb_changed,
+};
+
static void ltdb_callback(struct tevent_context *ev,
struct tevent_timer *te,
struct timeval t,
return LDB_SUCCESS;
}
+
+static int generic_lock_read(struct ldb_module *module)
+{
+ void *data = ldb_module_get_private(module);
+ struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
+ return ltdb->kv_ops->lock_read(module);
+}
+
+static int generic_unlock_read(struct ldb_module *module)
+{
+ void *data = ldb_module_get_private(module);
+ struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
+ return ltdb->kv_ops->unlock_read(module);
+}
+
static const struct ldb_module_ops ltdb_ops = {
.name = "tdb",
.init_context = ltdb_init_rootdse,
.end_transaction = ltdb_end_trans,
.prepare_commit = ltdb_prepare_commit,
.del_transaction = ltdb_del_trans,
- .read_lock = ltdb_lock_read,
- .read_unlock = ltdb_unlock_read,
+ .read_lock = generic_lock_read,
+ .read_unlock = generic_unlock_read,
};
+int init_store(struct ltdb_private *ltdb,
+ const char *name,
+ struct ldb_context *ldb,
+ const char *options[],
+ struct ldb_module **_module)
+{
+ struct ldb_module *module;
+
+ if (getenv("LDB_WARN_UNINDEXED")) {
+ ltdb->warn_unindexed = true;
+ }
+
+ if (getenv("LDB_WARN_REINDEX")) {
+ ltdb->warn_reindex = true;
+ }
+
+ ltdb->sequence_number = 0;
+
+ module = ldb_module_new(ldb, ldb, name, <db_ops);
+ if (!module) {
+ ldb_oom(ldb);
+ talloc_free(ltdb);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ ldb_module_set_private(module, ltdb);
+ talloc_steal(module, ltdb);
+
+ if (ltdb_cache_load(module) != 0) {
+ ldb_asprintf_errstring(ldb, "Unable to load ltdb cache "
+ "records for backend '%s'", name);
+ talloc_free(module);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ *_module = module;
+ /*
+ * Set the maximum key length
+ */
+ {
+ const char *len_str =
+ ldb_options_find(ldb, options,
+ "max_key_len_for_self_test");
+ if (len_str != NULL) {
+ unsigned len = strtoul(len_str, NULL, 0);
+ ltdb->max_key_length = len;
+ }
+ }
+
+ return LDB_SUCCESS;
+}
+
/*
connect to the database
*/
-static int ltdb_connect(struct ldb_context *ldb, const char *url,
- unsigned int flags, const char *options[],
- struct ldb_module **_module)
+int ltdb_connect(struct ldb_context *ldb, const char *url,
+ unsigned int flags, const char *options[],
+ struct ldb_module **_module)
{
- struct ldb_module *module;
const char *path;
int tdb_flags, open_flags;
struct ltdb_private *ltdb;
* We hold locks, so we must use a private event context
* on each returned handle
*/
-
ldb_set_require_private_event_context(ldb);
/* parse the url */
open_flags = O_CREAT | O_RDWR;
}
+ ltdb->kv_ops = &key_value_ops;
+
/* note that we use quite a large default hash size */
ltdb->tdb = ltdb_wrap_open(ltdb, path, 10000,
tdb_flags, open_flags,
return LDB_ERR_OPERATIONS_ERROR;
}
- if (getenv("LDB_WARN_UNINDEXED")) {
- ltdb->warn_unindexed = true;
- }
-
- if (getenv("LDB_WARN_REINDEX")) {
- ltdb->warn_reindex = true;
- }
-
- ltdb->sequence_number = 0;
-
- module = ldb_module_new(ldb, ldb, "ldb_tdb backend", <db_ops);
- if (!module) {
- ldb_oom(ldb);
- talloc_free(ltdb);
- return LDB_ERR_OPERATIONS_ERROR;
- }
- ldb_module_set_private(module, ltdb);
- talloc_steal(module, ltdb);
-
- if (ltdb_cache_load(module) != 0) {
- ldb_asprintf_errstring(ldb,
- "Unable to load ltdb cache records of tdb '%s'", path);
- talloc_free(module);
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- *_module = module;
- return LDB_SUCCESS;
-}
-
-int ldb_tdb_init(const char *version)
-{
- LDB_MODULE_CHECK_VERSION(version);
- return ldb_register_backend("tdb", ltdb_connect, false);
+ return init_store(ltdb, "ldb_tdb backend", ldb, options, _module);
}