Author: mkhl Date: 2006-06-26 22:07:25 +0000 (Mon, 26 Jun 2006) New Revision: 16534
WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=16534 Log: Add support for merging remote search results with local search results. Martin Modified: branches/SOC/mkhl/ldb-map/modules/ldb_map.c Changeset: Modified: branches/SOC/mkhl/ldb-map/modules/ldb_map.c =================================================================== --- branches/SOC/mkhl/ldb-map/modules/ldb_map.c 2006-06-26 21:21:59 UTC (rev 16533) +++ branches/SOC/mkhl/ldb-map/modules/ldb_map.c 2006-06-26 22:07:25 UTC (rev 16534) @@ -791,7 +791,6 @@ return NULL; } - /* local DN -> remote DN (as LDB values) */ static struct ldb_val @@ -1131,112 +1130,6 @@ /* } */ /* /\* XXX *\/ */ -/* /\* Remote message element -> Local message element *\/ */ -/* static struct ldb_message_element *mop_remote_msg_element(struct ldb_module *module, */ -/* struct ldb_message *msg, */ -/* const struct ldb_message *oldmsg, */ -/* const struct ldb_map_attribute *attr) */ -/* { */ -/* struct ldb_message_element *el, *oldel; */ -/* int i; */ - -/* el = talloc(msg, struct ldb_message_element); */ -/* if (el == NULL) */ -/* return NULL; */ - -/* switch (attr->type) { */ -/* case MAP_IGNORE: */ -/* goto failed; */ - -/* case MAP_KEEP: */ -/* ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_map: " */ -/* "Keeping remote attribute '%s'\n", attr->local_name); */ - -/* oldel = ldb_msg_find_element(oldmsg, attr->local_name); */ -/* if (oldel == NULL) */ -/* goto failed; */ - -/* el->name = talloc_strdup(el, attr->local_name); */ -/* el->flags = oldel->flags; */ -/* el->num_values = oldel->num_values; */ -/* el->values = talloc_array(el, struct ldb_val, el->num_values); */ -/* if (el->values == NULL) */ -/* goto failed; */ - -/* for (i = 0; i < el->num_values; i++) */ -/* el->values[i] = ldb_val_dup(el, &oldel->values[i]); */ - -/* return el; */ - -/* case MAP_RENAME: */ -/* ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_map: " */ -/* "Renaming remote attribute '%s' to '%s'\n", */ -/* attr->u.rename.remote_name, attr->local_name); */ - -/* oldel = ldb_msg_find_element(oldmsg, attr->u.rename.remote_name); */ -/* if (oldel == NULL) */ -/* goto failed; */ - -/* el->name = talloc_strdup(el, attr->local_name); */ -/* el->flags = oldel->flags; */ -/* el->num_values = oldel->num_values; */ -/* el->values = talloc_array(el, struct ldb_val, el->num_values); */ -/* if (el->values == NULL) */ -/* goto failed; */ - -/* for (i = 0; i < el->num_values; i++) */ -/* el->values[i] = ldb_val_dup(el, &oldel->values[i]); */ - -/* return el; */ - -/* case MAP_CONVERT: */ -/* ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_map: " */ -/* "Converting remote attribute '%s' to '%s'\n", */ -/* attr->u.rename.remote_name, attr->local_name); */ - -/* if (attr->u.convert.convert_remote == NULL) { */ -/* ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb_map: " */ -/* "'convert_remote' not set!\n"); */ -/* goto failed; */ -/* } */ - -/* oldel = ldb_msg_find_element(oldmsg, attr->u.rename.remote_name); */ -/* if (oldel == NULL) */ -/* goto failed; */ - -/* el->name = talloc_strdup(el, attr->local_name); */ -/* el->flags = oldel->flags; */ -/* el->num_values = oldel->num_values; */ -/* el->values = talloc_array(el, struct ldb_val, el->num_values); */ -/* if (el->values == NULL) */ -/* goto failed; */ - -/* for (i = 0; i < el->num_values; i++) */ -/* el->values[i] = attr->u.convert.convert_remote(module, el, &oldel->values[i]); */ - -/* return el; */ - -/* case MAP_GENERATE: */ -/* ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_map: " */ -/* "Generating local attribute '%s'\n", */ -/* attr->local_name); */ - -/* if (attr->u.generate.generate_local == NULL) { */ -/* ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb_map: " */ -/* "'generate_local' not set!\n"); */ -/* goto failed; */ -/* } */ - -/* talloc_free(el); */ -/* return attr->u.generate.generate_local(module, msg, attr->local_name, oldmsg); */ -/* } */ - -/* failed: */ -/* talloc_free(el); */ -/* return NULL; */ -/* } */ - -/* /\* XXX *\/ */ /* /\* Remote message -> Local message *\/ */ /* static struct ldb_message *mop_ldb_message_incoming(struct ldb_module *module, */ /* const char *const names[], */ @@ -1292,15 +1185,42 @@ /* return NULL; */ /* } */ +/* add element to message, overwriting old elements of the same name */ +static +int +ldb_msg_replace(struct ldb_message *msg, + const struct ldb_message_element *el) +{ + struct ldb_message_element *old; + + old = ldb_msg_find_element(msg, el->name); + /* no local result, add as new */ + if (old == NULL) { + if (ldb_msg_add_empty(msg, el->name, 0) != LDB_SUCCESS) + goto failed; + + old = ldb_msg_find_element(msg, el->name); + if (old == NULL) + goto failed; + } + + *old = *el; /* copy element */ + + return 0; + +failed: + return -1; +} + /* Create a copy of the given message element with the specified name. * If a mapping is specified, use it to convert the values. */ static struct ldb_message_element * copy_conv_msg_el(struct ldb_module *module, struct ldb_message *msg, - const struct ldb_map_attribute *map, const struct ldb_message_element *old, - const char *name) + const char *name, + const ldb_map_convert_func map) { struct ldb_message_element *el; int i; @@ -1326,8 +1246,7 @@ if (map == NULL) el->values[i] = ldb_val_dup(el, &old->values[i]); else - el->values[i] = map->u.convert - .convert_local(module, el, &old->values[i]); + el->values[i] = map(module, el, &old->values[i]); } return el; @@ -1360,13 +1279,11 @@ goto local; case MAP_KEEP: - el = copy_conv_msg_el(module, remote, NULL, old, - map->local_name); + el = copy_conv_msg_el(module, remote, old, map->local_name, NULL); break; case MAP_RENAME: - el = copy_conv_msg_el(module, remote, NULL, old, - map->u.rename.remote_name); + el = copy_conv_msg_el(module, remote, old, map->u.rename.remote_name, NULL); break; case MAP_CONVERT: @@ -1377,8 +1294,7 @@ map->local_name); goto failed; - el = copy_conv_msg_el(module, remote, map, old, - map->u.rename.remote_name); + el = copy_conv_msg_el(module, remote, old, map->u.convert.remote_name, map->u.convert.convert_local); break; case MAP_GENERATE: @@ -1442,6 +1358,7 @@ } map = find_local_attr(data, msg->elements[i].name); + ret = partition_msg_el(module, local, remote, map, msg, &msg->elements[i]); if (ret != 0) @@ -1451,14 +1368,97 @@ return 0; } +/* merge remote message element into local message */ static int -merge_mapped_results(struct map_async_search_context *context) +merge_msg_el(struct ldb_module *module, + struct ldb_message *local, + struct ldb_message *remote, + const struct ldb_map_attribute *map, + const struct ldb_message_element *old) { - return LDB_SUCCESS; /* TODO */ + struct ldb_message_element *el; + + /* no mapping: fail */ + if (map == NULL) { + ldb_debug(module->ldb, LDB_DEBUG_WARNING, "ldb_map: " + "Not mapping attribute '%s': no mapping found\n", + old->name); + goto failed; + } + + switch (map->type) { + case MAP_IGNORE: + goto failed; + + case MAP_KEEP: + case MAP_RENAME: + el = copy_conv_msg_el(module, local, old, map->local_name, NULL); + break; + + case MAP_CONVERT: + if (map->u.convert.convert_remote == NULL) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb_map: " + "Skipping attribute '%s': " + "'convert_remote' not set\n", + old->name); + goto unmapped; + } + + el = copy_conv_msg_el(module, local, old, map->local_name, map->u.convert.convert_remote); + break; + + case MAP_GENERATE: + if (map->u.generate.generate_local == NULL) { + ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb_map: " + "Skipping attribute '%s': " + "'generate_local' not set\n", + old->name); + goto unmapped; + } + + el = map->u.generate.generate_local(module, local, map->local_name, remote); + break; + } + + if (el == NULL) + goto failed; + return ldb_msg_replace(local, el); + +unmapped: + return 0; + +failed: + return -1; } +/* merge remote message into local message */ +static +int +merge_msg(struct ldb_module *module, + struct ldb_message *local, + struct ldb_message *remote) +{ + struct ldb_map_context *data = map_get_context(module); + const struct ldb_map_attribute *map; + int i, ret; + /* try to map each attribute back; + add to the local message is possible, + overwrite old local attribute if necessary */ + for (i = 0; i < remote->num_elements; i++) { + map = find_remote_attr(data, remote->elements[i].name); + + ret = merge_msg_el(module, local, remote, map, + &remote->elements[i]); + if (ret != 0) + return ret; + } + + return 0; +} + + /* store single search result in async context */ static int @@ -1577,7 +1577,7 @@ sc->remote_res = ares; /* merge remote into local record */ - ret = merge_mapped_results(sc); + ret = merge_msg(sc->ac->module, sc->local_res->message, sc->remote_res->message); if (ret != LDB_SUCCESS) talloc_free(ares); @@ -1648,6 +1648,7 @@ sc->local_res = ares; sc->remote_res = NULL; + /* TODO: map the remote parse-tree */ remote_attrs = select_mapped_attrs(ac->module, ac, ac->orig_req->op.search.attrs); req = search_base_req(ac, dn, remote_attrs, remote_search_callback);
