ctdb-ipalloc: Drop implicit dependency on ctdb-common
[sharpe/samba-autobuild/.git] / ctdb / server / ipalloc_nondeterministic.c
1 /*
2    ctdb ip takeover code
3
4    Copyright (C) Ronnie Sahlberg  2007
5    Copyright (C) Andrew Tridgell  2007
6    Copyright (C) Martin Schwenke  2011
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 "replace.h"
23 #include "system/network.h"
24
25 #include "ctdb_private.h"
26
27 #include "lib/util/debug.h"
28 #include "common/logging.h"
29 #include "common/common.h"
30
31 #include "protocol/protocol_api.h"
32
33 #include "server/ipalloc_private.h"
34
35 /* Basic non-deterministic rebalancing algorithm.
36  */
37 static void basic_failback(struct ipalloc_state *ipalloc_state,
38                            int num_ips)
39 {
40         int i, numnodes;
41         int maxnode, maxnum, minnode, minnum, num, retries;
42         struct public_ip_list *t;
43
44         numnodes = ipalloc_state->num;
45         retries = 0;
46
47 try_again:
48         maxnum=0;
49         minnum=0;
50
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.
55         */
56         for (t = ipalloc_state->all_ips; t != NULL; t = t->next) {
57                 if (t->pnn == -1) {
58                         continue;
59                 }
60
61                 /* Get the highest and lowest number of ips's served by any 
62                    valid node which can serve this ip.
63                 */
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;
72                         }
73
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;
82                                 }
83                         }
84                         if (minnode == -1) {
85                                 minnode = i;
86                                 minnum  = num;
87                         } else {
88                                 if (num < minnum) {
89                                         minnode = i;
90                                         minnum  = num;
91                                 }
92                         }
93                 }
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)));
99
100                         continue;
101                 }
102
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.
108                 */
109                 if ((maxnum > minnum+1) &&
110                     (retries < (num_ips + 5))){
111                         struct public_ip_list *tt;
112
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;;
120                                 }
121                         }
122                 }
123         }
124 }
125
126 bool ipalloc_nondeterministic(struct ipalloc_state *ipalloc_state)
127 {
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++;
133         }
134
135         unassign_unsuitable_ips(ipalloc_state);
136
137         basic_allocate_unassigned(ipalloc_state);
138
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;
142         }
143
144         /* Now, try to make sure the ip adresses are evenly distributed
145            across the nodes.
146         */
147         basic_failback(ipalloc_state, num_ips);
148
149         return true;
150 }