root/source4/wrepl_server/wrepl_out_push.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. wreplsrv_push_handler_creq
  2. wreplsrv_out_partner_push
  3. wreplsrv_calc_change_count
  4. wreplsrv_out_push_run

   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 #include "nbt_server/wins/winsdb.h"
  27 
  28 static void wreplsrv_out_partner_push(struct wreplsrv_partner *partner, bool propagate);
  29 
  30 static void wreplsrv_push_handler_creq(struct composite_context *creq)
     /* [<][>][^][v][top][bottom][index][help] */
  31 {
  32         struct wreplsrv_partner *partner = talloc_get_type(creq->async.private_data, struct wreplsrv_partner);
  33         struct wreplsrv_push_notify_io *old_notify_io;
  34 
  35         partner->push.last_status = wreplsrv_push_notify_recv(partner->push.creq);
  36         partner->push.creq = NULL;
  37 
  38         old_notify_io = partner->push.notify_io;
  39         partner->push.notify_io = NULL;
  40 
  41         if (NT_STATUS_IS_OK(partner->push.last_status)) {
  42                 partner->push.error_count = 0;
  43                 DEBUG(2,("wreplsrv_push_notify(%s): %s\n",
  44                          partner->address, nt_errstr(partner->push.last_status)));
  45                 goto done;
  46         }
  47 
  48         partner->push.error_count++;
  49 
  50         if (partner->push.error_count > 1) {
  51                 DEBUG(1,("wreplsrv_push_notify(%s): %s: error_count: %u: giving up\n",
  52                          partner->address, nt_errstr(partner->push.last_status),
  53                          partner->push.error_count));
  54                 goto done;
  55         }
  56 
  57         DEBUG(1,("wreplsrv_push_notify(%s): %s: error_count: %u: retry\n",
  58                  partner->address, nt_errstr(partner->push.last_status),
  59                  partner->push.error_count));
  60         wreplsrv_out_partner_push(partner, old_notify_io->in.propagate);
  61 done:
  62         talloc_free(old_notify_io);
  63 }
  64 
  65 static void wreplsrv_out_partner_push(struct wreplsrv_partner *partner, bool propagate)
     /* [<][>][^][v][top][bottom][index][help] */
  66 {
  67         /* a push for this partner is currently in progress, so we're done */
  68         if (partner->push.creq) return;
  69 
  70         /* now prepare the push notify */
  71         partner->push.notify_io = talloc(partner, struct wreplsrv_push_notify_io);
  72         if (!partner->push.notify_io) {
  73                 goto nomem;
  74         }
  75 
  76         partner->push.notify_io->in.partner     = partner;
  77         partner->push.notify_io->in.inform      = partner->push.use_inform;
  78         partner->push.notify_io->in.propagate   = propagate;
  79         partner->push.creq = wreplsrv_push_notify_send(partner->push.notify_io, partner->push.notify_io);
  80         if (!partner->push.creq) {
  81                 DEBUG(1,("wreplsrv_push_notify_send(%s) failed nomem?\n",
  82                          partner->address));
  83                 goto nomem;
  84         }
  85 
  86         partner->push.creq->async.fn            = wreplsrv_push_handler_creq;
  87         partner->push.creq->async.private_data  = partner;
  88 
  89         return;
  90 nomem:
  91         talloc_free(partner->push.notify_io);
  92         partner->push.notify_io = NULL;
  93         DEBUG(1,("wreplsrv_out_partner_push(%s,%u) failed nomem? (ignoring)\n",
  94                  partner->address, propagate));
  95         return;
  96 }
  97 
  98 static uint32_t wreplsrv_calc_change_count(struct wreplsrv_partner *partner, uint64_t maxVersionID)
     /* [<][>][^][v][top][bottom][index][help] */
  99 {
 100         uint64_t tmp_diff = UINT32_MAX;
 101 
 102         /* catch an overflow */
 103         if (partner->push.maxVersionID > maxVersionID) {
 104                 goto done;
 105         }
 106 
 107         tmp_diff = maxVersionID - partner->push.maxVersionID;
 108 
 109         if (tmp_diff > UINT32_MAX) {
 110                 tmp_diff = UINT32_MAX;
 111                 goto done;
 112         }
 113 
 114 done:
 115         partner->push.maxVersionID = maxVersionID;
 116         return (uint32_t)(tmp_diff & UINT32_MAX);
 117 }
 118 
 119 NTSTATUS wreplsrv_out_push_run(struct wreplsrv_service *service)
     /* [<][>][^][v][top][bottom][index][help] */
 120 {
 121         struct wreplsrv_partner *partner;
 122         uint64_t seqnumber;
 123         uint32_t change_count;
 124 
 125         seqnumber = winsdb_get_maxVersion(service->wins_db);
 126 
 127         for (partner = service->partners; partner; partner = partner->next) {
 128                 /* if it's not a push partner, go to the next partner */
 129                 if (!(partner->type & WINSREPL_PARTNER_PUSH)) continue;
 130 
 131                 /* if push notifies are disabled for this partner, go to the next partner */
 132                 if (partner->push.change_count == 0) continue;
 133 
 134                 /* get the actual change count for the partner */
 135                 change_count = wreplsrv_calc_change_count(partner, seqnumber);
 136 
 137                 /* if the configured change count isn't reached, go to the next partner */
 138                 if (change_count < partner->push.change_count) continue;
 139 
 140                 wreplsrv_out_partner_push(partner, false);
 141         }
 142 
 143         return NT_STATUS_OK;
 144 }

/* [<][>][^][v][top][bottom][index][help] */