1 /*
2 Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 #include <ndb_global.h>
26 #include <IPCConfig.hpp>
27
28 #include <TransporterRegistry.hpp>
29
30 #include <mgmapi.h>
31 #include <mgmapi_configuration.hpp>
32
33
34 /* Return true if node with "nodeId" is a MGM node */
is_mgmd(Uint32 nodeId,const struct ndb_mgm_configuration & config)35 static bool is_mgmd(Uint32 nodeId,
36 const struct ndb_mgm_configuration & config)
37 {
38 ndb_mgm_configuration_iterator iter(config, CFG_SECTION_NODE);
39 if (iter.find(CFG_NODE_ID, nodeId))
40 abort();
41 Uint32 type;
42 if(iter.get(CFG_TYPE_OF_SECTION, &type))
43 abort();
44
45 return (type == NODE_TYPE_MGM);
46 }
47
48
49 bool
configureTransporters(Uint32 nodeId,const struct ndb_mgm_configuration & config,class TransporterRegistry & tr,bool transporter_to_self)50 IPCConfig::configureTransporters(Uint32 nodeId,
51 const struct ndb_mgm_configuration & config,
52 class TransporterRegistry & tr,
53 bool transporter_to_self)
54 {
55 bool result= true;
56
57 DBUG_ENTER("IPCConfig::configureTransporters");
58
59
60 if (!is_mgmd(nodeId, config))
61 {
62
63 /**
64 * Iterate over all MGM's and construct a connectstring
65 * create mgm_handle and give it to the Transporter Registry
66 */
67
68 const char *separator= "";
69 BaseString connect_string;
70 ndb_mgm_configuration_iterator iter(config, CFG_SECTION_NODE);
71 for(iter.first(); iter.valid(); iter.next())
72 {
73 Uint32 type;
74 if(iter.get(CFG_TYPE_OF_SECTION, &type)) continue;
75 if(type != NODE_TYPE_MGM) continue;
76 const char* hostname;
77 Uint32 port;
78 if(iter.get(CFG_NODE_HOST, &hostname)) continue;
79 if( strlen(hostname) == 0 ) continue;
80 if(iter.get(CFG_MGM_PORT, &port)) continue;
81 connect_string.appfmt("%s%s:%u",separator,hostname,port);
82 separator= ",";
83 }
84 NdbMgmHandle h= ndb_mgm_create_handle();
85 if ( h && connect_string.length() > 0 )
86 {
87 ndb_mgm_set_connectstring(h,connect_string.c_str());
88 tr.set_mgm_handle(h);
89 }
90 }
91
92
93 /* Remove transporter to nodes that does not exist anymore */
94 for (int i= 1; i < MAX_NODES; i++)
95 {
96 ndb_mgm_configuration_iterator iter(config, CFG_SECTION_NODE);
97 if (tr.get_transporter(i) && iter.find(CFG_NODE_ID, i))
98 {
99 // Transporter exist in TransporterRegistry but not
100 // in configuration
101 ndbout_c("The connection to node %d could not "
102 "be removed at this time", i);
103 result= false; // Need restart
104 }
105 }
106
107 TransporterConfiguration conf;
108 TransporterConfiguration loopback_conf;
109 ndb_mgm_configuration_iterator iter(config, CFG_SECTION_CONNECTION);
110 for(iter.first(); iter.valid(); iter.next()){
111
112 bzero(&conf, sizeof(conf));
113 Uint32 nodeId1, nodeId2, remoteNodeId;
114 const char * remoteHostName= 0, * localHostName= 0;
115 if(iter.get(CFG_CONNECTION_NODE_1, &nodeId1)) continue;
116 if(iter.get(CFG_CONNECTION_NODE_2, &nodeId2)) continue;
117
118 if(nodeId1 != nodeId && nodeId2 != nodeId) continue;
119 remoteNodeId = (nodeId == nodeId1 ? nodeId2 : nodeId1);
120
121 if (nodeId1 == nodeId && nodeId2 == nodeId)
122 {
123 transporter_to_self = false; // One already present..ignore extra arg
124 }
125
126 {
127 const char * host1= 0, * host2= 0;
128 iter.get(CFG_CONNECTION_HOSTNAME_1, &host1);
129 iter.get(CFG_CONNECTION_HOSTNAME_2, &host2);
130 localHostName = (nodeId == nodeId1 ? host1 : host2);
131 remoteHostName = (nodeId == nodeId1 ? host2 : host1);
132 }
133
134 Uint32 sendSignalId = 1;
135 Uint32 checksum = 1;
136 if(iter.get(CFG_CONNECTION_SEND_SIGNAL_ID, &sendSignalId)) continue;
137 if(iter.get(CFG_CONNECTION_CHECKSUM, &checksum)) continue;
138
139 Uint32 type = ~0;
140 if(iter.get(CFG_TYPE_OF_SECTION, &type)) continue;
141
142 Uint32 server_port= 0;
143 if(iter.get(CFG_CONNECTION_SERVER_PORT, &server_port)) break;
144
145 Uint32 nodeIdServer= 0;
146 if(iter.get(CFG_CONNECTION_NODE_ID_SERVER, &nodeIdServer)) break;
147
148 if(is_mgmd(nodeId1, config) || is_mgmd(nodeId2, config))
149 {
150 // All connections with MGM uses the mgm port as server
151 conf.isMgmConnection= true;
152 }
153 else
154 conf.isMgmConnection= false;
155
156 Uint32 bindInAddrAny = 0;
157 iter.get(CFG_TCP_BIND_INADDR_ANY, &bindInAddrAny);
158
159 if (nodeId == nodeIdServer && !conf.isMgmConnection) {
160 tr.add_transporter_interface(remoteNodeId,
161 !bindInAddrAny ? localHostName : "",
162 server_port);
163 }
164
165 DBUG_PRINT("info", ("Transporter between this node %d and node %d using port %d, signalId %d, checksum %d",
166 nodeId, remoteNodeId, server_port, sendSignalId, checksum));
167 /*
168 This may be a dynamic port. It depends on when we're getting
169 our configuration. If we've been restarted, we'll be getting
170 a configuration with our old dynamic port in it, hence the number
171 here is negative (and we try the old port number first).
172
173 On a first-run, server_port will be zero (with dynamic ports)
174
175 If we're not using dynamic ports, we don't do anything.
176 */
177
178 conf.localNodeId = nodeId;
179 conf.remoteNodeId = remoteNodeId;
180 conf.checksum = checksum;
181 conf.signalId = sendSignalId;
182 conf.s_port = server_port;
183 conf.localHostName = localHostName;
184 conf.remoteHostName = remoteHostName;
185 conf.serverNodeId = nodeIdServer;
186
187 switch(type){
188 case CONNECTION_TYPE_SHM:
189 if(iter.get(CFG_SHM_KEY, &conf.shm.shmKey)) break;
190 if(iter.get(CFG_SHM_BUFFER_MEM, &conf.shm.shmSize)) break;
191
192 Uint32 signum;
193 if(iter.get(CFG_SHM_SIGNUM, &signum)) break;
194 conf.shm.signum= signum;
195
196 conf.type = tt_SHM_TRANSPORTER;
197
198 if(!tr.configureTransporter(&conf)){
199 DBUG_PRINT("error", ("Failed to configure SHM Transporter "
200 "from %d to %d",
201 conf.localNodeId, conf.remoteNodeId));
202 ndbout_c("Failed to configure SHM Transporter to node %d",
203 conf.remoteNodeId);
204 result = false;
205 }
206 DBUG_PRINT("info", ("Configured SHM Transporter using shmkey %d, "
207 "buf size = %d", conf.shm.shmKey, conf.shm.shmSize));
208 break;
209
210 case CONNECTION_TYPE_SCI:
211 if(iter.get(CFG_SCI_SEND_LIMIT, &conf.sci.sendLimit)) break;
212 if(iter.get(CFG_SCI_BUFFER_MEM, &conf.sci.bufferSize)) break;
213 if (nodeId == nodeId1) {
214 if(iter.get(CFG_SCI_HOST2_ID_0, &conf.sci.remoteSciNodeId0)) break;
215 if(iter.get(CFG_SCI_HOST2_ID_1, &conf.sci.remoteSciNodeId1)) break;
216 } else {
217 if(iter.get(CFG_SCI_HOST1_ID_0, &conf.sci.remoteSciNodeId0)) break;
218 if(iter.get(CFG_SCI_HOST1_ID_1, &conf.sci.remoteSciNodeId1)) break;
219 }
220 if (conf.sci.remoteSciNodeId1 == 0) {
221 conf.sci.nLocalAdapters = 1;
222 } else {
223 conf.sci.nLocalAdapters = 2;
224 }
225 conf.type = tt_SCI_TRANSPORTER;
226 if(!tr.configureTransporter(&conf)){
227 DBUG_PRINT("error", ("Failed to configure SCI Transporter "
228 "from %d to %d",
229 conf.localNodeId, conf.remoteNodeId));
230 ndbout_c("Failed to configure SCI Transporter to node %d",
231 conf.remoteNodeId);
232 result = false;
233 } else {
234 DBUG_PRINT("info", ("Configured SCI Transporter: Adapters = %d, "
235 "remote SCI node id %d",
236 conf.sci.nLocalAdapters, conf.sci.remoteSciNodeId0));
237 DBUG_PRINT("info", ("Host 1 = %s, Host 2 = %s, sendLimit = %d, "
238 "buf size = %d", conf.localHostName,
239 conf.remoteHostName, conf.sci.sendLimit,
240 conf.sci.bufferSize));
241 if (conf.sci.nLocalAdapters > 1) {
242 DBUG_PRINT("info", ("Fault-tolerant with 2 Remote Adapters, "
243 "second remote SCI node id = %d",
244 conf.sci.remoteSciNodeId1));
245 }
246 }
247 break;
248
249 case CONNECTION_TYPE_TCP:
250 if(iter.get(CFG_TCP_SEND_BUFFER_SIZE, &conf.tcp.sendBufferSize)) break;
251 if(iter.get(CFG_TCP_RECEIVE_BUFFER_SIZE, &conf.tcp.maxReceiveSize)) break;
252
253 const char * proxy;
254 if (!iter.get(CFG_TCP_PROXY, &proxy)) {
255 if (strlen(proxy) > 0 && nodeId2 == nodeId) {
256 // TODO handle host:port
257 conf.s_port = atoi(proxy);
258 }
259 }
260
261 iter.get(CFG_TCP_SND_BUF_SIZE, &conf.tcp.tcpSndBufSize);
262 iter.get(CFG_TCP_RCV_BUF_SIZE, &conf.tcp.tcpRcvBufSize);
263 iter.get(CFG_TCP_MAXSEG_SIZE, &conf.tcp.tcpMaxsegSize);
264 iter.get(CFG_CONNECTION_OVERLOAD, &conf.tcp.tcpOverloadLimit);
265
266 conf.type = tt_TCP_TRANSPORTER;
267
268 if(!tr.configureTransporter(&conf)){
269 ndbout_c("Failed to configure TCP Transporter to node %d",
270 conf.remoteNodeId);
271 result= false;
272 }
273 DBUG_PRINT("info", ("Configured TCP Transporter: sendBufferSize = %d, "
274 "maxReceiveSize = %d", conf.tcp.sendBufferSize,
275 conf.tcp.maxReceiveSize));
276 loopback_conf = conf; // reuse it...
277 break;
278 default:
279 ndbout << "Unknown transporter type from: " << nodeId <<
280 " to: " << remoteNodeId << endl;
281 break;
282 } // switch
283 } // for
284
285 if (transporter_to_self)
286 {
287 loopback_conf.remoteNodeId = nodeId;
288 loopback_conf.localNodeId = nodeId;
289 loopback_conf.serverNodeId = 0; // always client
290 loopback_conf.remoteHostName = "localhost";
291 loopback_conf.localHostName = "localhost";
292 loopback_conf.s_port = 1; // prevent asking ndb_mgmd for port...
293 if (!tr.configureTransporter(&loopback_conf))
294 {
295 ndbout_c("Failed to configure Loopback Transporter");
296 result= false;
297 }
298 }
299
300 DBUG_RETURN(result);
301 }
302
303