s4-repl: fixed replication notifications to RODCs
authorAndrew Tridgell <tridge@samba.org>
Mon, 8 Nov 2010 06:14:09 +0000 (17:14 +1100)
committerAndrew Tridgell <tridge@samba.org>
Mon, 8 Nov 2010 06:57:42 +0000 (06:57 +0000)
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 <tridge@samba.org>
Autobuild-Date: Mon Nov  8 06:57:43 UTC 2010 on sn-devel-104

source4/dsdb/repl/drepl_notify.c
source4/dsdb/repl/drepl_partitions.c
source4/dsdb/repl/drepl_service.h

index 836509b3eb1bfd0ad42fe551502639977d0a5892..0178e97e5596fd37ff35e5133dfd0721b427c3a9 100644 (file)
@@ -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; i<count; i++) {
                struct dreplsrv_partition_source_dsa *sdsa;
                uint32_t replica_flags;
-               sdsa = dreplsrv_find_source_dsa(p, &reps[i].ctr.ctr1.source_dsa_obj_guid);
+               sdsa = dreplsrv_find_notify_dsa(p, &reps[i].ctr.ctr1.source_dsa_obj_guid);
                replica_flags = reps[i].ctr.ctr1.replica_flags;
                if (sdsa == NULL) continue;
                if (sdsa->notify_uSN < uSNHighest) {
index 76f261d4f8d99dea950649ec4644410c88e13ce6..70173fea01387a1b32b8ee1968a8b5766c1a1cdf 100644 (file)
@@ -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);  
                }
        }
index ba1f1950ef378331cf712b669f494ce628282388..9ad62fd538d65939acec6ce81d0f727527ddb089 100644 (file)
@@ -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;
 };