From 8374d6f0dc1d6ce6c554b10b5133bd77c5ad6292 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 6 Mar 2009 12:12:24 +1100 Subject: Sort output of schema for OpenLDAP during conversion 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 | 230 +++++++++++++++++------------ 1 file changed, 132 insertions(+), 98 deletions(-) (limited to 'source4/dsdb/schema') diff --git a/source4/dsdb/schema/schema_convert_to_ol.c b/source4/dsdb/schema/schema_convert_to_ol.c index 375e4e3810..ebcb7ade59 100644 --- a/source4/dsdb/schema/schema_convert_to_ol.c +++ b/source4/dsdb/schema/schema_convert_to_ol.c @@ -23,6 +23,133 @@ #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. @@ -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; - struct oid_map { - char *old_oid; - char *new_oid; - } *oid_map = NULL; + struct oid_map *oid_map = NULL; 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; - struct dsdb_class *objectclass; 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); @@ -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; } + switch (target) { case TARGET_OPENLDAP: - seperator = "\n "; out = talloc_strdup(mem_ctx, ""); break; case TARGET_FEDORA_DS: - seperator = "\n "; 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, - seperator, + SEPERATOR, 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; } -- cgit