mirror of
https://github.com/samba-team/samba.git
synced 2024-12-27 03:21:53 +03:00
3593298c7e
Operation was scheduled already, so we need to call the callback function for it to be able to do its job. For instance, if we are blocking an rpc call until an operation is completed and there is no memory, then client will be blocked without knowing what is going on with the server.
182 lines
5.0 KiB
C
182 lines
5.0 KiB
C
/*
|
|
Unix SMB/CIFS mplementation.
|
|
DSDB replication service outgoing Pull-Replication
|
|
|
|
Copyright (C) Stefan Metzmacher 2007
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
#include "includes.h"
|
|
#include "dsdb/samdb/samdb.h"
|
|
#include "auth/auth.h"
|
|
#include "smbd/service.h"
|
|
#include "lib/events/events.h"
|
|
#include "lib/messaging/irpc.h"
|
|
#include "dsdb/repl/drepl_service.h"
|
|
#include "lib/ldb/include/ldb_errors.h"
|
|
#include "../lib/util/dlinklist.h"
|
|
#include "librpc/gen_ndr/ndr_misc.h"
|
|
#include "librpc/gen_ndr/ndr_drsuapi.h"
|
|
#include "librpc/gen_ndr/ndr_drsblobs.h"
|
|
#include "libcli/composite/composite.h"
|
|
#include "libcli/security/dom_sid.h"
|
|
|
|
WERROR dreplsrv_schedule_partition_pull_source(struct dreplsrv_service *s,
|
|
struct dreplsrv_partition_source_dsa *source,
|
|
enum drsuapi_DsExtendedOperation extended_op,
|
|
uint64_t fsmo_info,
|
|
dreplsrv_fsmo_callback_t callback,
|
|
void *cb_data)
|
|
{
|
|
struct dreplsrv_out_operation *op;
|
|
|
|
op = talloc_zero(s, struct dreplsrv_out_operation);
|
|
W_ERROR_HAVE_NO_MEMORY(op);
|
|
|
|
op->service = s;
|
|
op->source_dsa = source;
|
|
op->extended_op = extended_op;
|
|
op->fsmo_info = fsmo_info;
|
|
op->callback = callback;
|
|
op->cb_data = cb_data;
|
|
|
|
DLIST_ADD_END(s->ops.pending, op, struct dreplsrv_out_operation *);
|
|
|
|
return WERR_OK;
|
|
}
|
|
|
|
static WERROR dreplsrv_schedule_partition_pull(struct dreplsrv_service *s,
|
|
struct dreplsrv_partition *p,
|
|
TALLOC_CTX *mem_ctx)
|
|
{
|
|
WERROR status;
|
|
struct dreplsrv_partition_source_dsa *cur;
|
|
|
|
for (cur = p->sources; cur; cur = cur->next) {
|
|
status = dreplsrv_schedule_partition_pull_source(s, cur,
|
|
DRSUAPI_EXOP_NONE, 0,
|
|
NULL, NULL);
|
|
W_ERROR_NOT_OK_RETURN(status);
|
|
}
|
|
|
|
return WERR_OK;
|
|
}
|
|
|
|
WERROR dreplsrv_schedule_pull_replication(struct dreplsrv_service *s, TALLOC_CTX *mem_ctx)
|
|
{
|
|
WERROR status;
|
|
struct dreplsrv_partition *p;
|
|
|
|
for (p = s->partitions; p; p = p->next) {
|
|
status = dreplsrv_schedule_partition_pull(s, p, mem_ctx);
|
|
W_ERROR_NOT_OK_RETURN(status);
|
|
}
|
|
|
|
return WERR_OK;
|
|
}
|
|
|
|
|
|
static void dreplsrv_pending_op_callback(struct tevent_req *subreq)
|
|
{
|
|
struct dreplsrv_out_operation *op = tevent_req_callback_data(subreq,
|
|
struct dreplsrv_out_operation);
|
|
struct repsFromTo1 *rf = op->source_dsa->repsFrom1;
|
|
struct dreplsrv_service *s = op->service;
|
|
time_t t;
|
|
NTTIME now;
|
|
|
|
t = time(NULL);
|
|
unix_to_nt_time(&now, t);
|
|
|
|
rf->result_last_attempt = dreplsrv_op_pull_source_recv(subreq);
|
|
TALLOC_FREE(subreq);
|
|
if (W_ERROR_IS_OK(rf->result_last_attempt)) {
|
|
rf->consecutive_sync_failures = 0;
|
|
rf->last_success = now;
|
|
DEBUG(3,("dreplsrv_op_pull_source(%s)\n",
|
|
win_errstr(rf->result_last_attempt)));
|
|
goto done;
|
|
}
|
|
|
|
rf->consecutive_sync_failures++;
|
|
|
|
DEBUG(1,("dreplsrv_op_pull_source(%s/%s) for %s failures[%u]\n",
|
|
win_errstr(rf->result_last_attempt),
|
|
nt_errstr(werror_to_ntstatus(rf->result_last_attempt)),
|
|
ldb_dn_get_linearized(op->source_dsa->partition->dn),
|
|
rf->consecutive_sync_failures));
|
|
|
|
done:
|
|
if (op->callback) {
|
|
op->callback(s, rf->result_last_attempt, op->extended_ret, op->cb_data);
|
|
}
|
|
talloc_free(op);
|
|
s->ops.current = NULL;
|
|
dreplsrv_run_pending_ops(s);
|
|
dreplsrv_notify_run_ops(s);
|
|
}
|
|
|
|
void dreplsrv_run_pending_ops(struct dreplsrv_service *s)
|
|
{
|
|
struct dreplsrv_out_operation *op;
|
|
time_t t;
|
|
NTTIME now;
|
|
struct tevent_req *subreq;
|
|
|
|
if (s->ops.current || s->ops.n_current) {
|
|
/* if there's still one running, we're done */
|
|
return;
|
|
}
|
|
|
|
if (!s->ops.pending) {
|
|
/* if there're no pending operations, we're done */
|
|
return;
|
|
}
|
|
|
|
t = time(NULL);
|
|
unix_to_nt_time(&now, t);
|
|
|
|
op = s->ops.pending;
|
|
s->ops.current = op;
|
|
DLIST_REMOVE(s->ops.pending, op);
|
|
|
|
op->source_dsa->repsFrom1->last_attempt = now;
|
|
|
|
subreq = dreplsrv_op_pull_source_send(op, s->task->event_ctx, op);
|
|
if (!subreq) {
|
|
struct repsFromTo1 *rf = op->source_dsa->repsFrom1;
|
|
|
|
rf->result_last_attempt = WERR_NOMEM;
|
|
rf->consecutive_sync_failures++;
|
|
s->ops.current = NULL;
|
|
|
|
/*
|
|
* call the callback (if any) so it gets the chance
|
|
* to do its job just like in any other failure situation
|
|
*/
|
|
if (op->callback) {
|
|
op->callback(s, rf->result_last_attempt, op->extended_ret, op->cb_data);
|
|
}
|
|
|
|
DEBUG(1,("dreplsrv_op_pull_source(%s/%s) failures[%u]\n",
|
|
win_errstr(rf->result_last_attempt),
|
|
nt_errstr(werror_to_ntstatus(rf->result_last_attempt)),
|
|
rf->consecutive_sync_failures));
|
|
return;
|
|
}
|
|
tevent_req_set_callback(subreq, dreplsrv_pending_op_callback, op);
|
|
}
|