From 17aac8cad2b3fe4b23eaebd869b1538735a1954a Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 5 Mar 2009 16:52:11 +1100 Subject: Remove ad2oLschema, insted call it directly from provision-backend This removes a level of indirection via external binaries in the provision-backend code, and also makes better use of our internal code for loading schema from an LDIF file. Remaining to do: Sort the output again, as the load from LDIF is unsorted (also needed because the normal LDB load from sorted input is too slow anyway, and is only needed here). Andrew Bartlett --- source4/dsdb/schema/schema_set.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/dsdb/schema/schema_set.c') diff --git a/source4/dsdb/schema/schema_set.c b/source4/dsdb/schema/schema_set.c index 6abd8a8f88..d52976958d 100644 --- a/source4/dsdb/schema/schema_set.c +++ b/source4/dsdb/schema/schema_set.c @@ -277,7 +277,7 @@ void dsdb_make_schema_global(struct ldb_context *ldb) * schema itself to the directory. */ -WERROR dsdb_attach_schema_from_ldif_file(struct ldb_context *ldb, const char *pf, const char *df) +WERROR dsdb_attach_schema_from_ldif(struct ldb_context *ldb, const char *pf, const char *df) { struct ldb_ldif *ldif; struct ldb_message *msg; -- cgit From 9539e2b508b3340b49575e5022c365ec382b2097 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 2 Apr 2009 16:42:21 +1100 Subject: major upgrade to the ldb attribute handling This is all working towards supporting the full WSPP schema without a major performance penalty. We now use binary searches when looking up classes and attributes. We also avoid the loop loading the attributes into ldb, by adding a hook to override the ldb attribute search function in a module. The attributes can thus be loaded once, and then saved as part of the global schema. Also added support for a few more key attribute syntaxes, as needed for the full schema. --- source4/dsdb/schema/schema_set.c | 207 +++++++++++++++++++++++++++++++++------ 1 file changed, 178 insertions(+), 29 deletions(-) (limited to 'source4/dsdb/schema/schema_set.c') diff --git a/source4/dsdb/schema/schema_set.c b/source4/dsdb/schema/schema_set.c index d52976958d..9f23088c97 100644 --- a/source4/dsdb/schema/schema_set.c +++ b/source4/dsdb/schema/schema_set.c @@ -26,6 +26,21 @@ #include "lib/ldb/include/ldb_module.h" #include "param/param.h" +/* + override the name to attribute handler function + */ +const struct ldb_schema_attribute *dsdb_attribute_handler_override(struct ldb_context *ldb, + void *private_data, + const char *name) +{ + struct dsdb_schema *schema = talloc_get_type_abort(private_data, struct dsdb_schema); + const struct dsdb_attribute *a = dsdb_attribute_by_lDAPDisplayName(schema, name); + if (a == NULL) { + /* this will fall back to ldb internal handling */ + return NULL; + } + return a->ldb_schema_attribute; +} static int dsdb_schema_set_attributes(struct ldb_context *ldb, struct dsdb_schema *schema, bool write_attributes) { @@ -34,11 +49,19 @@ static int dsdb_schema_set_attributes(struct ldb_context *ldb, struct dsdb_schem struct ldb_result *res_idx; struct dsdb_attribute *attr; struct ldb_message *mod_msg; - TALLOC_CTX *mem_ctx = talloc_new(ldb); - + TALLOC_CTX *mem_ctx; struct ldb_message *msg; struct ldb_message *msg_idx; + /* setup our own attribute name to schema handler */ + ldb_schema_attribute_set_override_handler(ldb, dsdb_attribute_handler_override, schema); + + if (!write_attributes) { + talloc_free(mem_ctx); + return ret; + } + + mem_ctx = talloc_new(ldb); if (!mem_ctx) { return LDB_ERR_OPERATIONS_ERROR; } @@ -46,27 +69,27 @@ static int dsdb_schema_set_attributes(struct ldb_context *ldb, struct dsdb_schem msg = ldb_msg_new(mem_ctx); if (!msg) { ldb_oom(ldb); - return LDB_ERR_OPERATIONS_ERROR; + goto op_error; } msg_idx = ldb_msg_new(mem_ctx); if (!msg_idx) { ldb_oom(ldb); - return LDB_ERR_OPERATIONS_ERROR; + goto op_error; } msg->dn = ldb_dn_new(msg, ldb, "@ATTRIBUTES"); if (!msg->dn) { ldb_oom(ldb); - return LDB_ERR_OPERATIONS_ERROR; + goto op_error; } msg_idx->dn = ldb_dn_new(msg, ldb, "@INDEXLIST"); if (!msg_idx->dn) { ldb_oom(ldb); - return LDB_ERR_OPERATIONS_ERROR; + goto op_error; } for (attr = schema->attributes; attr; attr = attr->next) { - const struct ldb_schema_syntax *s; const char *syntax = attr->syntax->ldb_syntax; + if (!syntax) { syntax = attr->syntax->ldap_oid; } @@ -87,33 +110,13 @@ static int dsdb_schema_set_attributes(struct ldb_context *ldb, struct dsdb_schem break; } } - - if (!attr->syntax) { - continue; - } - - ret = ldb_schema_attribute_add(ldb, attr->lDAPDisplayName, LDB_ATTR_FLAG_FIXED, - syntax); - if (ret != LDB_SUCCESS) { - s = ldb_samba_syntax_by_name(ldb, attr->syntax->ldap_oid); - if (s) { - ret = ldb_schema_attribute_add_with_syntax(ldb, attr->lDAPDisplayName, LDB_ATTR_FLAG_FIXED, s); - } else { - ret = LDB_SUCCESS; /* Nothing to do here */ - } - } - - if (ret != LDB_SUCCESS) { - break; - } } - if (!write_attributes || ret != LDB_SUCCESS) { + if (ret != LDB_SUCCESS) { talloc_free(mem_ctx); return ret; } - /* Try to avoid churning the attributes too much - we only want to do this if they have changed */ ret = ldb_search(ldb, mem_ctx, &res, msg->dn, LDB_SCOPE_BASE, NULL, "dn=%s", ldb_dn_get_linearized(msg->dn)); if (ret == LDB_ERR_NO_SUCH_OBJECT) { @@ -165,6 +168,146 @@ static int dsdb_schema_set_attributes(struct ldb_context *ldb, struct dsdb_schem } talloc_free(mem_ctx); return ret; + +op_error: + talloc_free(mem_ctx); + return LDB_ERR_OPERATIONS_ERROR; +} + +static int dsdb_compare_class_by_lDAPDisplayName(struct dsdb_class **c1, struct dsdb_class **c2) +{ + return strcasecmp((*c1)->lDAPDisplayName, (*c2)->lDAPDisplayName); +} +static int dsdb_compare_class_by_governsID_id(struct dsdb_class **c1, struct dsdb_class **c2) +{ + return (*c1)->governsID_id - (*c2)->governsID_id; +} +static int dsdb_compare_class_by_governsID_oid(struct dsdb_class **c1, struct dsdb_class **c2) +{ + return strcasecmp((*c1)->governsID_oid, (*c2)->governsID_oid); +} +static int dsdb_compare_class_by_cn(struct dsdb_class **c1, struct dsdb_class **c2) +{ + return strcasecmp((*c1)->cn, (*c2)->cn); +} + +static int dsdb_compare_attribute_by_lDAPDisplayName(struct dsdb_attribute **a1, struct dsdb_attribute **a2) +{ + return strcasecmp((*a1)->lDAPDisplayName, (*a2)->lDAPDisplayName); +} +static int dsdb_compare_attribute_by_attributeID_id(struct dsdb_attribute **a1, struct dsdb_attribute **a2) +{ + return (*a1)->attributeID_id - (*a2)->attributeID_id; +} +static int dsdb_compare_attribute_by_attributeID_oid(struct dsdb_attribute **a1, struct dsdb_attribute **a2) +{ + return strcasecmp((*a1)->attributeID_oid, (*a2)->attributeID_oid); +} +static int dsdb_compare_attribute_by_linkID(struct dsdb_attribute **a1, struct dsdb_attribute **a2) +{ + return (*a1)->linkID - (*a2)->linkID; +} + +/* + create the sorted accessor arrays for the schema + */ +static int dsdb_setup_sorted_accessors(struct ldb_context *ldb, + struct dsdb_schema *schema) +{ + struct dsdb_class *cur; + struct dsdb_attribute *a; + uint32_t i; + + talloc_free(schema->classes_by_lDAPDisplayName); + talloc_free(schema->classes_by_governsID_id); + talloc_free(schema->classes_by_governsID_oid); + talloc_free(schema->classes_by_cn); + + /* count the classes */ + for (i=0, cur=schema->classes; cur; i++, cur=cur->next) /* noop */ ; + schema->num_classes = i; + + /* setup classes_by_* */ + schema->classes_by_lDAPDisplayName = talloc_array(schema, struct dsdb_class *, i); + schema->classes_by_governsID_id = talloc_array(schema, struct dsdb_class *, i); + schema->classes_by_governsID_oid = talloc_array(schema, struct dsdb_class *, i); + schema->classes_by_cn = talloc_array(schema, struct dsdb_class *, i); + if (schema->classes_by_lDAPDisplayName == NULL || + schema->classes_by_governsID_id == NULL || + schema->classes_by_governsID_oid == NULL || + schema->classes_by_cn == NULL) { + goto failed; + } + + for (i=0, cur=schema->classes; cur; i++, cur=cur->next) { + schema->classes_by_lDAPDisplayName[i] = cur; + schema->classes_by_governsID_id[i] = cur; + schema->classes_by_governsID_oid[i] = cur; + schema->classes_by_cn[i] = cur; + } + + /* sort the arrays */ + qsort(schema->classes_by_lDAPDisplayName, schema->num_classes, + sizeof(struct dsdb_class *), QSORT_CAST dsdb_compare_class_by_lDAPDisplayName); + qsort(schema->classes_by_governsID_id, schema->num_classes, + sizeof(struct dsdb_class *), QSORT_CAST dsdb_compare_class_by_governsID_id); + qsort(schema->classes_by_governsID_oid, schema->num_classes, + sizeof(struct dsdb_class *), QSORT_CAST dsdb_compare_class_by_governsID_oid); + qsort(schema->classes_by_cn, schema->num_classes, + sizeof(struct dsdb_class *), QSORT_CAST dsdb_compare_class_by_cn); + + /* now build the attribute accessor arrays */ + talloc_free(schema->attributes_by_lDAPDisplayName); + talloc_free(schema->attributes_by_attributeID_id); + talloc_free(schema->attributes_by_attributeID_oid); + talloc_free(schema->attributes_by_linkID); + + /* count the attributes */ + for (i=0, a=schema->attributes; a; i++, a=a->next) /* noop */ ; + schema->num_attributes = i; + + /* setup attributes_by_* */ + schema->attributes_by_lDAPDisplayName = talloc_array(schema, struct dsdb_attribute *, i); + schema->attributes_by_attributeID_id = talloc_array(schema, struct dsdb_attribute *, i); + schema->attributes_by_attributeID_oid = talloc_array(schema, struct dsdb_attribute *, i); + schema->attributes_by_linkID = talloc_array(schema, struct dsdb_attribute *, i); + if (schema->attributes_by_lDAPDisplayName == NULL || + schema->attributes_by_attributeID_id == NULL || + schema->attributes_by_attributeID_oid == NULL || + schema->attributes_by_linkID == NULL) { + goto failed; + } + + for (i=0, a=schema->attributes; a; i++, a=a->next) { + schema->attributes_by_lDAPDisplayName[i] = a; + schema->attributes_by_attributeID_id[i] = a; + schema->attributes_by_attributeID_oid[i] = a; + schema->attributes_by_linkID[i] = a; + } + + /* sort the arrays */ + qsort(schema->attributes_by_lDAPDisplayName, schema->num_attributes, + sizeof(struct dsdb_attribute *), QSORT_CAST dsdb_compare_attribute_by_lDAPDisplayName); + qsort(schema->attributes_by_attributeID_id, schema->num_attributes, + sizeof(struct dsdb_attribute *), QSORT_CAST dsdb_compare_attribute_by_attributeID_id); + qsort(schema->attributes_by_attributeID_oid, schema->num_attributes, + sizeof(struct dsdb_attribute *), QSORT_CAST dsdb_compare_attribute_by_attributeID_oid); + qsort(schema->attributes_by_linkID, schema->num_attributes, + sizeof(struct dsdb_attribute *), QSORT_CAST dsdb_compare_attribute_by_linkID); + + return LDB_SUCCESS; + +failed: + schema->classes_by_lDAPDisplayName = NULL; + schema->classes_by_governsID_id = NULL; + schema->classes_by_governsID_oid = NULL; + schema->classes_by_cn = NULL; + schema->attributes_by_lDAPDisplayName = NULL; + schema->attributes_by_attributeID_id = NULL; + schema->attributes_by_attributeID_oid = NULL; + schema->attributes_by_linkID = NULL; + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; } @@ -177,6 +320,11 @@ int dsdb_set_schema(struct ldb_context *ldb, struct dsdb_schema *schema) { int ret; + ret = dsdb_setup_sorted_accessors(ldb, schema); + if (ret != LDB_SUCCESS) { + return ret; + } + ret = ldb_set_opaque(ldb, "dsdb_schema", schema); if (ret != LDB_SUCCESS) { return ret; @@ -207,6 +355,7 @@ int dsdb_set_global_schema(struct ldb_context *ldb) if (!global_schema) { return LDB_SUCCESS; } + ret = ldb_set_opaque(ldb, "dsdb_schema", global_schema); if (ret != LDB_SUCCESS) { return ret; @@ -367,7 +516,7 @@ WERROR dsdb_attach_schema_from_ldif(struct ldb_context *ldb, const char *pf, con goto nomem; } - status = dsdb_attribute_from_ldb(schema, msg, sa, sa); + status = dsdb_attribute_from_ldb(ldb, schema, msg, sa, sa); if (!W_ERROR_IS_OK(status)) { goto failed; } -- cgit From 6e6094d780d372d0bc6cdf3bbdab360b5cd61219 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 3 Apr 2009 10:33:12 +1100 Subject: s4:schema Don't free mem_ctx before it is initilised --- source4/dsdb/schema/schema_set.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source4/dsdb/schema/schema_set.c') diff --git a/source4/dsdb/schema/schema_set.c b/source4/dsdb/schema/schema_set.c index 9f23088c97..725fe845ad 100644 --- a/source4/dsdb/schema/schema_set.c +++ b/source4/dsdb/schema/schema_set.c @@ -57,7 +57,6 @@ static int dsdb_schema_set_attributes(struct ldb_context *ldb, struct dsdb_schem ldb_schema_attribute_set_override_handler(ldb, dsdb_attribute_handler_override, schema); if (!write_attributes) { - talloc_free(mem_ctx); return ret; } -- cgit From db29383797e10496dab16fc4729272dcfe090858 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 8 Apr 2009 23:18:49 +1000 Subject: Make the schema_inferiors generation code to compile Sadly it still segfaults at this stage Andrew Bartlett --- source4/dsdb/schema/schema_set.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'source4/dsdb/schema/schema_set.c') diff --git a/source4/dsdb/schema/schema_set.c b/source4/dsdb/schema/schema_set.c index 725fe845ad..dcaeb4fc89 100644 --- a/source4/dsdb/schema/schema_set.c +++ b/source4/dsdb/schema/schema_set.c @@ -309,6 +309,23 @@ failed: return LDB_ERR_OPERATIONS_ERROR; } +int dsdb_setup_schema_inversion(struct ldb_context *ldb, struct dsdb_schema *schema) +{ + /* Walk the list of schema classes */ + + /* For each subClassOf, add us to subclasses of the parent */ + + /* collect these subclasses into a recursive list of total subclasses, preserving order */ + + /* For each subclass under 'top', write the index from it's + * order as an integer in the dsdb_class (for sorting + * objectClass lists efficiently) */ + + /* Walk the list of scheam classes */ + + /* Create a 'total possible superiors' on each class */ + return LDB_SUCCESS; +} /** * Attach the schema to an opaque pointer on the ldb, so ldb modules @@ -324,6 +341,8 @@ int dsdb_set_schema(struct ldb_context *ldb, struct dsdb_schema *schema) return ret; } + schema_fill_constructed(schema); + ret = ldb_set_opaque(ldb, "dsdb_schema", schema); if (ret != LDB_SUCCESS) { return ret; -- cgit