1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-23 09:57:40 +03:00

ldb: Avoid multiple tiny allocations during full DB scan

LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC allows us to consolidate some of these allocations

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>

Autobuild-User(master): Douglas Bagnall <dbagnall@samba.org>
Autobuild-Date(master): Wed Aug 31 10:53:09 CEST 2016 on sn-devel-144
This commit is contained in:
Andrew Bartlett 2016-08-23 11:38:26 +12:00 committed by Douglas Bagnall
parent 198471f9ed
commit 09580103fe
5 changed files with 59 additions and 7 deletions

View File

@ -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);

View File

@ -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.
*/
@ -427,5 +434,6 @@ int ldb_unpack_data_only_attr_list_flags(struct ldb_context *ldb,
#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

View File

@ -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 */

View File

@ -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);

View File

@ -1130,6 +1130,24 @@ static bool torture_ldb_unpack_flags(struct torture_context *torture)
ldif.msg = msg;
ldif_text = ldb_ldif_write_string(ldb, mem_ctx, &ldif);
torture_assert_int_equal(torture,
strcmp(ldif_text, dda1d01d_ldif), 0,
"ldif form differs from binary form");
torture_assert_int_equal(torture,
ldb_unpack_data_only_attr_list_flags(ldb, &data,
msg,
NULL, 0,
LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC|
LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC,
&nb_elements_in_db),
0,
"ldb_unpack_data failed");
ldif.changetype = LDB_CHANGETYPE_NONE;
ldif.msg = msg;
ldif_text = ldb_ldif_write_string(ldb, mem_ctx, &ldif);
torture_assert_int_equal(torture,
strcmp(ldif_text, dda1d01d_ldif), 0,
"ldif form differs from binary form");