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_convert_to_ol.c | 316 +++++++++++++++++++++++++++++ source4/dsdb/schema/schema_set.c | 2 +- 2 files changed, 317 insertions(+), 1 deletion(-) create mode 100644 source4/dsdb/schema/schema_convert_to_ol.c (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 new file mode 100644 index 0000000000..375e4e3810 --- /dev/null +++ b/source4/dsdb/schema/schema_convert_to_ol.c @@ -0,0 +1,316 @@ +/* + schema conversion routines + + Copyright (C) Andrew Bartlett 2006-2008 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +*/ + +#include "includes.h" +#include "ldb.h" +#include "dsdb/samdb/samdb.h" +#include "system/locale.h" + +/* Routine to linearise our internal schema into the format that + OpenLDAP and Fedora DS use for their backend. + + The 'mappings' are of a format like: + +#Standard OpenLDAP attributes +labeledURI +#The memberOf plugin provides this attribute +memberOf +#These conflict with OpenLDAP builtins +attributeTypes:samba4AttributeTypes +2.5.21.5:1.3.6.1.4.1.7165.4.255.7 + +*/ + + +char *dsdb_convert_schema_to_openldap(struct ldb_context *ldb, char *target_str, const char *mappings) +{ + /* Read list of attributes to skip, OIDs to map */ + TALLOC_CTX *mem_ctx = talloc_new(ldb); + char *line; + char *out; + const char **attrs_skip = NULL; + int num_skip = 0; + struct oid_map { + char *old_oid; + char *new_oid; + } *oid_map = NULL; + int num_oid_maps = 0; + struct attr_map { + char *old_attr; + char *new_attr; + } *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); + + if (!target_str || strcasecmp(target_str, "openldap") == 0) { + target = TARGET_OPENLDAP; + } else if (strcasecmp(target_str, "fedora-ds") == 0) { + target = TARGET_FEDORA_DS; + } else { + DEBUG(0, ("Invalid target type for schema conversion %s\n", target_str)); + return NULL; + } + + /* The mappings are line-seperated, and specify details such as OIDs to skip etc */ + while (1) { + line = next_line; + next_line = strchr(line, '\n'); + if (!next_line) { + break; + } + next_line[0] = '\0'; + next_line++; + + /* Blank Line */ + if (line[0] == '\0') { + continue; + } + /* Comment */ + if (line[0] == '#') { + continue; + } + + if (isdigit(line[0])) { + char *p = strchr(line, ':'); + if (!p) { + DEBUG(0, ("schema mapping file line has OID but no OID to map to: %s\n", line)); + return NULL; + } + p[0] = '\0'; + p++; + oid_map = talloc_realloc(mem_ctx, oid_map, struct oid_map, num_oid_maps + 2); + trim_string(line, " ", " "); + oid_map[num_oid_maps].old_oid = talloc_strdup(oid_map, line); + trim_string(p, " ", " "); + oid_map[num_oid_maps].new_oid = p; + num_oid_maps++; + oid_map[num_oid_maps].old_oid = NULL; + } else { + char *p = strchr(line, ':'); + if (p) { + /* remap attribute/objectClass */ + p[0] = '\0'; + p++; + attr_map = talloc_realloc(mem_ctx, attr_map, struct attr_map, num_attr_maps + 2); + trim_string(line, " ", " "); + attr_map[num_attr_maps].old_attr = talloc_strdup(attr_map, line); + trim_string(p, " ", " "); + attr_map[num_attr_maps].new_attr = p; + num_attr_maps++; + attr_map[num_attr_maps].old_attr = NULL; + } else { + /* skip attribute/objectClass */ + attrs_skip = talloc_realloc(mem_ctx, attrs_skip, const char *, num_skip + 2); + trim_string(line, " ", " "); + attrs_skip[num_skip] = talloc_strdup(attrs_skip, line); + num_skip++; + attrs_skip[num_skip] = NULL; + } + } + } + + schema = dsdb_get_schema(ldb); + if (!schema) { + 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; + } + + for (attribute=schema->attributes; attribute; attribute = attribute->next) { + const char *name = attribute->lDAPDisplayName; + const char *oid = attribute->attributeID_oid; + const char *syntax = attribute->attributeSyntax_oid; + const char *equality = NULL, *substring = NULL; + bool single_value = attribute->isSingleValued; + + char *schema_entry = NULL; + int j; + + /* 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 && oid_map && oid_map[j].old_oid; j++) { + if (strcasecmp(oid, oid_map[j].old_oid) == 0) { + oid = oid_map[j].new_oid; + break; + } + } + + if (attribute->syntax) { + /* We might have been asked to remap this oid, + * due to a conflict, or lack of + * implementation */ + syntax = attribute->syntax->ldap_oid; + /* We might have been asked to remap this oid, due to a conflict */ + for (j=0; syntax && oid_map && oid_map[j].old_oid; j++) { + if (strcasecmp(syntax, oid_map[j].old_oid) == 0) { + syntax = oid_map[j].new_oid; + break; + } + } + + equality = attribute->syntax->equality; + substring = attribute->syntax->substring; + } + + /* 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; + } + } + + schema_entry = schema_attribute_description(mem_ctx, + target, + seperator, + oid, + name, + equality, + substring, + syntax, + single_value, + false, + NULL, NULL, + NULL, NULL, + false, false); + + if (schema_entry == NULL) { + DEBUG(0, ("failed to generate attribute description for %s\n", name)); + return NULL; + } + + switch (target) { + case TARGET_OPENLDAP: + out = talloc_asprintf_append(out, "attributetype %s\n\n", schema_entry); + break; + case TARGET_FEDORA_DS: + out = talloc_asprintf_append(out, "attributeTypes: %s\n", schema_entry); + break; + } + } + + /* 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; + } + } + + return out; +} + 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 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 From bb6a2c8076e5e9eabad4ee7f09f6df979616fd13 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 6 Mar 2009 12:18:21 +1100 Subject: Load the schema with a more efficient single search This search uses the index, and is not recursive, so should avoid the major performance problem with the current sorted schema load. The ad2oLschema code (recently moved to provision-backend) no longer needs the schema to be sorted. Andrew Bartlett --- source4/dsdb/schema/schema_init.c | 108 ++++++-------------------------------- 1 file changed, 15 insertions(+), 93 deletions(-) (limited to 'source4/dsdb/schema') diff --git a/source4/dsdb/schema/schema_init.c b/source4/dsdb/schema/schema_init.c index a67aecd1e8..3396493636 100644 --- a/source4/dsdb/schema/schema_init.c +++ b/source4/dsdb/schema/schema_init.c @@ -808,6 +808,12 @@ WERROR dsdb_class_from_ldb(const struct dsdb_schema *schema, #define dsdb_oom(error_string, mem_ctx) *error_string = talloc_asprintf(mem_ctx, "dsdb out of memory at %s:%d\n", __FILE__, __LINE__) +/* + Create a DSDB schema from the ldb results provided. This is called + directly when the schema is provisioned from an on-disk LDIF file, or + from dsdb_schema_from_schema_dn below +*/ + int dsdb_schema_from_ldb_results(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, struct smb_iconv_convenience *iconv_convenience, struct ldb_result *schema_res, @@ -908,96 +914,9 @@ int dsdb_schema_from_ldb_results(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, return LDB_SUCCESS; } -/* This recursive load of the objectClasses presumes that they - * everything is in a strict subClassOf hirarchy. - * - * We load this in order so we produce certain outputs (such as the - * exported schema for openldap, and sorted objectClass attribute) 'in - * order' */ - -static int fetch_oc_recursive(struct ldb_context *ldb, struct ldb_dn *schemadn, - TALLOC_CTX *mem_ctx, - struct ldb_result *search_from, - struct ldb_result *res_list) -{ - int i; - int ret = 0; - for (i=0; i < search_from->count; i++) { - struct ldb_result *res; - const char *name = ldb_msg_find_attr_as_string(search_from->msgs[i], - "lDAPDisplayname", NULL); - - ret = ldb_search(ldb, mem_ctx, &res, - schemadn, LDB_SCOPE_SUBTREE, NULL, - "(&(&(objectClass=classSchema)(subClassOf=%s))(!(lDAPDisplayName=%s)))", - name, name); - if (ret != LDB_SUCCESS) { - return ret; - } - - res_list->msgs = talloc_realloc(res_list, res_list->msgs, - struct ldb_message *, res_list->count + 2); - if (!res_list->msgs) { - return LDB_ERR_OPERATIONS_ERROR; - } - res_list->msgs[res_list->count] = talloc_move(res_list, - &search_from->msgs[i]); - res_list->count++; - res_list->msgs[res_list->count] = NULL; - - if (res->count > 0) { - ret = fetch_oc_recursive(ldb, schemadn, mem_ctx, res, res_list); - } - if (ret != LDB_SUCCESS) { - return ret; - } - } - return ret; -} - -static int fetch_objectclass_schema(struct ldb_context *ldb, struct ldb_dn *schemadn, - TALLOC_CTX *mem_ctx, - struct ldb_result **objectclasses_res, - char **error_string) -{ - TALLOC_CTX *local_ctx = talloc_new(mem_ctx); - struct ldb_result *top_res, *ret_res; - int ret; - if (!local_ctx) { - return LDB_ERR_OPERATIONS_ERROR; - } - - /* Download 'top' */ - ret = ldb_search(ldb, local_ctx, &top_res, - schemadn, LDB_SCOPE_SUBTREE, NULL, - "(&(objectClass=classSchema)(lDAPDisplayName=top))"); - if (ret != LDB_SUCCESS) { - *error_string = talloc_asprintf(mem_ctx, - "dsdb_schema: failed to search for top classSchema object: %s", - ldb_errstring(ldb)); - return ret; - } - - if (top_res->count != 1) { - *error_string = talloc_asprintf(mem_ctx, - "dsdb_schema: failed to find top classSchema object"); - return LDB_ERR_NO_SUCH_OBJECT; - } - - ret_res = talloc_zero(local_ctx, struct ldb_result); - if (!ret_res) { - return LDB_ERR_OPERATIONS_ERROR; - } - - ret = fetch_oc_recursive(ldb, schemadn, local_ctx, top_res, ret_res); - - if (ret != LDB_SUCCESS) { - return ret; - } - - *objectclasses_res = talloc_move(mem_ctx, &ret_res); - return ret; -} +/* + Given an LDB, and the DN, return a populated schema +*/ int dsdb_schema_from_schema_dn(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, struct smb_iconv_convenience *iconv_convenience, @@ -1053,7 +972,7 @@ int dsdb_schema_from_schema_dn(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, */ ret = ldb_search(ldb, tmp_ctx, &a_res, schema_dn, LDB_SCOPE_ONELEVEL, NULL, - "(objectClass=attributeSchema)"); + "(objectCategory=attributeSchema)"); if (ret != LDB_SUCCESS) { *error_string_out = talloc_asprintf(mem_ctx, "dsdb_schema: failed to search attributeSchema objects: %s", @@ -1065,10 +984,13 @@ int dsdb_schema_from_schema_dn(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, /* * load the objectClass definitions */ - ret = fetch_objectclass_schema(ldb, schema_dn, tmp_ctx, &c_res, &error_string); + ret = ldb_search(ldb, tmp_ctx, &c_res, + schema_dn, LDB_SCOPE_ONELEVEL, NULL, + "(objectCategory=classSchema)"); if (ret != LDB_SUCCESS) { *error_string_out = talloc_asprintf(mem_ctx, - "Failed to fetch objectClass schema elements: %s", error_string); + "dsdb_schema: failed to search attributeSchema objects: %s", + ldb_errstring(ldb)); talloc_free(tmp_ctx); return ret; } -- cgit From 1f25b71d199a072f5ee1bdd8786e5c1c157f5888 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 11 Mar 2009 16:36:40 +1100 Subject: s4:schema Don't rely on objectCategory 'magic' when loading the schema The short-to-long name canonicalisation rules use the schema, so clearly they won't work when loading it. Andrew Bartlett --- source4/dsdb/schema/schema_init.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/dsdb/schema') diff --git a/source4/dsdb/schema/schema_init.c b/source4/dsdb/schema/schema_init.c index 3396493636..b6a7cf7cc8 100644 --- a/source4/dsdb/schema/schema_init.c +++ b/source4/dsdb/schema/schema_init.c @@ -972,7 +972,7 @@ int dsdb_schema_from_schema_dn(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, */ ret = ldb_search(ldb, tmp_ctx, &a_res, schema_dn, LDB_SCOPE_ONELEVEL, NULL, - "(objectCategory=attributeSchema)"); + "(objectClass=attributeSchema)"); if (ret != LDB_SUCCESS) { *error_string_out = talloc_asprintf(mem_ctx, "dsdb_schema: failed to search attributeSchema objects: %s", @@ -986,7 +986,7 @@ int dsdb_schema_from_schema_dn(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, */ ret = ldb_search(ldb, tmp_ctx, &c_res, schema_dn, LDB_SCOPE_ONELEVEL, NULL, - "(objectCategory=classSchema)"); + "(objectClass=classSchema)"); if (ret != LDB_SUCCESS) { *error_string_out = talloc_asprintf(mem_ctx, "dsdb_schema: failed to search attributeSchema objects: %s", -- cgit From 2fe17ae61e4f80b7c864bd6777c71557c97c0125 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 31 Mar 2009 16:31:16 +1100 Subject: possibleInferiors is a generated attribute - we can't pull it over DRS or from ldb --- source4/dsdb/schema/schema_init.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source4/dsdb/schema') diff --git a/source4/dsdb/schema/schema_init.c b/source4/dsdb/schema/schema_init.c index b6a7cf7cc8..e619e1ffac 100644 --- a/source4/dsdb/schema/schema_init.c +++ b/source4/dsdb/schema/schema_init.c @@ -788,7 +788,6 @@ WERROR dsdb_class_from_ldb(const struct dsdb_schema *schema, GET_STRING_LIST_LDB(msg, "systemPossSuperiors", mem_ctx, obj, systemPossSuperiors, false); GET_STRING_LIST_LDB(msg, "possSuperiors", mem_ctx, obj, possSuperiors, false); - GET_STRING_LIST_LDB(msg, "possibleInferiors", mem_ctx, obj, possibleInferiors, false); GET_STRING_LDB(msg, "defaultSecurityDescriptor", mem_ctx, obj, defaultSecurityDescriptor, false); @@ -1373,7 +1372,6 @@ WERROR dsdb_class_from_drsuapi(struct dsdb_schema *schema, GET_STRING_LIST_DS(schema, r, "systemPossSuperiors", mem_ctx, obj, systemPossSuperiors, false); GET_STRING_LIST_DS(schema, r, "possSuperiors", mem_ctx, obj, possSuperiors, false); - GET_STRING_LIST_DS(schema, r, "possibleInferiors", mem_ctx, obj, possibleInferiors, false); GET_STRING_DS(schema, r, "defaultSecurityDescriptor", mem_ctx, obj, defaultSecurityDescriptor, false); -- 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.h | 16 +++ source4/dsdb/schema/schema_init.c | 59 +++++++++- source4/dsdb/schema/schema_query.c | 145 ++++++++++++------------- source4/dsdb/schema/schema_set.c | 207 +++++++++++++++++++++++++++++++----- source4/dsdb/schema/schema_syntax.c | 13 ++- 5 files changed, 325 insertions(+), 115 deletions(-) (limited to 'source4/dsdb/schema') diff --git a/source4/dsdb/schema/schema.h b/source4/dsdb/schema/schema.h index f7d59a7c39..98ccf5ed9e 100644 --- a/source4/dsdb/schema/schema.h +++ b/source4/dsdb/schema/schema.h @@ -91,6 +91,7 @@ struct dsdb_attribute { /* internal stuff */ const struct dsdb_syntax *syntax; + const struct ldb_schema_attribute *ldb_schema_attribute; }; struct dsdb_class { @@ -156,6 +157,21 @@ struct dsdb_schema { struct dsdb_attribute *attributes; struct dsdb_class *classes; + /* lists of classes sorted by various attributes, for faster + access */ + uint32_t num_classes; + struct dsdb_class **classes_by_lDAPDisplayName; + struct dsdb_class **classes_by_governsID_id; + struct dsdb_class **classes_by_governsID_oid; + struct dsdb_class **classes_by_cn; + + /* lists of attributes sorted by various fields */ + uint32_t num_attributes; + struct dsdb_attribute **attributes_by_lDAPDisplayName; + struct dsdb_attribute **attributes_by_attributeID_id; + struct dsdb_attribute **attributes_by_attributeID_oid; + struct dsdb_attribute **attributes_by_linkID; + struct { bool we_are_master; struct ldb_dn *master_dn; diff --git a/source4/dsdb/schema/schema_init.c b/source4/dsdb/schema/schema_init.c index e619e1ffac..3a65c474fb 100644 --- a/source4/dsdb/schema/schema_init.c +++ b/source4/dsdb/schema/schema_init.c @@ -28,6 +28,7 @@ #include "librpc/gen_ndr/ndr_drsuapi.h" #include "librpc/gen_ndr/ndr_drsblobs.h" #include "param/param.h" +#include "lib/ldb/include/ldb_module.h" struct dsdb_schema *dsdb_new_schema(TALLOC_CTX *mem_ctx, struct smb_iconv_convenience *iconv_convenience) { @@ -582,6 +583,48 @@ WERROR dsdb_read_prefixes_from_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, return WERR_OK; } + +/* + setup the ldb_schema_attribute field for a dsdb_attribute + */ +static int dsdb_schema_setup_ldb_schema_attribute(struct ldb_context *ldb, + struct dsdb_attribute *attr) +{ + const char *syntax = attr->syntax->ldb_syntax; + const struct ldb_schema_syntax *s; + struct ldb_schema_attribute *a; + + if (!syntax) { + syntax = attr->syntax->ldap_oid; + } + + s = ldb_samba_syntax_by_lDAPDisplayName(ldb, attr->lDAPDisplayName); + if (s == NULL) { + s = ldb_samba_syntax_by_name(ldb, syntax); + } + if (s == NULL) { + s = ldb_standard_syntax_by_name(ldb, syntax); + } + + if (s == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + attr->ldb_schema_attribute = a = talloc(attr, struct ldb_schema_attribute); + if (attr->ldb_schema_attribute == NULL) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + a->name = attr->lDAPDisplayName; + a->flags = 0; + a->syntax = s; + + return LDB_SUCCESS; +} + + + #define GET_STRING_LDB(msg, attr, mem_ctx, p, elem, strict) do { \ (p)->elem = samdb_result_string(msg, attr, NULL);\ if (strict && (p)->elem == NULL) { \ @@ -676,7 +719,8 @@ WERROR dsdb_read_prefixes_from_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, }\ } while (0) -WERROR dsdb_attribute_from_ldb(const struct dsdb_schema *schema, +WERROR dsdb_attribute_from_ldb(struct ldb_context *ldb, + const struct dsdb_schema *schema, struct ldb_message *msg, TALLOC_CTX *mem_ctx, struct dsdb_attribute *attr) @@ -745,6 +789,10 @@ WERROR dsdb_attribute_from_ldb(const struct dsdb_schema *schema, return WERR_DS_ATT_SCHEMA_REQ_SYNTAX; } + if (dsdb_schema_setup_ldb_schema_attribute(ldb, attr) != LDB_SUCCESS) { + return WERR_DS_ATT_SCHEMA_REQ_SYNTAX; + } + return WERR_OK; } @@ -866,7 +914,7 @@ int dsdb_schema_from_ldb_results(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, return LDB_ERR_OPERATIONS_ERROR; } - status = dsdb_attribute_from_ldb(schema, attrs_res->msgs[i], sa, sa); + status = dsdb_attribute_from_ldb(ldb, schema, attrs_res->msgs[i], sa, sa); if (!W_ERROR_IS_OK(status)) { *error_string = talloc_asprintf(mem_ctx, "schema_fsmo_init: failed to load attribute definition: %s:%s", @@ -1274,7 +1322,8 @@ static struct drsuapi_DsReplicaAttribute *dsdb_find_object_attr_name(struct dsdb }\ } while (0) -WERROR dsdb_attribute_from_drsuapi(struct dsdb_schema *schema, +WERROR dsdb_attribute_from_drsuapi(struct ldb_context *ldb, + struct dsdb_schema *schema, struct drsuapi_DsReplicaObject *r, TALLOC_CTX *mem_ctx, struct dsdb_attribute *attr) @@ -1333,6 +1382,10 @@ WERROR dsdb_attribute_from_drsuapi(struct dsdb_schema *schema, return WERR_DS_ATT_SCHEMA_REQ_SYNTAX; } + if (dsdb_schema_setup_ldb_schema_attribute(ldb, attr) != LDB_SUCCESS) { + return WERR_DS_ATT_SCHEMA_REQ_SYNTAX; + } + return WERR_OK; } diff --git a/source4/dsdb/schema/schema_query.c b/source4/dsdb/schema/schema_query.c index 00de0f8983..f894ef5b1e 100644 --- a/source4/dsdb/schema/schema_query.c +++ b/source4/dsdb/schema/schema_query.c @@ -23,10 +23,44 @@ #include "includes.h" #include "dsdb/samdb/samdb.h" +/* a binary array search, where the array is an array of pointers to structures, + and we want to find a match for 'target' on 'field' in those structures. + + Inputs: + array: base pointer to an array of structures + arrray_size: number of elements in the array + field: the name of the field in the structure we are keying off + target: the field value we are looking for + comparison_fn: the comparison function + result: where the result of the search is put + + if the element is found, then 'result' is set to point to the found array element. If not, + then 'result' is set to NULL. + + The array is assumed to be sorted by the same comparison_fn as the + search (with, for example, qsort) + */ +#define BINARY_ARRAY_SEARCH(array, array_size, field, target, comparison_fn, result) do { \ + int32_t _b, _e; \ + (result) = NULL; \ + for (_b = 0, _e = (array_size)-1; _b <= _e; ) { \ + int32_t _i = (_b+_e)/2; \ + int _r = comparison_fn(target, array[_i]->field); \ + if (_r == 0) { (result) = array[_i]; break; } \ + if (_r < 0) _e = _i - 1; else _b = _i + 1; \ + } } while (0) + + +static int uint32_cmp(uint32_t c1, uint32_t c2) +{ + return c1 - c2; +} + + const struct dsdb_attribute *dsdb_attribute_by_attributeID_id(const struct dsdb_schema *schema, uint32_t id) { - struct dsdb_attribute *cur; + struct dsdb_attribute *c; /* * 0xFFFFFFFF is used as value when no mapping table is available, @@ -34,69 +68,49 @@ const struct dsdb_attribute *dsdb_attribute_by_attributeID_id(const struct dsdb_ */ if (id == 0xFFFFFFFF) return NULL; - /* TODO: add binary search */ - for (cur = schema->attributes; cur; cur = cur->next) { - if (cur->attributeID_id != id) continue; - - return cur; - } - - return NULL; + BINARY_ARRAY_SEARCH(schema->attributes_by_attributeID_id, + schema->num_attributes, attributeID_id, id, uint32_cmp, c); + return c; } const struct dsdb_attribute *dsdb_attribute_by_attributeID_oid(const struct dsdb_schema *schema, const char *oid) { - struct dsdb_attribute *cur; + struct dsdb_attribute *c; if (!oid) return NULL; - /* TODO: add binary search */ - for (cur = schema->attributes; cur; cur = cur->next) { - if (strcmp(cur->attributeID_oid, oid) != 0) continue; - - return cur; - } - - return NULL; + BINARY_ARRAY_SEARCH(schema->attributes_by_attributeID_oid, + schema->num_attributes, attributeID_oid, oid, strcasecmp, c); + return c; } const struct dsdb_attribute *dsdb_attribute_by_lDAPDisplayName(const struct dsdb_schema *schema, const char *name) { - struct dsdb_attribute *cur; + struct dsdb_attribute *c; if (!name) return NULL; - /* TODO: add binary search */ - for (cur = schema->attributes; cur; cur = cur->next) { - if (strcasecmp(cur->lDAPDisplayName, name) != 0) continue; - - return cur; - } - - return NULL; + BINARY_ARRAY_SEARCH(schema->attributes_by_lDAPDisplayName, + schema->num_attributes, lDAPDisplayName, name, strcasecmp, c); + return c; } const struct dsdb_attribute *dsdb_attribute_by_linkID(const struct dsdb_schema *schema, int linkID) { - struct dsdb_attribute *cur; - - /* TODO: add binary search */ - for (cur = schema->attributes; cur; cur = cur->next) { - if (cur->linkID != linkID) continue; + struct dsdb_attribute *c; - return cur; - } - - return NULL; + BINARY_ARRAY_SEARCH(schema->attributes_by_linkID, + schema->num_attributes, linkID, linkID, uint32_cmp, c); + return c; } const struct dsdb_class *dsdb_class_by_governsID_id(const struct dsdb_schema *schema, uint32_t id) { - struct dsdb_class *cur; + struct dsdb_class *c; /* * 0xFFFFFFFF is used as value when no mapping table is available, @@ -104,65 +118,39 @@ const struct dsdb_class *dsdb_class_by_governsID_id(const struct dsdb_schema *sc */ if (id == 0xFFFFFFFF) return NULL; - /* TODO: add binary search */ - for (cur = schema->classes; cur; cur = cur->next) { - if (cur->governsID_id != id) continue; - - return cur; - } - - return NULL; + BINARY_ARRAY_SEARCH(schema->classes_by_governsID_id, + schema->num_classes, governsID_id, id, uint32_cmp, c); + return c; } const struct dsdb_class *dsdb_class_by_governsID_oid(const struct dsdb_schema *schema, const char *oid) { - struct dsdb_class *cur; - + struct dsdb_class *c; if (!oid) return NULL; - - /* TODO: add binary search */ - for (cur = schema->classes; cur; cur = cur->next) { - if (strcmp(cur->governsID_oid, oid) != 0) continue; - - return cur; - } - - return NULL; + BINARY_ARRAY_SEARCH(schema->classes_by_governsID_oid, + schema->num_classes, governsID_oid, oid, strcasecmp, c); + return c; } const struct dsdb_class *dsdb_class_by_lDAPDisplayName(const struct dsdb_schema *schema, const char *name) { - struct dsdb_class *cur; - + struct dsdb_class *c; if (!name) return NULL; - - /* TODO: add binary search */ - for (cur = schema->classes; cur; cur = cur->next) { - if (strcasecmp(cur->lDAPDisplayName, name) != 0) continue; - - return cur; - } - - return NULL; + BINARY_ARRAY_SEARCH(schema->classes_by_lDAPDisplayName, + schema->num_classes, lDAPDisplayName, name, strcasecmp, c); + return c; } const struct dsdb_class *dsdb_class_by_cn(const struct dsdb_schema *schema, const char *cn) { - struct dsdb_class *cur; - + struct dsdb_class *c; if (!cn) return NULL; - - /* TODO: add binary search */ - for (cur = schema->classes; cur; cur = cur->next) { - if (strcasecmp(cur->cn, cn) != 0) continue; - - return cur; - } - - return NULL; + BINARY_ARRAY_SEARCH(schema->classes_by_cn, + schema->num_classes, cn, cn, strcasecmp, c); + return c; } const char *dsdb_lDAPDisplayName_by_id(const struct dsdb_schema *schema, @@ -171,7 +159,6 @@ const char *dsdb_lDAPDisplayName_by_id(const struct dsdb_schema *schema, const struct dsdb_attribute *a; const struct dsdb_class *c; - /* TODO: add binary search */ a = dsdb_attribute_by_attributeID_id(schema, id); if (a) { return a->lDAPDisplayName; 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; } diff --git a/source4/dsdb/schema/schema_syntax.c b/source4/dsdb/schema/schema_syntax.c index 27c9a6c4a4..4fd6501cc8 100644 --- a/source4/dsdb/schema/schema_syntax.c +++ b/source4/dsdb/schema/schema_syntax.c @@ -1227,7 +1227,7 @@ static WERROR dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi(struct ldb_context static const struct dsdb_syntax dsdb_syntaxes[] = { { .name = "Boolean", - .ldap_oid = "1.3.6.1.4.1.1466.115.121.1.7", + .ldap_oid = LDB_SYNTAX_BOOLEAN, .oMSyntax = 1, .attributeSyntax_oid = "2.5.5.8", .drsuapi_to_ldb = dsdb_syntax_BOOL_drsuapi_to_ldb, @@ -1289,7 +1289,8 @@ static const struct dsdb_syntax dsdb_syntaxes[] = { .ldb_to_drsuapi = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi, .equality = "numericStringMatch", .substring = "numericStringSubstringsMatch", - .comment = "Numeric String" + .comment = "Numeric String", + .ldb_syntax = LDB_SYNTAX_DIRECTORY_STRING, },{ .name = "String(Printable)", .ldap_oid = "1.3.6.1.4.1.1466.115.121.1.44", @@ -1297,6 +1298,7 @@ static const struct dsdb_syntax dsdb_syntaxes[] = { .attributeSyntax_oid = "2.5.5.5", .drsuapi_to_ldb = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb, .ldb_to_drsuapi = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi, + .ldb_syntax = LDB_SYNTAX_OCTET_STRING, },{ .name = "String(Teletex)", .ldap_oid = "1.2.840.113556.1.4.905", @@ -1316,7 +1318,8 @@ static const struct dsdb_syntax dsdb_syntaxes[] = { .drsuapi_to_ldb = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb, .ldb_to_drsuapi = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi, .equality = "caseExactIA5Match", - .comment = "Printable String" + .comment = "Printable String", + .ldb_syntax = LDB_SYNTAX_OCTET_STRING, },{ .name = "String(UTC-Time)", .ldap_oid = "1.3.6.1.4.1.1466.115.121.1.53", @@ -1423,7 +1426,8 @@ static const struct dsdb_syntax dsdb_syntaxes[] = { .attributeSyntax_oid = "2.5.5.13", .drsuapi_to_ldb = dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb, .ldb_to_drsuapi = dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi, - .comment = "Presentation Address" + .comment = "Presentation Address", + .ldb_syntax = LDB_SYNTAX_DIRECTORY_STRING, },{ /* not used in w2k3 schema */ .name = "Object(Access-Point)", @@ -1433,6 +1437,7 @@ static const struct dsdb_syntax dsdb_syntaxes[] = { .attributeSyntax_oid = "2.5.5.14", .drsuapi_to_ldb = dsdb_syntax_FOOBAR_drsuapi_to_ldb, .ldb_to_drsuapi = dsdb_syntax_FOOBAR_ldb_to_drsuapi, + .ldb_syntax = LDB_SYNTAX_DIRECTORY_STRING, },{ /* not used in w2k3 schema */ .name = "Object(DN-String)", -- 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') 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 217628f88119d1cadfa88dbfd57d0e9e94693838 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 7 Apr 2009 16:34:36 +1000 Subject: first cut at a C version of the possible inferiors code --- source4/dsdb/schema/schema_inferiors.c | 172 +++++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 source4/dsdb/schema/schema_inferiors.c (limited to 'source4/dsdb/schema') diff --git a/source4/dsdb/schema/schema_inferiors.c b/source4/dsdb/schema/schema_inferiors.c new file mode 100644 index 0000000000..d9afff24a3 --- /dev/null +++ b/source4/dsdb/schema/schema_inferiors.c @@ -0,0 +1,172 @@ +/* + Unix SMB/CIFS mplementation. + + implement possibleInferiors calculation + + Copyright (C) Andrew Tridgell 2009 + Copyright (C) Andrew Bartlett 2009 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +*/ +/* + This module is a C implementation of the logic in the + dsdb/samdb/ldb_modules/tests/possibleInferiors.py code + + To understand the C code, please see the python code first + */ + +#include "includes.h" +#include "dsdb/samdb/samdb.h" + + + +/* + create the SUPCLASSES() list + */ +static char **schema_supclasses(struct dsdb_schema *schema, + TALLOC_CTX *mem_ctx, const char *oc) +{ + char **list; + const struct dsdb_class *class; + + list = str_list_make(mem_ctx, NULL, NULL); + if (list == NULL) { + DEBUG(0,(__location__ " out of memory\n")); + return NULL; + } + + if (strcmp(oc, "top") == 0) { + return list; + } + + class = dsdb_class_by_lDAPDisplayName(schema, oc); + if (class == NULL) { + DEBUG(0,(__location__ " objectClass '%s' does not exist\n", oc)); + return NULL; + } + + if (class->supclasses) { + return class->supclasses; + } + + if (class->subClassOf) { + char **list2; + list = str_list_add(list, class->subClassOf); + list2 = schema_supclasses(schema, mem_ctx, class->subClassOf); + list = str_list_append(list, list2); + } + + class->supclasses = list; + + return list; +} + +/* + this one is used internally + matches SUBCLASSES() python function + */ +static char **schema_subclasses(struct dsdb_schema *schema, TALLOC_CTX *mem_ctx, + const char **oclist) +{ + const char *oc; + char **list = str_list_make(mem_ctx, NULL, NULL); + int i; + + for (i=0; oclist && oclist[i]; i++) { + struct dsdb_class *class = dsdb_class_by_lDAPDisplayName(schema, oclist[i]); + list = str_list_append(list, class->subclasses); + } + return list; +} + + +/* + equivalent of the POSSSUPERIORS() python function + */ +static char **schema_posssuperiors(struct dsdb_schema *schema, TALLOC_CTX *mem_ctx, + const char **oclist) +{ + const char *oc; + char **list = str_list_make(mem_ctx, NULL, NULL); + int i; + + for (i=0; oclist && oclist[i]; i++) { + struct dsdb_class *class = dsdb_class_by_lDAPDisplayName(schema, oclist[i]); + if (class->posssuperiors) { + list = str_list_append(list, class->posssuperiors); + } else { + char **list2 = str_list_make(mem_ctx, NULL, NULL); + list2 = str_list_append(list2, class->systemPossSuperiors); + list2 = str_list_append(list2, class->possSuperiors); + list2 = str_list_append(list2, schema_supclasses(schema, list2, oclist[i])); + list2 = str_list_append(list2, schema_subclasses(schema, list2, list2)); + class->posssuperiors = list2; + list = str_list_append(list, list2); + } + } + + return list; +} + +static char **schema_subclasses_recurse(struct dsdb_schema *schema, struct dsdb_class *class) +{ + char **list = str_list_copy(class, class->subclasses_direct); + int i; + for (i=0;list && list[i]; i++) { + struct dsdb_class *class2 = dsdb_class_by_lDAPDisplayName(schema, list[i]); + list = str_list_append(list, schema_subclasses_recurse(schema, class2)); + } + return list; +} + +static void schema_create_subclasses(struct dsdb_schema *schema) +{ + struct dsdb_class *class; + + for (class=schema->classes; class; class=class->next) { + struct dsdb_class *class2 = dsdb_class_by_lDAPDisplayName(schema, class->subClassOf); + class->subclasses_direct = str_list_make(class, NULL, NULL); + if (class != class2) { + if (class2->subclasses_direct == NULL) { + class2->subclasses_direct = str_list_make(class2, NULL, NULL); + } + class2->subclasses_direct = str_list_add(class2->subclasses_direct, + class->subClassOf); + } + } + + for (class=schema->classes; class; class=class->next) { + class->subclasses = schema_subclasses_recurse(schema, class); + } +} + +void schema_fill_possible_inferiors(struct dsdb_schema *schema, struct dsdb_class *class) +{ + struct dsdb_class *c2; + +} + +def possible_inferiors_constructed(db, classinfo, c): + list = [] + for oc in classinfo: + superiors = POSSSUPERIORS(classinfo, [oc]) + if (is_in_list(superiors, c) and + classinfo[oc]["systemOnly"] == False and + classinfo[oc]["objectClassCategory"] != 2 and + classinfo[oc]["objectClassCategory"] != 3): + list.append(oc) + list = uniq_list(list) + list.sort() + return list -- 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.h | 6 ++ source4/dsdb/schema/schema_inferiors.c | 143 +++++++++++++++++---------------- source4/dsdb/schema/schema_set.c | 19 +++++ 3 files changed, 99 insertions(+), 69 deletions(-) (limited to 'source4/dsdb/schema') diff --git a/source4/dsdb/schema/schema.h b/source4/dsdb/schema/schema.h index 98ccf5ed9e..92cfe113d4 100644 --- a/source4/dsdb/schema/schema.h +++ b/source4/dsdb/schema/schema.h @@ -132,6 +132,12 @@ struct dsdb_class { bool defaultHidingValue; bool isDefunct; bool systemOnly; + + char **supclasses; + char **subclasses; + char **subclasses_direct; + char **posssuperiors; + char **possible_inferiors; }; struct dsdb_schema_oid_prefix { diff --git a/source4/dsdb/schema/schema_inferiors.c b/source4/dsdb/schema/schema_inferiors.c index d9afff24a3..abd8f7e4b0 100644 --- a/source4/dsdb/schema/schema_inferiors.c +++ b/source4/dsdb/schema/schema_inferiors.c @@ -35,11 +35,14 @@ /* create the SUPCLASSES() list */ -static char **schema_supclasses(struct dsdb_schema *schema, - TALLOC_CTX *mem_ctx, const char *oc) +static char * const *schema_supclasses(struct dsdb_schema *schema, + TALLOC_CTX *mem_ctx, struct dsdb_class *schema_class) { - char **list; - const struct dsdb_class *class; + char * const *list; + + if (schema_class->supclasses) { + return schema_class->supclasses; + } list = str_list_make(mem_ctx, NULL, NULL); if (list == NULL) { @@ -47,28 +50,21 @@ static char **schema_supclasses(struct dsdb_schema *schema, return NULL; } - if (strcmp(oc, "top") == 0) { + /* Cope with 'top SUP top', ie top is subClassOf top */ + if (strcmp(schema_class->lDAPDisplayName, schema_class->subClassOf) == 0) { + schema_class->supclasses = list; return list; } - class = dsdb_class_by_lDAPDisplayName(schema, oc); - if (class == NULL) { - DEBUG(0,(__location__ " objectClass '%s' does not exist\n", oc)); - return NULL; - } - - if (class->supclasses) { - return class->supclasses; - } - - if (class->subClassOf) { + if (schema_class->subClassOf) { char **list2; - list = str_list_add(list, class->subClassOf); - list2 = schema_supclasses(schema, mem_ctx, class->subClassOf); + list = str_list_add(list, schema_class->subClassOf); + + list2 = schema_supclasses(schema, mem_ctx, dsdb_class_by_lDAPDisplayName(schema, schema_class->subClassOf)); list = str_list_append(list, list2); } - class->supclasses = list; + schema_class->supclasses = list; return list; } @@ -78,15 +74,14 @@ static char **schema_supclasses(struct dsdb_schema *schema, matches SUBCLASSES() python function */ static char **schema_subclasses(struct dsdb_schema *schema, TALLOC_CTX *mem_ctx, - const char **oclist) + const char * const *oclist) { - const char *oc; char **list = str_list_make(mem_ctx, NULL, NULL); int i; for (i=0; oclist && oclist[i]; i++) { - struct dsdb_class *class = dsdb_class_by_lDAPDisplayName(schema, oclist[i]); - list = str_list_append(list, class->subclasses); + struct dsdb_class *schema_class = dsdb_class_by_lDAPDisplayName(schema, oclist[i]); + list = str_list_append(list, schema_class->subclasses); } return list; } @@ -96,77 +91,87 @@ static char **schema_subclasses(struct dsdb_schema *schema, TALLOC_CTX *mem_ctx, equivalent of the POSSSUPERIORS() python function */ static char **schema_posssuperiors(struct dsdb_schema *schema, TALLOC_CTX *mem_ctx, - const char **oclist) + struct dsdb_class *schema_class) { - const char *oc; char **list = str_list_make(mem_ctx, NULL, NULL); - int i; - for (i=0; oclist && oclist[i]; i++) { - struct dsdb_class *class = dsdb_class_by_lDAPDisplayName(schema, oclist[i]); - if (class->posssuperiors) { - list = str_list_append(list, class->posssuperiors); - } else { - char **list2 = str_list_make(mem_ctx, NULL, NULL); - list2 = str_list_append(list2, class->systemPossSuperiors); - list2 = str_list_append(list2, class->possSuperiors); - list2 = str_list_append(list2, schema_supclasses(schema, list2, oclist[i])); - list2 = str_list_append(list2, schema_subclasses(schema, list2, list2)); - class->posssuperiors = list2; - list = str_list_append(list, list2); - } + if (schema_class->posssuperiors) { + return schema_class->posssuperiors; + } else { + char * const *list2 = str_list_make(mem_ctx, NULL, NULL); + list2 = str_list_append(list2, schema_class->systemPossSuperiors); + list2 = str_list_append(list2, schema_class->possSuperiors); + list2 = str_list_append(list2, schema_supclasses(schema, list2, schema_class)); + list2 = str_list_append(list2, schema_subclasses(schema, list2, list2)); + + schema_class->posssuperiors = list2; + return schema_class->posssuperiors; } return list; } -static char **schema_subclasses_recurse(struct dsdb_schema *schema, struct dsdb_class *class) +static char **schema_subclasses_recurse(struct dsdb_schema *schema, struct dsdb_class *schema_class) { - char **list = str_list_copy(class, class->subclasses_direct); + char * const *list = str_list_copy(schema_class, schema_class->subclasses_direct); int i; for (i=0;list && list[i]; i++) { - struct dsdb_class *class2 = dsdb_class_by_lDAPDisplayName(schema, list[i]); - list = str_list_append(list, schema_subclasses_recurse(schema, class2)); + struct dsdb_class *schema_class2 = dsdb_class_by_lDAPDisplayName(schema, list[i]); + if (schema_class != schema_class2) { + list = str_list_append(list, schema_subclasses_recurse(schema, schema_class2)); + } } return list; } static void schema_create_subclasses(struct dsdb_schema *schema) { - struct dsdb_class *class; - - for (class=schema->classes; class; class=class->next) { - struct dsdb_class *class2 = dsdb_class_by_lDAPDisplayName(schema, class->subClassOf); - class->subclasses_direct = str_list_make(class, NULL, NULL); - if (class != class2) { - if (class2->subclasses_direct == NULL) { - class2->subclasses_direct = str_list_make(class2, NULL, NULL); + struct dsdb_class *schema_class; + + for (schema_class=schema->classes; schema_class; schema_class=schema_class->next) { + struct dsdb_class *schema_class2 = dsdb_class_by_lDAPDisplayName(schema, schema_class->subClassOf); + schema_class->subclasses_direct = str_list_make(schema_class, NULL, NULL); + if (schema_class != schema_class2) { + if (schema_class2->subclasses_direct == NULL) { + schema_class2->subclasses_direct = str_list_make(schema_class2, NULL, NULL); } - class2->subclasses_direct = str_list_add(class2->subclasses_direct, - class->subClassOf); + schema_class2->subclasses_direct = str_list_add(schema_class2->subclasses_direct, + schema_class->subClassOf); } } - for (class=schema->classes; class; class=class->next) { - class->subclasses = schema_subclasses_recurse(schema, class); + for (schema_class=schema->classes; schema_class; schema_class=schema_class->next) { + schema_class->subclasses = schema_subclasses_recurse(schema, schema_class); } } -void schema_fill_possible_inferiors(struct dsdb_schema *schema, struct dsdb_class *class) +static void schema_fill_possible_inferiors(struct dsdb_schema *schema, struct dsdb_class *schema_class) { struct dsdb_class *c2; - + + for (c2=schema->classes; c2; c2=c2->next) { + char **superiors = schema_posssuperiors(schema, c2, c2); + if (c2->systemOnly == false + && c2->objectClassCategory != 2 + && c2->objectClassCategory != 3 + && str_list_check(superiors, schema_class->lDAPDisplayName)) { + if (c2->possible_inferiors == NULL) { + c2->possible_inferiors = str_list_make(c2, NULL, NULL); + } + c2->possible_inferiors = str_list_add_unique(c2->possible_inferiors, + schema_class->lDAPDisplayName); + } + talloc_free(superiors); + } } -def possible_inferiors_constructed(db, classinfo, c): - list = [] - for oc in classinfo: - superiors = POSSSUPERIORS(classinfo, [oc]) - if (is_in_list(superiors, c) and - classinfo[oc]["systemOnly"] == False and - classinfo[oc]["objectClassCategory"] != 2 and - classinfo[oc]["objectClassCategory"] != 3): - list.append(oc) - list = uniq_list(list) - list.sort() - return list +void schema_fill_constructed(struct dsdb_schema *schema) +{ + struct dsdb_class *schema_class; + + schema_create_subclasses(schema); + + for (schema_class=schema->classes; schema_class; schema_class=schema_class->next) { + schema_fill_possible_inferiors(schema, schema_class); + } +} 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 From 37254b7a76a458ee40fabd673e2adaf0dcd663cc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 9 Apr 2009 13:46:18 +1000 Subject: fixed the possibleInferiors calculation so it now passes the test We are probably still using more memory here than we need to. That needs to be looked at. --- source4/dsdb/schema/schema.h | 1 - source4/dsdb/schema/schema_inferiors.c | 54 ++++++++++++++++++---------------- 2 files changed, 28 insertions(+), 27 deletions(-) (limited to 'source4/dsdb/schema') diff --git a/source4/dsdb/schema/schema.h b/source4/dsdb/schema/schema.h index 92cfe113d4..e15f65a0a1 100644 --- a/source4/dsdb/schema/schema.h +++ b/source4/dsdb/schema/schema.h @@ -137,7 +137,6 @@ struct dsdb_class { char **subclasses; char **subclasses_direct; char **posssuperiors; - char **possible_inferiors; }; struct dsdb_schema_oid_prefix { diff --git a/source4/dsdb/schema/schema_inferiors.c b/source4/dsdb/schema/schema_inferiors.c index abd8f7e4b0..347af10531 100644 --- a/source4/dsdb/schema/schema_inferiors.c +++ b/source4/dsdb/schema/schema_inferiors.c @@ -31,14 +31,13 @@ #include "dsdb/samdb/samdb.h" - /* create the SUPCLASSES() list */ -static char * const *schema_supclasses(struct dsdb_schema *schema, - TALLOC_CTX *mem_ctx, struct dsdb_class *schema_class) +static char **schema_supclasses(struct dsdb_schema *schema, + TALLOC_CTX *mem_ctx, struct dsdb_class *schema_class) { - char * const *list; + char **list; if (schema_class->supclasses) { return schema_class->supclasses; @@ -60,11 +59,14 @@ static char * const *schema_supclasses(struct dsdb_schema *schema, char **list2; list = str_list_add(list, schema_class->subClassOf); - list2 = schema_supclasses(schema, mem_ctx, dsdb_class_by_lDAPDisplayName(schema, schema_class->subClassOf)); + list2 = schema_supclasses(schema, mem_ctx, + discard_const_p(struct dsdb_class, + dsdb_class_by_lDAPDisplayName(schema, + schema_class->subClassOf))); list = str_list_append(list, list2); } - schema_class->supclasses = list; + schema_class->supclasses = str_list_unique(list); return list; } @@ -73,8 +75,7 @@ static char * const *schema_supclasses(struct dsdb_schema *schema, this one is used internally matches SUBCLASSES() python function */ -static char **schema_subclasses(struct dsdb_schema *schema, TALLOC_CTX *mem_ctx, - const char * const *oclist) +static char **schema_subclasses(struct dsdb_schema *schema, TALLOC_CTX *mem_ctx, char **oclist) { char **list = str_list_make(mem_ctx, NULL, NULL); int i; @@ -93,27 +94,29 @@ static char **schema_subclasses(struct dsdb_schema *schema, TALLOC_CTX *mem_ctx, static char **schema_posssuperiors(struct dsdb_schema *schema, TALLOC_CTX *mem_ctx, struct dsdb_class *schema_class) { - char **list = str_list_make(mem_ctx, NULL, NULL); + if (schema_class->posssuperiors == NULL) { + char **list2 = str_list_make(mem_ctx, NULL, NULL); + char **list3; + int i; - if (schema_class->posssuperiors) { - return schema_class->posssuperiors; - } else { - char * const *list2 = str_list_make(mem_ctx, NULL, NULL); list2 = str_list_append(list2, schema_class->systemPossSuperiors); list2 = str_list_append(list2, schema_class->possSuperiors); - list2 = str_list_append(list2, schema_supclasses(schema, list2, schema_class)); + list3 = schema_supclasses(schema, list2, schema_class); + for (i=0; list3 && list3[i]; i++) { + struct dsdb_class *class2 = dsdb_class_by_lDAPDisplayName(schema, list3[i]); + list2 = str_list_append(list2, schema_posssuperiors(schema, mem_ctx, class2)); + } list2 = str_list_append(list2, schema_subclasses(schema, list2, list2)); - schema_class->posssuperiors = list2; - return schema_class->posssuperiors; + schema_class->posssuperiors = str_list_unique(list2); } - return list; + return schema_class->posssuperiors; } static char **schema_subclasses_recurse(struct dsdb_schema *schema, struct dsdb_class *schema_class) { - char * const *list = str_list_copy(schema_class, schema_class->subclasses_direct); + char **list = str_list_copy(schema_class, schema_class->subclasses_direct); int i; for (i=0;list && list[i]; i++) { struct dsdb_class *schema_class2 = dsdb_class_by_lDAPDisplayName(schema, list[i]); @@ -130,18 +133,17 @@ static void schema_create_subclasses(struct dsdb_schema *schema) for (schema_class=schema->classes; schema_class; schema_class=schema_class->next) { struct dsdb_class *schema_class2 = dsdb_class_by_lDAPDisplayName(schema, schema_class->subClassOf); - schema_class->subclasses_direct = str_list_make(schema_class, NULL, NULL); if (schema_class != schema_class2) { if (schema_class2->subclasses_direct == NULL) { schema_class2->subclasses_direct = str_list_make(schema_class2, NULL, NULL); } schema_class2->subclasses_direct = str_list_add(schema_class2->subclasses_direct, - schema_class->subClassOf); + schema_class->lDAPDisplayName); } } for (schema_class=schema->classes; schema_class; schema_class=schema_class->next) { - schema_class->subclasses = schema_subclasses_recurse(schema, schema_class); + schema_class->subclasses = str_list_unique(schema_subclasses_recurse(schema, schema_class)); } } @@ -155,14 +157,14 @@ static void schema_fill_possible_inferiors(struct dsdb_schema *schema, struct ds && c2->objectClassCategory != 2 && c2->objectClassCategory != 3 && str_list_check(superiors, schema_class->lDAPDisplayName)) { - if (c2->possible_inferiors == NULL) { - c2->possible_inferiors = str_list_make(c2, NULL, NULL); + if (schema_class->possibleInferiors == NULL) { + schema_class->possibleInferiors = str_list_make(schema_class, NULL, NULL); } - c2->possible_inferiors = str_list_add_unique(c2->possible_inferiors, - schema_class->lDAPDisplayName); + schema_class->possibleInferiors = str_list_add(schema_class->possibleInferiors, + c2->lDAPDisplayName); } - talloc_free(superiors); } + schema_class->possibleInferiors = str_list_unique(schema_class->possibleInferiors); } void schema_fill_constructed(struct dsdb_schema *schema) -- cgit From 87506b4a192eceeced856d33a0770deebada7ff5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 9 Apr 2009 14:29:36 +1000 Subject: make the memory usage of possibleInferiors much more efficient --- source4/dsdb/schema/schema_inferiors.c | 51 +++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 20 deletions(-) (limited to 'source4/dsdb/schema') diff --git a/source4/dsdb/schema/schema_inferiors.c b/source4/dsdb/schema/schema_inferiors.c index 347af10531..28f44ab263 100644 --- a/source4/dsdb/schema/schema_inferiors.c +++ b/source4/dsdb/schema/schema_inferiors.c @@ -34,8 +34,7 @@ /* create the SUPCLASSES() list */ -static char **schema_supclasses(struct dsdb_schema *schema, - TALLOC_CTX *mem_ctx, struct dsdb_class *schema_class) +static char **schema_supclasses(struct dsdb_schema *schema, struct dsdb_class *schema_class) { char **list; @@ -43,7 +42,7 @@ static char **schema_supclasses(struct dsdb_schema *schema, return schema_class->supclasses; } - list = str_list_make(mem_ctx, NULL, NULL); + list = str_list_make(schema_class, NULL, NULL); if (list == NULL) { DEBUG(0,(__location__ " out of memory\n")); return NULL; @@ -56,14 +55,14 @@ static char **schema_supclasses(struct dsdb_schema *schema, } if (schema_class->subClassOf) { - char **list2; - list = str_list_add(list, schema_class->subClassOf); + const char **list2; + list = str_list_add_const(list, schema_class->subClassOf); - list2 = schema_supclasses(schema, mem_ctx, + list2 = schema_supclasses(schema, discard_const_p(struct dsdb_class, dsdb_class_by_lDAPDisplayName(schema, schema_class->subClassOf))); - list = str_list_append(list, list2); + list = str_list_append_const(list, list2); } schema_class->supclasses = str_list_unique(list); @@ -82,7 +81,7 @@ static char **schema_subclasses(struct dsdb_schema *schema, TALLOC_CTX *mem_ctx, for (i=0; oclist && oclist[i]; i++) { struct dsdb_class *schema_class = dsdb_class_by_lDAPDisplayName(schema, oclist[i]); - list = str_list_append(list, schema_class->subclasses); + list = str_list_append_const(list, schema_class->subclasses); } return list; } @@ -91,22 +90,22 @@ static char **schema_subclasses(struct dsdb_schema *schema, TALLOC_CTX *mem_ctx, /* equivalent of the POSSSUPERIORS() python function */ -static char **schema_posssuperiors(struct dsdb_schema *schema, TALLOC_CTX *mem_ctx, +static char **schema_posssuperiors(struct dsdb_schema *schema, struct dsdb_class *schema_class) { if (schema_class->posssuperiors == NULL) { - char **list2 = str_list_make(mem_ctx, NULL, NULL); + char **list2 = str_list_make(schema_class, NULL, NULL); char **list3; int i; - list2 = str_list_append(list2, schema_class->systemPossSuperiors); - list2 = str_list_append(list2, schema_class->possSuperiors); - list3 = schema_supclasses(schema, list2, schema_class); + list2 = str_list_append_const(list2, schema_class->systemPossSuperiors); + list2 = str_list_append_const(list2, schema_class->possSuperiors); + list3 = schema_supclasses(schema, schema_class); for (i=0; list3 && list3[i]; i++) { struct dsdb_class *class2 = dsdb_class_by_lDAPDisplayName(schema, list3[i]); - list2 = str_list_append(list2, schema_posssuperiors(schema, mem_ctx, class2)); + list2 = str_list_append_const(list2, schema_posssuperiors(schema, class2)); } - list2 = str_list_append(list2, schema_subclasses(schema, list2, list2)); + list2 = str_list_append_const(list2, schema_subclasses(schema, list2, list2)); schema_class->posssuperiors = str_list_unique(list2); } @@ -116,12 +115,12 @@ static char **schema_posssuperiors(struct dsdb_schema *schema, TALLOC_CTX *mem_c static char **schema_subclasses_recurse(struct dsdb_schema *schema, struct dsdb_class *schema_class) { - char **list = str_list_copy(schema_class, schema_class->subclasses_direct); + char **list = str_list_copy_const(schema_class, schema_class->subclasses_direct); int i; for (i=0;list && list[i]; i++) { struct dsdb_class *schema_class2 = dsdb_class_by_lDAPDisplayName(schema, list[i]); if (schema_class != schema_class2) { - list = str_list_append(list, schema_subclasses_recurse(schema, schema_class2)); + list = str_list_append_const(list, schema_subclasses_recurse(schema, schema_class2)); } } return list; @@ -137,7 +136,7 @@ static void schema_create_subclasses(struct dsdb_schema *schema) if (schema_class2->subclasses_direct == NULL) { schema_class2->subclasses_direct = str_list_make(schema_class2, NULL, NULL); } - schema_class2->subclasses_direct = str_list_add(schema_class2->subclasses_direct, + schema_class2->subclasses_direct = str_list_add_const(schema_class2->subclasses_direct, schema_class->lDAPDisplayName); } } @@ -152,7 +151,7 @@ static void schema_fill_possible_inferiors(struct dsdb_schema *schema, struct ds struct dsdb_class *c2; for (c2=schema->classes; c2; c2=c2->next) { - char **superiors = schema_posssuperiors(schema, c2, c2); + char **superiors = schema_posssuperiors(schema, c2); if (c2->systemOnly == false && c2->objectClassCategory != 2 && c2->objectClassCategory != 3 @@ -160,7 +159,7 @@ static void schema_fill_possible_inferiors(struct dsdb_schema *schema, struct ds if (schema_class->possibleInferiors == NULL) { schema_class->possibleInferiors = str_list_make(schema_class, NULL, NULL); } - schema_class->possibleInferiors = str_list_add(schema_class->possibleInferiors, + schema_class->possibleInferiors = str_list_add_const(schema_class->possibleInferiors, c2->lDAPDisplayName); } } @@ -176,4 +175,16 @@ void schema_fill_constructed(struct dsdb_schema *schema) for (schema_class=schema->classes; schema_class; schema_class=schema_class->next) { schema_fill_possible_inferiors(schema, schema_class); } + + /* free up our internal cache elements */ + for (schema_class=schema->classes; schema_class; schema_class=schema_class->next) { + talloc_free(schema_class->supclasses); + talloc_free(schema_class->subclasses_direct); + talloc_free(schema_class->subclasses); + talloc_free(schema_class->posssuperiors); + schema_class->supclasses = NULL; + schema_class->subclasses_direct = NULL; + schema_class->subclasses = NULL; + schema_class->posssuperiors = NULL; + } } -- cgit