ldb: make key/value backends expose if there is an active transaction
[samba.git] / lib / ldb / ldb_tdb / ldb_tdb.c
index 20796f2162dd2180721f8bc5a31053ddd2f52f88..31b4a7d9abb4c3e1f2f9856a1aa45a3c910d0258 100644 (file)
@@ -417,8 +417,21 @@ static int ltdb_modified(struct ldb_module *module, struct ldb_dn *dn)
        return ret;
 }
 
-static int ltdb_tdb_store(struct ltdb_private *ltdb, TDB_DATA key, TDB_DATA data, int flags)
+static int ltdb_tdb_store(struct ltdb_private *ltdb, struct ldb_val ldb_key,
+                         struct ldb_val ldb_data, int flags)
 {
+       TDB_DATA key = {
+               .dptr = ldb_key.data,
+               .dsize = ldb_key.length
+       };
+       TDB_DATA data = {
+               .dptr = ldb_data.data,
+               .dsize = ldb_data.length
+       };
+       bool transaction_active = tdb_transaction_active(ltdb->tdb);
+       if (transaction_active == false){
+               return LDB_ERR_PROTOCOL_ERROR;
+       }
        return tdb_store(ltdb->tdb, key, data, flags);
 }
 
@@ -439,7 +452,8 @@ int ltdb_store(struct ldb_module *module, const struct ldb_message *msg, int flg
 {
        void *data = ldb_module_get_private(module);
        struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
-       TDB_DATA tdb_key, tdb_data;
+       TDB_DATA tdb_key;
+       struct ldb_val ldb_key;
        struct ldb_val ldb_data;
        int ret = LDB_SUCCESS;
        TALLOC_CTX *tdb_key_ctx = talloc_new(module);
@@ -465,10 +479,10 @@ int ltdb_store(struct ldb_module *module, const struct ldb_message *msg, int flg
                return LDB_ERR_OTHER;
        }
 
-       tdb_data.dptr = ldb_data.data;
-       tdb_data.dsize = ldb_data.length;
+       ldb_key.data = tdb_key.dptr;
+       ldb_key.length = tdb_key.dsize;
 
-       ret = ltdb->kv_ops->store(ltdb, tdb_key, tdb_data, flgs);
+       ret = ltdb->kv_ops->store(ltdb, ldb_key, ldb_data, flgs);
        if (ret != 0) {
                bool is_special = ldb_dn_is_special(msg->dn);
                ret = ltdb->kv_ops->error(ltdb);
@@ -637,6 +651,16 @@ static int ltdb_add(struct ltdb_context *ctx)
        struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
        int ret = LDB_SUCCESS;
 
+       if (ltdb->max_key_length != 0 &&
+           ltdb->cache->GUID_index_attribute == NULL &&
+           !ldb_dn_is_special(req->op.add.message->dn))
+       {
+               ldb_set_errstring(ldb_module_get_ctx(module),
+                                 "Must operate ldb_mdb in GUID "
+                                 "index mode, but " LTDB_IDXGUID " not set.");
+               return LDB_ERR_UNWILLING_TO_PERFORM;
+       }
+
        ret = ltdb_check_special_dn(module, req->op.add.message);
        if (ret != LDB_SUCCESS) {
                return ret;
@@ -654,8 +678,16 @@ static int ltdb_add(struct ltdb_context *ctx)
        return ret;
 }
 
-static int ltdb_tdb_delete(struct ltdb_private *ltdb, TDB_DATA tdb_key)
+static int ltdb_tdb_delete(struct ltdb_private *ltdb, struct ldb_val ldb_key)
 {
+       TDB_DATA tdb_key = {
+               .dptr = ldb_key.data,
+               .dsize = ldb_key.length
+       };
+       bool transaction_active = tdb_transaction_active(ltdb->tdb);
+       if (transaction_active == false){
+               return LDB_ERR_PROTOCOL_ERROR;
+       }
        return tdb_delete(ltdb->tdb, tdb_key);
 }
 
@@ -668,6 +700,7 @@ int ltdb_delete_noindex(struct ldb_module *module,
 {
        void *data = ldb_module_get_private(module);
        struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
+       struct ldb_val ldb_key;
        TDB_DATA tdb_key;
        int ret;
        TALLOC_CTX *tdb_key_ctx = talloc_new(module);
@@ -686,7 +719,10 @@ int ltdb_delete_noindex(struct ldb_module *module,
                return LDB_ERR_OTHER;
        }
 
-       ret = ltdb->kv_ops->delete(ltdb, tdb_key);
+       ldb_key.data = tdb_key.dptr;
+       ldb_key.length = tdb_key.dsize;
+
+       ret = ltdb->kv_ops->delete(ltdb, ldb_key);
        TALLOC_FREE(tdb_key_ctx);
 
        if (ret != 0) {
@@ -1747,6 +1783,9 @@ struct kv_ctx {
        ldb_kv_traverse_fn kv_traverse_fn;
        void *ctx;
        struct ltdb_private *ltdb;
+       int (*parser)(struct ldb_val key,
+                     struct ldb_val data,
+                     void *private_data);
 };
 
 static int ldb_tdb_traverse_fn_wrapper(struct tdb_context *tdb, TDB_DATA tdb_key, TDB_DATA tdb_data, void *ctx)
@@ -1777,12 +1816,27 @@ static int ltdb_tdb_traverse_fn(struct ltdb_private *ltdb, ldb_kv_traverse_fn fn
        }
 }
 
-static int ltdb_tdb_update_in_iterate(struct ltdb_private *ltdb, TDB_DATA key, TDB_DATA key2, TDB_DATA data, void *state)
+static int ltdb_tdb_update_in_iterate(struct ltdb_private *ltdb,
+                                     struct ldb_val ldb_key,
+                                     struct ldb_val ldb_key2,
+                                     struct ldb_val ldb_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;
+       TDB_DATA key = {
+               .dptr = ldb_key.data,
+               .dsize = ldb_key.length
+       };
+       TDB_DATA key2 = {
+               .dptr = ldb_key2.data,
+               .dsize = ldb_key2.length
+       };
+       TDB_DATA data = {
+               .dptr = ldb_data.data,
+               .dsize = ldb_data.length
+       };
 
        ldb = ldb_module_get_ctx(module);
 
@@ -1814,12 +1868,46 @@ static int ltdb_tdb_update_in_iterate(struct ltdb_private *ltdb, TDB_DATA key, T
        return tdb_ret;
 }
 
-static int ltdb_tdb_parse_record(struct ltdb_private *ltdb, TDB_DATA key,
-                                int (*parser)(TDB_DATA key, TDB_DATA data,
+static int ltdb_tdb_parse_record_wrapper(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->parser(key, data, kv_ctx->ctx);
+}
+
+static int ltdb_tdb_parse_record(struct ltdb_private *ltdb,
+                                struct ldb_val ldb_key,
+                                int (*parser)(struct ldb_val key,
+                                              struct ldb_val data,
                                               void *private_data),
                                 void *ctx)
 {
-       return tdb_parse_record(ltdb->tdb, key, parser, ctx);
+       struct kv_ctx kv_ctx = {
+               .parser = parser,
+               .ctx = ctx,
+               .ltdb = ltdb
+       };
+       TDB_DATA key = {
+               .dptr = ldb_key.data,
+               .dsize = ldb_key.length
+       };
+       int ret;
+
+       ret = tdb_parse_record(ltdb->tdb, key, ltdb_tdb_parse_record_wrapper,
+                              &kv_ctx);
+       if (ret == 0) {
+               return LDB_SUCCESS;
+       }
+       return ltdb_err_map(tdb_error(ltdb->tdb));
 }
 
 static const char * ltdb_tdb_name(struct ltdb_private *ltdb)
@@ -1837,6 +1925,11 @@ static bool ltdb_tdb_changed(struct ltdb_private *ltdb)
        return has_changed;
 }
 
+static bool ltdb_transaction_active(struct ltdb_private *ltdb)
+{
+       return tdb_transaction_active(ltdb->tdb);
+}
+
 static const struct kv_db_ops key_value_ops = {
        .store = ltdb_tdb_store,
        .delete = ltdb_tdb_delete,
@@ -1853,6 +1946,7 @@ static const struct kv_db_ops key_value_ops = {
        .errorstr = ltdb_errorstr,
        .name = ltdb_tdb_name,
        .has_changed = ltdb_tdb_changed,
+       .transaction_active = ltdb_transaction_active,
 };
 
 static void ltdb_callback(struct tevent_context *ev,
@@ -2071,7 +2165,13 @@ int init_store(struct ltdb_private *ltdb,
 
        *_module = module;
        /*
-        * Set the maximum key length
+        * Set or override the maximum key length
+        *
+        * The ldb_mdb code will have set this to 511, but our tests
+        * set this even smaller (to make the tests more practical).
+        *
+        * This must only be used for the selftest as the length
+        * becomes encoded in the index keys.
         */
        {
                const char *len_str =