From: Garming Sam Date: Fri, 16 Feb 2018 00:06:31 +0000 (+1300) Subject: ldb_tdb: Implement a traversal function in key value ops X-Git-Tag: talloc-2.1.12~249 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4d5180e45c58dc68f8d5dca09c4a87b6830468af;p=thirdparty%2Fsamba.git ldb_tdb: Implement a traversal function in key value ops This can handle both read-only and writable traverses. Signed-off-by: Garming Sam Reviewed-by: Andrew Bartlett --- diff --git a/lib/ldb/ldb_tdb/ldb_index.c b/lib/ldb/ldb_tdb/ldb_index.c index 97cc6109662..bb534c3833c 100644 --- a/lib/ldb/ldb_tdb/ldb_index.c +++ b/lib/ldb/ldb_tdb/ldb_index.c @@ -2673,17 +2673,16 @@ int ltdb_index_delete(struct ldb_module *module, const struct ldb_message *msg) 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 @@ -2692,8 +2691,8 @@ static int delete_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, vo 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); @@ -2713,29 +2712,23 @@ static int delete_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, vo 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); @@ -2790,32 +2783,11 @@ static int re_key(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *st } 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); @@ -2834,18 +2806,16 @@ static int re_key(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *st /* 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; @@ -2955,7 +2925,7 @@ int ltdb_reindex(struct ldb_module *module) /* 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", @@ -2967,8 +2937,7 @@ int ltdb_reindex(struct ldb_module *module) 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", @@ -2986,7 +2955,7 @@ int ltdb_reindex(struct ldb_module *module) 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", diff --git a/lib/ldb/ldb_tdb/ldb_search.c b/lib/ldb/ldb_tdb/ldb_search.c index 4332036790b..78ef8b0abb1 100644 --- a/lib/ldb/ldb_tdb/ldb_search.c +++ b/lib/ldb/ldb_tdb/ldb_search.c @@ -487,23 +487,23 @@ failed: /* 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; } @@ -528,7 +528,7 @@ static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, voi 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; @@ -581,11 +581,7 @@ static int ltdb_search_full(struct ltdb_context *ctx) 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; diff --git a/lib/ldb/ldb_tdb/ldb_tdb.c b/lib/ldb/ldb_tdb/ldb_tdb.c index f02ad5b53b1..9a2b47b87c4 100644 --- a/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/lib/ldb/ldb_tdb/ldb_tdb.c @@ -926,7 +926,6 @@ static int msg_delete_element(struct ldb_module *module, return LDB_ERR_NO_SUCH_ATTRIBUTE; } - /* modify a record - internal interface @@ -1714,6 +1713,77 @@ static void ltdb_handle_extended(struct ltdb_context *ctx) 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), @@ -1739,6 +1809,8 @@ static bool ltdb_tdb_changed(struct ltdb_private *ltdb) 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, diff --git a/lib/ldb/ldb_tdb/ldb_tdb.h b/lib/ldb/ldb_tdb/ldb_tdb.h index ce8f19c2265..bf679900764 100644 --- a/lib/ldb/ldb_tdb/ldb_tdb.h +++ b/lib/ldb/ldb_tdb/ldb_tdb.h @@ -5,9 +5,16 @@ #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), @@ -86,6 +93,13 @@ struct ltdb_context { 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"