From 11b42022c7f1fe60ce0be0911f17a7ff70881986 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 8 Nov 2010 17:14:09 +1100 Subject: s4-repl: fixed replication notifications to RODCs We need a separate source dsa list for RODCs, as they are not in the repsFrom for our partitions, but are in the repsTo. This adds a new 'notifies' list, which contains all the source dsas for the DCs that we should send notifies to, but which we don't replicate from Autobuild-User: Andrew Tridgell Autobuild-Date: Mon Nov 8 06:57:43 UTC 2010 on sn-devel-104 --- source4/dsdb/repl/drepl_notify.c | 14 ++++++++--- source4/dsdb/repl/drepl_partitions.c | 45 ++++++++++++++++++++++++++++++++---- source4/dsdb/repl/drepl_service.h | 6 +++++ 3 files changed, 58 insertions(+), 7 deletions(-) (limited to 'source4/dsdb/repl') diff --git a/source4/dsdb/repl/drepl_notify.c b/source4/dsdb/repl/drepl_notify.c index 836509b3eb..0178e97e55 100644 --- a/source4/dsdb/repl/drepl_notify.c +++ b/source4/dsdb/repl/drepl_notify.c @@ -270,16 +270,24 @@ void dreplsrv_notify_run_ops(struct dreplsrv_service *s) /* find a source_dsa for a given guid */ -static struct dreplsrv_partition_source_dsa *dreplsrv_find_source_dsa(struct dreplsrv_partition *p, +static struct dreplsrv_partition_source_dsa *dreplsrv_find_notify_dsa(struct dreplsrv_partition *p, struct GUID *guid) { struct dreplsrv_partition_source_dsa *s; + /* first check the sources list */ for (s=p->sources; s; s=s->next) { if (GUID_compare(&s->repsFrom1->source_dsa_obj_guid, guid) == 0) { return s; } } + + /* then the notifies list */ + for (s=p->notifies; s; s=s->next) { + if (GUID_compare(&s->repsFrom1->source_dsa_obj_guid, guid) == 0) { + return s; + } + } return NULL; } @@ -298,7 +306,7 @@ static WERROR dreplsrv_schedule_notify_sync(struct dreplsrv_service *service, struct dreplsrv_notify_operation *op; struct dreplsrv_partition_source_dsa *s; - s = dreplsrv_find_source_dsa(p, &reps->ctr.ctr1.source_dsa_obj_guid); + s = dreplsrv_find_notify_dsa(p, &reps->ctr.ctr1.source_dsa_obj_guid); if (s == NULL) { DEBUG(0,(__location__ ": Unable to find source_dsa for %s\n", GUID_string(mem_ctx, &reps->ctr.ctr1.source_dsa_obj_guid))); @@ -375,7 +383,7 @@ static WERROR dreplsrv_notify_check(struct dreplsrv_service *s, for (i=0; inotify_uSN < uSNHighest) { diff --git a/source4/dsdb/repl/drepl_partitions.c b/source4/dsdb/repl/drepl_partitions.c index 76f261d4f8..70173fea01 100644 --- a/source4/dsdb/repl/drepl_partitions.c +++ b/source4/dsdb/repl/drepl_partitions.c @@ -209,8 +209,27 @@ WERROR dreplsrv_out_connection_attach(struct dreplsrv_service *s, return WERR_OK; } +/* + find an existing source dsa in a list + */ +static struct dreplsrv_partition_source_dsa *dreplsrv_find_source_dsa(struct dreplsrv_partition_source_dsa *list, + struct GUID *guid) +{ + struct dreplsrv_partition_source_dsa *s; + for (s=list; s; s=s->next) { + if (GUID_compare(&s->repsFrom1->source_dsa_obj_guid, guid) == 0) { + return s; + } + } + return NULL; +} + + + static WERROR dreplsrv_partition_add_source_dsa(struct dreplsrv_service *s, struct dreplsrv_partition *p, + struct dreplsrv_partition_source_dsa **listp, + struct dreplsrv_partition_source_dsa *check_list, const struct ldb_val *val) { WERROR status; @@ -240,8 +259,15 @@ static WERROR dreplsrv_partition_add_source_dsa(struct dreplsrv_service *s, status = dreplsrv_out_connection_attach(s, source->repsFrom1, &source->conn); W_ERROR_NOT_OK_RETURN(status); - /* remove any existing source with the same GUID */ - for (s2=p->sources; s2; s2=s2->next) { + if (check_list && + dreplsrv_find_source_dsa(check_list, &source->repsFrom1->source_dsa_obj_guid)) { + /* its in the check list, don't add it again */ + talloc_free(source); + return WERR_OK; + } + + /* re-use an existing source if found */ + for (s2=*listp; s2; s2=s2->next) { if (GUID_compare(&s2->repsFrom1->source_dsa_obj_guid, &source->repsFrom1->source_dsa_obj_guid) == 0) { talloc_free(s2->repsFrom1->other_info); @@ -252,7 +278,7 @@ static WERROR dreplsrv_partition_add_source_dsa(struct dreplsrv_service *s, } } - DLIST_ADD_END(p->sources, source, struct dreplsrv_partition_source_dsa *); + DLIST_ADD_END(*listp, source, struct dreplsrv_partition_source_dsa *); return WERR_OK; } @@ -343,6 +369,7 @@ static WERROR dreplsrv_refresh_partition(struct dreplsrv_service *s, "objectSid", "objectGUID", "repsFrom", + "repsTo", NULL }; @@ -380,7 +407,17 @@ static WERROR dreplsrv_refresh_partition(struct dreplsrv_service *s, orf_el = ldb_msg_find_element(r->msgs[0], "repsFrom"); if (orf_el) { for (i=0; i < orf_el->num_values; i++) { - status = dreplsrv_partition_add_source_dsa(s, p, &orf_el->values[i]); + status = dreplsrv_partition_add_source_dsa(s, p, &p->sources, + NULL, &orf_el->values[i]); + W_ERROR_NOT_OK_RETURN(status); + } + } + + orf_el = ldb_msg_find_element(r->msgs[0], "repsTo"); + if (orf_el) { + for (i=0; i < orf_el->num_values; i++) { + status = dreplsrv_partition_add_source_dsa(s, p, &p->notifies, + p->sources, &orf_el->values[i]); W_ERROR_NOT_OK_RETURN(status); } } diff --git a/source4/dsdb/repl/drepl_service.h b/source4/dsdb/repl/drepl_service.h index ba1f1950ef..9ad62fd538 100644 --- a/source4/dsdb/repl/drepl_service.h +++ b/source4/dsdb/repl/drepl_service.h @@ -103,6 +103,12 @@ struct dreplsrv_partition { */ struct dreplsrv_partition_source_dsa *sources; + /* + * a linked list of all source dsa's we will notify, + * that are not also in sources + */ + struct dreplsrv_partition_source_dsa *notifies; + bool incoming_only; }; -- cgit