ldb: Add flags to ltdb_search_dn1() to control memory allocation
authorAndrew Bartlett <abartlet@samba.org>
Tue, 26 Jul 2016 12:20:27 +0000 (00:20 +1200)
committerStefan Metzmacher <metze@samba.org>
Thu, 28 Jul 2016 08:06:12 +0000 (10:06 +0200)
This is used in the index code in particular to avoid an allocation per value
(as there may be one value per DB object at times

Pair-Programmed-With: Stefan Metzmacher <metze@samba.org>

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
lib/ldb/ldb_tdb/ldb_cache.c
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 6467af1d00cf7e7381703f3d386acace02a9fe45..2f19d276eceb60473e8e60689e3cbd543eb57278 100644 (file)
@@ -126,7 +126,7 @@ static int ltdb_attributes_load(struct ldb_module *module)
        dn = ldb_dn_new(module, ldb, LTDB_ATTRIBUTES);
        if (dn == NULL) goto failed;
 
-       r = ltdb_search_dn1(module, dn, msg);
+       r = ltdb_search_dn1(module, dn, msg, 0);
        talloc_free(dn);
        if (r != LDB_SUCCESS && r != LDB_ERR_NO_SUCH_OBJECT) {
                goto failed;
@@ -301,7 +301,7 @@ int ltdb_cache_load(struct ldb_module *module)
        baseinfo_dn = ldb_dn_new(baseinfo, ldb, LTDB_BASEINFO);
        if (baseinfo_dn == NULL) goto failed;
 
-       r= ltdb_search_dn1(module, baseinfo_dn, baseinfo);
+       r= ltdb_search_dn1(module, baseinfo_dn, baseinfo, 0);
        if (r != LDB_SUCCESS && r != LDB_ERR_NO_SUCH_OBJECT) {
                goto failed;
        }
@@ -319,7 +319,7 @@ int ltdb_cache_load(struct ldb_module *module)
 
                tdb_transaction_commit(ltdb->tdb);
 
-               if (ltdb_search_dn1(module, baseinfo_dn, baseinfo) != LDB_SUCCESS) {
+               if (ltdb_search_dn1(module, baseinfo_dn, baseinfo, 0) != LDB_SUCCESS) {
                        goto failed;
                }
        }
@@ -341,7 +341,7 @@ int ltdb_cache_load(struct ldb_module *module)
        options_dn = ldb_dn_new(options, ldb, LTDB_OPTIONS);
        if (options_dn == NULL) goto failed;
 
-       r= ltdb_search_dn1(module, options_dn, options);
+       r= ltdb_search_dn1(module, options_dn, options, 0);
        if (r != LDB_SUCCESS && r != LDB_ERR_NO_SUCH_OBJECT) {
                goto failed;
        }
@@ -374,7 +374,7 @@ int ltdb_cache_load(struct ldb_module *module)
        indexlist_dn = ldb_dn_new(module, ldb, LTDB_INDEXLIST);
        if (indexlist_dn == NULL) goto failed;
 
-       r = ltdb_search_dn1(module, indexlist_dn, ltdb->cache->indexlist);
+       r = ltdb_search_dn1(module, indexlist_dn, ltdb->cache->indexlist, 0);
        if (r != LDB_SUCCESS && r != LDB_ERR_NO_SUCH_OBJECT) {
                goto failed;
        }
index e6bfb1b623988607383c72c8911a8e8bffcc24f0..800363a0a3da7e3a2c807407c17366a44fbe66f1 100644 (file)
@@ -178,7 +178,9 @@ normal_index:
                return LDB_ERR_OPERATIONS_ERROR;
        }
 
-       ret = ltdb_search_dn1(module, dn, msg);
+       ret = ltdb_search_dn1(module, dn, msg,
+                             LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC
+                             |LDB_UNPACK_DATA_FLAG_NO_DN);
        if (ret != LDB_SUCCESS) {
                talloc_free(msg);
                return ret;
@@ -949,7 +951,7 @@ static int ltdb_index_filter(const struct dn_list *dn_list,
                        return LDB_ERR_OPERATIONS_ERROR;
                }
 
-               ret = ltdb_search_dn1(ac->module, dn, msg);
+               ret = ltdb_search_dn1(ac->module, dn, msg, 0);
                talloc_free(dn);
                if (ret == LDB_ERR_NO_SUCH_OBJECT) {
                        /* the record has disappeared? yes, this can happen */
index 62a36c7c252d46d40fc783416627f840a13b3bc8..979e7c83f97628634d8a8efdbbb5c2cab80e19b9 100644 (file)
@@ -238,16 +238,50 @@ static int ltdb_search_base(struct ldb_module *module, struct ldb_dn *dn)
 struct ltdb_parse_data_unpack_ctx {
        struct ldb_message *msg;
        struct ldb_module *module;
+       unsigned int unpack_flags;
 };
 
 static int ltdb_parse_data_unpack(TDB_DATA key, TDB_DATA data,
                                  void *private_data)
 {
        struct ltdb_parse_data_unpack_ctx *ctx = private_data;
-
+       unsigned int nb_elements_in_db;
+       int ret;
        struct ldb_context *ldb = ldb_module_get_ctx(ctx->module);
-       int ret = ldb_unpack_data(ldb, (struct ldb_val *)&data, ctx->msg);
+       struct ldb_val data_parse = {
+               .data = data.dptr,
+               .length = data.dsize
+       };
+
+       if (ctx->unpack_flags & LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC) {
+               /*
+                * If we got LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC
+                * we need at least do a memdup on the whole
+                * data buffer as that may change later
+                * and the caller needs a stable result.
+                */
+               data_parse.data = talloc_memdup(ctx->msg,
+                                               data.dptr,
+                                               data.dsize);
+               if (data_parse.data == NULL) {
+                       ldb_debug(ldb, LDB_DEBUG_ERROR,
+                                 "Unable to allocate data(%d) for %*.*s\n",
+                                 (int)data.dsize,
+                                 (int)key.dsize, (int)key.dsize, key.dptr);
+                       return LDB_ERR_OPERATIONS_ERROR;
+               }
+       }
+
+       ret = ldb_unpack_data_only_attr_list_flags(ldb, &data_parse,
+                                                  ctx->msg,
+                                                  NULL, 0,
+                                                  ctx->unpack_flags,
+                                                  &nb_elements_in_db);
        if (ret == -1) {
+               if (data_parse.data != data.dptr) {
+                       talloc_free(data_parse.data);
+               }
+
                ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid data for index %*.*s\n",
                          (int)key.dsize, (int)key.dsize, key.dptr);
                return LDB_ERR_OPERATIONS_ERROR;                
@@ -262,7 +296,8 @@ static int ltdb_parse_data_unpack(TDB_DATA key, TDB_DATA data,
   return LDB_ERR_NO_SUCH_OBJECT on record-not-found
   and LDB_SUCCESS on success
 */
-int ltdb_search_dn1(struct ldb_module *module, struct ldb_dn *dn, struct ldb_message *msg)
+int ltdb_search_dn1(struct ldb_module *module, struct ldb_dn *dn, struct ldb_message *msg,
+                   unsigned int unpack_flags)
 {
        void *data = ldb_module_get_private(module);
        struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
@@ -270,7 +305,8 @@ int ltdb_search_dn1(struct ldb_module *module, struct ldb_dn *dn, struct ldb_mes
        TDB_DATA tdb_key;
        struct ltdb_parse_data_unpack_ctx ctx = {
                .msg = msg,
-               .module = module
+               .module = module,
+               .unpack_flags = unpack_flags
        };
 
        /* form the key */
@@ -296,12 +332,14 @@ int ltdb_search_dn1(struct ldb_module *module, struct ldb_dn *dn, struct ldb_mes
        } else if (ret != LDB_SUCCESS) {
                return ret;
        }
-       
-       if (!msg->dn) {
-               msg->dn = ldb_dn_copy(msg, dn);
-       }
-       if (!msg->dn) {
-               return LDB_ERR_OPERATIONS_ERROR;
+
+       if ((unpack_flags & LDB_UNPACK_DATA_FLAG_NO_DN) == 0) {
+               if (!msg->dn) {
+                       msg->dn = ldb_dn_copy(msg, dn);
+               }
+               if (!msg->dn) {
+                       return LDB_ERR_OPERATIONS_ERROR;
+               }
        }
 
        return LDB_SUCCESS;
index 1a4f4cad4c4b67108e95c300bcf418e6b759e2b6..7cc0a2e08d17f9c6950c582f5c39b2824e1970c1 100644 (file)
@@ -449,7 +449,7 @@ static int ltdb_delete_internal(struct ldb_module *module, struct ldb_dn *dn)
 
        /* in case any attribute of the message was indexed, we need
           to fetch the old record */
-       ret = ltdb_search_dn1(module, dn, msg);
+       ret = ltdb_search_dn1(module, dn, msg, LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC);
        if (ret != LDB_SUCCESS) {
                /* not finding the old record is an error */
                goto done;
@@ -1033,7 +1033,8 @@ static int ltdb_rename(struct ltdb_context *ctx)
        }
 
        /* we need to fetch the old record to re-add under the new name */
-       ret = ltdb_search_dn1(module, req->op.rename.olddn, msg);
+       ret = ltdb_search_dn1(module, req->op.rename.olddn, msg,
+                             LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC);
        if (ret != LDB_SUCCESS) {
                /* not finding the old record is an error */
                return ret;
@@ -1232,7 +1233,7 @@ static int ltdb_sequence_number(struct ltdb_context *ctx,
                goto done;
        }
 
-       ret = ltdb_search_dn1(module, dn, msg);
+       ret = ltdb_search_dn1(module, dn, msg, 0);
        if (ret != LDB_SUCCESS) {
                goto done;
        }
index caa98ebf8efbd0d3b51f95ab5dafb2b789ff801f..7390a047b20f61e1feea36222b1ac7bc8519f6ec 100644 (file)
@@ -101,7 +101,8 @@ int ltdb_index_transaction_cancel(struct ldb_module *module);
 int ltdb_has_wildcard(struct ldb_module *module, const char *attr_name, 
                      const struct ldb_val *val);
 void ltdb_search_dn1_free(struct ldb_module *module, struct ldb_message *msg);
-int ltdb_search_dn1(struct ldb_module *module, struct ldb_dn *dn, struct ldb_message *msg);
+int ltdb_search_dn1(struct ldb_module *module, struct ldb_dn *dn, struct ldb_message *msg,
+                   unsigned int unpack_flags);
 int ltdb_add_attr_results(struct ldb_module *module,
                          TALLOC_CTX *mem_ctx, 
                          struct ldb_message *msg,