ConfigRetriever.cpp 9.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/* Copyright (C) 2003 MySQL AB

   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 2 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, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

17 18 19
#include <ndb_global.h>
#include <ndb_version.h>

20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
#include <ConfigRetriever.hpp>

#include "LocalConfig.hpp"
#include <NdbSleep.h>
#include <NdbOut.hpp>

#include <NdbTCP.h>
#include <NdbEnv.h>
#include "MgmtErrorReporter.hpp"

#include <uucode.h>
#include <Properties.hpp>

#include <socket_io.h>
#include <NdbConfig.h>

36 37 38 39
#include <NdbAutoPtr.hpp>
 
#include <mgmapi.h>
#include <mgmapi_config_parameters.h>
40
#include <mgmapi_configuration.hpp>
41 42
#include <ConfigValues.hpp>
#include <NdbHost.h>
43 44 45 46

//****************************************************************************
//****************************************************************************

unknown's avatar
unknown committed
47
ConfigRetriever::ConfigRetriever(Uint32 version, Uint32 node_type) {
48
  
49
  m_handle= 0;
unknown's avatar
unknown committed
50 51
  m_version = version;
  m_node_type = node_type;
52 53 54
}

ConfigRetriever::~ConfigRetriever(){
55 56 57 58 59

  if (m_handle) {
    ndb_mgm_disconnect(m_handle);
    ndb_mgm_destroy_handle(&m_handle);
  }
60 61 62 63 64 65 66
}


//****************************************************************************
//****************************************************************************
 
int 
unknown's avatar
unknown committed
67 68 69 70 71 72 73 74
ConfigRetriever::init() {
  if (!_localConfig.init(m_connectString.c_str(), 
			 _localConfigFileName.c_str())){
    
    setError(CR_ERROR, "error in retrieving contact info for mgmtsrvr");
    _localConfig.printError();
    _localConfig.printUsage();
    return -1;
75 76
  }
  
unknown's avatar
unknown committed
77 78
  return _ownNodeId = _localConfig._ownNodeId;
}
79

unknown's avatar
unknown committed
80 81
int
ConfigRetriever::do_connect(){
82

unknown's avatar
unknown committed
83 84 85 86 87 88
  if(!m_handle)
    m_handle= ndb_mgm_create_handle();

  if (m_handle == 0) {
    setError(CR_ERROR, "Unable to allocate mgm handle");
    return -1;
89 90 91 92 93
  }

  int retry = 1;
  int retry_max = 12;    // Max number of retry attempts
  int retry_interval= 5; // Seconds between each retry
unknown's avatar
unknown committed
94
  while(retry < retry_max){
95
    Uint32 type = CR_ERROR;
unknown's avatar
unknown committed
96 97 98
    BaseString tmp;
    for (int i = 0; i<_localConfig.ids.size(); i++){
      MgmtSrvrId * m = &_localConfig.ids[i];
99 100
      switch(m->type){
      case MgmId_TCP:
unknown's avatar
unknown committed
101 102
	tmp.assfmt("%s:%d", m->name.c_str(), m->port);
	if (ndb_mgm_connect(m_handle, tmp.c_str()) == 0) {
103 104
	  return 0;
	}
unknown's avatar
unknown committed
105 106 107
	setError(CR_RETRY, ndb_mgm_get_latest_error_desc(m_handle));
      case MgmId_File:
	break;
108
      }
unknown's avatar
unknown committed
109 110 111
    }

    if(latestErrorType == CR_RETRY){
112 113 114
      REPORT_WARNING("Failed to retrieve cluster configuration");
      ndbout << "(Cause of failure: " << getErrorString() << ")" << endl;
      ndbout << "Attempt " << retry << " of " << retry_max << ". " 
115 116
	     << "Trying again in "<< retry_interval <<" seconds..." 
	     << endl << endl;
117 118 119 120 121
      NdbSleep_SecSleep(retry_interval);
    } else {
      break;
    }
    retry++;
unknown's avatar
unknown committed
122
  }
123
  
unknown's avatar
unknown committed
124 125 126
  ndb_mgm_destroy_handle(&m_handle);
  m_handle= 0;
  return -1;
127 128
}

unknown's avatar
unknown committed
129 130 131 132 133 134
//****************************************************************************
//****************************************************************************
//****************************************************************************
//****************************************************************************
struct ndb_mgm_configuration*
ConfigRetriever::getConfig() {
135

unknown's avatar
unknown committed
136
  struct ndb_mgm_configuration * p = 0;
137

unknown's avatar
unknown committed
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
  if(m_handle != 0){
    p = getConfig(m_handle);
  } else {
    for (int i = 0; i<_localConfig.ids.size(); i++){
      MgmtSrvrId * m = &_localConfig.ids[i];
      switch(m->type){
      case MgmId_File:
	p = getConfig(m->name.c_str());
	break;
      case MgmId_TCP:
	break;
      }
      if(p)
	break;
    }
153
  }
unknown's avatar
unknown committed
154
  if(p == 0)
155
    return 0;
unknown's avatar
unknown committed
156
  
157
  if(!verifyConfig(p, _ownNodeId)){
unknown's avatar
unknown committed
158 159
    free(p);
    p= 0;
160
  }
unknown's avatar
unknown committed
161 162 163
  
  return p;
}
164

unknown's avatar
unknown committed
165 166 167 168
ndb_mgm_configuration *
ConfigRetriever::getConfig(NdbMgmHandle m_handle){
  
  ndb_mgm_configuration * conf = ndb_mgm_get_configuration(m_handle,m_version);
169
  if(conf == 0){
170
    setError(CR_ERROR, ndb_mgm_get_latest_error_desc(m_handle));
unknown's avatar
unknown committed
171 172
    return 0;
  }
unknown's avatar
unknown committed
173
  
174
  return conf;
175 176
}
	
177
ndb_mgm_configuration *
unknown's avatar
unknown committed
178
ConfigRetriever::getConfig(const char * filename){
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

  struct stat sbuf;
  const int res = stat(filename, &sbuf);
  if(res != 0){
    char buf[255];
    snprintf(buf, sizeof(buf), "Could not find file: \"%s\"", filename);
    setError(CR_ERROR, buf);
    return 0;
  }
  const Uint32 bytes = sbuf.st_size;
  
  Uint32 * buf2 = new Uint32[bytes/4+1];
  
  FILE * f = fopen(filename, "rb");
  if(f == 0){
    setError(CR_ERROR, "Failed to open file");
    delete []buf2;
    return 0;
  }
  Uint32 sz = fread(buf2, 1, bytes, f);
  fclose(f);
  if(sz != bytes){
    setError(CR_ERROR, "Failed to read file");
    delete []buf2;
    return 0;
  }
  
206 207
  ConfigValuesFactory cvf;
  if(!cvf.unpack(buf2, bytes)){
208
    char buf[255];
209
    snprintf(buf, sizeof(buf), "Error while unpacking"); 
210 211 212 213 214 215
    setError(CR_ERROR, buf);
    delete []buf2;
    return 0;
  }
  delete [] buf2;

216
  return (ndb_mgm_configuration*)cvf.m_cfg;
217 218 219 220
}			   

void
ConfigRetriever::setError(ErrorType et, const char * s){
unknown's avatar
unknown committed
221
  errorString.assign(s ? s : "");
222 223 224 225 226 227
  latestErrorType = et;
}


const char * 
ConfigRetriever::getErrorString(){
unknown's avatar
unknown committed
228
  return errorString.c_str();
229 230 231 232
}

void 
ConfigRetriever::setLocalConfigFileName(const char * localConfigFileName) {
unknown's avatar
unknown committed
233
  _localConfigFileName.assign(localConfigFileName ? localConfigFileName : "");
234 235 236 237
}

void 
ConfigRetriever::setConnectString(const char * connectString) {
unknown's avatar
unknown committed
238
  m_connectString.assign(connectString ? connectString : "");
239
}
240 241

bool
242
ConfigRetriever::verifyConfig(const struct ndb_mgm_configuration * conf, Uint32 nodeid){
unknown's avatar
unknown committed
243

244 245 246 247 248 249 250 251 252 253 254 255
  char buf[255];
  ndb_mgm_configuration_iterator * it;
  it = ndb_mgm_create_configuration_iterator((struct ndb_mgm_configuration *)conf, CFG_SECTION_NODE);

  if(it == 0){
    snprintf(buf, 255, "Unable to create config iterator");
    setError(CR_ERROR, buf);
    return false;
    
  }
  NdbAutoPtr<ndb_mgm_configuration_iterator> ptr(it);
  
256 257
  if(ndb_mgm_find(it, CFG_NODE_ID, nodeid) != 0){
    snprintf(buf, 255, "Unable to find node with id: %d", nodeid);
258 259 260 261 262 263 264 265 266 267 268
    setError(CR_ERROR, buf);
    return false;
  }
     
  const char * hostname;
  if(ndb_mgm_get_string_parameter(it, CFG_NODE_HOST, &hostname)){
    snprintf(buf, 255, "Unable to get hostname(%d) from config",CFG_NODE_HOST);
    setError(CR_ERROR, buf);
    return false;
  }

269 270 271 272 273
  const char * datadir;
  if(!ndb_mgm_get_string_parameter(it, CFG_NODE_DATADIR, &datadir)){
    NdbConfig_SetPath(datadir);
  }

274 275
  char localhost[MAXHOSTNAMELEN];
  if(NdbHost_GetHostName(localhost) != 0){
276
    snprintf(buf, 255, "Unable to get own hostname");
277 278 279 280 281
    setError(CR_ERROR, buf);
    return false;
  }

  do {
unknown's avatar
unknown committed
282 283 284
    if(strlen(hostname) == 0)
      break;

285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318
    if(strcasecmp(hostname, localhost) == 0)
      break;

    if(strcasecmp(hostname, "localhost") == 0)
      break;

    struct in_addr local, config;
    bool b1 = false, b2 = false, b3 = false;
    b1 = Ndb_getInAddr(&local, localhost) == 0;
    b2 = Ndb_getInAddr(&config, hostname) == 0;
    b3 = memcmp(&local, &config, sizeof(local)) == 0;

    if(b1 && b2 && b3)
      break;
    
    b1 = Ndb_getInAddr(&local, "localhost") == 0;
    b3 = memcmp(&local, &config, sizeof(local)) == 0;
    if(b1 && b2 && b3)
      break;
    
    snprintf(buf, 255, "Local hostname(%s) and config hostname(%s) dont match",
	     localhost, hostname);
    setError(CR_ERROR, buf);
    return false;
  } while(false);

  unsigned int _type;
  if(ndb_mgm_get_int_parameter(it, CFG_TYPE_OF_SECTION, &_type)){
    snprintf(buf, 255, "Unable to get type of node(%d) from config",
	     CFG_TYPE_OF_SECTION);
    setError(CR_ERROR, buf);
    return false;
  }
  
unknown's avatar
unknown committed
319
  if(_type != m_node_type){
320
    snprintf(buf, 255, "Supplied node type(%d) and config node type(%d) "
unknown's avatar
unknown committed
321
	     " don't match", m_node_type, _type);
322 323 324
    setError(CR_ERROR, buf);
    return false;
  }
unknown's avatar
unknown committed
325

326 327 328 329 330 331 332 333 334 335 336 337 338 339
  /**
   * Check hostnames
   */
  ndb_mgm_configuration_iterator iter(* conf, CFG_SECTION_CONNECTION);
  for(iter.first(); iter.valid(); iter.next()){

    Uint32 type = CONNECTION_TYPE_TCP + 1;
    if(iter.get(CFG_TYPE_OF_SECTION, &type)) continue;
    if(type != CONNECTION_TYPE_TCP) continue;
    
    Uint32 nodeId1, nodeId2, remoteNodeId;
    if(iter.get(CFG_CONNECTION_NODE_1, &nodeId1)) continue;
    if(iter.get(CFG_CONNECTION_NODE_2, &nodeId2)) continue;
    
340 341
    if(nodeId1 != nodeid && nodeId2 != nodeid) continue;
    remoteNodeId = (nodeid == nodeId1 ? nodeId2 : nodeId1);
342 343 344 345 346 347 348 349

    const char * name;
    struct in_addr addr;
    BaseString tmp;
    if(!iter.get(CFG_TCP_HOSTNAME_1, &name) && strlen(name)){
      if(Ndb_getInAddr(&addr, name) != 0){
	tmp.assfmt("Unable to lookup/illegal hostname %s, "
		   "connection from node %d to node %d",
350
		   name, nodeid, remoteNodeId);
351 352 353 354 355 356 357 358 359
	setError(CR_ERROR, tmp.c_str());
	return false;
      }
    }

    if(!iter.get(CFG_TCP_HOSTNAME_2, &name) && strlen(name)){
      if(Ndb_getInAddr(&addr, name) != 0){
	tmp.assfmt("Unable to lookup/illegal hostname %s, "
		   "connection from node %d to node %d",
360
		   name, nodeid, remoteNodeId);
361 362 363 364 365
	setError(CR_ERROR, tmp.c_str());
	return false;
      }
    }
  }
366 367
  return true;
}
unknown's avatar
unknown committed
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382

Uint32
ConfigRetriever::allocNodeId(){
  unsigned nodeid= _ownNodeId;
  
  if(m_handle != 0){
    int res= ndb_mgm_alloc_nodeid(m_handle, m_version, &nodeid, m_node_type);
    if(res != 0) {
      setError(CR_ERROR, ndb_mgm_get_latest_error_desc(m_handle));
      return 0;
    }
  }
  
  return _ownNodeId= nodeid;
}