summaryrefslogtreecommitdiff
path: root/source4/dsdb/schema/schema_query.c
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2009-04-02 16:42:21 +1100
committerAndrew Tridgell <tridge@samba.org>2009-04-02 16:42:21 +1100
commit9539e2b508b3340b49575e5022c365ec382b2097 (patch)
tree57f28e0743b527bcb28fad2a79863e47be9b1416 /source4/dsdb/schema/schema_query.c
parent1bc9c3923574d548810733b512716d5758814328 (diff)
downloadsamba-9539e2b508b3340b49575e5022c365ec382b2097.tar.gz
samba-9539e2b508b3340b49575e5022c365ec382b2097.tar.bz2
samba-9539e2b508b3340b49575e5022c365ec382b2097.zip
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.
Diffstat (limited to 'source4/dsdb/schema/schema_query.c')
-rw-r--r--source4/dsdb/schema/schema_query.c145
1 files changed, 66 insertions, 79 deletions
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;