diff options
Diffstat (limited to 'source4/lib/ldb/ldb_tdb/ldb_index.c')
-rw-r--r-- | source4/lib/ldb/ldb_tdb/ldb_index.c | 208 |
1 files changed, 146 insertions, 62 deletions
diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index dda80a6b2a..8cda8abff8 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -74,13 +74,22 @@ static char *ldb_dn_key(const char *attr, const struct ldb_val *value) /* see if a attribute value is in the list of indexed attributes */ -static int ldb_msg_find_idx(const struct ldb_message *msg, const char *attr) +static int ldb_msg_find_idx(const struct ldb_message *msg, const char *attr, + int *v_idx) { - int i; + int i, j; for (i=0;i<msg->num_elements;i++) { - if (strcmp(msg->elements[i].name, "@IDXATTR") == 0 && - strcmp((char *)msg->elements[i].value.data, attr) == 0) { - return i; + if (strcmp(msg->elements[i].name, "@IDXATTR") == 0) { + const struct ldb_message_element *el = + &msg->elements[i]; + for (j=0;j<el->num_values;j++) { + if (strcmp((char *)el->values[j].data, attr) == 0) { + if (v_idx) { + *v_idx = j; + } + return i; + } + } } } return -1; @@ -95,7 +104,7 @@ static int ltdb_index_dn_simple(struct ldb_context *ldb, struct dn_list *list) { char *dn = NULL; - int ret, i; + int ret, i, j; struct ldb_message msg; list->count = 0; @@ -110,7 +119,7 @@ static int ltdb_index_dn_simple(struct ldb_context *ldb, /* if the attribute isn't in the list of indexed attributes then this node needs a full search */ - if (ldb_msg_find_idx(index_list, tree->u.simple.attr) == -1) { + if (ldb_msg_find_idx(index_list, tree->u.simple.attr, NULL) == -1) { return -1; } @@ -125,23 +134,30 @@ static int ltdb_index_dn_simple(struct ldb_context *ldb, return ret; } - list->dn = malloc_array_p(char *, msg.num_elements); - if (!list->dn) { - ltdb_search_dn1_free(ldb, &msg); - } - for (i=0;i<msg.num_elements;i++) { + struct ldb_message_element *el; + if (strcmp(msg.elements[i].name, "@IDX") != 0) { continue; } - list->dn[list->count] = - strdup((char *)msg.elements[i].value.data); - if (!list->dn[list->count]) { - dn_list_free(list); - ltdb_search_dn1_free(ldb, &msg); - return -1; + + el = &msg.elements[i]; + + list->dn = malloc_array_p(char *, el->num_values); + if (!list->dn) { + break; + } + + for (j=0;j<el->num_values;j++) { + list->dn[list->count] = + strdup((char *)el->values[j].data); + if (!list->dn[list->count]) { + dn_list_free(list); + ltdb_search_dn1_free(ldb, &msg); + return -1; + } + list->count++; } - list->count++; } ltdb_search_dn1_free(ldb, &msg); @@ -471,17 +487,75 @@ int ltdb_search_indexed(struct ldb_context *ldb, } /* + add a index element where this is the first indexed DN for this value +*/ +static int ltdb_index_add1_new(struct ldb_context *ldb, + struct ldb_message *msg, + struct ldb_message_element *el, + const char *dn) +{ + struct ldb_message_element *el2; + + /* add another entry */ + el2 = realloc_p(msg->elements, struct ldb_message_element, msg->num_elements+1); + if (!el2) { + return -1; + } + + msg->elements = el2; + msg->elements[msg->num_elements].name = "@IDX"; + msg->elements[msg->num_elements].num_values = 0; + msg->elements[msg->num_elements].values = malloc_p(struct ldb_val); + if (!msg->elements[msg->num_elements].values) { + return -1; + } + msg->elements[msg->num_elements].values[0].length = strlen(dn); + msg->elements[msg->num_elements].values[0].data = dn; + msg->elements[msg->num_elements].num_values = 1; + msg->num_elements++; + + return 0; +} + + +/* + add a index element where this is not the first indexed DN for this + value +*/ +static int ltdb_index_add1_add(struct ldb_context *ldb, + struct ldb_message *msg, + struct ldb_message_element *el, + int idx, + const char *dn) +{ + struct ldb_val *v2; + + v2 = realloc_p(msg->elements[idx].values, + struct ldb_val, + msg->elements[idx].num_values+1); + if (!v2) { + return -1; + } + msg->elements[idx].values = v2; + + msg->elements[idx].values[msg->elements[idx].num_values].length = strlen(dn); + msg->elements[idx].values[msg->elements[idx].num_values].data = dn; + msg->elements[idx].num_values++; + + return 0; +} + +/* add an index entry for one message element */ static int ltdb_index_add1(struct ldb_context *ldb, const char *dn, - struct ldb_message_element *el) + struct ldb_message_element *el, int v_idx) { struct ldb_message msg; char *dn_key; - int ret; - struct ldb_message_element *el2; + int ret, i; - dn_key = ldb_dn_key(el->name, &el->value); + dn_key = ldb_dn_key(el->name, &el->values[v_idx]); if (!dn_key) { return -1; } @@ -493,36 +567,37 @@ static int ltdb_index_add1(struct ldb_context *ldb, const char *dn, } if (ret == 0) { - msg.dn = dn_key; + msg.dn = strdup(dn_key); + if (!msg.dn) { + free(dn_key); + errno = ENOMEM; + return -1; + } msg.num_elements = 0; msg.elements = NULL; msg.private = NULL; } - /* add another entry */ - el2 = realloc_p(msg.elements, struct ldb_message_element, msg.num_elements+1); - if (!el2) { - if (ret == 1) { - ltdb_search_dn1_free(ldb, &msg); + free(dn_key); + + for (i=0;i<msg.num_elements;i++) { + if (strcmp("@IDX", msg.elements[i].name) == 0) { + break; } - free(dn_key); - return -1; } - msg.elements = el2; - msg.elements[msg.num_elements].name = "@IDX"; - msg.elements[msg.num_elements].value.length = strlen(dn); - msg.elements[msg.num_elements].value.data = dn; - msg.num_elements++; - - ret = ltdb_store(ldb, &msg, TDB_REPLACE); - - if (msg.num_elements == 1) { - free(msg.elements); + if (i == msg.num_elements) { + ret = ltdb_index_add1_new(ldb, &msg, el, dn); } else { - ltdb_search_dn1_free(ldb, &msg); + ret = ltdb_index_add1_add(ldb, &msg, el, i, dn); + } + + if (ret == 0) { + ret = ltdb_store(ldb, &msg, TDB_REPLACE); } + ltdb_search_dn1_free(ldb, &msg); + return ret; } @@ -532,7 +607,7 @@ static int ltdb_index_add1(struct ldb_context *ldb, const char *dn, */ int ltdb_index_add(struct ldb_context *ldb, const struct ldb_message *msg) { - int ret, i; + int ret, i, j; struct ldb_message index_list; /* find the list of indexed fields */ @@ -543,17 +618,21 @@ int ltdb_index_add(struct ldb_context *ldb, const struct ldb_message *msg) } for (i=0;i<msg->num_elements;i++) { - ret = ldb_msg_find_idx(&index_list, msg->elements[i].name); + ret = ldb_msg_find_idx(&index_list, msg->elements[i].name, NULL); if (ret == -1) { continue; } - ret = ltdb_index_add1(ldb, msg->dn, &msg->elements[i]); - if (ret == -1) { - ltdb_search_dn1_free(ldb, &index_list); - return -1; + for (j=0;j<msg->elements[i].num_values;j++) { + ret = ltdb_index_add1(ldb, msg->dn, &msg->elements[i], j); + if (ret == -1) { + ltdb_search_dn1_free(ldb, &index_list); + return -1; + } } } + ltdb_search_dn1_free(ldb, &index_list); + return 0; } @@ -562,13 +641,13 @@ int ltdb_index_add(struct ldb_context *ldb, const struct ldb_message *msg) delete an index entry for one message element */ static int ltdb_index_del1(struct ldb_context *ldb, const char *dn, - struct ldb_message_element *el) + struct ldb_message_element *el, int v_idx) { struct ldb_message msg; char *dn_key; - int ret, i; + int ret, i, j; - dn_key = ldb_dn_key(el->name, &el->value); + dn_key = ldb_dn_key(el->name, &el->values[v_idx]); if (!dn_key) { return -1; } @@ -586,19 +665,22 @@ static int ltdb_index_del1(struct ldb_context *ldb, const char *dn, return 0; } - i = ldb_msg_find_idx(&msg, dn); + i = ldb_msg_find_idx(&msg, dn, &j); if (i == -1) { /* it ain't there. hmmm */ ltdb_search_dn1_free(ldb, &msg); return 0; } - if (i != msg.num_elements - 1) { - memmove(&msg.elements[i], &msg.elements[i+1], sizeof(msg.elements[i])); + if (j != msg.elements[i].num_values - 1) { + memmove(&msg.elements[i].values[j], + &msg.elements[i].values[j+1], + (msg.elements[i].num_values-1) * + sizeof(msg.elements[i].values[0])); } - msg.num_elements--; + msg.elements[i].num_values--; - if (msg.num_elements == 0) { + if (msg.elements[i].num_values == 0) { ret = ltdb_delete_noindex(ldb, dn_key); } else { ret = ltdb_store(ldb, &msg, TDB_REPLACE); @@ -615,7 +697,7 @@ static int ltdb_index_del1(struct ldb_context *ldb, const char *dn, */ int ltdb_index_del(struct ldb_context *ldb, const struct ldb_message *msg) { - int ret, i; + int ret, i, j; struct ldb_message index_list; /* find the list of indexed fields */ @@ -626,14 +708,16 @@ int ltdb_index_del(struct ldb_context *ldb, const struct ldb_message *msg) } for (i=0;i<msg->num_elements;i++) { - ret = ldb_msg_find_idx(&index_list, msg->elements[i].name); + ret = ldb_msg_find_idx(&index_list, msg->elements[i].name, NULL); if (ret == -1) { continue; } - ret = ltdb_index_del1(ldb, msg->dn, &msg->elements[i]); - if (ret == -1) { - ltdb_search_dn1_free(ldb, &index_list); - return -1; + for (j=0;j<msg->elements[i].num_values;j++) { + ret = ltdb_index_del1(ldb, msg->dn, &msg->elements[i], j); + if (ret == -1) { + ltdb_search_dn1_free(ldb, &index_list); + return -1; + } } } |