replace: Fix checking for config.h #define in gssapi.h
[Samba.git] / ctdb / server / ipalloc_nondeterministic.c
blob534ac5b9ee7420d55f34763419c6fb44f7c0300e
1 /*
2 ctdb ip takeover code
4 Copyright (C) Ronnie Sahlberg 2007
5 Copyright (C) Andrew Tridgell 2007
6 Copyright (C) Martin Schwenke 2011
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.
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.
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/>.
22 #include "replace.h"
23 #include "system/network.h"
25 #include "ctdb_private.h"
27 #include "lib/util/debug.h"
28 #include "common/logging.h"
29 #include "common/common.h"
31 #include "protocol/protocol_util.h"
33 #include "server/ipalloc_private.h"
35 /* Basic non-deterministic rebalancing algorithm.
37 static void basic_failback(struct ipalloc_state *ipalloc_state,
38 int num_ips)
40 int i, numnodes;
41 int maxnode, maxnum, minnode, minnum, num, retries;
42 struct public_ip_list *t;
44 numnodes = ipalloc_state->num;
45 retries = 0;
47 try_again:
48 maxnum=0;
49 minnum=0;
51 /* for each ip address, loop over all nodes that can serve
52 this ip and make sure that the difference between the node
53 serving the most and the node serving the least ip's are
54 not greater than 1.
56 for (t = ipalloc_state->all_ips; t != NULL; t = t->next) {
57 if (t->pnn == -1) {
58 continue;
61 /* Get the highest and lowest number of ips's served by any
62 valid node which can serve this ip.
64 maxnode = -1;
65 minnode = -1;
66 for (i=0; i<numnodes; i++) {
67 /* only check nodes that can actually serve this ip */
68 if (!can_node_takeover_ip(ipalloc_state, i,
69 t)) {
70 /* no it couldnt so skip to the next node */
71 continue;
74 num = node_ip_coverage(i, ipalloc_state->all_ips);
75 if (maxnode == -1) {
76 maxnode = i;
77 maxnum = num;
78 } else {
79 if (num > maxnum) {
80 maxnode = i;
81 maxnum = num;
84 if (minnode == -1) {
85 minnode = i;
86 minnum = num;
87 } else {
88 if (num < minnum) {
89 minnode = i;
90 minnum = num;
94 if (maxnode == -1) {
95 DEBUG(DEBUG_WARNING,
96 (__location__ " Could not find maxnode. May not be able to serve ip '%s'\n",
97 ctdb_sock_addr_to_string(ipalloc_state,
98 &t->addr, false)));
100 continue;
103 /* if the spread between the smallest and largest coverage by
104 a node is >=2 we steal one of the ips from the node with
105 most coverage to even things out a bit.
106 try to do this a limited number of times since we dont
107 want to spend too much time balancing the ip coverage.
109 if ((maxnum > minnum+1) &&
110 (retries < (num_ips + 5))){
111 struct public_ip_list *tt;
113 /* Reassign one of maxnode's VNNs */
114 for (tt = ipalloc_state->all_ips; tt != NULL; tt = tt->next) {
115 if (tt->pnn == maxnode) {
116 (void)find_takeover_node(ipalloc_state,
117 tt);
118 retries++;
119 goto try_again;;
126 bool ipalloc_nondeterministic(struct ipalloc_state *ipalloc_state)
128 /* This should be pushed down into basic_failback. */
129 struct public_ip_list *t;
130 int num_ips = 0;
131 for (t = ipalloc_state->all_ips; t != NULL; t = t->next) {
132 num_ips++;
135 unassign_unsuitable_ips(ipalloc_state);
137 basic_allocate_unassigned(ipalloc_state);
139 /* If we don't want IPs to fail back then don't rebalance IPs. */
140 if (ipalloc_state->no_ip_failback) {
141 return true;
144 /* Now, try to make sure the ip adresses are evenly distributed
145 across the nodes.
147 basic_failback(ipalloc_state, num_ips);
149 return true;