MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ConfigRetriever.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 
20 #include <ConfigRetriever.hpp>
21 
22 #include <SocketServer.hpp>
23 #include <NdbSleep.h>
24 
25 #include <mgmapi.h>
26 #include <mgmapi_config_parameters.h>
27 #include <mgmapi_configuration.hpp>
28 #include <mgmapi_internal.h>
29 #include <ConfigValues.hpp>
30 
31 
32 //****************************************************************************
33 //****************************************************************************
34 
35 ConfigRetriever::ConfigRetriever(const char * _connect_string,
36  int force_nodeid,
37  Uint32 version,
38  ndb_mgm_node_type node_type,
39  const char * _bindaddress,
40  int timeout_ms) :
41  m_end_session(true),
42  m_version(version),
43  m_node_type(node_type)
44 {
45  DBUG_ENTER("ConfigRetriever::ConfigRetriever");
46  DBUG_PRINT("enter", ("connect_string: '%s', force_nodeid: %d",
47  _connect_string, force_nodeid));
48  DBUG_PRINT("enter", ("version: %d, node_type: %d, bind: %s, timeout: %d",
49  version, node_type,_bindaddress, timeout_ms));
50 
51  m_handle= ndb_mgm_create_handle();
52 
53  if (m_handle == 0) {
54  setError(CR_ERROR, "Unable to allocate mgm handle");
55  DBUG_VOID_RETURN;
56  }
57 
58  ndb_mgm_set_timeout(m_handle, timeout_ms);
59 
60  if (ndb_mgm_set_connectstring(m_handle, _connect_string))
61  {
63  tmp.append(" : ");
64  tmp.append(ndb_mgm_get_latest_error_desc(m_handle));
65  setError(CR_ERROR, tmp.c_str());
66  DBUG_VOID_RETURN;
67  }
68 
69  if (force_nodeid &&
70  ndb_mgm_set_configuration_nodeid(m_handle, force_nodeid))
71  {
72  setError(CR_ERROR, "Failed to set forced nodeid");
73  DBUG_VOID_RETURN;
74  }
75 
76  if (_bindaddress)
77  {
78  if (ndb_mgm_set_bindaddress(m_handle, _bindaddress))
79  {
80  setError(CR_ERROR, ndb_mgm_get_latest_error_desc(m_handle));
81  DBUG_VOID_RETURN;
82  }
83  }
84  resetError();
85  DBUG_VOID_RETURN;
86 }
87 
88 ConfigRetriever::~ConfigRetriever()
89 {
90  DBUG_ENTER("ConfigRetriever::~ConfigRetriever");
91  if (m_handle) {
92  if (ndb_mgm_is_connected(m_handle)) {
93  if(m_end_session)
94  ndb_mgm_end_session(m_handle);
95  ndb_mgm_disconnect(m_handle);
96  }
97  ndb_mgm_destroy_handle(&m_handle);
98  }
99  DBUG_VOID_RETURN;
100 }
101 
102 Uint32
103 ConfigRetriever::get_configuration_nodeid() const
104 {
105  return ndb_mgm_get_configuration_nodeid(m_handle);
106 }
107 
108 Uint32 ConfigRetriever::get_mgmd_port() const
109 {
110  return ndb_mgm_get_connected_port(m_handle);
111 }
112 
113 const char *ConfigRetriever::get_mgmd_host() const
114 {
115  return ndb_mgm_get_connected_host(m_handle);
116 }
117 
118 const char *ConfigRetriever::get_connectstring(char *buf, int buf_sz) const
119 {
120  return ndb_mgm_get_connectstring(m_handle, buf, buf_sz);
121 }
122 
123 //****************************************************************************
124 //****************************************************************************
125 
126 int
127 ConfigRetriever::do_connect(int no_retries,
128  int retry_delay_in_seconds, int verbose)
129 {
130  return
131  (ndb_mgm_connect(m_handle,no_retries,retry_delay_in_seconds,verbose)==0) ?
132  0 : -1;
133 }
134 
135 int
136 ConfigRetriever::disconnect()
137 {
138  return ndb_mgm_disconnect(m_handle);
139 }
140 
141 bool
142 ConfigRetriever::is_connected(void)
143 {
144  return (ndb_mgm_is_connected(m_handle) != 0);
145 }
146 
147 //****************************************************************************
148 //****************************************************************************
149 //****************************************************************************
150 //****************************************************************************
151 struct ndb_mgm_configuration*
153 
154  struct ndb_mgm_configuration * p = 0;
155 
156  if(m_handle != 0)
157  p = getConfig(m_handle);
158 
159  if(p == 0)
160  return 0;
161 
162  if(!verifyConfig(p, nodeid)){
163  free(p);
164  p= 0;
165  }
166 
167  return p;
168 }
169 
172 {
173  const int from_node = 0;
174  ndb_mgm_configuration * conf =
175  ndb_mgm_get_configuration2(mgm_handle,
176  m_version,
177  m_node_type,
178  from_node);
179  if(conf == 0)
180  {
181  BaseString tmp(ndb_mgm_get_latest_error_msg(mgm_handle));
182  tmp.append(" : ");
183  tmp.append(ndb_mgm_get_latest_error_desc(mgm_handle));
184  setError(CR_ERROR, tmp.c_str());
185  return 0;
186  }
187  return conf;
188 }
189 
191 ConfigRetriever::getConfig(const char * filename)
192 {
193  if (access(filename, F_OK))
194  {
195  BaseString err;
196  err.assfmt("Could not find file: '%s'", filename);
197  setError(CR_ERROR, err);
198  return 0;
199  }
200 
201  FILE * f = fopen(filename, "rb");
202  if(f == 0)
203  {
204  setError(CR_ERROR, "Failed to open file");
205  return 0;
206  }
207 
208  size_t read_sz;
209  char read_buf[512];
210  UtilBuffer config_buf;
211  while ((read_sz = fread(read_buf, 1, sizeof(read_buf), f)) != 0)
212  {
213  if (config_buf.append(read_buf, read_sz) != 0)
214  {
215  setError(CR_ERROR, "Out of memory when appending read data");
216  fclose(f);
217  return 0;
218  }
219  }
220  fclose(f);
221 
223  if(!cvf.unpack(config_buf))
224  {
225  setError(CR_ERROR, "Error while unpacking");
226  return 0;
227  }
228  return (ndb_mgm_configuration*)cvf.getConfigValues();
229 }
230 
231 void
232 ConfigRetriever::setError(ErrorType et, const char * s){
233  errorString.assign(s ? s : "");
234  latestErrorType = et;
235  DBUG_PRINT("info", ("latestErrorType: %u, '%s'",
236  latestErrorType, errorString.c_str()));
237 }
238 
239 void
240 ConfigRetriever::setError(ErrorType et, BaseString err){
241  setError(et, err.c_str());
242 }
243 
244 void
245 ConfigRetriever::resetError(){
246  setError(CR_NO_ERROR,0);
247 }
248 
249 int
250 ConfigRetriever::hasError()
251 {
252  return latestErrorType != CR_NO_ERROR;
253 }
254 
255 const char *
256 ConfigRetriever::getErrorString(){
257  return errorString.c_str();
258 }
259 
260 
261 bool
263  Uint32 nodeid)
264 {
265  char buf[255];
266  ndb_mgm_configuration_iterator it(* conf, CFG_SECTION_NODE);
267 
268  if(it.find(CFG_NODE_ID, nodeid)){
269  BaseString::snprintf(buf, 255, "Unable to find node with id: %d", nodeid);
270  setError(CR_ERROR, buf);
271  return false;
272  }
273 
274  const char * hostname;
275  if(it.get(CFG_NODE_HOST, &hostname)){
276  BaseString::snprintf(buf, 255, "Unable to get hostname(%d) from config",
277  CFG_NODE_HOST);
278  setError(CR_ERROR, buf);
279  return false;
280  }
281 
282  if (hostname && hostname[0] != 0 &&
283  !SocketServer::tryBind(0,hostname)) {
284  BaseString::snprintf(buf, 255,
285  "The hostname this node should have according "
286  "to the configuration does not match a local "
287  "interface. Attempt to bind '%s' "
288  "failed with error: %d '%s'",
289  hostname, errno, strerror(errno));
290  setError(CR_ERROR, buf);
291  return false;
292  }
293 
294  unsigned int _type;
295  if(it.get(CFG_TYPE_OF_SECTION, &_type)){
296  BaseString::snprintf(buf, 255, "Unable to get type of node(%d) from config",
297  CFG_TYPE_OF_SECTION);
298  setError(CR_ERROR, buf);
299  return false;
300  }
301 
302  if(_type != (unsigned int)m_node_type){
303  const char *type_s, *alias_s, *type_s2, *alias_s2;
304  alias_s=
306  &type_s);
307  alias_s2=
309  &type_s2);
310  BaseString::snprintf(buf, 255,
311  "This node type %s(%s) and config "
312  "node type %s(%s) don't match for nodeid %d",
313  alias_s, type_s, alias_s2, type_s2, nodeid);
314  setError(CR_ERROR, buf);
315  return false;
316  }
317 
321  ndb_mgm_configuration_iterator iter(* conf, CFG_SECTION_CONNECTION);
322  for(iter.first(); iter.valid(); iter.next()){
323 
324  Uint32 type = CONNECTION_TYPE_TCP + 1;
325  if(iter.get(CFG_TYPE_OF_SECTION, &type)) continue;
326  if(type != CONNECTION_TYPE_TCP) continue;
327 
328  Uint32 nodeId1, nodeId2, remoteNodeId;
329  if(iter.get(CFG_CONNECTION_NODE_1, &nodeId1)) continue;
330  if(iter.get(CFG_CONNECTION_NODE_2, &nodeId2)) continue;
331 
332  if(nodeId1 != nodeid && nodeId2 != nodeid) continue;
333  remoteNodeId = (nodeid == nodeId1 ? nodeId2 : nodeId1);
334 
335  const char * name;
336  struct in_addr addr;
337  BaseString tmp;
338  if(!iter.get(CFG_CONNECTION_HOSTNAME_1, &name) && strlen(name)){
339  if(Ndb_getInAddr(&addr, name) != 0){
340  tmp.assfmt("Unable to lookup/illegal hostname %s, "
341  "connection from node %d to node %d",
342  name, nodeid, remoteNodeId);
343  setError(CR_ERROR, tmp.c_str());
344  return false;
345  }
346  }
347 
348  if(!iter.get(CFG_CONNECTION_HOSTNAME_2, &name) && strlen(name)){
349  if(Ndb_getInAddr(&addr, name) != 0){
350  tmp.assfmt("Unable to lookup/illegal hostname %s, "
351  "connection from node %d to node %d",
352  name, nodeid, remoteNodeId);
353  setError(CR_ERROR, tmp.c_str());
354  return false;
355  }
356  }
357  }
358 
359  return true;
360 }
361 
362 int
363 ConfigRetriever::setNodeId(Uint32 nodeid)
364 {
365  return ndb_mgm_set_configuration_nodeid(m_handle, nodeid);
366 }
367 
368 Uint32
369 ConfigRetriever::allocNodeId(int no_retries, int retry_delay_in_seconds)
370 {
371  int res;
372  if(m_handle != 0)
373  {
374  while (1)
375  {
376  if(!ndb_mgm_is_connected(m_handle))
377  if(!ndb_mgm_connect(m_handle, 0, 0, 0))
378  goto next;
379 
380  res= ndb_mgm_alloc_nodeid(m_handle, m_version, m_node_type,
381  no_retries == 0 /* only log last retry */);
382  if(res >= 0)
383  return (Uint32)res;
384 
385  next:
386  int error = ndb_mgm_get_latest_error(m_handle);
387  if (no_retries == 0 || error == NDB_MGM_ALLOCID_CONFIG_MISMATCH)
388  break;
389  no_retries--;
390  NdbSleep_SecSleep(retry_delay_in_seconds);
391  }
393  tmp.append(" : ");
394  tmp.append(ndb_mgm_get_latest_error_desc(m_handle));
395  setError(CR_ERROR, tmp.c_str());
396  } else
397  setError(CR_ERROR, "management server handle not initialized");
398  return 0;
399 }