mirror of
https://github.com/samba-team/samba.git
synced 2024-12-22 13:34:15 +03:00
change the tickle list from one global list into an array per public
ip/node once we have started sending all tickles for a specific ip delete the entire array so that the tickles dont remain forever in the ctdb server add a control to send the full list of every tickle that is registered for a particular public ip/node (This used to be ctdb commit d0eee33e44d3f8e26debbec21d41e2cbdbb520e6)
This commit is contained in:
parent
865e68db2b
commit
7b17afdfcd
@ -139,6 +139,9 @@ struct ctdb_node {
|
||||
/* the node number that has taken over this nodes public address, if any.
|
||||
If not taken over, then set to -1 */
|
||||
int32_t takeover_vnn;
|
||||
|
||||
/* List of clients to tickle for this public address */
|
||||
struct ctdb_tcp_array *tcp_array;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -305,7 +308,6 @@ struct ctdb_context {
|
||||
uint32_t recovery_master;
|
||||
struct ctdb_call_state *pending_calls;
|
||||
struct ctdb_takeover takeover;
|
||||
struct ctdb_tcp_list *tcp_list;
|
||||
struct ctdb_client_ip *client_ip_list;
|
||||
bool do_setsched;
|
||||
void *saved_scheduler_param;
|
||||
@ -410,6 +412,7 @@ enum ctdb_controls {CTDB_CONTROL_PROCESS_EXISTS = 0,
|
||||
CTDB_CONTROL_MODIFY_FLAGS = 52,
|
||||
CTDB_CONTROL_GET_ALL_TUNABLES = 53,
|
||||
CTDB_CONTROL_KILL_TCP = 54,
|
||||
CTDB_CONTROL_TCP_TICKLE_LIST = 55,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -1003,11 +1006,12 @@ int ctdb_set_event_script(struct ctdb_context *ctdb, const char *script);
|
||||
int ctdb_takeover_run(struct ctdb_context *ctdb, struct ctdb_node_map *nodemap);
|
||||
|
||||
int32_t ctdb_control_tcp_client(struct ctdb_context *ctdb, uint32_t client_id,
|
||||
uint32_t srcnode, TDB_DATA indata);
|
||||
TDB_DATA indata);
|
||||
int32_t ctdb_control_tcp_add(struct ctdb_context *ctdb, TDB_DATA indata);
|
||||
int32_t ctdb_control_tcp_remove(struct ctdb_context *ctdb, TDB_DATA indata);
|
||||
int32_t ctdb_control_startup(struct ctdb_context *ctdb, uint32_t vnn);
|
||||
int32_t ctdb_control_kill_tcp(struct ctdb_context *ctdb, TDB_DATA indata);
|
||||
int32_t ctdb_control_tcp_tickle_list(struct ctdb_context *ctdb, TDB_DATA indata);
|
||||
|
||||
void ctdb_takeover_client_destructor_hook(struct ctdb_client *client);
|
||||
int ctdb_event_script(struct ctdb_context *ctdb, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
|
||||
|
@ -259,7 +259,7 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
|
||||
|
||||
case CTDB_CONTROL_TCP_CLIENT:
|
||||
CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_control_tcp));
|
||||
return ctdb_control_tcp_client(ctdb, client_id, srcnode, indata);
|
||||
return ctdb_control_tcp_client(ctdb, client_id, indata);
|
||||
|
||||
case CTDB_CONTROL_STARTUP:
|
||||
CHECK_CONTROL_DATA_SIZE(0);
|
||||
@ -290,6 +290,10 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
|
||||
CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_control_killtcp));
|
||||
return ctdb_control_kill_tcp(ctdb, indata);
|
||||
|
||||
case CTDB_CONTROL_TCP_TICKLE_LIST:
|
||||
/* data size is verified in the called function */
|
||||
return ctdb_control_tcp_tickle_list(ctdb, indata);
|
||||
|
||||
default:
|
||||
DEBUG(0,(__location__ " Unknown CTDB control opcode %u\n", opcode));
|
||||
return -1;
|
||||
|
@ -39,17 +39,37 @@ struct ctdb_takeover_arp {
|
||||
struct ctdb_tcp_list *tcp_list;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
a tcp connection description
|
||||
*/
|
||||
struct ctdb_tcp_connection {
|
||||
struct sockaddr_in saddr;
|
||||
struct sockaddr_in daddr;
|
||||
};
|
||||
|
||||
/*
|
||||
array of tcp connections
|
||||
*/
|
||||
struct ctdb_tcp_array {
|
||||
uint32_t num;
|
||||
struct ctdb_tcp_connection connections[1];
|
||||
};
|
||||
|
||||
struct ctdb_control_tcp_tickle_list {
|
||||
int32_t vnn;
|
||||
struct ctdb_tcp_array tickles;
|
||||
};
|
||||
|
||||
/*
|
||||
lists of tcp endpoints
|
||||
*/
|
||||
struct ctdb_tcp_list {
|
||||
struct ctdb_tcp_list *prev, *next;
|
||||
uint32_t vnn;
|
||||
struct sockaddr_in saddr;
|
||||
struct sockaddr_in daddr;
|
||||
struct ctdb_tcp_connection connection;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
list of clients to kill on IP release
|
||||
*/
|
||||
@ -85,13 +105,14 @@ static void ctdb_control_send_arp(struct event_context *ev, struct timed_event *
|
||||
|
||||
for (tcp=arp->tcp_list;tcp;tcp=tcp->next) {
|
||||
DEBUG(2,("sending tcp tickle ack for %u->%s:%u\n",
|
||||
(unsigned)ntohs(tcp->daddr.sin_port),
|
||||
inet_ntoa(tcp->saddr.sin_addr),
|
||||
(unsigned)ntohs(tcp->saddr.sin_port)));
|
||||
ret = ctdb_sys_send_tcp(s, &tcp->saddr, &tcp->daddr, 0, 0, 0);
|
||||
(unsigned)ntohs(tcp->connection.daddr.sin_port),
|
||||
inet_ntoa(tcp->connection.saddr.sin_addr),
|
||||
(unsigned)ntohs(tcp->connection.saddr.sin_port)));
|
||||
ret = ctdb_sys_send_tcp(s, &tcp->connection.saddr,
|
||||
&tcp->connection.daddr, 0, 0, 0);
|
||||
if (ret != 0) {
|
||||
DEBUG(0,(__location__ " Failed to send tcp tickle ack for %s\n",
|
||||
inet_ntoa(tcp->saddr.sin_addr)));
|
||||
inet_ntoa(tcp->connection.saddr.sin_addr)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,6 +132,7 @@ static void ctdb_control_send_arp(struct event_context *ev, struct timed_event *
|
||||
struct takeover_callback_state {
|
||||
struct ctdb_req_control *c;
|
||||
struct sockaddr_in *sin;
|
||||
int32_t takeover_vnn;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -123,7 +145,7 @@ static void takeover_ip_callback(struct ctdb_context *ctdb, int status,
|
||||
talloc_get_type(private_data, struct takeover_callback_state);
|
||||
struct ctdb_takeover_arp *arp;
|
||||
char *ip = inet_ntoa(state->sin->sin_addr);
|
||||
struct ctdb_tcp_list *tcp;
|
||||
struct ctdb_tcp_array *tcparray;
|
||||
|
||||
ctdb_start_monitoring(ctdb);
|
||||
|
||||
@ -146,15 +168,28 @@ static void takeover_ip_callback(struct ctdb_context *ctdb, int status,
|
||||
arp->ctdb = ctdb;
|
||||
arp->sin = *state->sin;
|
||||
|
||||
/* add all of the known tcp connections for this IP to the
|
||||
list of tcp connections to send tickle acks for */
|
||||
for (tcp=ctdb->tcp_list;tcp;tcp=tcp->next) {
|
||||
if (state->sin->sin_addr.s_addr == tcp->daddr.sin_addr.s_addr) {
|
||||
tcparray = ctdb->nodes[state->takeover_vnn]->tcp_array;
|
||||
if (tcparray) {
|
||||
int i;
|
||||
|
||||
/* add all of the known tcp connections for this IP to the
|
||||
list of tcp connections to send tickle acks for */
|
||||
for (i=0;i<tcparray->num;i++) {
|
||||
struct ctdb_tcp_list *t2 = talloc(arp, struct ctdb_tcp_list);
|
||||
if (t2 == NULL) goto failed;
|
||||
*t2 = *tcp;
|
||||
t2->vnn = state->takeover_vnn;
|
||||
t2->connection.saddr = tcparray->connections[i].saddr;
|
||||
t2->connection.daddr = tcparray->connections[i].daddr;
|
||||
DLIST_ADD(arp->tcp_list, t2);
|
||||
}
|
||||
|
||||
/* Delete the entire tickle array for this public address
|
||||
We have tickled them now so we dont need them
|
||||
anymore
|
||||
*/
|
||||
talloc_free(tcparray);
|
||||
ctdb->nodes[state->takeover_vnn]->tcp_array = NULL;
|
||||
|
||||
}
|
||||
|
||||
event_add_timed(arp->ctdb->ev, arp->ctdb->takeover.last_ctx,
|
||||
@ -171,6 +206,26 @@ failed:
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
Find the vnn of the node that has a public ip address
|
||||
returns -1 if the address is not known as a public address
|
||||
*/
|
||||
static int32_t find_public_ip_vnn(struct ctdb_context *ctdb, char *ip)
|
||||
{
|
||||
int32_t vnn = -1;
|
||||
int i;
|
||||
|
||||
for (i=0;i<ctdb->num_nodes;i++) {
|
||||
if (!strcmp(ip, ctdb->nodes[i]->public_address)) {
|
||||
vnn = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return vnn;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
take over an ip address
|
||||
*/
|
||||
@ -201,6 +256,12 @@ int32_t ctdb_control_takeover_ip(struct ctdb_context *ctdb,
|
||||
CTDB_NO_MEMORY(ctdb, state->sin);
|
||||
*state->sin = pip->sin;
|
||||
|
||||
state->takeover_vnn = find_public_ip_vnn(ctdb, ip);
|
||||
if (state->takeover_vnn == -1) {
|
||||
DEBUG(0,("Could not takover of IP %s. It is not a public address.\n", ip));
|
||||
return -1;
|
||||
}
|
||||
|
||||
DEBUG(0,("Takover of IP %s/%u on interface %s\n",
|
||||
ip, ctdb->nodes[ctdb->vnn]->public_netmask_bits,
|
||||
ctdb->takeover.interface));
|
||||
@ -259,7 +320,7 @@ static void release_ip_callback(struct ctdb_context *ctdb, int status,
|
||||
talloc_get_type(private_data, struct takeover_callback_state);
|
||||
char *ip = inet_ntoa(state->sin->sin_addr);
|
||||
TDB_DATA data;
|
||||
struct ctdb_tcp_list *tcp;
|
||||
struct ctdb_tcp_array *tcparray;
|
||||
|
||||
ctdb_start_monitoring(ctdb);
|
||||
|
||||
@ -276,21 +337,25 @@ static void release_ip_callback(struct ctdb_context *ctdb, int status,
|
||||
|
||||
|
||||
/* tell other nodes about any tcp connections we were holding with this IP */
|
||||
for (tcp=ctdb->tcp_list;tcp;tcp=tcp->next) {
|
||||
if (tcp->vnn == ctdb->vnn &&
|
||||
state->sin->sin_addr.s_addr == tcp->daddr.sin_addr.s_addr) {
|
||||
tcparray = ctdb->nodes[state->takeover_vnn]->tcp_array;
|
||||
if (tcparray) {
|
||||
int i;
|
||||
|
||||
for (i=0;i<tcparray->num;i++) {
|
||||
struct ctdb_control_tcp_vnn t;
|
||||
|
||||
t.vnn = ctdb->vnn;
|
||||
t.src = tcp->saddr;
|
||||
t.dest = tcp->daddr;
|
||||
t.vnn = state->takeover_vnn;
|
||||
t.src = tcparray->connections[i].saddr;
|
||||
t.dest = tcparray->connections[i].daddr;
|
||||
|
||||
data.dptr = (uint8_t *)&t;
|
||||
data.dsize = sizeof(t);
|
||||
|
||||
ctdb_daemon_send_control(ctdb, CTDB_BROADCAST_CONNECTED, 0,
|
||||
CTDB_CONTROL_TCP_ADD,
|
||||
0, CTDB_CTRL_FLAG_NOREPLY, data, NULL, NULL);
|
||||
ctdb_daemon_send_control(ctdb,
|
||||
CTDB_BROADCAST_CONNECTED, 0,
|
||||
CTDB_CONTROL_TCP_ADD, 0,
|
||||
CTDB_CTRL_FLAG_NOREPLY, data,
|
||||
NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -299,7 +364,6 @@ static void release_ip_callback(struct ctdb_context *ctdb, int status,
|
||||
talloc_free(state);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
release an ip address
|
||||
*/
|
||||
@ -336,6 +400,12 @@ int32_t ctdb_control_release_ip(struct ctdb_context *ctdb,
|
||||
CTDB_NO_MEMORY(ctdb, state->sin);
|
||||
*state->sin = pip->sin;
|
||||
|
||||
state->takeover_vnn = find_public_ip_vnn(ctdb, ip);
|
||||
if (state->takeover_vnn == -1) {
|
||||
DEBUG(0,("Could not release IP %s. It is not a public address.\n", ip));
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctdb_stop_monitoring(ctdb);
|
||||
|
||||
ret = ctdb_event_script_callback(ctdb,
|
||||
@ -608,7 +678,7 @@ static int ctdb_client_ip_destructor(struct ctdb_client_ip *ip)
|
||||
called by a client to inform us of a TCP connection that it is managing
|
||||
that should tickled with an ACK when IP takeover is done
|
||||
*/
|
||||
int32_t ctdb_control_tcp_client(struct ctdb_context *ctdb, uint32_t client_id, uint32_t vnn,
|
||||
int32_t ctdb_control_tcp_client(struct ctdb_context *ctdb, uint32_t client_id,
|
||||
TDB_DATA indata)
|
||||
{
|
||||
struct ctdb_client *client = ctdb_reqid_find(ctdb, client_id, struct ctdb_client);
|
||||
@ -618,6 +688,8 @@ int32_t ctdb_control_tcp_client(struct ctdb_context *ctdb, uint32_t client_id, u
|
||||
int ret;
|
||||
TDB_DATA data;
|
||||
struct ctdb_client_ip *ip;
|
||||
char *addr;
|
||||
int32_t takeover_vnn;
|
||||
|
||||
ip = talloc(client, struct ctdb_client_ip);
|
||||
CTDB_NO_MEMORY(ctdb, ip);
|
||||
@ -631,13 +703,21 @@ int32_t ctdb_control_tcp_client(struct ctdb_context *ctdb, uint32_t client_id, u
|
||||
tcp = talloc(client, struct ctdb_tcp_list);
|
||||
CTDB_NO_MEMORY(ctdb, tcp);
|
||||
|
||||
tcp->vnn = vnn;
|
||||
tcp->saddr = p->src;
|
||||
tcp->daddr = p->dest;
|
||||
addr = inet_ntoa(p->src.sin_addr);
|
||||
|
||||
takeover_vnn = find_public_ip_vnn(ctdb, addr);
|
||||
if (takeover_vnn == -1) {
|
||||
DEBUG(0,("Could not add client IP %s. It is not a public address.\n", addr));
|
||||
return -1;
|
||||
}
|
||||
|
||||
tcp->vnn = takeover_vnn;
|
||||
tcp->connection.saddr = p->src;
|
||||
tcp->connection.daddr = p->dest;
|
||||
|
||||
DLIST_ADD(client->tcp_list, tcp);
|
||||
|
||||
t.vnn = vnn;
|
||||
t.vnn = takeover_vnn;
|
||||
t.src = p->src;
|
||||
t.dest = p->dest;
|
||||
|
||||
@ -646,7 +726,7 @@ int32_t ctdb_control_tcp_client(struct ctdb_context *ctdb, uint32_t client_id, u
|
||||
|
||||
DEBUG(2,("registered tcp client for %u->%s:%u\n",
|
||||
(unsigned)ntohs(p->dest.sin_port),
|
||||
inet_ntoa(p->src.sin_addr),
|
||||
addr,
|
||||
(unsigned)ntohs(p->src.sin_port)));
|
||||
|
||||
/* tell all nodes about this tcp connection */
|
||||
@ -674,15 +754,20 @@ static bool same_sockaddr_in(struct sockaddr_in *in1, struct sockaddr_in *in2)
|
||||
/*
|
||||
find a tcp address on a list
|
||||
*/
|
||||
static struct ctdb_tcp_list *ctdb_tcp_find(struct ctdb_tcp_list *list,
|
||||
struct ctdb_tcp_list *tcp)
|
||||
static struct ctdb_tcp_connection *ctdb_tcp_find(struct ctdb_tcp_array *array,
|
||||
struct ctdb_tcp_connection *tcp)
|
||||
{
|
||||
while (list) {
|
||||
if (same_sockaddr_in(&list->saddr, &tcp->saddr) &&
|
||||
same_sockaddr_in(&list->daddr, &tcp->daddr)) {
|
||||
return list;
|
||||
int i;
|
||||
|
||||
if (array == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i=0;i<array->num;i++) {
|
||||
if (same_sockaddr_in(&array->connections[i].saddr, &tcp->saddr) &&
|
||||
same_sockaddr_in(&array->connections[i].daddr, &tcp->daddr)) {
|
||||
return &array->connections[i];
|
||||
}
|
||||
list = list->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@ -695,26 +780,56 @@ static struct ctdb_tcp_list *ctdb_tcp_find(struct ctdb_tcp_list *list,
|
||||
int32_t ctdb_control_tcp_add(struct ctdb_context *ctdb, TDB_DATA indata)
|
||||
{
|
||||
struct ctdb_control_tcp_vnn *p = (struct ctdb_control_tcp_vnn *)indata.dptr;
|
||||
struct ctdb_tcp_list *tcp;
|
||||
struct ctdb_tcp_array *tcparray;
|
||||
struct ctdb_tcp_connection tcp;
|
||||
|
||||
tcp = talloc(ctdb, struct ctdb_tcp_list);
|
||||
CTDB_NO_MEMORY(ctdb, tcp);
|
||||
|
||||
tcp->vnn = p->vnn;
|
||||
tcp->saddr = p->src;
|
||||
tcp->daddr = p->dest;
|
||||
tcparray = ctdb->nodes[p->vnn]->tcp_array;
|
||||
|
||||
if (NULL == ctdb_tcp_find(ctdb->tcp_list, tcp)) {
|
||||
DLIST_ADD(ctdb->tcp_list, tcp);
|
||||
DEBUG(2,("Added tickle info for %s:%u from vnn %u\n",
|
||||
inet_ntoa(tcp->daddr.sin_addr), ntohs(tcp->daddr.sin_port),
|
||||
tcp->vnn));
|
||||
} else {
|
||||
DEBUG(4,("Already had tickle info for %s:%u from vnn %u\n",
|
||||
inet_ntoa(tcp->daddr.sin_addr), ntohs(tcp->daddr.sin_port),
|
||||
tcp->vnn));
|
||||
/* If this is the first tickle */
|
||||
if (tcparray == NULL) {
|
||||
tcparray = talloc_size(ctdb->nodes,
|
||||
offsetof(struct ctdb_tcp_array, connections) +
|
||||
sizeof(struct ctdb_tcp_connection) * 1);
|
||||
CTDB_NO_MEMORY(ctdb, tcparray);
|
||||
ctdb->nodes[p->vnn]->tcp_array = tcparray;
|
||||
|
||||
tcparray->num = 0;
|
||||
tcparray->connections[tcparray->num].saddr = p->src;
|
||||
tcparray->connections[tcparray->num].daddr = p->dest;
|
||||
tcparray->num++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Do we already have this tickle ?*/
|
||||
tcp.saddr = p->src;
|
||||
tcp.daddr = p->dest;
|
||||
if (ctdb_tcp_find(ctdb->nodes[p->vnn]->tcp_array, &tcp) != NULL) {
|
||||
DEBUG(4,("Already had tickle info for %s:%u from vnn %u\n",
|
||||
inet_ntoa(tcp.daddr.sin_addr),
|
||||
ntohs(tcp.daddr.sin_port),
|
||||
p->vnn));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* A new tickle, we must add it to the array */
|
||||
tcparray = talloc_realloc(ctdb->nodes, tcparray,
|
||||
struct ctdb_tcp_array,
|
||||
offsetof(struct ctdb_tcp_array, connections) +
|
||||
sizeof(struct ctdb_tcp_connection) * (tcparray->num+1) );
|
||||
CTDB_NO_MEMORY(ctdb, tcparray);
|
||||
|
||||
ctdb->nodes[p->vnn]->tcp_array = tcparray;
|
||||
tcparray->connections[tcparray->num].saddr = p->src;
|
||||
tcparray->connections[tcparray->num].daddr = p->dest;
|
||||
tcparray->num++;
|
||||
|
||||
DEBUG(2,("Added tickle info for %s:%u from vnn %u\n",
|
||||
inet_ntoa(tcp.daddr.sin_addr),
|
||||
ntohs(tcp.daddr.sin_port),
|
||||
p->vnn));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -727,56 +842,73 @@ int32_t ctdb_control_tcp_add(struct ctdb_context *ctdb, TDB_DATA indata)
|
||||
int32_t ctdb_control_tcp_remove(struct ctdb_context *ctdb, TDB_DATA indata)
|
||||
{
|
||||
struct ctdb_control_tcp_vnn *p = (struct ctdb_control_tcp_vnn *)indata.dptr;
|
||||
struct ctdb_tcp_list t, *tcp;
|
||||
struct ctdb_tcp_array *tcparray;
|
||||
struct ctdb_tcp_connection tcp, *tcpp;
|
||||
|
||||
t.vnn = p->vnn;
|
||||
t.saddr = p->src;
|
||||
t.daddr = p->dest;
|
||||
tcparray = ctdb->nodes[p->vnn]->tcp_array;
|
||||
|
||||
tcp = ctdb_tcp_find(ctdb->tcp_list, &t);
|
||||
if (tcp) {
|
||||
DEBUG(2,("Removed tickle info for %s:%u from vnn %u\n",
|
||||
inet_ntoa(tcp->daddr.sin_addr), ntohs(tcp->daddr.sin_port),
|
||||
tcp->vnn));
|
||||
DLIST_REMOVE(ctdb->tcp_list, tcp);
|
||||
talloc_free(tcp);
|
||||
/* if the array is empty we cant remove it
|
||||
and we dont need to do anything
|
||||
*/
|
||||
if (tcparray == NULL) {
|
||||
DEBUG(2,("Trying to remove tickle that doesnt exist (array is empty) %s:%u from vnn %u\n",
|
||||
inet_ntoa(p->dest.sin_addr),
|
||||
ntohs(p->dest.sin_port),
|
||||
p->vnn));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* See if we know this connection
|
||||
if we dont know this connection then we dont need to do anything
|
||||
*/
|
||||
tcp.saddr = p->src;
|
||||
tcp.daddr = p->dest;
|
||||
tcpp = ctdb_tcp_find(ctdb->nodes[p->vnn]->tcp_array, &tcp);
|
||||
if (tcpp == NULL) {
|
||||
DEBUG(2,("Trying to remove tickle that doesnt exist %s:%u from vnn %u\n",
|
||||
inet_ntoa(p->dest.sin_addr),
|
||||
ntohs(p->dest.sin_port),
|
||||
p->vnn));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* We need to remove this entry from the array.
|
||||
Instead of allocating a new array and copying data to it
|
||||
we cheat and just copy the last entry in the existing array
|
||||
to the entry that is to be removed and just shring the
|
||||
->num field
|
||||
*/
|
||||
tcpp->saddr = tcparray->connections[tcparray->num-1].saddr;
|
||||
tcpp->daddr = tcparray->connections[tcparray->num-1].daddr;
|
||||
tcparray->num--;
|
||||
|
||||
/* If we deleted the last entry we also need to remove the entire array
|
||||
*/
|
||||
if (tcparray->num == 0) {
|
||||
talloc_free(tcparray);
|
||||
ctdb->nodes[p->vnn]->tcp_array = NULL;
|
||||
}
|
||||
|
||||
DEBUG(2,("Removed tickle info for %s:%u from vnn %u\n",
|
||||
inet_ntoa(p->src.sin_addr),
|
||||
ntohs(p->src.sin_port),
|
||||
p->vnn));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
called when a daemon restarts - wipes all tcp entries from that vnn
|
||||
called when a daemon restarts - send all tickes for all public addresses
|
||||
we are serving immediately to the new node.
|
||||
*/
|
||||
int32_t ctdb_control_startup(struct ctdb_context *ctdb, uint32_t vnn)
|
||||
{
|
||||
struct ctdb_tcp_list *tcp, *next;
|
||||
for (tcp=ctdb->tcp_list;tcp;tcp=next) {
|
||||
next = tcp->next;
|
||||
if (tcp->vnn == vnn) {
|
||||
DLIST_REMOVE(ctdb->tcp_list, tcp);
|
||||
talloc_free(tcp);
|
||||
}
|
||||
|
||||
/* and tell the new guy about any that he should have
|
||||
from us */
|
||||
if (tcp->vnn == ctdb->vnn) {
|
||||
struct ctdb_control_tcp_vnn t;
|
||||
TDB_DATA data;
|
||||
|
||||
t.vnn = tcp->vnn;
|
||||
t.src = tcp->saddr;
|
||||
t.dest = tcp->daddr;
|
||||
|
||||
data.dptr = (uint8_t *)&t;
|
||||
data.dsize = sizeof(t);
|
||||
|
||||
ctdb_daemon_send_control(ctdb, vnn, 0,
|
||||
CTDB_CONTROL_TCP_ADD,
|
||||
0, CTDB_CTRL_FLAG_NOREPLY, data, NULL, NULL);
|
||||
}
|
||||
}
|
||||
/*XXX here we should send all tickes we are serving to the new node */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -792,9 +924,10 @@ void ctdb_takeover_client_destructor_hook(struct ctdb_client *client)
|
||||
struct ctdb_control_tcp_vnn p;
|
||||
struct ctdb_tcp_list *tcp = client->tcp_list;
|
||||
DLIST_REMOVE(client->tcp_list, tcp);
|
||||
p.vnn = tcp->vnn;
|
||||
p.src = tcp->saddr;
|
||||
p.dest = tcp->daddr;
|
||||
|
||||
p.vnn = tcp->vnn;
|
||||
p.src = tcp->connection.saddr;
|
||||
p.dest = tcp->connection.daddr;
|
||||
data.dptr = (uint8_t *)&p;
|
||||
data.dsize = sizeof(p);
|
||||
if (ctdb_sys_have_ip(inet_ntoa(p.dest.sin_addr))) {
|
||||
@ -1092,3 +1225,63 @@ int32_t ctdb_control_kill_tcp(struct ctdb_context *ctdb, TDB_DATA indata)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
called by a daemon to inform us of the entire list of TCP tickles for
|
||||
a particular public address.
|
||||
this control should only be sent by the node that is currently serving
|
||||
that public address.
|
||||
*/
|
||||
int32_t ctdb_control_tcp_tickle_list(struct ctdb_context *ctdb, TDB_DATA indata)
|
||||
{
|
||||
struct ctdb_control_tcp_tickle_list *list = (struct ctdb_control_tcp_tickle_list *)indata.dptr;
|
||||
struct ctdb_tcp_array *tcparray;
|
||||
int size;
|
||||
|
||||
|
||||
/* We must at least have tickles.num or else we cant verify the size
|
||||
of the received data blob
|
||||
*/
|
||||
if (indata.dsize < offsetof(struct ctdb_control_tcp_tickle_list,
|
||||
tickles.connections)) {
|
||||
DEBUG(0,("Bad indata in ctdb_control_tcp_tickle_list. Not enough data for the tickle.num field\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* verify that the size of data matches what we expect */
|
||||
if (indata.dsize < offsetof(struct ctdb_control_tcp_tickle_list,
|
||||
tickles.connections)
|
||||
+ sizeof(struct ctdb_tcp_connection)
|
||||
* list->tickles.num) {
|
||||
DEBUG(0,("Bad indata in ctdb_control_tcp_tickle_list\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Make sure the vnn looks sane */
|
||||
if ( (list->vnn < 0) || (list->vnn >= ctdb->num_nodes) ) {
|
||||
DEBUG(0,("Bad indata in ctdb_control_tcp_tickle_list. Invalid vnn:%d\n", list->vnn));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* remove any old ticklelist we might have */
|
||||
tcparray = ctdb->nodes[list->vnn]->tcp_array;
|
||||
if (tcparray) {
|
||||
talloc_free(tcparray);
|
||||
ctdb->nodes[list->vnn]->tcp_array = NULL;
|
||||
}
|
||||
|
||||
/* allocate a new tcparray and copy all data that was sent to us */
|
||||
size = offsetof(struct ctdb_tcp_array, connections) +
|
||||
sizeof(struct ctdb_tcp_connection) * list->tickles.num;
|
||||
|
||||
tcparray = talloc_size(ctdb->nodes, size);
|
||||
CTDB_NO_MEMORY(ctdb, tcparray);
|
||||
|
||||
memcpy(tcparray, &list->tickles, size);
|
||||
|
||||
/* We now have a new fresh tickle list array for this vnn */
|
||||
ctdb->nodes[list->vnn]->tcp_array = tcparray;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user