diff options
Diffstat (limited to 'lib/ldb')
-rw-r--r-- | lib/ldb/common/ldb_pack.c | 25 | ||||
-rw-r--r-- | lib/ldb/include/ldb_module.h | 16 | ||||
-rw-r--r-- | lib/ldb/ldb_tdb/ldb_index.c | 4 | ||||
-rw-r--r-- | lib/ldb/ldb_tdb/ldb_search.c | 3 |
4 files changed, 41 insertions, 7 deletions
diff --git a/lib/ldb/common/ldb_pack.c b/lib/ldb/common/ldb_pack.c index 7e6dd2d55d3..a63dd5840ef 100644 --- a/lib/ldb/common/ldb_pack.c +++ b/lib/ldb/common/ldb_pack.c @@ -233,6 +233,7 @@ int ldb_unpack_data_only_attr_list_flags(struct ldb_context *ldb, unsigned int nelem = 0; size_t len; unsigned int found = 0; + struct ldb_val *ldb_val_single_array = NULL; if (list == NULL) { list_size = 0; @@ -313,6 +314,26 @@ int ldb_unpack_data_only_attr_list_flags(struct ldb_context *ldb, goto failed; } + /* + * In typical use, most values are single-valued. This makes + * it quite expensive to allocate an array of ldb_val for each + * of these, just to then hold the pointer to the data buffer + * (in the LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC we don't + * allocate the data). So with + * LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC we allocate this ahead + * of time and use it for the single values where possible. + * (This is used the the normal search case, but not in the + * index case because of caller requirements). + */ + if (flags & LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC) { + ldb_val_single_array = talloc_array(message->elements, struct ldb_val, + message->num_elements); + if (ldb_val_single_array == NULL) { + errno = ENOMEM; + goto failed; + } + } + for (i=0;i<message->num_elements;i++) { const char *attr = NULL; size_t attr_len; @@ -396,7 +417,9 @@ int ldb_unpack_data_only_attr_list_flags(struct ldb_context *ldb, p += attr_len + 1; element->num_values = pull_uint32(p, 0); element->values = NULL; - if (element->num_values != 0) { + if ((flags & LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC) && element->num_values == 1) { + element->values = &ldb_val_single_array[nelem]; + } else if (element->num_values != 0) { element->values = talloc_array(message->elements, struct ldb_val, element->num_values); diff --git a/lib/ldb/include/ldb_module.h b/lib/ldb/include/ldb_module.h index 1c48590a381..833d5a8f3d0 100644 --- a/lib/ldb/include/ldb_module.h +++ b/lib/ldb/include/ldb_module.h @@ -412,8 +412,15 @@ int ldb_unpack_data(struct ldb_context *ldb, * Giving a NULL list (or a list_size of 0) unpacks all the attributes. * * Flags allow control of allocation, so that if - * LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC is specified, then values are - * not allocate, instead they point into the supplier constant buffer. + * LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC is specified, then data in values are + * not allocated, instead they point into the supplier constant buffer. + * + * If LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC is specified, then values + * array are not allocated individually (for single-valued + * attributes), instead they point into a single buffer per message. + * + * LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC is only valid when + * LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC is also specified. * * Likewise if LDB_UNPACK_DATA_FLAG_NO_DN is specified, the DN is omitted. */ @@ -425,7 +432,8 @@ int ldb_unpack_data_only_attr_list_flags(struct ldb_context *ldb, unsigned int flags, unsigned int *nb_elements_in_db); -#define LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC 0x0001 -#define LDB_UNPACK_DATA_FLAG_NO_DN 0x0002 +#define LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC 0x0001 +#define LDB_UNPACK_DATA_FLAG_NO_DN 0x0002 +#define LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC 0x0004 #endif diff --git a/lib/ldb/ldb_tdb/ldb_index.c b/lib/ldb/ldb_tdb/ldb_index.c index 6c238562970..79241721c9f 100644 --- a/lib/ldb/ldb_tdb/ldb_index.c +++ b/lib/ldb/ldb_tdb/ldb_index.c @@ -952,7 +952,9 @@ static int ltdb_index_filter(const struct dn_list *dn_list, return LDB_ERR_OPERATIONS_ERROR; } - ret = ltdb_search_dn1(ac->module, dn, msg, LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC); + ret = ltdb_search_dn1(ac->module, dn, msg, + LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC| + LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC); talloc_free(dn); if (ret == LDB_ERR_NO_SUCH_OBJECT) { /* the record has disappeared? yes, this can happen */ diff --git a/lib/ldb/ldb_tdb/ldb_search.c b/lib/ldb/ldb_tdb/ldb_search.c index 8dc93d68ace..373855fd428 100644 --- a/lib/ldb/ldb_tdb/ldb_search.c +++ b/lib/ldb/ldb_tdb/ldb_search.c @@ -559,7 +559,8 @@ static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, voi ret = ldb_unpack_data_only_attr_list_flags(ldb, &val, msg, NULL, 0, - LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC, + LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC| + LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC, &nb_elements_in_db); if (ret == -1) { talloc_free(msg); |