ldb_tdb: Implement a traversal function in key value ops
authorGarming Sam <garming@catalyst.net.nz>
Fri, 16 Feb 2018 00:06:31 +0000 (13:06 +1300)
committerAndrew Bartlett <abartlet@samba.org>
Mon, 5 Mar 2018 19:50:15 +0000 (20:50 +0100)
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>
lib/ldb/ldb_tdb/ldb_index.c
lib/ldb/ldb_tdb/ldb_search.c
lib/ldb/ldb_tdb/ldb_tdb.c
lib/ldb/ldb_tdb/ldb_tdb.h

index 97cc6109662f27fcd0dcffa2e3052d3d1e26f80b..bb534c3833c38a8835ca3ec8f15e8ffc9a32a2aa 100644 (file)
@@ -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",
index 4332036790b8684c3ae1ec11ae7c5c871f595453..78ef8b0abb1128be99462560607e69159dabbee2 100644 (file)
@@ -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;
index f02ad5b53b16fd391281f1a32f4abf9c7282ebd8..9a2b47b87c4a2970b4f705ea92ca244b48d12861 100644 (file)
@@ -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,
index ce8f19c2265bc71440b59e5b00ccf2b1d4609cf3..bf67990076412a96836871b4dc0197fe11340ede 100644 (file)
@@ -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"