mirror of
https://github.com/samba-team/samba.git
synced 2025-03-08 04:58:40 +03:00
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
This commit is contained in:
parent
8352650fee
commit
8374d6f0dc
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user