Line data Source code
1 : /* 2 : Unix SMB/CIFS Implementation. 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 "samba/service.h" 27 : #include "dsdb/repl/drepl_service.h" 28 : #include <ldb_errors.h> 29 : #include "../lib/util/dlinklist.h" 30 : #include "librpc/gen_ndr/ndr_misc.h" 31 : #include "librpc/gen_ndr/ndr_drsuapi.h" 32 : #include "librpc/gen_ndr/ndr_drsblobs.h" 33 : 34 : #undef DBGC_CLASS 35 : #define DBGC_CLASS DBGC_DRS_REPL 36 : 37 : static void dreplsrv_periodic_run(struct dreplsrv_service *service); 38 : 39 206 : static void dreplsrv_periodic_handler_te(struct tevent_context *ev, struct tevent_timer *te, 40 : struct timeval t, void *ptr) 41 : { 42 206 : struct dreplsrv_service *service = talloc_get_type(ptr, struct dreplsrv_service); 43 2 : WERROR status; 44 : 45 206 : service->periodic.te = NULL; 46 : 47 206 : dreplsrv_periodic_run(service); 48 : 49 206 : status = dreplsrv_periodic_schedule(service, service->periodic.interval); 50 206 : if (!W_ERROR_IS_OK(status)) { 51 0 : task_server_terminate(service->task, win_errstr(status), false); 52 0 : return; 53 : } 54 : } 55 : 56 265 : WERROR dreplsrv_periodic_schedule(struct dreplsrv_service *service, uint32_t next_interval) 57 : { 58 4 : TALLOC_CTX *tmp_mem; 59 4 : struct tevent_timer *new_te; 60 4 : struct timeval next_time; 61 : 62 : /* prevent looping */ 63 265 : if (next_interval == 0) next_interval = 1; 64 : 65 265 : next_time = timeval_current_ofs(next_interval, 50); 66 : 67 265 : if (service->periodic.te) { 68 : /* 69 : * if the timestamp of the new event is higher, 70 : * as current next we don't need to reschedule 71 : */ 72 0 : if (timeval_compare(&next_time, &service->periodic.next_event) > 0) { 73 0 : return WERR_OK; 74 : } 75 : } 76 : 77 : /* reset the next scheduled timestamp */ 78 265 : service->periodic.next_event = next_time; 79 : 80 265 : new_te = tevent_add_timer(service->task->event_ctx, service, 81 : service->periodic.next_event, 82 : dreplsrv_periodic_handler_te, service); 83 265 : W_ERROR_HAVE_NO_MEMORY(new_te); 84 : 85 265 : tmp_mem = talloc_new(service); 86 265 : DEBUG(4,("dreplsrv_periodic_schedule(%u) %sscheduled for: %s\n", 87 : next_interval, 88 : (service->periodic.te?"re":""), 89 : nt_time_string(tmp_mem, timeval_to_nttime(&next_time)))); 90 265 : talloc_free(tmp_mem); 91 : 92 265 : talloc_free(service->periodic.te); 93 265 : service->periodic.te = new_te; 94 : 95 265 : return WERR_OK; 96 : } 97 : 98 206 : static void dreplsrv_periodic_run(struct dreplsrv_service *service) 99 : { 100 2 : TALLOC_CTX *mem_ctx; 101 : 102 206 : DEBUG(4,("dreplsrv_periodic_run(): schedule pull replication\n")); 103 : 104 : /* 105 : * KCC or some administrative tool 106 : * might have changed Topology graph 107 : * i.e. repsFrom/repsTo 108 : */ 109 206 : dreplsrv_refresh_partitions(service); 110 : 111 206 : mem_ctx = talloc_new(service); 112 206 : dreplsrv_schedule_pull_replication(service, mem_ctx); 113 206 : talloc_free(mem_ctx); 114 : 115 206 : DEBUG(4,("dreplsrv_periodic_run(): run pending_ops memory=%u\n", 116 : (unsigned)talloc_total_blocks(service))); 117 : 118 206 : dreplsrv_ridalloc_check_rid_pool(service); 119 : 120 206 : dreplsrv_run_pending_ops(service); 121 206 : } 122 : 123 : /* 124 : run the next pending op, either a notify or a pull 125 : */ 126 21804 : void dreplsrv_run_pending_ops(struct dreplsrv_service *s) 127 : { 128 21804 : if (!s->ops.notifies && !s->ops.pending) { 129 13584 : return; 130 : } 131 8130 : if (!s->ops.notifies || 132 5703 : (s->ops.pending && 133 307 : s->ops.notifies->schedule_time > s->ops.pending->schedule_time)) { 134 2470 : dreplsrv_run_pull_ops(s); 135 : } else { 136 5660 : dreplsrv_notify_run_ops(s); 137 : } 138 : } 139 : 140 2103 : static void dreplsrv_pending_pull_handler_im(struct tevent_context *ev, 141 : struct tevent_immediate *im, 142 : void *ptr) 143 : { 144 2103 : struct dreplsrv_service *service = talloc_get_type(ptr, struct dreplsrv_service); 145 : 146 2103 : dreplsrv_run_pull_ops(service); 147 2103 : } 148 : 149 2103 : void dreplsrv_pendingops_schedule_pull_now(struct dreplsrv_service *service) 150 : { 151 2103 : tevent_schedule_immediate(service->pending.im, service->task->event_ctx, 152 : dreplsrv_pending_pull_handler_im, 153 0 : service); 154 : 155 2103 : return; 156 : } 157 :