LocalConfig.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 "LocalConfig.hpp"
00018 #include <NdbEnv.h>
00019 #include <NdbConfig.h>
00020 #include <NdbAutoPtr.hpp>
00021 #include <NdbMem.h>
00022 
00023 LocalConfig::LocalConfig(){
00024   error_line = 0; error_msg[0] = 0;
00025   _ownNodeId= 0;
00026 }
00027 
00028 bool
00029 LocalConfig::init(const char *connectString,
00030                   const char *fileName)
00031 {
00032   DBUG_ENTER("LocalConfig::init");
00043   _ownNodeId= 0;
00044 
00045   //1. Check connectString
00046   if(connectString != 0 && connectString[0] != 0){
00047     if(readConnectString(connectString, "connect string")){
00048       if (ids.size())
00049         DBUG_RETURN(true);
00050       // only nodeid given, continue to find hosts
00051     } else
00052       DBUG_RETURN(false);
00053   }
00054 
00055   //2. Check given filename
00056   if (fileName && strlen(fileName) > 0) {
00057     bool fopenError;
00058     if(readFile(fileName, fopenError)){
00059       DBUG_RETURN(true);
00060     }
00061     DBUG_RETURN(false);
00062   }
00063 
00064   //3. Check environment variable
00065   char buf[255];  
00066   if(NdbEnv_GetEnv("NDB_CONNECTSTRING", buf, sizeof(buf)) &&
00067      strlen(buf) != 0){
00068     if(readConnectString(buf, "NDB_CONNECTSTRING")){
00069       DBUG_RETURN(true);
00070     }
00071     DBUG_RETURN(false);
00072   }
00073   
00074   //4. Check Ndb.cfg in NDB_HOME
00075   {
00076     bool fopenError;
00077     char *buf= NdbConfig_NdbCfgName(1 /*true*/);
00078     NdbAutoPtr<char> tmp_aptr(buf);
00079     if(readFile(buf, fopenError))
00080       DBUG_RETURN(true);
00081     if (!fopenError)
00082       DBUG_RETURN(false);
00083   }
00084 
00085   //5. Check Ndb.cfg in cwd
00086   {
00087     bool fopenError;
00088     char *buf= NdbConfig_NdbCfgName(0 /*false*/);
00089     NdbAutoPtr<char> tmp_aptr(buf);
00090     if(readFile(buf, fopenError))
00091       DBUG_RETURN(true);
00092     if (!fopenError)
00093       DBUG_RETURN(false);
00094   }
00095 
00096   //7. Check
00097   {
00098     char buf[256];
00099     BaseString::snprintf(buf, sizeof(buf), "host=localhost:%s", NDB_PORT);
00100     if(readConnectString(buf, "default connect string"))
00101       DBUG_RETURN(true);
00102   }
00103 
00104   setError(0, "");
00105 
00106   DBUG_RETURN(false);
00107 }
00108 
00109 LocalConfig::~LocalConfig(){
00110 }
00111   
00112 void LocalConfig::setError(int lineNumber, const char * _msg) {
00113   error_line = lineNumber;
00114   strncpy(error_msg, _msg, sizeof(error_msg));
00115 }
00116 
00117 void LocalConfig::printError() const {
00118   ndbout << "Configuration error" << endl;
00119   if (error_line)
00120     ndbout << "Line: "<< error_line << ", ";
00121   ndbout << error_msg << endl << endl;
00122 }
00123 
00124 void LocalConfig::printUsage() const {
00125   ndbout << "This node needs information on how to connect"<<endl
00126          << "to the NDB Management Server."<<endl
00127          << "The information can be supplied in one of the following ways:"
00128          << endl;
00129     
00130   ndbout << "1. Put a Ndb.cfg file in the directory where you start"<<endl 
00131          << "   the node. "<< endl
00132          << "   Ex: Ndb.cfg" << endl
00133          << "   | host=localhost:"<<NDB_PORT<<endl;
00134     
00135   ndbout << "2. Use the environment variable NDB_CONNECTSTRING to "<<endl
00136          << "   provide this information." <<endl
00137          << "   Ex: " << endl
00138          << "   >export NDB_CONNECTSTRING=\"host=localhost:"<<NDB_PORT<<"\""
00139          <<endl<<endl;
00140 }
00141   
00142 const char *nodeIdTokens[] = {
00143   "OwnProcessId %i",
00144   "nodeid=%i",
00145   0
00146 };
00147 
00148 const char *hostNameTokens[] = {
00149   "host://%[^:]:%i",
00150   "host=%[^:]:%i",
00151   "mgmd=%[^:]:%i",
00152   "%[^:^=^ ]:%i",
00153   "%s %i",
00154   0
00155 };
00156 
00157 const char *fileNameTokens[] = {
00158   "file://%s",
00159   "file=%s",
00160   0
00161 };
00162 
00163 bool
00164 LocalConfig::parseNodeId(const char * buf){
00165   for(int i = 0; nodeIdTokens[i] != 0; i++)
00166     if (sscanf(buf, nodeIdTokens[i], &_ownNodeId) == 1)
00167       return true;
00168   return false;
00169 }
00170 
00171 bool
00172 LocalConfig::parseHostName(const char * buf){
00173   char tempString[1024];
00174   char tempString2[1024];
00175   int port;
00176   do {
00177     for(int i = 0; hostNameTokens[i] != 0; i++) {
00178       if (sscanf(buf, hostNameTokens[i], tempString, &port) == 2) {
00179         MgmtSrvrId mgmtSrvrId;
00180         mgmtSrvrId.type = MgmId_TCP;
00181         mgmtSrvrId.name.assign(tempString);
00182         mgmtSrvrId.port = port;
00183         ids.push_back(mgmtSrvrId);
00184         return true;
00185       }
00186     }
00187     if (buf == tempString2)
00188       break;
00189     // try to add default port to see if it works
00190     snprintf(tempString2, sizeof(tempString2),"%s:%s", buf, NDB_PORT);
00191     buf= tempString2;
00192   } while(1);
00193   return false;
00194 }
00195 
00196 bool
00197 LocalConfig::parseFileName(const char * buf){
00198   char tempString[1024];
00199   for(int i = 0; fileNameTokens[i] != 0; i++) {
00200     if (sscanf(buf, fileNameTokens[i], tempString) == 1) {
00201       MgmtSrvrId mgmtSrvrId;
00202       mgmtSrvrId.type = MgmId_File;
00203       mgmtSrvrId.name.assign(tempString);
00204       ids.push_back(mgmtSrvrId);
00205       return true;
00206     }
00207   }
00208   return false;
00209 }
00210 
00211 bool
00212 LocalConfig::parseString(const char * connectString, BaseString &err){
00213   char * for_strtok;
00214   char * copy = strdup(connectString);
00215   NdbAutoPtr<char> tmp_aptr(copy);
00216 
00217   for (char *tok = strtok_r(copy,";,",&for_strtok); tok != 0;
00218        tok = strtok_r(NULL, ";,", &for_strtok)) {
00219     if (tok[0] == '#') continue;
00220 
00221     if (!_ownNodeId) // only one nodeid definition allowed
00222       if (parseNodeId(tok))
00223         continue;
00224     if (parseHostName(tok))
00225       continue;
00226     if (parseFileName(tok))
00227       continue;
00228     
00229     err.assfmt("Unexpected entry: \"%s\"", tok);
00230     return false;
00231   }
00232 
00233   return true;
00234 }
00235 
00236 bool LocalConfig::readFile(const char * filename, bool &fopenError)
00237 {
00238   char line[1024];
00239   
00240   fopenError = false;
00241   
00242   FILE * file = fopen(filename, "r");
00243   if(file == 0){
00244     BaseString::snprintf(line, sizeof(line),
00245              "Unable to open local config file: %s", filename);
00246     setError(0, line);
00247     fopenError = true;
00248     return false;
00249   }
00250 
00251   BaseString theString;
00252 
00253   while(fgets(line, sizeof(line), file)){
00254     BaseString tmp(line);
00255     tmp.trim(" \t\n\r");
00256     if(tmp.length() > 0 && tmp.c_str()[0] != '#'){
00257       theString.append(tmp);
00258       break;
00259     }
00260   }
00261   while (fgets(line, sizeof(line), file)) {
00262     BaseString tmp(line);
00263     tmp.trim(" \t\n\r");
00264     if(tmp.length() > 0 && tmp.c_str()[0] != '#'){
00265       theString.append(";");
00266       theString.append(tmp);
00267     }
00268   }
00269   
00270   BaseString err;
00271   bool return_value = parseString(theString.c_str(), err);
00272 
00273   if (!return_value) {
00274     BaseString tmp;
00275     tmp.assfmt("Reading %s: %s", filename, err.c_str());
00276     setError(0, tmp.c_str());
00277   }
00278 
00279   fclose(file);
00280   return return_value;
00281 }
00282 
00283 bool
00284 LocalConfig::readConnectString(const char * connectString,
00285                                const char * info){
00286   BaseString err;
00287   bool return_value = parseString(connectString, err);
00288   if (!return_value) {
00289     BaseString err2;
00290     err2.assfmt("Reading %d \"%s\": %s", info, connectString, err.c_str());
00291     setError(0,err2.c_str());
00292   }
00293   return return_value;
00294 }
00295 
00296 char *
00297 LocalConfig::makeConnectString(char *buf, int sz)
00298 {
00299   int p= BaseString::snprintf(buf,sz,"nodeid=%d", _ownNodeId);
00300   if (p < sz)
00301     for (unsigned i = 0; i < ids.size(); i++)
00302     {
00303       if (ids[i].type != MgmId_TCP)
00304         continue;
00305       int new_p= p+BaseString::snprintf(buf+p,sz-p,",%s:%d",
00306                                         ids[i].name.c_str(), ids[i].port);
00307       if (new_p < sz)
00308         p= new_p;
00309       else 
00310       {
00311         buf[p]= 0;
00312         break;
00313       }
00314     }
00315   buf[sz-1]=0;
00316   return buf;
00317 }
00318 
00319 template class Vector<MgmtSrvrId>;

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