MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
IPCConfig.cpp
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 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 St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 #include <ndb_global.h>
19 #include <IPCConfig.hpp>
20 
21 #include <TransporterRegistry.hpp>
22 
23 #include <mgmapi.h>
24 #include <mgmapi_configuration.hpp>
25 
26 
27 /* Return true if node with "nodeId" is a MGM node */
28 static bool is_mgmd(Uint32 nodeId,
29  const struct ndb_mgm_configuration & config)
30 {
31  ndb_mgm_configuration_iterator iter(config, CFG_SECTION_NODE);
32  if (iter.find(CFG_NODE_ID, nodeId))
33  abort();
34  Uint32 type;
35  if(iter.get(CFG_TYPE_OF_SECTION, &type))
36  abort();
37 
38  return (type == NODE_TYPE_MGM);
39 }
40 
41 
42 bool
44  const struct ndb_mgm_configuration & config,
45  class TransporterRegistry & tr,
46  bool transporter_to_self)
47 {
48  bool result= true;
49 
50  DBUG_ENTER("IPCConfig::configureTransporters");
51 
52 
53  if (!is_mgmd(nodeId, config))
54  {
55 
61  const char *separator= "";
62  BaseString connect_string;
63  ndb_mgm_configuration_iterator iter(config, CFG_SECTION_NODE);
64  for(iter.first(); iter.valid(); iter.next())
65  {
66  Uint32 type;
67  if(iter.get(CFG_TYPE_OF_SECTION, &type)) continue;
68  if(type != NODE_TYPE_MGM) continue;
69  const char* hostname;
70  Uint32 port;
71  if(iter.get(CFG_NODE_HOST, &hostname)) continue;
72  if( strlen(hostname) == 0 ) continue;
73  if(iter.get(CFG_MGM_PORT, &port)) continue;
74  connect_string.appfmt("%s%s:%u",separator,hostname,port);
75  separator= ",";
76  }
78  if ( h && connect_string.length() > 0 )
79  {
80  ndb_mgm_set_connectstring(h,connect_string.c_str());
81  tr.set_mgm_handle(h);
82  }
83  }
84 
85 
86  /* Remove transporter to nodes that does not exist anymore */
87  for (int i= 1; i < MAX_NODES; i++)
88  {
89  ndb_mgm_configuration_iterator iter(config, CFG_SECTION_NODE);
90  if (tr.get_transporter(i) && iter.find(CFG_NODE_ID, i))
91  {
92  // Transporter exist in TransporterRegistry but not
93  // in configuration
94  ndbout_c("The connection to node %d could not "
95  "be removed at this time", i);
96  result= false; // Need restart
97  }
98  }
99 
101  TransporterConfiguration loopback_conf;
102  ndb_mgm_configuration_iterator iter(config, CFG_SECTION_CONNECTION);
103  for(iter.first(); iter.valid(); iter.next()){
104 
105  bzero(&conf, sizeof(conf));
106  Uint32 nodeId1, nodeId2, remoteNodeId;
107  const char * remoteHostName= 0, * localHostName= 0;
108  if(iter.get(CFG_CONNECTION_NODE_1, &nodeId1)) continue;
109  if(iter.get(CFG_CONNECTION_NODE_2, &nodeId2)) continue;
110 
111  if(nodeId1 != nodeId && nodeId2 != nodeId) continue;
112  remoteNodeId = (nodeId == nodeId1 ? nodeId2 : nodeId1);
113 
114  if (nodeId1 == nodeId && nodeId2 == nodeId)
115  {
116  transporter_to_self = false; // One already present..ignore extra arg
117  }
118 
119  {
120  const char * host1= 0, * host2= 0;
121  iter.get(CFG_CONNECTION_HOSTNAME_1, &host1);
122  iter.get(CFG_CONNECTION_HOSTNAME_2, &host2);
123  localHostName = (nodeId == nodeId1 ? host1 : host2);
124  remoteHostName = (nodeId == nodeId1 ? host2 : host1);
125  }
126 
127  Uint32 sendSignalId = 1;
128  Uint32 checksum = 1;
129  if(iter.get(CFG_CONNECTION_SEND_SIGNAL_ID, &sendSignalId)) continue;
130  if(iter.get(CFG_CONNECTION_CHECKSUM, &checksum)) continue;
131 
132  Uint32 type = ~0;
133  if(iter.get(CFG_TYPE_OF_SECTION, &type)) continue;
134 
135  Uint32 server_port= 0;
136  if(iter.get(CFG_CONNECTION_SERVER_PORT, &server_port)) break;
137 
138  Uint32 nodeIdServer= 0;
139  if(iter.get(CFG_CONNECTION_NODE_ID_SERVER, &nodeIdServer)) break;
140 
141  if(is_mgmd(nodeId1, config) || is_mgmd(nodeId2, config))
142  {
143  // All connections with MGM uses the mgm port as server
144  conf.isMgmConnection= true;
145  }
146  else
147  conf.isMgmConnection= false;
148 
149  Uint32 bindInAddrAny = 0;
150  iter.get(CFG_TCP_BIND_INADDR_ANY, &bindInAddrAny);
151 
152  if (nodeId == nodeIdServer && !conf.isMgmConnection) {
153  tr.add_transporter_interface(remoteNodeId,
154  !bindInAddrAny ? localHostName : "",
155  server_port);
156  }
157 
158  DBUG_PRINT("info", ("Transporter between this node %d and node %d using port %d, signalId %d, checksum %d",
159  nodeId, remoteNodeId, server_port, sendSignalId, checksum));
160  /*
161  This may be a dynamic port. It depends on when we're getting
162  our configuration. If we've been restarted, we'll be getting
163  a configuration with our old dynamic port in it, hence the number
164  here is negative (and we try the old port number first).
165 
166  On a first-run, server_port will be zero (with dynamic ports)
167 
168  If we're not using dynamic ports, we don't do anything.
169  */
170 
171  conf.localNodeId = nodeId;
172  conf.remoteNodeId = remoteNodeId;
173  conf.checksum = checksum;
174  conf.signalId = sendSignalId;
175  conf.s_port = server_port;
176  conf.localHostName = localHostName;
177  conf.remoteHostName = remoteHostName;
178  conf.serverNodeId = nodeIdServer;
179 
180  switch(type){
181  case CONNECTION_TYPE_SHM:
182  if(iter.get(CFG_SHM_KEY, &conf.shm.shmKey)) break;
183  if(iter.get(CFG_SHM_BUFFER_MEM, &conf.shm.shmSize)) break;
184 
185  Uint32 signum;
186  if(iter.get(CFG_SHM_SIGNUM, &signum)) break;
187  conf.shm.signum= signum;
188 
189  conf.type = tt_SHM_TRANSPORTER;
190 
191  if(!tr.configureTransporter(&conf)){
192  DBUG_PRINT("error", ("Failed to configure SHM Transporter "
193  "from %d to %d",
194  conf.localNodeId, conf.remoteNodeId));
195  ndbout_c("Failed to configure SHM Transporter to node %d",
196  conf.remoteNodeId);
197  result = false;
198  }
199  DBUG_PRINT("info", ("Configured SHM Transporter using shmkey %d, "
200  "buf size = %d", conf.shm.shmKey, conf.shm.shmSize));
201  break;
202 
203  case CONNECTION_TYPE_SCI:
204  if(iter.get(CFG_SCI_SEND_LIMIT, &conf.sci.sendLimit)) break;
205  if(iter.get(CFG_SCI_BUFFER_MEM, &conf.sci.bufferSize)) break;
206  if (nodeId == nodeId1) {
207  if(iter.get(CFG_SCI_HOST2_ID_0, &conf.sci.remoteSciNodeId0)) break;
208  if(iter.get(CFG_SCI_HOST2_ID_1, &conf.sci.remoteSciNodeId1)) break;
209  } else {
210  if(iter.get(CFG_SCI_HOST1_ID_0, &conf.sci.remoteSciNodeId0)) break;
211  if(iter.get(CFG_SCI_HOST1_ID_1, &conf.sci.remoteSciNodeId1)) break;
212  }
213  if (conf.sci.remoteSciNodeId1 == 0) {
214  conf.sci.nLocalAdapters = 1;
215  } else {
216  conf.sci.nLocalAdapters = 2;
217  }
218  conf.type = tt_SCI_TRANSPORTER;
219  if(!tr.configureTransporter(&conf)){
220  DBUG_PRINT("error", ("Failed to configure SCI Transporter "
221  "from %d to %d",
222  conf.localNodeId, conf.remoteNodeId));
223  ndbout_c("Failed to configure SCI Transporter to node %d",
224  conf.remoteNodeId);
225  result = false;
226  } else {
227  DBUG_PRINT("info", ("Configured SCI Transporter: Adapters = %d, "
228  "remote SCI node id %d",
229  conf.sci.nLocalAdapters, conf.sci.remoteSciNodeId0));
230  DBUG_PRINT("info", ("Host 1 = %s, Host 2 = %s, sendLimit = %d, "
231  "buf size = %d", conf.localHostName,
232  conf.remoteHostName, conf.sci.sendLimit,
233  conf.sci.bufferSize));
234  if (conf.sci.nLocalAdapters > 1) {
235  DBUG_PRINT("info", ("Fault-tolerant with 2 Remote Adapters, "
236  "second remote SCI node id = %d",
237  conf.sci.remoteSciNodeId1));
238  }
239  }
240  break;
241 
242  case CONNECTION_TYPE_TCP:
243  if(iter.get(CFG_TCP_SEND_BUFFER_SIZE, &conf.tcp.sendBufferSize)) break;
244  if(iter.get(CFG_TCP_RECEIVE_BUFFER_SIZE, &conf.tcp.maxReceiveSize)) break;
245 
246  const char * proxy;
247  if (!iter.get(CFG_TCP_PROXY, &proxy)) {
248  if (strlen(proxy) > 0 && nodeId2 == nodeId) {
249  // TODO handle host:port
250  conf.s_port = atoi(proxy);
251  }
252  }
253 
254  iter.get(CFG_TCP_SND_BUF_SIZE, &conf.tcp.tcpSndBufSize);
255  iter.get(CFG_TCP_RCV_BUF_SIZE, &conf.tcp.tcpRcvBufSize);
256  iter.get(CFG_TCP_MAXSEG_SIZE, &conf.tcp.tcpMaxsegSize);
257  iter.get(CFG_CONNECTION_OVERLOAD, &conf.tcp.tcpOverloadLimit);
258 
259  conf.type = tt_TCP_TRANSPORTER;
260 
261  if(!tr.configureTransporter(&conf)){
262  ndbout_c("Failed to configure TCP Transporter to node %d",
263  conf.remoteNodeId);
264  result= false;
265  }
266  DBUG_PRINT("info", ("Configured TCP Transporter: sendBufferSize = %d, "
267  "maxReceiveSize = %d", conf.tcp.sendBufferSize,
268  conf.tcp.maxReceiveSize));
269  loopback_conf = conf; // reuse it...
270  break;
271  default:
272  ndbout << "Unknown transporter type from: " << nodeId <<
273  " to: " << remoteNodeId << endl;
274  break;
275  } // switch
276  } // for
277 
278  if (transporter_to_self)
279  {
280  loopback_conf.remoteNodeId = nodeId;
281  loopback_conf.localNodeId = nodeId;
282  loopback_conf.serverNodeId = 0; // always client
283  loopback_conf.remoteHostName = "localhost";
284  loopback_conf.localHostName = "localhost";
285  loopback_conf.s_port = 1; // prevent asking ndb_mgmd for port...
286  if (!tr.configureTransporter(&loopback_conf))
287  {
288  ndbout_c("Failed to configure Loopback Transporter");
289  result= false;
290  }
291  }
292 
293  DBUG_RETURN(result);
294 }
295