ConfigRetriever.cpp

Go to the documentation of this file.
00001 /* Copyright (C) 2003 MySQL AB
00002 
00003    This program is free software; you can redistribute it and/or modify
00004    it under the terms of the GNU General Public License as published by
00005    the Free Software Foundation; either version 2 of the License, or
00006    (at your option) any later version.
00007 
00008    This program is distributed in the hope that it will be useful,
00009    but WITHOUT ANY WARRANTY; without even the implied warranty of
00010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011    GNU General Public License for more details.
00012 
00013    You should have received a copy of the GNU General Public License
00014    along with this program; if not, write to the Free Software
00015    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
00016 
00017 #include <ndb_global.h>
00018 #include <ndb_version.h>
00019 
00020 #include <ConfigRetriever.hpp>
00021 #include <SocketServer.hpp>
00022 
00023 #include <NdbSleep.h>
00024 #include <NdbOut.hpp>
00025 
00026 #include <NdbTCP.h>
00027 #include <NdbEnv.h>
00028 #include "MgmtErrorReporter.hpp"
00029 
00030 #include <uucode.h>
00031 #include <Properties.hpp>
00032 
00033 #include <socket_io.h>
00034 #include <NdbConfig.h>
00035 
00036 #include <NdbAutoPtr.hpp>
00037  
00038 #include <mgmapi.h>
00039 #include <mgmapi_config_parameters.h>
00040 #include <mgmapi_configuration.hpp>
00041 #include <ConfigValues.hpp>
00042 #include <NdbHost.h>
00043 
00044 //****************************************************************************
00045 //****************************************************************************
00046 
00047 ConfigRetriever::ConfigRetriever(const char * _connect_string,
00048                                  Uint32 version, Uint32 node_type)
00049 {
00050   m_version = version;
00051   m_node_type = node_type;
00052   _ownNodeId= 0;
00053 
00054   m_handle= ndb_mgm_create_handle();
00055 
00056   if (m_handle == 0) {
00057     setError(CR_ERROR, "Unable to allocate mgm handle");
00058     return;
00059   }
00060 
00061   if (ndb_mgm_set_connectstring(m_handle, _connect_string))
00062   {
00063     setError(CR_ERROR, ndb_mgm_get_latest_error_desc(m_handle));
00064     return;
00065   }
00066   resetError();
00067 }
00068 
00069 ConfigRetriever::~ConfigRetriever()
00070 {
00071   if (m_handle) {
00072     ndb_mgm_disconnect(m_handle);
00073     ndb_mgm_destroy_handle(&m_handle);
00074   }
00075 }
00076 
00077 Uint32 
00078 ConfigRetriever::get_configuration_nodeid() const
00079 {
00080   return ndb_mgm_get_configuration_nodeid(m_handle);
00081 }
00082 
00083 Uint32 ConfigRetriever::get_mgmd_port() const
00084 {
00085   return ndb_mgm_get_connected_port(m_handle);
00086 }
00087 
00088 const char *ConfigRetriever::get_mgmd_host() const
00089 {
00090   return ndb_mgm_get_connected_host(m_handle);
00091 }
00092 
00093 const char *ConfigRetriever::get_connectstring(char *buf, int buf_sz) const
00094 {
00095   return ndb_mgm_get_connectstring(m_handle, buf, buf_sz);
00096 }
00097 
00098 //****************************************************************************
00099 //****************************************************************************
00100  
00101 int
00102 ConfigRetriever::do_connect(int no_retries,
00103                             int retry_delay_in_seconds, int verbose)
00104 {
00105   return
00106     (ndb_mgm_connect(m_handle,no_retries,retry_delay_in_seconds,verbose)==0) ?
00107     0 : -1;
00108 }
00109 
00110 //****************************************************************************
00111 //****************************************************************************
00112 //****************************************************************************
00113 //****************************************************************************
00114 struct ndb_mgm_configuration*
00115 ConfigRetriever::getConfig() {
00116 
00117   struct ndb_mgm_configuration * p = 0;
00118 
00119   if(m_handle != 0)
00120     p = getConfig(m_handle);
00121 
00122   if(p == 0)
00123     return 0;
00124   
00125   if(!verifyConfig(p, _ownNodeId)){
00126     free(p);
00127     p= 0;
00128   }
00129   
00130   return p;
00131 }
00132 
00133 ndb_mgm_configuration *
00134 ConfigRetriever::getConfig(NdbMgmHandle m_handle){
00135   
00136   ndb_mgm_configuration * conf = ndb_mgm_get_configuration(m_handle,m_version);
00137   if(conf == 0){
00138     setError(CR_ERROR, ndb_mgm_get_latest_error_desc(m_handle));
00139     return 0;
00140   }
00141 
00142   return conf;
00143 }
00144 
00145 ndb_mgm_configuration *
00146 ConfigRetriever::getConfig(const char * filename){
00147 #ifndef NDB_WIN32       
00148 
00149   struct stat sbuf;
00150   const int res = stat(filename, &sbuf);
00151   if(res != 0){
00152     char buf[255];
00153     BaseString::snprintf(buf, sizeof(buf), "Could not find file: \"%s\"", filename);
00154     setError(CR_ERROR, buf);
00155     return 0;
00156   }
00157   const Uint32 bytes = sbuf.st_size;
00158   
00159   Uint32 * buf2 = new Uint32[bytes/4+1];
00160   
00161   FILE * f = fopen(filename, "rb");
00162   if(f == 0){
00163     setError(CR_ERROR, "Failed to open file");
00164     delete []buf2;
00165     return 0;
00166   }
00167   Uint32 sz = fread(buf2, 1, bytes, f);
00168   fclose(f);
00169   if(sz != bytes){
00170     setError(CR_ERROR, "Failed to read file");
00171     delete []buf2;
00172     return 0;
00173   }
00174   
00175   ConfigValuesFactory cvf;
00176   if(!cvf.unpack(buf2, bytes)){
00177     char buf[255];
00178     BaseString::snprintf(buf, sizeof(buf), "Error while unpacking"); 
00179     setError(CR_ERROR, buf);
00180     delete []buf2;
00181     return 0;
00182   }
00183   delete [] buf2;
00184   return (ndb_mgm_configuration*)cvf.m_cfg;
00185 #else
00186   return 0;
00187 #endif
00188 }                          
00189 
00190 void
00191 ConfigRetriever::setError(ErrorType et, const char * s){
00192   errorString.assign(s ? s : "");
00193   latestErrorType = et;
00194 }
00195 
00196 void
00197 ConfigRetriever::resetError(){
00198   setError(CR_NO_ERROR,0);
00199 }
00200 
00201 int
00202 ConfigRetriever::hasError()
00203 {
00204   return latestErrorType != CR_NO_ERROR;
00205 }
00206 
00207 const char * 
00208 ConfigRetriever::getErrorString(){
00209   return errorString.c_str();
00210 }
00211 
00212 bool
00213 ConfigRetriever::verifyConfig(const struct ndb_mgm_configuration * conf, Uint32 nodeid){
00214 
00215   char buf[255];
00216   ndb_mgm_configuration_iterator * it;
00217   it = ndb_mgm_create_configuration_iterator((struct ndb_mgm_configuration *)conf,
00218                                              CFG_SECTION_NODE);
00219 
00220   if(it == 0){
00221     BaseString::snprintf(buf, 255, "Unable to create config iterator");
00222     setError(CR_ERROR, buf);
00223     return false;
00224     
00225   }
00226   NdbAutoPtr<ndb_mgm_configuration_iterator> ptr(it);
00227   
00228   if(ndb_mgm_find(it, CFG_NODE_ID, nodeid) != 0){
00229     BaseString::snprintf(buf, 255, "Unable to find node with id: %d", nodeid);
00230     setError(CR_ERROR, buf);
00231     return false;
00232   }
00233      
00234   const char * hostname;
00235   if(ndb_mgm_get_string_parameter(it, CFG_NODE_HOST, &hostname)){
00236     BaseString::snprintf(buf, 255, "Unable to get hostname(%d) from config",CFG_NODE_HOST);
00237     setError(CR_ERROR, buf);
00238     return false;
00239   }
00240 
00241   const char * datadir;
00242   if(!ndb_mgm_get_string_parameter(it, CFG_NODE_DATADIR, &datadir)){
00243     NdbConfig_SetPath(datadir);
00244   }
00245 
00246   if (hostname && hostname[0] != 0 &&
00247       !SocketServer::tryBind(0,hostname)) {
00248     BaseString::snprintf(buf, 255, "Config hostname(%s) don't match a local interface,"
00249              " tried to bind, error = %d - %s",
00250              hostname, errno, strerror(errno));
00251     setError(CR_ERROR, buf);
00252     return false;
00253   }
00254 
00255   unsigned int _type;
00256   if(ndb_mgm_get_int_parameter(it, CFG_TYPE_OF_SECTION, &_type)){
00257     BaseString::snprintf(buf, 255, "Unable to get type of node(%d) from config",
00258              CFG_TYPE_OF_SECTION);
00259     setError(CR_ERROR, buf);
00260     return false;
00261   }
00262   
00263   if(_type != m_node_type){
00264     const char *type_s, *alias_s, *type_s2, *alias_s2;
00265     alias_s= ndb_mgm_get_node_type_alias_string((enum ndb_mgm_node_type)m_node_type,
00266                                                 &type_s);
00267     alias_s2= ndb_mgm_get_node_type_alias_string((enum ndb_mgm_node_type)_type,
00268                                                  &type_s2);
00269     BaseString::snprintf(buf, 255, "This node type %s(%s) and config "
00270                          "node type %s(%s) don't match for nodeid %d", 
00271                          alias_s, type_s, alias_s2, type_s2, nodeid);
00272     setError(CR_ERROR, buf);
00273     return false;
00274   }
00275 
00279   ndb_mgm_configuration_iterator iter(* conf, CFG_SECTION_CONNECTION);
00280   for(iter.first(); iter.valid(); iter.next()){
00281 
00282     Uint32 type = CONNECTION_TYPE_TCP + 1;
00283     if(iter.get(CFG_TYPE_OF_SECTION, &type)) continue;
00284     if(type != CONNECTION_TYPE_TCP) continue;
00285     
00286     Uint32 nodeId1, nodeId2, remoteNodeId;
00287     if(iter.get(CFG_CONNECTION_NODE_1, &nodeId1)) continue;
00288     if(iter.get(CFG_CONNECTION_NODE_2, &nodeId2)) continue;
00289     
00290     if(nodeId1 != nodeid && nodeId2 != nodeid) continue;
00291     remoteNodeId = (nodeid == nodeId1 ? nodeId2 : nodeId1);
00292 
00293     const char * name;
00294     struct in_addr addr;
00295     BaseString tmp;
00296     if(!iter.get(CFG_CONNECTION_HOSTNAME_1, &name) && strlen(name)){
00297       if(Ndb_getInAddr(&addr, name) != 0){
00298         tmp.assfmt("Unable to lookup/illegal hostname %s, "
00299                    "connection from node %d to node %d",
00300                    name, nodeid, remoteNodeId);
00301         setError(CR_ERROR, tmp.c_str());
00302         return false;
00303       }
00304     }
00305 
00306     if(!iter.get(CFG_CONNECTION_HOSTNAME_2, &name) && strlen(name)){
00307       if(Ndb_getInAddr(&addr, name) != 0){
00308         tmp.assfmt("Unable to lookup/illegal hostname %s, "
00309                    "connection from node %d to node %d",
00310                    name, nodeid, remoteNodeId);
00311         setError(CR_ERROR, tmp.c_str());
00312         return false;
00313       }
00314     }
00315   }
00316   return true;
00317 }
00318 
00319 int
00320 ConfigRetriever::setNodeId(Uint32 nodeid)
00321 {
00322   return ndb_mgm_set_configuration_nodeid(m_handle, nodeid);
00323 }
00324 
00325 Uint32
00326 ConfigRetriever::allocNodeId(int no_retries, int retry_delay_in_seconds)
00327 {
00328   _ownNodeId= 0;
00329   if(m_handle != 0)
00330   {
00331     while (1)
00332     {
00333       int res= ndb_mgm_alloc_nodeid(m_handle, m_version, m_node_type);
00334       if(res >= 0)
00335         return _ownNodeId= (Uint32)res;
00336       if (no_retries == 0)
00337         break;
00338       no_retries--;
00339       NdbSleep_SecSleep(retry_delay_in_seconds);
00340     }
00341     setError(CR_ERROR, ndb_mgm_get_latest_error_desc(m_handle));
00342   } else
00343     setError(CR_ERROR, "management server handle not initialized");    
00344   return 0;
00345 }

Generated on Wed Jul 20 21:05:10 2005 for MySQL 5.0.9 Beta by  doxygen 1.4.3