1 /* Copyright (c) 2003-2006 MySQL AB
2 Use is subject to license terms
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 as published by
6 the Free Software Foundation; version 2 of the License.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
16
17 #include <ndb_global.h>
18 #include <ndb_opt_defaults.h>
19 #include <IPCConfig.hpp>
20 #include <NdbOut.hpp>
21 #include <NdbHost.h>
22
23 #include <TransporterDefinitions.hpp>
24 #include <TransporterRegistry.hpp>
25 #include <Properties.hpp>
26
27 #include <mgmapi_configuration.hpp>
28 #include <mgmapi_config_parameters.h>
29
30 #if defined DEBUG_TRANSPORTER
31 #define DEBUG(t) ndbout << __FILE__ << ":" << __LINE__ << ":" << t << endl;
32 #else
33 #define DEBUG(t)
34 #endif
35
IPCConfig(Properties * p)36 IPCConfig::IPCConfig(Properties * p)
37 {
38 theNoOfRemoteNodes = 0;
39 the_ownId = 0;
40 if(p != 0)
41 props = new Properties(* p);
42 else
43 props = 0;
44 }
45
46
~IPCConfig()47 IPCConfig::~IPCConfig()
48 {
49 if(props != 0){
50 delete props;
51 }
52 }
53
54 int
init()55 IPCConfig::init(){
56 Uint32 nodeId;
57
58 if(props == 0) return -1;
59 if(!props->get("LocalNodeId", &nodeId)) {
60 DEBUG( "Did not find local node id." );
61 return -1;
62 }
63 the_ownId = nodeId;
64
65 Uint32 noOfConnections;
66 if(!props->get("NoOfConnections", &noOfConnections)) {
67 DEBUG( "Did not find noOfConnections." );
68 return -1;
69 }
70
71 for(Uint32 i = 0; i<noOfConnections; i++){
72 const Properties * tmp;
73 Uint32 node1, node2;
74
75 if(!props->get("Connection", i, &tmp)) {
76 DEBUG( "Did not find Connection." );
77 return -1;
78 }
79 if(!tmp->get("NodeId1", &node1)) {
80 DEBUG( "Did not find NodeId1." );
81 return -1;
82 }
83 if(!tmp->get("NodeId2", &node2)) {
84 DEBUG( "Did not find NodeId2." );
85 return -1;
86 }
87
88 if(node1 == the_ownId && node2 != the_ownId)
89 if(!addRemoteNodeId(node2)) {
90 DEBUG( "addRemoteNodeId(node2) failed." );
91 return -1;
92 }
93
94 if(node1 != the_ownId && node2 == the_ownId)
95 if(!addRemoteNodeId(node1)) {
96 DEBUG( "addRemoteNodeId(node2) failed." );
97 return -1;
98 }
99 }
100 return 0;
101 }
102
103 bool
addRemoteNodeId(NodeId nodeId)104 IPCConfig::addRemoteNodeId(NodeId nodeId){
105 for(int i = 0; i<theNoOfRemoteNodes; i++)
106 if(theRemoteNodeIds[i] == nodeId)
107 return false;
108 theRemoteNodeIds[theNoOfRemoteNodes] = nodeId;
109 theNoOfRemoteNodes++;
110 return true;
111 }
112
113 /**
114 * Supply a nodeId,
115 * and get next higher node id
116 * Returns false if none found
117 */
118 bool
getNextRemoteNodeId(NodeId & nodeId) const119 IPCConfig::getNextRemoteNodeId(NodeId & nodeId) const {
120 NodeId returnNode = MAX_NODES + 1;
121 for(int i = 0; i<theNoOfRemoteNodes; i++)
122 if(theRemoteNodeIds[i] > nodeId){
123 if(theRemoteNodeIds[i] < returnNode){
124 returnNode = theRemoteNodeIds[i];
125 }
126 }
127 if(returnNode == (MAX_NODES + 1))
128 return false;
129 nodeId = returnNode;
130 return true;
131 }
132
133
134 Uint32
getREPHBFrequency(NodeId id) const135 IPCConfig::getREPHBFrequency(NodeId id) const {
136 const Properties * tmp;
137 Uint32 out;
138
139 /**
140 * Todo: Fix correct heartbeat
141 */
142 if (!props->get("Node", id, &tmp) ||
143 !tmp->get("HeartbeatIntervalRepRep", &out)) {
144 DEBUG("Illegal Node or HeartbeatIntervalRepRep in config.");
145 out = 10000;
146 }
147
148 return out;
149 }
150
151 const char*
getNodeType(NodeId id) const152 IPCConfig::getNodeType(NodeId id) const {
153 const char * out;
154 const Properties * tmp;
155
156 if (!props->get("Node", id, &tmp) || !tmp->get("Type", &out)) {
157 DEBUG("Illegal Node or NodeType in config.");
158 out = "Unknown";
159 }
160
161 return out;
162 }
163
164 #include <mgmapi.h>
165 Uint32
configureTransporters(Uint32 nodeId,const class ndb_mgm_configuration & config,class TransporterRegistry & tr)166 IPCConfig::configureTransporters(Uint32 nodeId,
167 const class ndb_mgm_configuration & config,
168 class TransporterRegistry & tr){
169 TransporterConfiguration conf;
170
171 DBUG_ENTER("IPCConfig::configureTransporters");
172
173 /**
174 * Iterate over all MGM's an construct a connectstring
175 * create mgm_handle and give it to the Transporter Registry
176 */
177 {
178 const char *separator= "";
179 BaseString connect_string;
180 ndb_mgm_configuration_iterator iter(config, CFG_SECTION_NODE);
181 for(iter.first(); iter.valid(); iter.next())
182 {
183 Uint32 type;
184 if(iter.get(CFG_TYPE_OF_SECTION, &type)) continue;
185 if(type != NODE_TYPE_MGM) continue;
186 const char* hostname;
187 Uint32 port;
188 if(iter.get(CFG_NODE_HOST, &hostname)) continue;
189 if( strlen(hostname) == 0 ) continue;
190 if(iter.get(CFG_MGM_PORT, &port)) continue;
191 connect_string.appfmt("%s%s:%u",separator,hostname,port);
192 separator= ",";
193 }
194 NdbMgmHandle h= ndb_mgm_create_handle();
195 if ( h && connect_string.length() > 0 )
196 {
197 ndb_mgm_set_connectstring(h,connect_string.c_str());
198 tr.set_mgm_handle(h);
199 }
200 }
201
202 Uint32 noOfTransportersCreated= 0;
203 ndb_mgm_configuration_iterator iter(config, CFG_SECTION_CONNECTION);
204
205 for(iter.first(); iter.valid(); iter.next()){
206
207 Uint32 nodeId1, nodeId2, remoteNodeId;
208 const char * remoteHostName= 0, * localHostName= 0;
209 if(iter.get(CFG_CONNECTION_NODE_1, &nodeId1)) continue;
210 if(iter.get(CFG_CONNECTION_NODE_2, &nodeId2)) continue;
211
212 if(nodeId1 != nodeId && nodeId2 != nodeId) continue;
213 remoteNodeId = (nodeId == nodeId1 ? nodeId2 : nodeId1);
214
215 {
216 const char * host1= 0, * host2= 0;
217 iter.get(CFG_CONNECTION_HOSTNAME_1, &host1);
218 iter.get(CFG_CONNECTION_HOSTNAME_2, &host2);
219 localHostName = (nodeId == nodeId1 ? host1 : host2);
220 remoteHostName = (nodeId == nodeId1 ? host2 : host1);
221 }
222
223 Uint32 sendSignalId = 1;
224 Uint32 checksum = 1;
225 if(iter.get(CFG_CONNECTION_SEND_SIGNAL_ID, &sendSignalId)) continue;
226 if(iter.get(CFG_CONNECTION_CHECKSUM, &checksum)) continue;
227
228 Uint32 type = ~0;
229 if(iter.get(CFG_TYPE_OF_SECTION, &type)) continue;
230
231 Uint32 server_port= 0;
232 if(iter.get(CFG_CONNECTION_SERVER_PORT, &server_port)) break;
233
234 Uint32 nodeIdServer= 0;
235 if(iter.get(CFG_CONNECTION_NODE_ID_SERVER, &nodeIdServer)) break;
236
237 /*
238 We check the node type.
239 */
240 Uint32 node1type, node2type;
241 ndb_mgm_configuration_iterator node1iter(config, CFG_SECTION_NODE);
242 ndb_mgm_configuration_iterator node2iter(config, CFG_SECTION_NODE);
243 node1iter.find(CFG_NODE_ID,nodeId1);
244 node2iter.find(CFG_NODE_ID,nodeId2);
245 node1iter.get(CFG_TYPE_OF_SECTION,&node1type);
246 node2iter.get(CFG_TYPE_OF_SECTION,&node2type);
247
248 if(node1type==NODE_TYPE_MGM || node2type==NODE_TYPE_MGM)
249 conf.isMgmConnection= true;
250 else
251 conf.isMgmConnection= false;
252
253 if (nodeId == nodeIdServer && !conf.isMgmConnection) {
254 tr.add_transporter_interface(remoteNodeId, localHostName, server_port);
255 }
256
257 DBUG_PRINT("info", ("Transporter between this node %d and node %d using port %d, signalId %d, checksum %d",
258 nodeId, remoteNodeId, server_port, sendSignalId, checksum));
259 /*
260 This may be a dynamic port. It depends on when we're getting
261 our configuration. If we've been restarted, we'll be getting
262 a configuration with our old dynamic port in it, hence the number
263 here is negative (and we try the old port number first).
264
265 On a first-run, server_port will be zero (with dynamic ports)
266
267 If we're not using dynamic ports, we don't do anything.
268 */
269
270 conf.localNodeId = nodeId;
271 conf.remoteNodeId = remoteNodeId;
272 conf.checksum = checksum;
273 conf.signalId = sendSignalId;
274 conf.s_port = server_port;
275 conf.localHostName = localHostName;
276 conf.remoteHostName = remoteHostName;
277 conf.serverNodeId = nodeIdServer;
278
279 switch(type){
280 case CONNECTION_TYPE_SHM:
281 if(iter.get(CFG_SHM_KEY, &conf.shm.shmKey)) break;
282 if(iter.get(CFG_SHM_BUFFER_MEM, &conf.shm.shmSize)) break;
283
284 Uint32 tmp;
285 if(iter.get(CFG_SHM_SIGNUM, &tmp)) break;
286 conf.shm.signum= tmp;
287
288 if(!tr.createSHMTransporter(&conf)){
289 DBUG_PRINT("error", ("Failed to create SHM Transporter from %d to %d",
290 conf.localNodeId, conf.remoteNodeId));
291 ndbout << "Failed to create SHM Transporter from: "
292 << conf.localNodeId << " to: " << conf.remoteNodeId << endl;
293 } else {
294 noOfTransportersCreated++;
295 }
296 DBUG_PRINT("info", ("Created SHM Transporter using shmkey %d, "
297 "buf size = %d", conf.shm.shmKey, conf.shm.shmSize));
298
299 break;
300
301 case CONNECTION_TYPE_SCI:
302 if(iter.get(CFG_SCI_SEND_LIMIT, &conf.sci.sendLimit)) break;
303 if(iter.get(CFG_SCI_BUFFER_MEM, &conf.sci.bufferSize)) break;
304 if (nodeId == nodeId1) {
305 if(iter.get(CFG_SCI_HOST2_ID_0, &conf.sci.remoteSciNodeId0)) break;
306 if(iter.get(CFG_SCI_HOST2_ID_1, &conf.sci.remoteSciNodeId1)) break;
307 } else {
308 if(iter.get(CFG_SCI_HOST1_ID_0, &conf.sci.remoteSciNodeId0)) break;
309 if(iter.get(CFG_SCI_HOST1_ID_1, &conf.sci.remoteSciNodeId1)) break;
310 }
311 if (conf.sci.remoteSciNodeId1 == 0) {
312 conf.sci.nLocalAdapters = 1;
313 } else {
314 conf.sci.nLocalAdapters = 2;
315 }
316 if(!tr.createSCITransporter(&conf)){
317 DBUG_PRINT("error", ("Failed to create SCI Transporter from %d to %d",
318 conf.localNodeId, conf.remoteNodeId));
319 ndbout << "Failed to create SCI Transporter from: "
320 << conf.localNodeId << " to: " << conf.remoteNodeId << endl;
321 } else {
322 DBUG_PRINT("info", ("Created SCI Transporter: Adapters = %d, "
323 "remote SCI node id %d",
324 conf.sci.nLocalAdapters, conf.sci.remoteSciNodeId0));
325 DBUG_PRINT("info", ("Host 1 = %s, Host 2 = %s, sendLimit = %d, "
326 "buf size = %d", conf.localHostName,
327 conf.remoteHostName, conf.sci.sendLimit,
328 conf.sci.bufferSize));
329 if (conf.sci.nLocalAdapters > 1) {
330 DBUG_PRINT("info", ("Fault-tolerant with 2 Remote Adapters, "
331 "second remote SCI node id = %d",
332 conf.sci.remoteSciNodeId1));
333 }
334 noOfTransportersCreated++;
335 continue;
336 }
337 break;
338
339 case CONNECTION_TYPE_TCP:
340 if(iter.get(CFG_TCP_SEND_BUFFER_SIZE, &conf.tcp.sendBufferSize)) break;
341 if(iter.get(CFG_TCP_RECEIVE_BUFFER_SIZE, &conf.tcp.maxReceiveSize)) break;
342
343 const char * proxy;
344 if (!iter.get(CFG_TCP_PROXY, &proxy)) {
345 if (strlen(proxy) > 0 && nodeId2 == nodeId) {
346 // TODO handle host:port
347 conf.s_port = atoi(proxy);
348 }
349 }
350
351 if(!tr.createTCPTransporter(&conf)){
352 ndbout << "Failed to create TCP Transporter from: "
353 << nodeId << " to: " << remoteNodeId << endl;
354 } else {
355 noOfTransportersCreated++;
356 }
357 DBUG_PRINT("info", ("Created TCP Transporter: sendBufferSize = %d, "
358 "maxReceiveSize = %d", conf.tcp.sendBufferSize,
359 conf.tcp.maxReceiveSize));
360 break;
361 default:
362 ndbout << "Unknown transporter type from: " << nodeId <<
363 " to: " << remoteNodeId << endl;
364 break;
365 } // switch
366 } // for
367
368 DBUG_RETURN(noOfTransportersCreated);
369 }
370
371