s4: Remove expired source if not used
authorMatthieu Patou <mat@matws.net>
Fri, 12 Apr 2013 05:02:38 +0000 (22:02 -0700)
committerMatthieu Patou <mat@matws.net>
Sun, 18 May 2014 04:51:14 +0000 (21:51 -0700)
source4/dsdb/repl/drepl_extended.c
source4/dsdb/repl/drepl_notify.c
source4/dsdb/repl/drepl_out_pull.c
source4/dsdb/repl/drepl_partitions.c
source4/dsdb/repl/drepl_service.h

index 8735005941b1635e1d4caab5a84878d30313c3fb..dc02c16c3ca2a11fc9b90f04a1938c614b65d015 100644 (file)
@@ -194,6 +194,8 @@ WERROR drepl_request_extended_op(struct dreplsrv_service *service,
 
        data->callback = callback;
        data->callback_data = callback_data;
+       data->sdsa = sdsa;
+       sdsa->used++;
 
        werr = dreplsrv_schedule_partition_pull_source(service, data->sdsa,
                                                       0, extended_op, fsmo_info,
index 905fe5f604fe44f84d351d5d8870665889f4ef67..2ec9b0f84227a0e783d30be4b05b77379e6dfe26 100644 (file)
@@ -203,6 +203,13 @@ static void dreplsrv_notify_op_callback(struct tevent_req *subreq)
        drepl_reps_update(s, "repsTo", op->source_dsa->partition->dn,
                          &op->source_dsa->repsFrom1->source_dsa_obj_guid,
                          werr);
+       /* Decrement the number of call that are using this source */
+       op->source_dsa->used--;
+       SMB_ASSERT(op->source_dsa->used >= 0);
+       DEBUG(10, ("Source DSA to %s partition %s is still used in %d calls\n",
+                       op->source_dsa->repsFrom1->other_info->dns_name,
+                       ldb_dn_get_linearized(op->source_dsa->partition->dn),
+                       op->source_dsa->used));
 
        talloc_free(op);
        s->ops.n_current = NULL;
@@ -323,6 +330,7 @@ static WERROR dreplsrv_schedule_notify_sync(struct dreplsrv_service *service,
        op->replica_flags = replica_flags;
        op->schedule_time = time(NULL);
 
+       s->used++;
        DLIST_ADD_END(service->ops.notifies, op, struct dreplsrv_notify_operation *);
        talloc_steal(service, op);
        return WERR_OK;
index 58d877870eb7996d1528660d9d6ff3e6426cafaf..ebf8a0fe127896aa8f22fae2763effcce315c46a 100644 (file)
@@ -126,6 +126,7 @@ WERROR dreplsrv_schedule_partition_pull_source(struct dreplsrv_service *s,
        op->callback    = callback;
        op->cb_data     = cb_data;
        op->schedule_time = time(NULL);
+       source->used++;
 
        DLIST_ADD_END(s->ops.pending, op, struct dreplsrv_out_operation *);
 
@@ -185,6 +186,8 @@ static void dreplsrv_pending_op_callback(struct tevent_req *subreq)
        if (op->callback) {
                op->callback(s, werr, op->extended_ret, op->cb_data);
        }
+       op->source_dsa->used--;
+       SMB_ASSERT(op->source_dsa->used >= 0);
        talloc_free(op);
        s->ops.current = NULL;
        dreplsrv_run_pending_ops(s);
@@ -245,6 +248,9 @@ failed:
                drepl_reps_update(s, "repsFrom", op->source_dsa->partition->dn,
                                  &op->source_dsa->repsFrom1->source_dsa_obj_guid, werr);
        }
+       op->source_dsa->used--;
+       SMB_ASSERT(op->source_dsa->used >= 0);
+
        /* unblock queue processing */
        s->ops.current = NULL;
        /*
index 7be069e0dc57200fb3cfa43c27e2f4d60beeeb9f..a27674309d1aac9c3364a45a081c652bf1e5278f 100644 (file)
@@ -377,6 +377,7 @@ 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,
+                                               struct dreplsrv_partition_source_dsa **oldlist,
                                                const struct ldb_val *val)
 {
        WERROR status;
@@ -414,14 +415,16 @@ static WERROR dreplsrv_partition_add_source_dsa(struct dreplsrv_service *s,
        }
 
        /* re-use an existing source if found */
-       for (s2=*listp; s2; s2=s2->next) {
+       for (s2=*oldlist; 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);
                        *s2->repsFrom1 = *source->repsFrom1;
                        talloc_steal(s2, s2->repsFrom1->other_info);
                        talloc_free(source);
-                       return WERR_OK;
+                       source = s2;
+                       DLIST_REMOVE(*oldlist, s2);
+                       break;
                }
        }
 
@@ -572,6 +575,7 @@ static WERROR dreplsrv_refresh_partition(struct dreplsrv_service *s,
                NULL
        };
        struct ldb_dn *dn;
+       struct dreplsrv_partition_source_dsa *src, *oldsources, *oldnotifies;
 
        DEBUG(4, ("dreplsrv_refresh_partition(%s)\n",
                ldb_dn_get_linearized(p->dn)));
@@ -613,22 +617,72 @@ static WERROR dreplsrv_refresh_partition(struct dreplsrv_service *s,
 
        status = WERR_OK;
 
+       oldsources = p->sources;
+       p->sources = NULL;
        if (r != NULL && (orf_el = ldb_msg_find_element(r->msgs[0], "repsFrom"))) {
                for (i=0; i < orf_el->num_values; i++) {
                        status = dreplsrv_partition_add_source_dsa(s, p, &p->sources,
-                                                                  NULL, &orf_el->values[i]);
+                                                                  NULL, &oldsources,
+                                                                  &orf_el->values[i]);
                        W_ERROR_NOT_OK_GOTO_DONE(status);
                }
+       } else {
+               if (r != NULL && p->sources) {
+                       DEBUG(0, ("repsFrom do not exists or is empty\n"));
+               }
        }
 
+       oldnotifies = p->notifies;
+       p->notifies = NULL;
        if (r != NULL && (orf_el = ldb_msg_find_element(r->msgs[0], "repsTo"))) {
                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]);
+                                                                  p->sources,
+                                                                  &oldnotifies,
+                                                                  &orf_el->values[i]);
                        W_ERROR_NOT_OK_GOTO_DONE(status);
                }
        }
 
+       if (oldsources) {
+               src = oldsources;
+               while(src) {
+                       struct dreplsrv_partition_source_dsa *tmp = src->next;
+
+                       /*
+                        * Keep sources that are still in use or we can
+                        * face some strange behavior
+                        */
+
+                       if (src->used > 0) {
+                               DLIST_ADD(p->sources, src);
+                       } else {
+                               talloc_free(src);
+                       }
+                       src = tmp;
+               }
+       }
+
+
+       if (oldnotifies) {
+               src = oldnotifies;
+               while(src) {
+                       struct dreplsrv_partition_source_dsa *tmp = src->next;
+
+                       /*
+                        * Keep sources that are still in use or we can
+                        * face some strange behavior
+                        */
+
+                       if (src->used > 0) {
+                               DLIST_ADD(p->sources, src);
+                       } else {
+                               talloc_free(src);
+                       }
+                       src = tmp;
+               }
+       }
+
 done:
        talloc_free(mem_ctx);
        return status;
index edba4c4a49b5c47b9fb124d6fe67b4603e495142..232f86e8a2e6877b378cb074a77cfcfdc1b6cebb 100644 (file)
@@ -75,6 +75,9 @@ struct dreplsrv_partition_source_dsa {
        
        /* the reference to the source_dsa and its outgoing connection */
        struct dreplsrv_out_connection *conn;
+
+       /* Number of call using this source */
+       uint32_t used;
 };
 
 struct dreplsrv_partition {