Sort output of schema for OpenLDAP during conversion
authorAndrew Bartlett <abartlet@samba.org>
Fri, 6 Mar 2009 01:12:24 +0000 (12:12 +1100)
committerAndrew Bartlett <abartlet@samba.org>
Fri, 6 Mar 2009 01:12:24 +0000 (12:12 +1100)
This avoids the need to assume that the schema is sorted on load,
which happens more often and is a major performace issue in the
Samba4's use of ldb.

Andrew Bartlett

source4/dsdb/schema/schema_convert_to_ol.c

index 375e4e381031c7b6d9117ad827e5e08b6792ecda..ebcb7ade59e3f73cb23ae253a14fead094c0d3f7 100644 (file)
 #include "dsdb/samdb/samdb.h"
 #include "system/locale.h"
 
 #include "dsdb/samdb/samdb.h"
 #include "system/locale.h"
 
+#define SEPERATOR "\n  "
+
+struct attr_map {
+       char *old_attr;
+       char *new_attr;
+};
+
+struct oid_map {
+       char *old_oid;
+       char *new_oid;
+};
+
+static char *print_schema_recursive(char *append_to_string, struct dsdb_schema *schema, const char *print_class,
+                                   enum dsdb_schema_convert_target target, 
+                                   const char **attrs_skip, const struct attr_map *attr_map, const struct oid_map *oid_map) 
+{
+       char *out = append_to_string;
+       const struct dsdb_class *objectclass;
+       objectclass = dsdb_class_by_lDAPDisplayName(schema, print_class);
+       if (!objectclass) {
+               DEBUG(0, ("Cannot find class %s in schema\n", print_class));
+               return NULL;
+       }
+
+       do {
+               TALLOC_CTX *mem_ctx = talloc_new(append_to_string);
+               const char *name = objectclass->lDAPDisplayName;
+               const char *oid = objectclass->governsID_oid;
+               const char *subClassOf = objectclass->subClassOf;
+               int objectClassCategory = objectclass->objectClassCategory;
+               const char **must;
+               const char **may;
+               char *schema_entry = NULL;
+               const char *objectclass_name_as_list[] = {
+                       objectclass->lDAPDisplayName,
+                       NULL
+               };
+               int j;
+               int attr_idx;
+               
+               if (!mem_ctx) {
+                       DEBUG(0, ("Failed to create new talloc context\n"));
+                       return NULL;
+               }
+
+               /* We have been asked to skip some attributes/objectClasses */
+               if (attrs_skip && str_list_check_ci(attrs_skip, name)) {
+                       continue;
+               }
+
+               /* We might have been asked to remap this oid, due to a conflict */
+               for (j=0; oid_map && oid_map[j].old_oid; j++) {
+                       if (strcasecmp(oid, oid_map[j].old_oid) == 0) {
+                               oid =  oid_map[j].new_oid;
+                               break;
+                       }
+               }
+               
+               /* We might have been asked to remap this name, due to a conflict */
+               for (j=0; name && attr_map && attr_map[j].old_attr; j++) {
+                       if (strcasecmp(name, attr_map[j].old_attr) == 0) {
+                               name =  attr_map[j].new_attr;
+                               break;
+                       }
+               }
+               
+               may = dsdb_full_attribute_list(mem_ctx, schema, objectclass_name_as_list, DSDB_SCHEMA_ALL_MAY);
+
+               for (j=0; may && may[j]; j++) {
+                       /* We might have been asked to remap this name, due to a conflict */ 
+                       for (attr_idx=0; attr_map && attr_map[attr_idx].old_attr; attr_idx++) { 
+                               if (strcasecmp(may[j], attr_map[attr_idx].old_attr) == 0) { 
+                                       may[j] =  attr_map[attr_idx].new_attr; 
+                                       break;                          
+                               }                                       
+                       }                                               
+               }
+
+               must = dsdb_full_attribute_list(mem_ctx, schema, objectclass_name_as_list, DSDB_SCHEMA_ALL_MUST);
+
+               for (j=0; must && must[j]; j++) {
+                       /* We might have been asked to remap this name, due to a conflict */ 
+                       for (attr_idx=0; attr_map && attr_map[attr_idx].old_attr; attr_idx++) { 
+                               if (strcasecmp(must[j], attr_map[attr_idx].old_attr) == 0) { 
+                                       must[j] =  attr_map[attr_idx].new_attr; 
+                                       break;                          
+                               }                                       
+                       }                                               
+               }
+
+               schema_entry = schema_class_description(mem_ctx, target, 
+                                                       SEPERATOR,
+                                                       oid, 
+                                                       name,
+                                                       NULL, 
+                                                       subClassOf,
+                                                       objectClassCategory,
+                                                       must,
+                                                       may,
+                                                       NULL);
+               if (schema_entry == NULL) {
+                       DEBUG(0, ("failed to generate schema description for %s\n", name));
+                       return NULL;
+               }
+
+               switch (target) {
+               case TARGET_OPENLDAP:
+                       out = talloc_asprintf_append(out, "objectclass %s\n\n", schema_entry);
+                       break;
+               case TARGET_FEDORA_DS:
+                       out = talloc_asprintf_append(out, "objectClasses: %s\n", schema_entry);
+                       break;
+               }
+               talloc_free(mem_ctx);
+       } while (0);
+
+       
+       for (objectclass=schema->classes; objectclass; objectclass = objectclass->next) {
+               if (ldb_attr_cmp(objectclass->subClassOf, print_class) == 0 
+                   && ldb_attr_cmp(objectclass->lDAPDisplayName, print_class) != 0) {
+                       out = print_schema_recursive(out, schema, objectclass->lDAPDisplayName, 
+                                                    target, attrs_skip, attr_map, oid_map);
+               }
+       }
+       return out;
+}
+
 /* Routine to linearise our internal schema into the format that
    OpenLDAP and Fedora DS use for their backend.  
 
 /* Routine to linearise our internal schema into the format that
    OpenLDAP and Fedora DS use for their backend.  
 
@@ -47,20 +174,12 @@ char *dsdb_convert_schema_to_openldap(struct ldb_context *ldb, char *target_str,
        char *out;
        const char **attrs_skip = NULL;
        int num_skip = 0;
        char *out;
        const char **attrs_skip = NULL;
        int num_skip = 0;
-       struct oid_map {
-               char *old_oid;
-               char *new_oid;
-       } *oid_map = NULL;
+       struct oid_map *oid_map = NULL;
        int num_oid_maps = 0;
        int num_oid_maps = 0;
-       struct attr_map {
-               char *old_attr;
-               char *new_attr;
-       } *attr_map = NULL;
+       struct attr_map *attr_map = NULL;
        int num_attr_maps = 0;  
        int num_attr_maps = 0;  
-       struct dsdb_class *objectclass;
        struct dsdb_attribute *attribute;
        struct dsdb_schema *schema;
        struct dsdb_attribute *attribute;
        struct dsdb_schema *schema;
-       const char *seperator;
        enum dsdb_schema_convert_target target;
 
        char *next_line = talloc_strdup(mem_ctx, mappings);
        enum dsdb_schema_convert_target target;
 
        char *next_line = talloc_strdup(mem_ctx, mappings);
@@ -137,13 +256,12 @@ char *dsdb_convert_schema_to_openldap(struct ldb_context *ldb, char *target_str,
                DEBUG(0, ("No schema on ldb to convert!\n"));
                return NULL;
        }
                DEBUG(0, ("No schema on ldb to convert!\n"));
                return NULL;
        }
+
        switch (target) {
        case TARGET_OPENLDAP:
        switch (target) {
        case TARGET_OPENLDAP:
-               seperator = "\n  ";
                out = talloc_strdup(mem_ctx, "");
                break;
        case TARGET_FEDORA_DS:
                out = talloc_strdup(mem_ctx, "");
                break;
        case TARGET_FEDORA_DS:
-               seperator = "\n  ";
                out = talloc_strdup(mem_ctx, "dn: cn=schema\n");
                break;
        }
                out = talloc_strdup(mem_ctx, "dn: cn=schema\n");
                break;
        }
@@ -198,7 +316,7 @@ char *dsdb_convert_schema_to_openldap(struct ldb_context *ldb, char *target_str,
                
                schema_entry = schema_attribute_description(mem_ctx, 
                                                            target, 
                
                schema_entry = schema_attribute_description(mem_ctx, 
                                                            target, 
-                                                           seperator
+                                                           SEPERATOR
                                                            oid, 
                                                            name, 
                                                            equality, 
                                                            oid, 
                                                            name, 
                                                            equality, 
@@ -225,91 +343,7 @@ char *dsdb_convert_schema_to_openldap(struct ldb_context *ldb, char *target_str,
                }
        }
 
                }
        }
 
-       /* This is already sorted to have 'top' and similar classes first */
-       for (objectclass=schema->classes; objectclass; objectclass = objectclass->next) {
-               const char *name = objectclass->lDAPDisplayName;
-               const char *oid = objectclass->governsID_oid;
-               const char *subClassOf = objectclass->subClassOf;
-               int objectClassCategory = objectclass->objectClassCategory;
-               const char **must;
-               const char **may;
-               char *schema_entry = NULL;
-               const char *objectclass_name_as_list[] = {
-                       objectclass->lDAPDisplayName,
-                       NULL
-               };
-               int j;
-               int attr_idx;
-               
-               /* We have been asked to skip some attributes/objectClasses */
-               if (attrs_skip && str_list_check_ci(attrs_skip, name)) {
-                       continue;
-               }
-
-               /* We might have been asked to remap this oid, due to a conflict */
-               for (j=0; oid_map && oid_map[j].old_oid; j++) {
-                       if (strcasecmp(oid, oid_map[j].old_oid) == 0) {
-                               oid =  oid_map[j].new_oid;
-                               break;
-                       }
-               }
-               
-               /* We might have been asked to remap this name, due to a conflict */
-               for (j=0; name && attr_map && attr_map[j].old_attr; j++) {
-                       if (strcasecmp(name, attr_map[j].old_attr) == 0) {
-                               name =  attr_map[j].new_attr;
-                               break;
-                       }
-               }
-               
-               may = dsdb_full_attribute_list(mem_ctx, schema, objectclass_name_as_list, DSDB_SCHEMA_ALL_MAY);
-
-               for (j=0; may && may[j]; j++) {
-                       /* We might have been asked to remap this name, due to a conflict */ 
-                       for (attr_idx=0; attr_map && attr_map[attr_idx].old_attr; attr_idx++) { 
-                               if (strcasecmp(may[j], attr_map[attr_idx].old_attr) == 0) { 
-                                       may[j] =  attr_map[attr_idx].new_attr; 
-                                       break;                          
-                               }                                       
-                       }                                               
-               }
-
-               must = dsdb_full_attribute_list(mem_ctx, schema, objectclass_name_as_list, DSDB_SCHEMA_ALL_MUST);
-
-               for (j=0; must && must[j]; j++) {
-                       /* We might have been asked to remap this name, due to a conflict */ 
-                       for (attr_idx=0; attr_map && attr_map[attr_idx].old_attr; attr_idx++) { 
-                               if (strcasecmp(must[j], attr_map[attr_idx].old_attr) == 0) { 
-                                       must[j] =  attr_map[attr_idx].new_attr; 
-                                       break;                          
-                               }                                       
-                       }                                               
-               }
-
-               schema_entry = schema_class_description(mem_ctx, target, 
-                                                       seperator,
-                                                       oid, 
-                                                       name,
-                                                       NULL, 
-                                                       subClassOf,
-                                                       objectClassCategory,
-                                                       must,
-                                                       may,
-                                                       NULL);
-               if (schema_entry == NULL) {
-                       DEBUG(0, ("failed to generate schema description for %s\n", name));
-                       return NULL;
-               }
-
-               switch (target) {
-               case TARGET_OPENLDAP:
-                       out = talloc_asprintf_append(out, "objectclass %s\n\n", schema_entry);
-                       break;
-               case TARGET_FEDORA_DS:
-                       out = talloc_asprintf_append(out, "objectClasses: %s\n", schema_entry);
-                       break;
-               }
-       }
+       out = print_schema_recursive(out, schema, "top", target, attrs_skip, attr_map, oid_map);
 
        return out;
 }
 
        return out;
 }