ctdb-ipalloc: Move IP allocation state into its own struct
authorMartin Schwenke <martin@meltin.net>
Thu, 29 Oct 2015 05:49:44 +0000 (16:49 +1100)
committerAmitay Isaacs <amitay@samba.org>
Fri, 20 Nov 2015 00:36:31 +0000 (01:36 +0100)
Most of the IP allocation code does not need a CTDB context.  However,
temporarily hang this off the CTDB context and make only the changes
relating to known/available IP address.  This makes those logic
changes obvious without burying them in function type changes.

Signed-off-by: Martin Schwenke <martin@meltin.net>
Reviewed-by: Amitay Isaacs <amitay@gmail.com>
ctdb/include/ctdb_private.h
ctdb/server/ctdb_takeover.c
ctdb/tests/src/ctdb_takeover_tests.c

index 57a13d946163311af6286ee2eaf722a8998b2524..7bda626894cb1911bf09610172a04bc811cb4261 100644 (file)
@@ -126,12 +126,6 @@ struct ctdb_node {
           if the node becomes disconnected */
        struct daemon_control_state *pending_controls;
 
-       /* used by the recovery daemon when distributing ip addresses 
-          across the nodes.  it needs to know which public ip's can be handled
-          by each node.
-       */
-       struct ctdb_public_ip_list_old *known_public_ips;
-       struct ctdb_public_ip_list_old *available_public_ips;
        /* used by the recovery dameon to track when a node should be banned */
        struct ctdb_banning_state *ban_state; 
 };
@@ -373,6 +367,10 @@ struct ctdb_context {
        /* mapping from pid to ctdb_client * */
        struct ctdb_client_pid_list *client_pids;
 
+       /* Temporarily used by IP takeover code to make changes easier
+        * to review */
+       struct ipalloc_state *ipalloc_state;
+
        /* used in the recovery daemon to remember the ip allocation */
        struct trbt_tree *ip_tree;
 
index c84e3cacee0b884b4e35bc900e313112080cdcd1..1e30daf82b6b7daa5001de71edf753a99c42f78a 100644 (file)
@@ -53,6 +53,14 @@ struct ctdb_ipflags {
        bool noiphost;
 };
 
+struct ipalloc_state {
+       uint32_t num;
+
+       /* Arrays with data for each node */
+       struct ctdb_public_ip_list_old **known_public_ips;
+       struct ctdb_public_ip_list_old **available_public_ips;
+};
+
 struct ctdb_interface {
        struct ctdb_interface *prev, *next;
        const char *name;
@@ -1269,7 +1277,7 @@ static bool can_node_host_ip(struct ctdb_context *ctdb, int32_t pnn,
                return false;
        }
 
-       public_ips = ctdb->nodes[pnn]->available_public_ips;
+       public_ips = ctdb->ipalloc_state->available_public_ips[pnn];
 
        if (public_ips == NULL) {
                return false;
@@ -1397,25 +1405,21 @@ static int verify_remote_ip_allocation(struct ctdb_context *ctdb,
                                       uint32_t pnn);
 
 static int ctdb_reload_remote_public_ips(struct ctdb_context *ctdb,
+                                        struct ipalloc_state *ipalloc_state,
                                         struct ctdb_node_map_old *nodemap)
 {
        int j;
        int ret;
 
-       if (ctdb->num_nodes != nodemap->num) {
-               DEBUG(DEBUG_ERR, (__location__ " ctdb->num_nodes (%d) != nodemap->num (%d) invalid param\n",
-                                 ctdb->num_nodes, nodemap->num));
+       if (ipalloc_state->num != nodemap->num) {
+               DEBUG(DEBUG_ERR,
+                     (__location__
+                      " ipalloc_state->num (%d) != nodemap->num (%d) invalid param\n",
+                      ipalloc_state->num, nodemap->num));
                return -1;
        }
 
        for (j=0; j<nodemap->num; j++) {
-               /* For readability */
-               struct ctdb_node *node = ctdb->nodes[j];
-
-               /* release any existing data */
-               TALLOC_FREE(node->known_public_ips);
-               TALLOC_FREE(node->available_public_ips);
-
                if (nodemap->nodes[j].flags & NODE_FLAGS_INACTIVE) {
                        continue;
                }
@@ -1423,34 +1427,34 @@ static int ctdb_reload_remote_public_ips(struct ctdb_context *ctdb,
                /* Retrieve the list of known public IPs from the node */
                ret = ctdb_ctrl_get_public_ips_flags(ctdb,
                                        TAKEOVER_TIMEOUT(),
-                                       node->pnn,
+                                       j,
                                        ctdb->nodes,
                                        0,
-                                       &node->known_public_ips);
+                                       &ipalloc_state->known_public_ips[j]);
                if (ret != 0) {
                        DEBUG(DEBUG_ERR,
                              ("Failed to read known public IPs from node: %u\n",
-                              node->pnn));
+                              j));
                        return -1;
                }
 
                if (ctdb->do_checkpublicip) {
                        verify_remote_ip_allocation(ctdb,
-                                                   node->known_public_ips,
-                                                   node->pnn);
+                                                   ipalloc_state->known_public_ips[j],
+                                                   j);
                }
 
                /* Retrieve the list of available public IPs from the node */
                ret = ctdb_ctrl_get_public_ips_flags(ctdb,
                                        TAKEOVER_TIMEOUT(),
-                                       node->pnn,
+                                       j,
                                        ctdb->nodes,
                                        CTDB_PUBLIC_IP_FLAGS_ONLY_AVAILABLE,
-                                       &node->available_public_ips);
+                                       &ipalloc_state->available_public_ips[j]);
                if (ret != 0) {
                        DEBUG(DEBUG_ERR,
                              ("Failed to read available public IPs from node: %u\n",
-                              node->pnn));
+                              j));
                        return -1;
                }
        }
@@ -1472,7 +1476,7 @@ create_merged_ip_list(struct ctdb_context *ctdb)
        ctdb->ip_tree = trbt_create(ctdb, 0);
 
        for (i=0;i<ctdb->num_nodes;i++) {
-               public_ips = ctdb->nodes[i]->known_public_ips;
+               public_ips = ctdb->ipalloc_state->known_public_ips[i];
 
                if (ctdb->nodes[i]->flags & NODE_FLAGS_DELETED) {
                        continue;
@@ -2428,6 +2432,39 @@ static struct ctdb_ipflags *set_ipflags(struct ctdb_context *ctdb,
        return ipflags;
 }
 
+static struct ipalloc_state * ipalloc_state_init(struct ctdb_context *ctdb,
+                                                TALLOC_CTX *mem_ctx)
+{
+       struct ipalloc_state *ipalloc_state =
+               talloc_zero(mem_ctx, struct ipalloc_state);
+       if (ipalloc_state == NULL) {
+               DEBUG(DEBUG_ERR, (__location__ " Out of memory\n"));
+               return NULL;
+       }
+
+       ipalloc_state->num = ctdb->num_nodes;
+       ipalloc_state->known_public_ips =
+               talloc_zero_array(ipalloc_state,
+                                 struct ctdb_public_ip_list_old *,
+                                 ipalloc_state->num);
+       if (ipalloc_state->known_public_ips == NULL) {
+               DEBUG(DEBUG_ERR, (__location__ " Out of memory\n"));
+               talloc_free(ipalloc_state);
+               return NULL;
+       }
+       ipalloc_state->available_public_ips =
+               talloc_zero_array(ipalloc_state,
+                                 struct ctdb_public_ip_list_old *,
+                                 ipalloc_state->num);
+       if (ipalloc_state->available_public_ips == NULL) {
+               DEBUG(DEBUG_ERR, (__location__ " Out of memory\n"));
+               talloc_free(ipalloc_state);
+               return NULL;
+       }
+
+       return ipalloc_state;
+}
+
 struct iprealloc_callback_data {
        bool *retry_nodes;
        int retry_count;
@@ -2541,6 +2578,7 @@ int ctdb_takeover_run(struct ctdb_context *ctdb, struct ctdb_node_map_old *nodem
        struct ctdb_client_control_state *state;
        TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
        struct ctdb_ipflags *ipflags;
+       struct ipalloc_state *ipalloc_state;
        struct takeover_callback_data *takeover_data;
        struct iprealloc_callback_data iprealloc_data;
        bool *retry_data;
@@ -2554,6 +2592,13 @@ int ctdb_takeover_run(struct ctdb_context *ctdb, struct ctdb_node_map_old *nodem
                goto ipreallocated;
        }
 
+       ipalloc_state = ipalloc_state_init(ctdb, tmp_ctx);
+       if (ipalloc_state == NULL) {
+               talloc_free(tmp_ctx);
+               return -1;
+       }
+       ctdb->ipalloc_state = ipalloc_state;
+
        ipflags = set_ipflags(ctdb, tmp_ctx, nodemap);
        if (ipflags == NULL) {
                DEBUG(DEBUG_ERR,("Failed to set IP flags - aborting takeover run\n"));
@@ -2562,7 +2607,7 @@ int ctdb_takeover_run(struct ctdb_context *ctdb, struct ctdb_node_map_old *nodem
        }
 
        /* Fetch known/available public IPs from each active node */
-       ret = ctdb_reload_remote_public_ips(ctdb, nodemap);
+       ret = ctdb_reload_remote_public_ips(ctdb, ipalloc_state, nodemap);
        if (ret != 0) {
                talloc_free(tmp_ctx);
                return -1;
@@ -2570,8 +2615,8 @@ int ctdb_takeover_run(struct ctdb_context *ctdb, struct ctdb_node_map_old *nodem
 
        /* Short-circuit IP allocation if no node has available IPs */
        can_host_ips = false;
-       for (i=0; i < ctdb->num_nodes; i++) {
-               if (ctdb->nodes[i]->available_public_ips != NULL) {
+       for (i=0; i < ipalloc_state->num; i++) {
+               if (ipalloc_state->available_public_ips[i] != NULL) {
                        can_host_ips = true;
                }
        }
index f26515834a525d3a47785f3c17196d3470519c09..8a9938280db846405afd9e7fac1b417edc42dd39 100644 (file)
@@ -496,6 +496,8 @@ static void ctdb_test_init(const char nodestates[],
 
        (*ctdb)->nodes = talloc_array(*ctdb, struct ctdb_node *, numnodes); // FIXME: bogus size, overkill
 
+       (*ctdb)->ipalloc_state = ipalloc_state_init(*ctdb, *ctdb);
+
        for (i=0; i < numnodes; i++) {
                nodemap->nodes[i].pnn = i;
                nodemap->nodes[i].flags = nodeflags[i];
@@ -509,8 +511,9 @@ static void ctdb_test_init(const char nodestates[],
                (*ctdb)->nodes[i] = talloc(*ctdb, struct ctdb_node);
                (*ctdb)->nodes[i]->pnn = i;
                (*ctdb)->nodes[i]->flags = nodeflags[i];
-               (*ctdb)->nodes[i]->available_public_ips = avail[i];
-               (*ctdb)->nodes[i]->known_public_ips = known[i];
+
+               (*ctdb)->ipalloc_state->available_public_ips[i] = avail[i];
+               (*ctdb)->ipalloc_state->known_public_ips[i] = known[i];
        }
 
        *ipflags = set_ipflags_internal(*ctdb, *ctdb, nodemap,