ConfigRetriever.cpp 8.29 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 40 41
#include <NdbAutoPtr.hpp>
 
#include <mgmapi.h>
#include <mgmapi_config_parameters.h>
#include <ConfigValues.hpp>
#include <NdbHost.h>
42 43 44 45

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

joreland@mysql.com's avatar
joreland@mysql.com committed
46
ConfigRetriever::ConfigRetriever(Uint32 version, Uint32 node_type) {
47
  
48
  m_handle= 0;
joreland@mysql.com's avatar
joreland@mysql.com committed
49 50
  m_version = version;
  m_node_type = node_type;
51 52 53
}

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

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


//****************************************************************************
//****************************************************************************
 
int 
joreland@mysql.com's avatar
joreland@mysql.com committed
66 67 68 69 70 71 72 73
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;
74 75
  }
  
joreland@mysql.com's avatar
joreland@mysql.com committed
76 77
  return _ownNodeId = _localConfig._ownNodeId;
}
78

joreland@mysql.com's avatar
joreland@mysql.com committed
79 80
int
ConfigRetriever::do_connect(){
81

joreland@mysql.com's avatar
joreland@mysql.com committed
82 83 84 85 86 87
  if(!m_handle)
    m_handle= ndb_mgm_create_handle();

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

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

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

joreland@mysql.com's avatar
joreland@mysql.com committed
128 129 130 131 132 133
//****************************************************************************
//****************************************************************************
//****************************************************************************
//****************************************************************************
struct ndb_mgm_configuration*
ConfigRetriever::getConfig() {
134

joreland@mysql.com's avatar
joreland@mysql.com committed
135
  struct ndb_mgm_configuration * p = 0;
136

joreland@mysql.com's avatar
joreland@mysql.com committed
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
  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;
    }
152
  }
joreland@mysql.com's avatar
joreland@mysql.com committed
153
  if(p == 0)
154
    return 0;
joreland@mysql.com's avatar
joreland@mysql.com committed
155 156 157 158
  
  if(!verifyConfig(p)){
    free(p);
    p= 0;
159
  }
joreland@mysql.com's avatar
joreland@mysql.com committed
160 161 162
  
  return p;
}
163

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

  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;
  }
  
205 206
  ConfigValuesFactory cvf;
  if(!cvf.unpack(buf2, bytes)){
207
    char buf[255];
208
    snprintf(buf, sizeof(buf), "Error while unpacking"); 
209 210 211 212 213 214
    setError(CR_ERROR, buf);
    delete []buf2;
    return 0;
  }
  delete [] buf2;

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

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


const char * 
ConfigRetriever::getErrorString(){
joreland@mysql.com's avatar
joreland@mysql.com committed
227
  return errorString.c_str();
228 229 230 231
}

void 
ConfigRetriever::setLocalConfigFileName(const char * localConfigFileName) {
joreland@mysql.com's avatar
joreland@mysql.com committed
232
  _localConfigFileName.assign(localConfigFileName ? localConfigFileName : "");
233 234 235 236
}

void 
ConfigRetriever::setConnectString(const char * connectString) {
joreland@mysql.com's avatar
joreland@mysql.com committed
237
  m_connectString.assign(connectString ? connectString : "");
238
}
239 240

bool
joreland@mysql.com's avatar
joreland@mysql.com committed
241 242
ConfigRetriever::verifyConfig(const struct ndb_mgm_configuration * conf){

243 244 245 246 247 248 249 250 251 252 253 254
  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);
  
joreland@mysql.com's avatar
joreland@mysql.com committed
255 256
  if(ndb_mgm_find(it, CFG_NODE_ID, _ownNodeId) != 0){
    snprintf(buf, 255, "Unable to find node with id: %d", _ownNodeId);
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275
    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;
  }

  char localhost[MAXHOSTNAMELEN];
  if(NdbHost_GetHostName(localhost) != 0){
    snprintf(buf, 255, "Unable to own hostname");
    setError(CR_ERROR, buf);
    return false;
  }

  do {
tomas@poseidon.bredbandsbolaget.se's avatar
tomas@poseidon.bredbandsbolaget.se committed
276 277 278
    if(strlen(hostname) == 0)
      break;

279 280 281 282 283 284 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
    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;
  }
  
joreland@mysql.com's avatar
joreland@mysql.com committed
313
  if(_type != m_node_type){
314
    snprintf(buf, 255, "Supplied node type(%d) and config node type(%d) "
joreland@mysql.com's avatar
joreland@mysql.com committed
315
	     " don't match", m_node_type, _type);
316 317 318
    setError(CR_ERROR, buf);
    return false;
  }
joreland@mysql.com's avatar
joreland@mysql.com committed
319

320 321
  return true;
}
joreland@mysql.com's avatar
joreland@mysql.com committed
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336

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;
}