00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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 }