summaryrefslogtreecommitdiff
path: root/ctdb/tcp/tcp_init.c
blob: dc92abd4e6c802dcbcad56bcaa763af0156963ab (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
/* 
   ctdb over TCP

   Copyright (C) Andrew Tridgell  2006

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   
   You should have received a copy of the GNU General Public License
   along with this program; if not, see <http://www.gnu.org/licenses/>.
*/

#include "replace.h"
#include "system/network.h"
#include "system/filesys.h"

#include <talloc.h>
#include <tevent.h>

#include "lib/util/time.h"
#include "lib/util/debug.h"

#include "ctdb_private.h"

#include "common/common.h"
#include "common/logging.h"

#include "ctdb_tcp.h"

static int tnode_destructor(struct ctdb_tcp_node *tnode)
{
  //	struct ctdb_node *node = talloc_find_parent_bytype(tnode, struct ctdb_node);

	if (tnode->out_fd != -1) {
		close(tnode->out_fd);
		tnode->out_fd = -1;
	}

	return 0;
}

/*
  initialise tcp portion of a ctdb node
*/
static int ctdb_tcp_add_node(struct ctdb_node *node)
{
	struct ctdb_tcp_node *tnode;
	tnode = talloc_zero(node, struct ctdb_tcp_node);
	CTDB_NO_MEMORY(node->ctdb, tnode);

	tnode->out_fd = -1;
	tnode->ctdb = node->ctdb;

	node->private_data = tnode;
	talloc_set_destructor(tnode, tnode_destructor);

	return 0;
}

/*
  initialise transport structures
*/
static int ctdb_tcp_initialise(struct ctdb_context *ctdb)
{
	int i;

	/* listen on our own address */
	if (ctdb_tcp_listen(ctdb) != 0) {
		DEBUG(DEBUG_CRIT, (__location__ " Failed to start listening on the CTDB socket\n"));
		exit(1);
	}

	for (i=0; i < ctdb->num_nodes; i++) {
		if (ctdb->nodes[i]->flags & NODE_FLAGS_DELETED) {
			continue;
		}
		if (ctdb_tcp_add_node(ctdb->nodes[i]) != 0) {
			DEBUG(DEBUG_CRIT, ("methods->add_node failed at %d\n", i));
			return -1;
		}
	}
	
	return 0;
}

/*
  start the protocol going
*/
static int ctdb_tcp_connect_node(struct ctdb_node *node)
{
	struct ctdb_context *ctdb = node->ctdb;
	struct ctdb_tcp_node *tnode = talloc_get_type(
		node->private_data, struct ctdb_tcp_node);

	/* startup connection to the other server - will happen on
	   next event loop */
	if (!ctdb_same_address(ctdb->address, &node->address)) {
		tnode->connect_te = tevent_add_timer(ctdb->ev, tnode,
						    timeval_zero(),
						    ctdb_tcp_node_connect,
						    node);
	}

	return 0;
}

/*
  shutdown and try to restart a connection to a node after it has been
  disconnected
*/
static void ctdb_tcp_restart(struct ctdb_node *node)
{
	struct ctdb_tcp_node *tnode = talloc_get_type(
		node->private_data, struct ctdb_tcp_node);

	DEBUG(DEBUG_NOTICE,("Tearing down connection to dead node :%d\n", node->pnn));

	ctdb_tcp_stop_connection(node);

	tnode->connect_te = tevent_add_timer(node->ctdb->ev, tnode,
					     timeval_zero(),
					     ctdb_tcp_node_connect, node);
}


/*
  shutdown the transport
*/
static void ctdb_tcp_shutdown(struct ctdb_context *ctdb)
{
	struct ctdb_tcp *ctcp = talloc_get_type(ctdb->private_data,
						struct ctdb_tcp);
	uint32_t i;

	talloc_free(ctcp);
	ctdb->private_data = NULL;

	for (i=0; i<ctdb->num_nodes; i++) {
		TALLOC_FREE(ctdb->nodes[i]->private_data);
	}
}

/*
  start the transport
*/
static int ctdb_tcp_start(struct ctdb_context *ctdb)
{
	int i;

	for (i=0; i < ctdb->num_nodes; i++) {
		if (ctdb->nodes[i]->flags & NODE_FLAGS_DELETED) {
			continue;
		}
		ctdb_tcp_connect_node(ctdb->nodes[i]);
	}

	return 0;
}


/*
  transport packet allocator - allows transport to control memory for packets
*/
static void *ctdb_tcp_allocate_pkt(TALLOC_CTX *mem_ctx, size_t size)
{
	/* tcp transport needs to round to 8 byte alignment to ensure
	   that we can use a length header and 64 bit elements in
	   structures */
	size = (size+(CTDB_TCP_ALIGNMENT-1)) & ~(CTDB_TCP_ALIGNMENT-1);
	return talloc_size(mem_ctx, size);
}


static const struct ctdb_methods ctdb_tcp_methods = {
	.initialise   = ctdb_tcp_initialise,
	.start        = ctdb_tcp_start,
	.queue_pkt    = ctdb_tcp_queue_pkt,
	.add_node     = ctdb_tcp_add_node,
	.connect_node = ctdb_tcp_connect_node,
	.allocate_pkt = ctdb_tcp_allocate_pkt,
	.shutdown     = ctdb_tcp_shutdown,
	.restart      = ctdb_tcp_restart,
};

static int tcp_ctcp_destructor(struct ctdb_tcp *ctcp)
{
	ctcp->ctdb->private_data = NULL;
	ctcp->ctdb->methods = NULL;
	
	return 0;
}

		
/*
  initialise tcp portion of ctdb 
*/
int ctdb_tcp_init(struct ctdb_context *ctdb)
{
	struct ctdb_tcp *ctcp;
	ctcp = talloc_zero(ctdb, struct ctdb_tcp);
	CTDB_NO_MEMORY(ctdb, ctcp);

	ctcp->listen_fd = -1;
	ctcp->ctdb      = ctdb;
	ctdb->private_data = ctcp;
	ctdb->methods = &ctdb_tcp_methods;

	talloc_set_destructor(ctcp, tcp_ctcp_destructor);
	return 0;
}