This can handle both read-only and writable traverses.
Signed-off-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
commit, which in turn greatly reduces DB churn as we will likely
be able to do a direct update into the old record.
*/
-static int delete_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state)
+static int delete_index(struct ltdb_private *ltdb, struct ldb_val key, struct ldb_val data, void *state)
{
struct ldb_module *module = state;
- struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
const char *dnstr = "DN=" LTDB_INDEX ":";
struct dn_list list;
struct ldb_dn *dn;
struct ldb_val v;
int ret;
- if (strncmp((char *)key.dptr, dnstr, strlen(dnstr)) != 0) {
+ if (strncmp((char *)key.data, dnstr, strlen(dnstr)) != 0) {
return 0;
}
/* we need to put a empty list in the internal tdb for this
list.count = 0;
/* the offset of 3 is to remove the DN= prefix. */
- v.data = key.dptr + 3;
- v.length = strnlen((char *)key.dptr, key.dsize) - 3;
+ v.data = key.data + 3;
+ v.length = strnlen((char *)key.data, key.length) - 3;
dn = ldb_dn_from_ldb_val(ltdb, ldb_module_get_ctx(module), &v);
return 0;
}
-struct ltdb_reindex_context {
- struct ldb_module *module;
- int error;
- uint32_t count;
-};
-
/*
- traversal function that adds @INDEX records during a re index
+ traversal function that adds @INDEX records during a re index TODO wrong comment
*/
-static int re_key(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state)
+static int re_key(struct ltdb_private *ltdb, struct ldb_val ldb_key, struct ldb_val val, void *state)
{
struct ldb_context *ldb;
struct ltdb_reindex_context *ctx = (struct ltdb_reindex_context *)state;
struct ldb_module *module = ctx->module;
struct ldb_message *msg;
unsigned int nb_elements_in_db;
- const struct ldb_val val = {
- .data = data.dptr,
- .length = data.dsize,
- };
int ret;
TDB_DATA key2;
bool is_record;
+ TDB_DATA key = {
+ .dptr = ldb_key.data,
+ .dsize = ldb_key.length
+ };
ldb = ldb_module_get_ctx(module);
}
if (key.dsize != key2.dsize ||
(memcmp(key.dptr, key2.dptr, key.dsize) != 0)) {
- int tdb_ret;
- tdb_ret = tdb_delete(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(tdb));
- ctx->error = ltdb_err_map(tdb_error(tdb));
- return -1;
- }
- tdb_ret = tdb_store(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(tdb));
- ctx->error = ltdb_err_map(tdb_error(tdb));
- return -1;
- }
+ TDB_DATA data = {
+ .dptr = val.data,
+ .dsize = val.length
+ };
+ ltdb->kv_ops->update_in_iterate(ltdb, key, key2, data, ctx);
}
talloc_free(key2.dptr);
/*
traversal function that adds @INDEX records during a re index
*/
-static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state)
+static int re_index(struct ltdb_private *ltdb, struct ldb_val ldb_key, struct ldb_val val, void *state)
{
struct ldb_context *ldb;
struct ltdb_reindex_context *ctx = (struct ltdb_reindex_context *)state;
struct ldb_module *module = ctx->module;
- struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module),
- struct ltdb_private);
struct ldb_message *msg;
unsigned int nb_elements_in_db;
- const struct ldb_val val = {
- .data = data.dptr,
- .length = data.dsize,
+ TDB_DATA key = {
+ .dptr = ldb_key.data,
+ .dsize = ldb_key.length
};
int ret;
bool is_record;
/* first traverse the database deleting any @INDEX records by
* putting NULL entries in the in-memory tdb
*/
- ret = tdb_traverse(ltdb->tdb, delete_index, module);
+ ret = ltdb->kv_ops->iterate(ltdb, delete_index, module);
if (ret < 0) {
struct ldb_context *ldb = ldb_module_get_ctx(module);
ldb_asprintf_errstring(ldb, "index deletion traverse failed: %s",
ctx.error = 0;
ctx.count = 0;
- /* now traverse adding any indexes for normal LDB records */
- ret = tdb_traverse(ltdb->tdb, re_key, &ctx);
+ ret = ltdb->kv_ops->iterate(ltdb, re_key, &ctx);
if (ret < 0) {
struct ldb_context *ldb = ldb_module_get_ctx(module);
ldb_asprintf_errstring(ldb, "key correction traverse failed: %s",
ctx.count = 0;
/* now traverse adding any indexes for normal LDB records */
- ret = tdb_traverse(ltdb->tdb, re_index, &ctx);
+ ret = ltdb->kv_ops->iterate(ltdb, re_index, &ctx);
if (ret < 0) {
struct ldb_context *ldb = ldb_module_get_ctx(module);
ldb_asprintf_errstring(ldb, "reindexing traverse failed: %s",
/*
search function for a non-indexed search
*/
-static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state)
+static int search_func(struct ltdb_private *ltdb, struct ldb_val key, struct ldb_val val, void *state)
{
struct ldb_context *ldb;
struct ltdb_context *ac;
struct ldb_message *msg, *filtered_msg;
- const struct ldb_val val = {
- .data = data.dptr,
- .length = data.dsize,
- };
int ret;
bool matched;
unsigned int nb_elements_in_db;
+ TDB_DATA tdb_key = {
+ .dptr = key.data,
+ .dsize = key.length
+ };
ac = talloc_get_type(state, struct ltdb_context);
ldb = ldb_module_get_ctx(ac->module);
- if (ltdb_key_is_record(key) == false) {
+ if (ltdb_key_is_record(tdb_key) == false) {
return 0;
}
if (!msg->dn) {
msg->dn = ldb_dn_new(msg, ldb,
- (char *)key.dptr + 3);
+ (char *)key.data + 3);
if (msg->dn == NULL) {
talloc_free(msg);
ac->error = LDB_ERR_OPERATIONS_ERROR;
int ret;
ctx->error = LDB_SUCCESS;
- if (ltdb->in_transaction != 0) {
- ret = tdb_traverse(ltdb->tdb, search_func, ctx);
- } else {
- ret = tdb_traverse_read(ltdb->tdb, search_func, ctx);
- }
+ ret = ltdb->kv_ops->iterate(ltdb, search_func, ctx);
if (ret < 0) {
return LDB_ERR_OPERATIONS_ERROR;
return LDB_ERR_NO_SUCH_ATTRIBUTE;
}
-
/*
modify a record - internal interface
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),
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,
#include "ldb_module.h"
struct ltdb_private;
+typedef int (*ldb_kv_traverse_fn)(struct ltdb_private *ltdb,
+ struct ldb_val key, struct ldb_val data,
+ void *ctx);
+
struct kv_db_ops {
int (*store)(struct ltdb_private *ltdb, TDB_DATA key, TDB_DATA data, int flags);
int (*delete)(struct ltdb_private *ltdb, TDB_DATA key);
+ int (*iterate)(struct ltdb_private *ltdb, ldb_kv_traverse_fn fn, void *ctx);
+ int (*update_in_iterate)(struct ltdb_private *ltdb, TDB_DATA key,
+ TDB_DATA key2, TDB_DATA data, void *ctx);
int (*fetch_and_parse)(struct ltdb_private *ltdb, TDB_DATA key,
int (*parser)(TDB_DATA key, TDB_DATA data,
void *private_data),
int error;
};
+struct ltdb_reindex_context {
+ struct ldb_module *module;
+ int error;
+ uint32_t count;
+};
+
+
/* special record types */
#define LTDB_INDEX "@INDEX"
#define LTDB_INDEXLIST "@INDEXLIST"