/* 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 */ #include <ndb_global.h> #include <ndb_version.h> #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> #include <NdbAutoPtr.hpp> #include <mgmapi.h> #include <mgmapi_config_parameters.h> #include <ConfigValues.hpp> #include <NdbHost.h> //**************************************************************************** //**************************************************************************** ConfigRetriever::ConfigRetriever(Uint32 version, Uint32 node_type) { m_handle= 0; m_version = version; m_node_type = node_type; } ConfigRetriever::~ConfigRetriever(){ if (m_handle) { ndb_mgm_disconnect(m_handle); ndb_mgm_destroy_handle(&m_handle); } } //**************************************************************************** //**************************************************************************** int 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; } return _ownNodeId = _localConfig._ownNodeId; } int ConfigRetriever::do_connect(){ if(!m_handle) m_handle= ndb_mgm_create_handle(); if (m_handle == 0) { setError(CR_ERROR, "Unable to allocate mgm handle"); return -1; } int retry = 1; int retry_max = 12; // Max number of retry attempts int retry_interval= 5; // Seconds between each retry while(retry < retry_max){ Uint32 type = CR_ERROR; BaseString tmp; for (int i = 0; i<_localConfig.ids.size(); i++){ MgmtSrvrId * m = &_localConfig.ids[i]; switch(m->type){ case MgmId_TCP: tmp.assfmt("%s:%d", m->name.c_str(), m->port); if (ndb_mgm_connect(m_handle, tmp.c_str()) == 0) { return 0; } setError(CR_RETRY, ndb_mgm_get_latest_error_desc(m_handle)); case MgmId_File: break; } } if(latestErrorType == CR_RETRY){ REPORT_WARNING("Failed to retrieve cluster configuration"); ndbout << "(Cause of failure: " << getErrorString() << ")" << endl; ndbout << "Attempt " << retry << " of " << retry_max << ". " << "Trying again in "<< retry_interval <<" seconds..." << endl << endl; NdbSleep_SecSleep(retry_interval); } else { break; } retry++; } ndb_mgm_destroy_handle(&m_handle); m_handle= 0; return -1; } //**************************************************************************** //**************************************************************************** //**************************************************************************** //**************************************************************************** struct ndb_mgm_configuration* ConfigRetriever::getConfig() { struct ndb_mgm_configuration * p = 0; 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; } } if(p == 0) return 0; if(!verifyConfig(p)){ free(p); p= 0; } return p; } ndb_mgm_configuration * ConfigRetriever::getConfig(NdbMgmHandle m_handle){ ndb_mgm_configuration * conf = ndb_mgm_get_configuration(m_handle,m_version); if(conf == 0){ setError(CR_ERROR, ndb_mgm_get_latest_error_desc(m_handle)); return 0; } return conf; } ndb_mgm_configuration * ConfigRetriever::getConfig(const char * filename){ 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; } ConfigValuesFactory cvf; if(!cvf.unpack(buf2, bytes)){ char buf[255]; snprintf(buf, sizeof(buf), "Error while unpacking"); setError(CR_ERROR, buf); delete []buf2; return 0; } delete [] buf2; return (ndb_mgm_configuration*)cvf.m_cfg; } void ConfigRetriever::setError(ErrorType et, const char * s){ errorString.assign(s ? s : ""); latestErrorType = et; } const char * ConfigRetriever::getErrorString(){ return errorString.c_str(); } void ConfigRetriever::setLocalConfigFileName(const char * localConfigFileName) { _localConfigFileName.assign(localConfigFileName ? localConfigFileName : ""); } void ConfigRetriever::setConnectString(const char * connectString) { m_connectString.assign(connectString ? connectString : ""); } bool ConfigRetriever::verifyConfig(const struct ndb_mgm_configuration * conf){ 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); if(ndb_mgm_find(it, CFG_NODE_ID, _ownNodeId) != 0){ snprintf(buf, 255, "Unable to find node with id: %d", _ownNodeId); 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 { if(strlen(hostname) == 0) break; 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; } if(_type != m_node_type){ snprintf(buf, 255, "Supplied node type(%d) and config node type(%d) " " don't match", m_node_type, _type); setError(CR_ERROR, buf); return false; } return true; } 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; }