mirror of
https://github.com/samba-team/samba.git
synced 2024-12-22 13:34:15 +03:00
ldb: Add ldb_unpack_data_only_attr_list_flags()
This function allows us to control allocation of memory during parse of the packed ldb data. This in turn can have an important performance impact as each small allocation can have a large overhead Signed-off-by: Andrew Bartlett <abartlet@samba.org> Reviewed-by: Andrew Bartlett <abartlet@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
This commit is contained in:
parent
ebdf6e079b
commit
f6e87188b6
@ -254,6 +254,7 @@ ldb_transaction_prepare_commit: int (struct ldb_context *)
|
||||
ldb_transaction_start: int (struct ldb_context *)
|
||||
ldb_unpack_data: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *)
|
||||
ldb_unpack_data_only_attr_list: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *, const char * const *, unsigned int, unsigned int *)
|
||||
ldb_unpack_data_only_attr_list_flags: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *, const char * const *, unsigned int, unsigned int, unsigned int *)
|
||||
ldb_val_dup: struct ldb_val (TALLOC_CTX *, const struct ldb_val *)
|
||||
ldb_val_equal_exact: int (const struct ldb_val *, const struct ldb_val *)
|
||||
ldb_val_map_local: struct ldb_val (struct ldb_module *, void *, const struct ldb_map_attribute *, const struct ldb_val *)
|
||||
|
@ -211,20 +211,20 @@ static bool ldb_consume_element_data(uint8_t **pp, size_t *premaining)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Unpack a ldb message from a linear buffer in ldb_val
|
||||
*
|
||||
* Providing a list of attributes to this function allows selective unpacking.
|
||||
* Giving a NULL list (or a list_size of 0) unpacks all the attributes.
|
||||
*
|
||||
* Free with ldb_unpack_data_free()
|
||||
*/
|
||||
int ldb_unpack_data_only_attr_list(struct ldb_context *ldb,
|
||||
const struct ldb_val *data,
|
||||
struct ldb_message *message,
|
||||
const char * const *list,
|
||||
unsigned int list_size,
|
||||
unsigned int *nb_elements_in_db)
|
||||
int ldb_unpack_data_only_attr_list_flags(struct ldb_context *ldb,
|
||||
const struct ldb_val *data,
|
||||
struct ldb_message *message,
|
||||
const char * const *list,
|
||||
unsigned int list_size,
|
||||
unsigned int flags,
|
||||
unsigned int *nb_elements_in_db)
|
||||
{
|
||||
uint8_t *p;
|
||||
size_t remaining;
|
||||
@ -271,10 +271,14 @@ int ldb_unpack_data_only_attr_list(struct ldb_context *ldb,
|
||||
errno = EIO;
|
||||
goto failed;
|
||||
}
|
||||
message->dn = ldb_dn_new(message, ldb, (char *)p);
|
||||
if (message->dn == NULL) {
|
||||
errno = ENOMEM;
|
||||
goto failed;
|
||||
if (flags & LDB_UNPACK_DATA_FLAG_NO_DN) {
|
||||
message->dn = NULL;
|
||||
} else {
|
||||
message->dn = ldb_dn_new(message, ldb, (char *)p);
|
||||
if (message->dn == NULL) {
|
||||
errno = ENOMEM;
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Redundant: by definition, remaining must be more
|
||||
@ -373,11 +377,15 @@ int ldb_unpack_data_only_attr_list(struct ldb_context *ldb,
|
||||
}
|
||||
}
|
||||
element = &message->elements[nelem];
|
||||
element->name = talloc_memdup(message->elements, attr, attr_len+1);
|
||||
if (flags & LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC) {
|
||||
element->name = attr;
|
||||
} else {
|
||||
element->name = talloc_memdup(message->elements, attr, attr_len+1);
|
||||
|
||||
if (element->name == NULL) {
|
||||
errno = ENOMEM;
|
||||
goto failed;
|
||||
if (element->name == NULL) {
|
||||
errno = ENOMEM;
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
element->flags = 0;
|
||||
|
||||
@ -422,15 +430,18 @@ int ldb_unpack_data_only_attr_list(struct ldb_context *ldb,
|
||||
}
|
||||
|
||||
element->values[j].length = len;
|
||||
element->values[j].data = talloc_size(element->values, len+1);
|
||||
if (element->values[j].data == NULL) {
|
||||
errno = ENOMEM;
|
||||
goto failed;
|
||||
if (flags & LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC) {
|
||||
element->values[j].data = p + 4;
|
||||
} else {
|
||||
element->values[j].data = talloc_size(element->values, len+1);
|
||||
if (element->values[j].data == NULL) {
|
||||
errno = ENOMEM;
|
||||
goto failed;
|
||||
}
|
||||
memcpy(element->values[j].data, p + 4,
|
||||
len);
|
||||
element->values[j].data[len] = 0;
|
||||
}
|
||||
memcpy(element->values[j].data, p + 4,
|
||||
len);
|
||||
element->values[j].data[len] = 0;
|
||||
|
||||
remaining -= len;
|
||||
p += len+4+1;
|
||||
}
|
||||
@ -463,6 +474,30 @@ failed:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unpack a ldb message from a linear buffer in ldb_val
|
||||
*
|
||||
* Providing a list of attributes to this function allows selective unpacking.
|
||||
* Giving a NULL list (or a list_size of 0) unpacks all the attributes.
|
||||
*
|
||||
* Free with ldb_unpack_data_free()
|
||||
*/
|
||||
int ldb_unpack_data_only_attr_list(struct ldb_context *ldb,
|
||||
const struct ldb_val *data,
|
||||
struct ldb_message *message,
|
||||
const char * const *list,
|
||||
unsigned int list_size,
|
||||
unsigned int *nb_elements_in_db)
|
||||
{
|
||||
return ldb_unpack_data_only_attr_list_flags(ldb,
|
||||
data,
|
||||
message,
|
||||
list,
|
||||
list_size,
|
||||
0,
|
||||
nb_elements_in_db);
|
||||
}
|
||||
|
||||
int ldb_unpack_data(struct ldb_context *ldb,
|
||||
const struct ldb_val *data,
|
||||
struct ldb_message *message)
|
||||
|
@ -390,6 +390,12 @@ int ldb_register_extended_match_rule(struct ldb_context *ldb,
|
||||
int ldb_pack_data(struct ldb_context *ldb,
|
||||
const struct ldb_message *message,
|
||||
struct ldb_val *data);
|
||||
/*
|
||||
* Unpack a ldb message from a linear buffer in ldb_val
|
||||
*
|
||||
* Providing a list of attributes to this function allows selective unpacking.
|
||||
* Giving a NULL list (or a list_size of 0) unpacks all the attributes.
|
||||
*/
|
||||
int ldb_unpack_data_only_attr_list(struct ldb_context *ldb,
|
||||
const struct ldb_val *data,
|
||||
struct ldb_message *message,
|
||||
@ -399,5 +405,27 @@ int ldb_unpack_data_only_attr_list(struct ldb_context *ldb,
|
||||
int ldb_unpack_data(struct ldb_context *ldb,
|
||||
const struct ldb_val *data,
|
||||
struct ldb_message *message);
|
||||
/*
|
||||
* Unpack a ldb message from a linear buffer in ldb_val
|
||||
*
|
||||
* Providing a list of attributes to this function allows selective unpacking.
|
||||
* 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.
|
||||
*
|
||||
* Likewise if LDB_UNPACK_DATA_FLAG_NO_DN is specified, the DN is omitted.
|
||||
*/
|
||||
int ldb_unpack_data_only_attr_list_flags(struct ldb_context *ldb,
|
||||
const struct ldb_val *data,
|
||||
struct ldb_message *message,
|
||||
const char * const *list,
|
||||
unsigned int list_size,
|
||||
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
|
||||
|
||||
#endif
|
||||
|
@ -1102,6 +1102,54 @@ static bool torture_ldb_unpack(struct torture_context *torture)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool torture_ldb_unpack_flags(struct torture_context *torture)
|
||||
{
|
||||
TALLOC_CTX *mem_ctx = talloc_new(torture);
|
||||
struct ldb_context *ldb;
|
||||
struct ldb_val data = data_blob_const(dda1d01d_bin, sizeof(dda1d01d_bin));
|
||||
struct ldb_message *msg = ldb_msg_new(mem_ctx);
|
||||
const char *ldif_text = dda1d01d_ldif;
|
||||
struct ldb_ldif ldif;
|
||||
unsigned int nb_elements_in_db;
|
||||
|
||||
ldb = samba_ldb_init(mem_ctx, torture->ev, NULL, NULL, NULL);
|
||||
torture_assert(torture,
|
||||
ldb != NULL,
|
||||
"Failed to init ldb");
|
||||
|
||||
torture_assert_int_equal(torture,
|
||||
ldb_unpack_data_only_attr_list_flags(ldb, &data,
|
||||
msg,
|
||||
NULL, 0,
|
||||
LDB_UNPACK_DATA_FLAG_NO_DATA_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");
|
||||
|
||||
torture_assert_int_equal(torture,
|
||||
ldb_unpack_data_only_attr_list_flags(ldb, &data,
|
||||
msg,
|
||||
NULL, 0,
|
||||
LDB_UNPACK_DATA_FLAG_NO_DN,
|
||||
&nb_elements_in_db),
|
||||
0,
|
||||
"ldb_unpack_data failed");
|
||||
|
||||
torture_assert(torture,
|
||||
msg->dn == NULL,
|
||||
"msg->dn should be NULL");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool torture_ldb_parse_ldif(struct torture_context *torture)
|
||||
{
|
||||
TALLOC_CTX *mem_ctx = talloc_new(torture);
|
||||
@ -1265,6 +1313,8 @@ struct torture_suite *torture_ldb(TALLOC_CTX *mem_ctx)
|
||||
torture_suite_add_simple_test(suite, "dn", torture_ldb_dn);
|
||||
torture_suite_add_simple_test(suite, "unpack-data",
|
||||
torture_ldb_unpack);
|
||||
torture_suite_add_simple_test(suite, "unpack-data-flags",
|
||||
torture_ldb_unpack_flags);
|
||||
torture_suite_add_simple_test(suite, "parse-ldif",
|
||||
torture_ldb_parse_ldif);
|
||||
torture_suite_add_simple_test(suite, "unpack-data-only-attr-list",
|
||||
|
Loading…
Reference in New Issue
Block a user