2 Unix SMB/CIFS mplementation.
3 DSDB replication service outgoing Pull-Replication
5 Copyright (C) Stefan Metzmacher 2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "dsdb/samdb/samdb.h"
24 #include "auth/auth.h"
25 #include "smbd/service.h"
26 #include "lib/events/events.h"
27 #include "lib/messaging/irpc.h"
28 #include "dsdb/repl/drepl_service.h"
29 #include "lib/ldb/include/ldb_errors.h"
30 #include "../lib/util/dlinklist.h"
31 #include "librpc/gen_ndr/ndr_misc.h"
32 #include "librpc/gen_ndr/ndr_drsuapi.h"
33 #include "librpc/gen_ndr/ndr_drsblobs.h"
34 #include "libcli/composite/composite.h"
36 WERROR
dreplsrv_schedule_partition_pull_source(struct dreplsrv_service
*s
,
37 struct dreplsrv_partition_source_dsa
*source
,
38 enum drsuapi_DsExtendedOperation extended_op
,
40 dreplsrv_fsmo_callback_t callback
)
42 struct dreplsrv_out_operation
*op
;
44 op
= talloc_zero(s
, struct dreplsrv_out_operation
);
45 W_ERROR_HAVE_NO_MEMORY(op
);
48 op
->source_dsa
= source
;
49 op
->extended_op
= extended_op
;
50 op
->fsmo_info
= fsmo_info
;
51 op
->callback
= callback
;
53 DLIST_ADD_END(s
->ops
.pending
, op
, struct dreplsrv_out_operation
*);
58 static WERROR
dreplsrv_schedule_partition_pull(struct dreplsrv_service
*s
,
59 struct dreplsrv_partition
*p
,
63 struct dreplsrv_partition_source_dsa
*cur
;
65 for (cur
= p
->sources
; cur
; cur
= cur
->next
) {
66 status
= dreplsrv_schedule_partition_pull_source(s
, cur
, DRSUAPI_EXOP_NONE
, 0, NULL
);
67 W_ERROR_NOT_OK_RETURN(status
);
73 WERROR
dreplsrv_schedule_pull_replication(struct dreplsrv_service
*s
, TALLOC_CTX
*mem_ctx
)
76 struct dreplsrv_partition
*p
;
78 for (p
= s
->partitions
; p
; p
= p
->next
) {
79 status
= dreplsrv_schedule_partition_pull(s
, p
, mem_ctx
);
80 W_ERROR_NOT_OK_RETURN(status
);
87 /* force an immediate of the specified partition by GUID */
88 WERROR
dreplsrv_schedule_partition_pull_by_guid(struct dreplsrv_service
*s
, TALLOC_CTX
*mem_ctx
,
91 struct dreplsrv_partition
*p
;
93 for (p
= s
->partitions
; p
; p
= p
->next
) {
94 if (GUID_compare(&p
->nc
.guid
, guid
) == 0) {
95 return dreplsrv_schedule_partition_pull(s
, p
, mem_ctx
);
99 return WERR_NOT_FOUND
;
102 static void dreplsrv_pending_op_callback(struct tevent_req
*subreq
)
104 struct dreplsrv_out_operation
*op
= tevent_req_callback_data(subreq
,
105 struct dreplsrv_out_operation
);
106 struct repsFromTo1
*rf
= op
->source_dsa
->repsFrom1
;
107 struct dreplsrv_service
*s
= op
->service
;
112 unix_to_nt_time(&now
, t
);
114 rf
->result_last_attempt
= dreplsrv_op_pull_source_recv(subreq
);
116 if (W_ERROR_IS_OK(rf
->result_last_attempt
)) {
117 rf
->consecutive_sync_failures
= 0;
118 rf
->last_success
= now
;
119 DEBUG(3,("dreplsrv_op_pull_source(%s)\n",
120 win_errstr(rf
->result_last_attempt
)));
124 rf
->consecutive_sync_failures
++;
126 DEBUG(1,("dreplsrv_op_pull_source(%s/%s) for %s failures[%u]\n",
127 win_errstr(rf
->result_last_attempt
),
128 win_errstr(rf
->result_last_attempt
),
129 ldb_dn_get_linearized(op
->source_dsa
->partition
->dn
),
130 rf
->consecutive_sync_failures
));
134 op
->callback(s
, rf
->result_last_attempt
);
137 s
->ops
.current
= NULL
;
138 dreplsrv_run_pending_ops(s
);
139 dreplsrv_notify_run_ops(s
);
142 void dreplsrv_run_pending_ops(struct dreplsrv_service
*s
)
144 struct dreplsrv_out_operation
*op
;
147 struct tevent_req
*subreq
;
149 if (s
->ops
.current
|| s
->ops
.n_current
) {
150 /* if there's still one running, we're done */
154 if (!s
->ops
.pending
) {
155 /* if there're no pending operations, we're done */
160 unix_to_nt_time(&now
, t
);
164 DLIST_REMOVE(s
->ops
.pending
, op
);
166 op
->source_dsa
->repsFrom1
->last_attempt
= now
;
168 subreq
= dreplsrv_op_pull_source_send(op
, s
->task
->event_ctx
, op
);
170 struct repsFromTo1
*rf
= op
->source_dsa
->repsFrom1
;
172 rf
->result_last_attempt
= WERR_NOMEM
;
173 rf
->consecutive_sync_failures
++;
174 s
->ops
.current
= NULL
;
176 DEBUG(1,("dreplsrv_op_pull_source(%s/%s) failures[%u]\n",
177 win_errstr(rf
->result_last_attempt
),
178 nt_errstr(werror_to_ntstatus(rf
->result_last_attempt
)),
179 rf
->consecutive_sync_failures
));
182 tevent_req_set_callback(subreq
, dreplsrv_pending_op_callback
, op
);