WIP: sort attributes in ldb when storing them in DB
authorMatthieu Patou <mat@matws.net>
Mon, 21 Jan 2013 07:10:38 +0000 (23:10 -0800)
committerMatthieu Patou <mat@matws.net>
Wed, 27 May 2015 05:01:39 +0000 (22:01 -0700)
Change-Id: I0e8d33f1f3ae74af894810cf7ff8dff59cf16d78

lib/ldb/common/ldb_ldif.c
lib/ldb/common/ldb_msg.c
lib/ldb/common/ldb_pack.c
lib/ldb/include/ldb.h
lib/ldb/include/ldb_private.h
lib/ldb/ldb_tdb/ldb_search.c
lib/ldb/ldb_tdb/ldb_tdb.c
source4/ldap_server/ldap_backend.c

index f9743dca8b78b105dd71c9aefa3fa3229b8a55cc..ea1482cdefb1af98b09cad50d994aacb9b4e1a3e 100644 (file)
@@ -761,7 +761,7 @@ struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb,
        ldif = talloc(ldb, struct ldb_ldif);
        if (!ldif) return NULL;
 
-       ldif->msg = talloc(ldif, struct ldb_message);
+       ldif->msg = talloc_zero(ldif, struct ldb_message);
        if (ldif->msg == NULL) {
                talloc_free(ldif);
                return NULL;
@@ -770,10 +770,6 @@ struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb,
        ldif->changetype = LDB_CHANGETYPE_NONE;
        msg = ldif->msg;
 
-       msg->dn = NULL;
-       msg->elements = NULL;
-       msg->num_elements = 0;
-
        chunk = next_chunk(ldb, fgetc_fn, private_data);
        if (!chunk) {
                goto failed;
index 3f65351ff293f0d656835038813372e26a9bbc36..9c5d73760a6321d0977f707f14f4835405950243 100644 (file)
@@ -32,6 +32,7 @@
  */
 
 #include "ldb_private.h"
+#include "lib/util/binsearch.h"
 
 /*
   create a new ldb_message in a given memory context (NULL for top level)
@@ -48,6 +49,22 @@ struct ldb_message_element *ldb_msg_find_element(const struct ldb_message *msg,
                                                 const char *attr_name)
 {
        unsigned int i;
+       if (msg->flags & LDB_FLAG_SORTED_ATTRIBUTES) {
+               struct ldb_message_element *e;
+               if (msg->num_elements == 0) {
+                       return NULL;
+               }
+               BINARY_ARRAY_SEARCH(msg->elements, msg->num_elements, name,
+                                   attr_name, strcasecmp, e);
+               /* distinguishedname if present on sorted message is always at the end */
+               if (e == NULL &&
+                   strcasecmp(attr_name, "distinguishedname") == 0 &&
+                   strcasecmp(msg->elements[msg->num_elements - 1].name, attr_name) == 0)
+               {
+                       return &msg->elements[msg->num_elements - 1];
+               }
+               return e;
+       }
        for (i=0;i<msg->num_elements;i++) {
                if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
                        return &msg->elements[i];
@@ -122,6 +139,8 @@ static int _ldb_msg_add_el(struct ldb_message *msg,
 {
        struct ldb_message_element *els;
 
+       /* do not concidere attributes to be sorted */
+       msg->flags = 0;
        /*
         * TODO: Find out a way to assert on input parameters.
         * msg and return_el must be valid
@@ -153,6 +172,7 @@ int ldb_msg_add_empty(struct ldb_message *msg,
 {
        int ret;
        struct ldb_message_element *el;
+       int msgflags = msg->flags;
 
        ret = _ldb_msg_add_el(msg, &el);
        if (ret != LDB_SUCCESS) {
@@ -165,6 +185,11 @@ int ldb_msg_add_empty(struct ldb_message *msg,
        if (!el->name) {
                return LDB_ERR_OPERATIONS_ERROR;
        }
+       /* Restore flags as distinguisedName is always at the end in sorted
+        * message */
+       if (strcasecmp(attr_name, "distinguishedName") == 0) {
+               msg->flags = msgflags;
+       }
 
        if (return_el) {
                *return_el = el;
@@ -722,6 +747,7 @@ int ldb_msg_normalize(struct ldb_context *ldb,
        struct ldb_message *msg2;
 
        msg2 = ldb_msg_copy(mem_ctx, msg);
+       msg2->flags = 0;
        if (msg2 == NULL) {
                return LDB_ERR_OPERATIONS_ERROR;
        }
@@ -974,6 +1000,7 @@ int ldb_attr_in_list(const char * const *attrs, const char *attr)
 int ldb_msg_rename_attr(struct ldb_message *msg, const char *attr, const char *replace)
 {
        struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
+       msg->flags = 0;
        if (el == NULL) {
                return LDB_SUCCESS;
        }
index e722f08124bddccba1054194b243358ff0384eba..7468c1b24769f7704604883f0252ee5b1e935cbb 100644 (file)
@@ -35,6 +35,7 @@
 
 /* change this if the data format ever changes */
 #define LDB_PACKING_FORMAT 0x26011967
+#define LDB_PACKING_FORMAT_SORTED 0x26011968
 
 /* old packing formats */
 #define LDB_PACKING_FORMAT_NODN 0x26011966
@@ -64,6 +65,11 @@ static int attribute_storable_values(const struct ldb_message_element *el)
        return el->num_values;
 }
 
+static int message_element_cmp(const struct ldb_message_element *v1,
+                              const struct ldb_message_element *v2)
+{
+       return strcasecmp(v1->name, v2->name);
+}
 /*
   pack a ldb message into a linear buffer in a ldb_val
 
@@ -81,6 +87,7 @@ int ldb_pack_data(struct ldb_context *ldb,
        const char *dn;
        uint8_t *p;
        size_t len;
+       int format;
 
        dn = ldb_dn_get_linearized(message->dn);
        if (dn == NULL) {
@@ -114,8 +121,11 @@ int ldb_pack_data(struct ldb_context *ldb,
        }
        data->length = size;
 
+       format = LDB_PACKING_FORMAT_SORTED;
        p = data->data;
-       put_uint32(p, 0, LDB_PACKING_FORMAT);
+
+       /* FIXME this needs to be made a bit more configurable */
+       put_uint32(p, 0, format);
        put_uint32(p, 4, real_elements);
        p += 8;
 
@@ -125,6 +135,10 @@ int ldb_pack_data(struct ldb_context *ldb,
        memcpy(p, dn, len+1);
        p += len + 1;
 
+       if (format == LDB_PACKING_FORMAT_SORTED) {
+               TYPESAFE_QSORT(message->elements, message->num_elements, message_element_cmp);
+       }
+
        for (i=0;i<message->num_elements;i++) {
                if (attribute_storable_values(&message->elements[i]) == 0) {
                        continue;
@@ -218,6 +232,7 @@ int ldb_unpack_data_withlist(struct ldb_context *ldb,
                message->dn = NULL;
                break;
 
+       case LDB_PACKING_FORMAT_SORTED:
        case LDB_PACKING_FORMAT:
                len = strnlen((char *)p, remaining);
                if (len == remaining) {
@@ -346,6 +361,9 @@ int ldb_unpack_data_withlist(struct ldb_context *ldb,
         * bad.
         */
        message->num_elements = nelem;
+       if (format == LDB_PACKING_FORMAT_SORTED) {
+               message->flags |= LDB_FLAG_SORTED_ATTRIBUTES;
+       }
 
        if (remaining != 0) {
                ldb_debug(ldb, LDB_DEBUG_ERROR,
index 8205db8a7a1f8232d96fb8eb71fb24f4b58af5c4..38fda65f44331c1d13262e68f358a1cdc3c25f73 100644 (file)
@@ -177,6 +177,7 @@ struct ldb_message {
        struct ldb_dn *dn;
        unsigned int num_elements;
        struct ldb_message_element *elements;
+       int flags;
 };
 
 enum ldb_changetype {
index c8301be8b0ed1a5bda70f0766b77ecb34ff125ae..a42cbbff1e8353545c75ee53ae798030d47b87c5 100644 (file)
@@ -53,6 +53,9 @@ struct ldb_backend_ops;
 /* call is from an untrusted source - eg. over ldap:// */
 #define LDB_HANDLE_FLAG_UNTRUSTED   2
 
+/* Bitfield in the flag member */
+#define LDB_FLAG_SORTED_ATTRIBUTES 1
+
 struct ldb_handle {
        int status;
        enum ldb_state state;
index 1df97f9ce0022b4716d1466359ac8317e7ff6764..d7be9928901c5e1a1d4de9926058d61980c3ceff 100644 (file)
@@ -173,6 +173,7 @@ static struct ldb_message *ltdb_pull_attrs(struct ldb_module *module,
 
        ret->num_elements = 0;
        ret->elements = NULL;
+       ret->flags = msg->flags;
 
        if (!attrs) {
                if (msg_add_all_elements(module, ret, msg) != 0) {
index 493e4b9b41023d103671284b904487cf3bc7f066..1de71e0679031f755c1c69fb9288abb3590873da 100644 (file)
@@ -764,6 +764,7 @@ int ltdb_modify_internal(struct ldb_module *module,
        if (!msg2->dn) {
                msg2->dn = msg->dn;
        }
+       msg2->flags = 0;
 
        for (i=0; i<msg->num_elements; i++) {
                struct ldb_message_element *el = &msg->elements[i], *el2;
index fd2b57936c5d6bd872b286246506662bd3d17de1..177053012b7578ea2bfef02cd88e4b209c8e0020 100644 (file)
@@ -750,12 +750,10 @@ static NTSTATUS ldapsrv_ModifyRequest(struct ldapsrv_call *call)
 
        DEBUG(10, ("ModifyRequest: dn: [%s]\n", req->dn));
 
-       msg = talloc(local_ctx, struct ldb_message);
+       msg = talloc_zero(local_ctx, struct ldb_message);
        NT_STATUS_HAVE_NO_MEMORY(msg);
 
        msg->dn = dn;
-       msg->num_elements = 0;
-       msg->elements = NULL;
 
        if (req->num_mods > 0) {
                msg->num_elements = req->num_mods;
@@ -858,12 +856,10 @@ static NTSTATUS ldapsrv_AddRequest(struct ldapsrv_call *call)
 
        DEBUG(10, ("AddRequest: dn: [%s]\n", req->dn));
 
-       msg = talloc(local_ctx, struct ldb_message);
+       msg = talloc_zero(local_ctx, struct ldb_message);
        NT_STATUS_HAVE_NO_MEMORY(msg);
 
        msg->dn = dn;
-       msg->num_elements = 0;
-       msg->elements = NULL;
 
        if (req->num_attributes > 0) {
                msg->num_elements = req->num_attributes;