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:
parent
198471f9ed
commit
09580103fe
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
Loading…
x
Reference in New Issue
Block a user