dsdb-operational: rework the loop for attribute removal
authorMatthieu Patou <mat@matws.net>
Fri, 28 Dec 2012 02:29:49 +0000 (18:29 -0800)
committerStefan Metzmacher <metze@samba.org>
Tue, 29 Jan 2013 21:03:14 +0000 (22:03 +0100)
Instead of doing ldb_in_list size(operational_remove) * (attrs_user +
attr_searched) * number of entries times to get the list of attributes to remove we construct this
list before the search and then use it for every entries.

source4/dsdb/samdb/ldb_modules/operational.c

index b1122b3d4294ea2092938e0c54682c290522c670..a34dee04f8b967255bddac4108a1843b5e36c030 100644 (file)
@@ -667,10 +667,12 @@ enum op_remove {
 
   Some of these are attributes that were once stored, but are now calculated
 */
-static const struct {
+struct op_attributes_operations {
        const char *attr;
        enum op_remove op;
-} operational_remove[] = {
+};
+
+static const struct op_attributes_operations operational_remove[] = {
        { "nTSecurityDescriptor",    OPERATIONAL_SD_FLAGS },
        { "msDS-KeyVersionNumber",   OPERATIONAL_REMOVE_UNLESS_CONTROL  },
        { "parentGUID",              OPERATIONAL_REMOVE_ALWAYS  },
@@ -692,6 +694,8 @@ static int operational_search_post_process(struct ldb_module *module,
                                           const char * const *attrs_from_user,
                                           const char * const *attrs_searched_for,
                                           struct op_controls_flags* controls_flags,
+                                          struct op_attributes_operations *list,
+                                          unsigned int list_size,
                                           struct ldb_request *parent)
 {
        struct ldb_context *ldb;
@@ -701,43 +705,8 @@ static int operational_search_post_process(struct ldb_module *module,
        ldb = ldb_module_get_ctx(module);
 
        /* removed any attrs that should not be shown to the user */
-       for (i=0; i<ARRAY_SIZE(operational_remove); i++) {
-               switch (operational_remove[i].op) {
-               case OPERATIONAL_REMOVE_UNASKED:
-                       if (ldb_attr_in_list(attrs_from_user, operational_remove[i].attr)) {
-                               continue;
-                       }
-                       if (ldb_attr_in_list(attrs_searched_for, operational_remove[i].attr)) {
-                               continue;
-                       }
-               case OPERATIONAL_REMOVE_ALWAYS:
-                       ldb_msg_remove_attr(msg, operational_remove[i].attr);
-                       break;
-               case OPERATIONAL_REMOVE_UNLESS_CONTROL:
-                       if (!check_keep_control_for_attribute(controls_flags, operational_remove[i].attr)) {
-                               ldb_msg_remove_attr(msg, operational_remove[i].attr);
-                               break;
-                       } else {
-                               continue;
-                       }
-               case OPERATIONAL_SD_FLAGS:
-                       if (ldb_attr_in_list(attrs_from_user, operational_remove[i].attr)) {
-                               continue;
-                       }
-                       if (controls_flags->sd) {
-                               if (attrs_from_user == NULL) {
-                                       continue;
-                               }
-                               if (attrs_from_user[0] == NULL) {
-                                       continue;
-                               }
-                               if (ldb_attr_in_list(attrs_from_user, "*")) {
-                                       continue;
-                               }
-                       }
-                       ldb_msg_remove_attr(msg, operational_remove[i].attr);
-                       break;
-               }
+       for (i=0; i < list_size; i++) {
+               ldb_msg_remove_attr(msg, list[i].attr);
        }
 
        for (a=0;attrs_from_user && attrs_from_user[a];a++) {
@@ -802,6 +771,8 @@ struct operational_context {
        enum ldb_scope scope;
        const char * const *attrs;
        struct op_controls_flags* controls_flags;
+       struct op_attributes_operations *list_operations;
+       unsigned int list_operations_size;
 };
 
 static int operational_callback(struct ldb_request *req, struct ldb_reply *ares)
@@ -829,7 +800,10 @@ static int operational_callback(struct ldb_request *req, struct ldb_reply *ares)
                                                      ac->scope,
                                                      ac->attrs,
                                                      req->op.search.attrs,
-                                                     ac->controls_flags, req);
+                                                     ac->controls_flags,
+                                                     ac->list_operations,
+                                                     ac->list_operations_size,
+                                                     req);
                if (ret != 0) {
                        return ldb_module_done(ac->req, NULL, NULL,
                                                LDB_ERR_OPERATIONS_ERROR);
@@ -849,6 +823,74 @@ static int operational_callback(struct ldb_request *req, struct ldb_reply *ares)
        return LDB_SUCCESS;
 }
 
+static struct op_attributes_operations* operation_get_op_list(TALLOC_CTX *ctx,
+                                                             const char* const* attrs,
+                                                             const char* const* searched_attrs,
+                                                             struct op_controls_flags* controls_flags)
+{
+       int idx = 0;
+       int i;
+       struct op_attributes_operations *list = talloc_zero_array(ctx,
+                                                                 struct op_attributes_operations,
+                                                                 ARRAY_SIZE(operational_remove) + 1);
+
+       if (list == NULL) {
+               return NULL;
+       }
+
+       for (i=0; i<ARRAY_SIZE(operational_remove); i++) {
+               switch (operational_remove[i].op) {
+               case OPERATIONAL_REMOVE_UNASKED:
+                       if (ldb_attr_in_list(attrs, operational_remove[i].attr)) {
+                               continue;
+                       }
+                       if (ldb_attr_in_list(searched_attrs, operational_remove[i].attr)) {
+                               continue;
+                       }
+                       list[idx].attr = operational_remove[i].attr;
+                       list[idx].op = OPERATIONAL_REMOVE_UNASKED;
+                       idx++;
+                       break;
+
+               case OPERATIONAL_REMOVE_ALWAYS:
+                       list[idx].attr = operational_remove[i].attr;
+                       list[idx].op = OPERATIONAL_REMOVE_ALWAYS;
+                       idx++;
+                       break;
+
+               case OPERATIONAL_REMOVE_UNLESS_CONTROL:
+                       if (!check_keep_control_for_attribute(controls_flags, operational_remove[i].attr)) {
+                               list[idx].attr = operational_remove[i].attr;
+                               list[idx].op = OPERATIONAL_REMOVE_UNLESS_CONTROL;
+                               idx++;
+                       }
+                       break;
+
+               case OPERATIONAL_SD_FLAGS:
+                       if (ldb_attr_in_list(attrs, operational_remove[i].attr)) {
+                               continue;
+                       }
+                       if (controls_flags->sd) {
+                               if (attrs == NULL) {
+                                       continue;
+                               }
+                               if (attrs[0] == NULL) {
+                                       continue;
+                               }
+                               if (ldb_attr_in_list(attrs, "*")) {
+                                       continue;
+                               }
+                       }
+                       list[idx].attr = operational_remove[i].attr;
+                       list[idx].op = OPERATIONAL_SD_FLAGS;
+                       idx++;
+                       break;
+               }
+       }
+
+       return list;
+}
+
 static int operational_search(struct ldb_module *module, struct ldb_request *req)
 {
        struct ldb_context *ldb;
@@ -930,7 +972,16 @@ static int operational_search(struct ldb_module *module, struct ldb_request *req
                        }
                }
        }
-
+       ac->list_operations = operation_get_op_list(ac, ac->attrs,
+                                                   search_attrs == NULL?req->op.search.attrs:search_attrs,
+                                                   ac->controls_flags);
+       ac->list_operations_size = 0;
+       i = 0;
+
+       while (ac->list_operations && ac->list_operations[i].attr != NULL) {
+               i++;
+       }
+       ac->list_operations_size = i;
        ret = ldb_build_search_req_ex(&down_req, ldb, ac,
                                        req->op.search.base,
                                        req->op.search.scope,