Line data Source code
1 : /* 2 : Unix SMB/CIFS implementation. 3 : 4 : WINS Replication server 5 : 6 : Copyright (C) Stefan Metzmacher 2005 7 : 8 : This program is free software; you can redistribute it and/or modify 9 : it under the terms of the GNU General Public License as published by 10 : the Free Software Foundation; either version 3 of the License, or 11 : (at your option) any later version. 12 : 13 : This program is distributed in the hope that it will be useful, 14 : but WITHOUT ANY WARRANTY; without even the implied warranty of 15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 : GNU General Public License for more details. 17 : 18 : You should have received a copy of the GNU General Public License 19 : along with this program. If not, see <http://www.gnu.org/licenses/>. 20 : */ 21 : 22 : #include "includes.h" 23 : #include "librpc/gen_ndr/winsrepl.h" 24 : #include "wrepl_server/wrepl_server.h" 25 : #include "libcli/composite/composite.h" 26 : 27 0 : static void wreplsrv_out_pull_reschedule(struct wreplsrv_partner *partner, uint32_t interval) 28 : { 29 0 : NTSTATUS status; 30 : 31 0 : partner->pull.next_run = timeval_current_ofs(interval, 0); 32 0 : status = wreplsrv_periodic_schedule(partner->service, interval); 33 0 : if (!NT_STATUS_IS_OK(status)) { 34 0 : DEBUG(0,("wreplsrv_periodic_schedule() failed\n")); 35 : } 36 0 : } 37 : 38 0 : static void wreplsrv_pull_handler_creq(struct composite_context *creq) 39 : { 40 0 : struct wreplsrv_partner *partner = talloc_get_type(creq->async.private_data, struct wreplsrv_partner); 41 0 : struct wreplsrv_pull_cycle_io *old_cycle_io; 42 0 : struct wrepl_table inform_in; 43 : 44 0 : partner->pull.last_status = wreplsrv_pull_cycle_recv(partner->pull.creq); 45 0 : partner->pull.creq = NULL; 46 : 47 0 : old_cycle_io = partner->pull.cycle_io; 48 0 : partner->pull.cycle_io = NULL; 49 : 50 0 : if (NT_STATUS_IS_OK(partner->pull.last_status)) { 51 0 : partner->pull.error_count = 0; 52 0 : DEBUG(1,("wreplsrv_pull_cycle(%s): %s\n", 53 : partner->address, nt_errstr(partner->pull.last_status))); 54 0 : goto done; 55 : } 56 : 57 0 : partner->pull.error_count++; 58 : 59 0 : if (partner->pull.error_count > 1) { 60 0 : uint32_t retry_interval; 61 : 62 0 : retry_interval = partner->pull.error_count * partner->pull.retry_interval; 63 0 : retry_interval = MIN(retry_interval, partner->pull.interval); 64 : 65 0 : DEBUG(0,("wreplsrv_pull_cycle(%s): %s: error_count: %u: reschedule(%u)\n", 66 : partner->address, nt_errstr(partner->pull.last_status), 67 : partner->pull.error_count, retry_interval)); 68 : 69 0 : wreplsrv_out_pull_reschedule(partner, retry_interval); 70 0 : goto done; 71 : } 72 : 73 0 : DEBUG(0,("wreplsrv_pull_cycle(%s): %s: error_count:%u retry\n", 74 : partner->address, nt_errstr(partner->pull.last_status), 75 : partner->pull.error_count)); 76 0 : inform_in.partner_count = old_cycle_io->in.num_owners; 77 0 : inform_in.partners = old_cycle_io->in.owners; 78 0 : wreplsrv_out_partner_pull(partner, &inform_in); 79 0 : done: 80 0 : talloc_free(old_cycle_io); 81 0 : } 82 : 83 0 : void wreplsrv_out_partner_pull(struct wreplsrv_partner *partner, struct wrepl_table *inform_in) 84 : { 85 : /* there's already a pull in progress, so we're done */ 86 0 : if (partner->pull.creq) return; 87 : 88 0 : partner->pull.cycle_io = talloc(partner, struct wreplsrv_pull_cycle_io); 89 0 : if (!partner->pull.cycle_io) { 90 0 : goto nomem; 91 : } 92 : 93 0 : partner->pull.cycle_io->in.partner = partner; 94 0 : partner->pull.cycle_io->in.wreplconn = NULL; 95 0 : if (inform_in) { 96 0 : partner->pull.cycle_io->in.num_owners = inform_in->partner_count; 97 0 : partner->pull.cycle_io->in.owners = inform_in->partners; 98 0 : talloc_steal(partner->pull.cycle_io, inform_in->partners); 99 : } else { 100 0 : partner->pull.cycle_io->in.num_owners = 0; 101 0 : partner->pull.cycle_io->in.owners = NULL; 102 : } 103 0 : partner->pull.creq = wreplsrv_pull_cycle_send(partner->pull.cycle_io, partner->pull.cycle_io); 104 0 : if (!partner->pull.creq) { 105 0 : DEBUG(1,("wreplsrv_pull_cycle_send(%s) failed\n", 106 : partner->address)); 107 0 : goto nomem; 108 : } 109 : 110 0 : partner->pull.creq->async.fn = wreplsrv_pull_handler_creq; 111 0 : partner->pull.creq->async.private_data = partner; 112 : 113 0 : return; 114 0 : nomem: 115 0 : talloc_free(partner->pull.cycle_io); 116 0 : partner->pull.cycle_io = NULL; 117 0 : DEBUG(0,("wreplsrv_out_partner_pull(%s): no memory? (ignoring)\n", 118 : partner->address)); 119 0 : return; 120 : } 121 : 122 3626 : NTSTATUS wreplsrv_out_pull_run(struct wreplsrv_service *service) 123 : { 124 31 : struct wreplsrv_partner *partner; 125 : 126 6736 : for (partner = service->partners; partner; partner = partner->next) { 127 : /* if it's not a pull partner, go to the next partner */ 128 3110 : if (!(partner->type & WINSREPL_PARTNER_PULL)) continue; 129 : 130 : /* if pulling is disabled for the partner, go to the next one */ 131 3110 : if (partner->pull.interval == 0) continue; 132 : 133 : /* if the next timer isn't reached, go to the next partner */ 134 0 : if (!timeval_expired(&partner->pull.next_run)) continue; 135 : 136 0 : wreplsrv_out_pull_reschedule(partner, partner->pull.interval); 137 : 138 0 : wreplsrv_out_partner_pull(partner, NULL); 139 : } 140 : 141 3626 : return NT_STATUS_OK; 142 : }