1/* 2 Unix SMB/CIFS mplementation. 3 DSDB replication service periodic handling 4 5 Copyright (C) Stefan Metzmacher 2007 6 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. 11 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. 16 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/>. 19 20*/ 21 22#include "includes.h" 23#include "lib/events/events.h" 24#include "dsdb/samdb/samdb.h" 25#include "auth/auth.h" 26#include "smbd/service.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 35static void dreplsrv_periodic_run(struct dreplsrv_service *service); 36 37static void dreplsrv_periodic_handler_te(struct tevent_context *ev, struct tevent_timer *te, 38 struct timeval t, void *ptr) 39{ 40 struct dreplsrv_service *service = talloc_get_type(ptr, struct dreplsrv_service); 41 WERROR status; 42 43 service->periodic.te = NULL; 44 45 dreplsrv_periodic_run(service); 46 47 status = dreplsrv_periodic_schedule(service, service->periodic.interval); 48 if (!W_ERROR_IS_OK(status)) { 49 task_server_terminate(service->task, win_errstr(status), false); 50 return; 51 } 52} 53 54WERROR dreplsrv_periodic_schedule(struct dreplsrv_service *service, uint32_t next_interval) 55{ 56 TALLOC_CTX *tmp_mem; 57 struct tevent_timer *new_te; 58 struct timeval next_time; 59 60 /* prevent looping */ 61 if (next_interval == 0) next_interval = 1; 62 63 next_time = timeval_current_ofs(next_interval, 50); 64 65 if (service->periodic.te) { 66 /* 67 * if the timestamp of the new event is higher, 68 * as current next we don't need to reschedule 69 */ 70 if (timeval_compare(&next_time, &service->periodic.next_event) > 0) { 71 return WERR_OK; 72 } 73 } 74 75 /* reset the next scheduled timestamp */ 76 service->periodic.next_event = next_time; 77 78 new_te = event_add_timed(service->task->event_ctx, service, 79 service->periodic.next_event, 80 dreplsrv_periodic_handler_te, service); 81 W_ERROR_HAVE_NO_MEMORY(new_te); 82 83 tmp_mem = talloc_new(service); 84 DEBUG(2,("dreplsrv_periodic_schedule(%u) %sscheduled for: %s\n", 85 next_interval, 86 (service->periodic.te?"re":""), 87 nt_time_string(tmp_mem, timeval_to_nttime(&next_time)))); 88 talloc_free(tmp_mem); 89 90 talloc_free(service->periodic.te); 91 service->periodic.te = new_te; 92 93 return WERR_OK; 94} 95 96static void dreplsrv_periodic_run(struct dreplsrv_service *service) 97{ 98 TALLOC_CTX *mem_ctx; 99 100 DEBUG(2,("dreplsrv_periodic_run(): schedule pull replication\n")); 101 102 mem_ctx = talloc_new(service); 103 dreplsrv_schedule_pull_replication(service, mem_ctx); 104 talloc_free(mem_ctx); 105 106 DEBUG(2,("dreplsrv_periodic_run(): run pending_ops memory=%u\n", 107 (unsigned)talloc_total_blocks(service))); 108 109 /* the KCC might have changed repsFrom */ 110 dreplsrv_refresh_partitions(service); 111 112 dreplsrv_run_pending_ops(service); 113 dreplsrv_notify_run_ops(service); 114} 115