LocalConfig.cpp 6.76 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/* 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 "LocalConfig.hpp"
#include <NdbEnv.h>
#include <NdbConfig.h>
20
#include <NdbAutoPtr.hpp>
mronstrom@mysql.com's avatar
mronstrom@mysql.com committed
21
#include <NdbMem.h>
22 23 24

LocalConfig::LocalConfig(){
  error_line = 0; error_msg[0] = 0;
tomas@poseidon.bredbandsbolaget.se's avatar
tomas@poseidon.bredbandsbolaget.se committed
25
  _ownNodeId= 0;
26 27 28
}

bool
joreland@mysql.com's avatar
joreland@mysql.com committed
29 30
LocalConfig::init(const char *connectString,
		  const char *fileName) {
31 32 33 34 35 36 37 38 39 40 41
  /** 
   * Escalation:
   *  1. Check connectString
   *  2. Check given filename
   *  3. Check environment variable NDB_CONNECTSTRING
   *  4. Check Ndb.cfg in NDB_HOME
   *  5. Check Ndb.cfg in cwd
   *  6. Check defaultConnectString
   */
  
  //1. Check connectString
joreland@mysql.com's avatar
joreland@mysql.com committed
42 43
  if(connectString != 0 && connectString[0] != 0){
    if(readConnectString(connectString)){
44 45 46 47 48 49 50 51
      return true;
    }
    return false;
  }

  //2. Check given filename
  if (fileName && strlen(fileName) > 0) {
    bool fopenError;
joreland@mysql.com's avatar
joreland@mysql.com committed
52
    if(readFile(fileName, fopenError)){
53 54 55 56 57 58 59 60 61
      return true;
    }
    return false;
  }

  //3. Check environment variable
  char buf[255];  
  if(NdbEnv_GetEnv("NDB_CONNECTSTRING", buf, sizeof(buf)) &&
     strlen(buf) != 0){
joreland@mysql.com's avatar
joreland@mysql.com committed
62
    if(readConnectString(buf)){
63 64 65 66 67 68 69 70
      return true;
    }
    return false;
  }
  
  //4. Check Ndb.cfg in NDB_HOME
  {
    bool fopenError;
71 72
    char *buf= NdbConfig_NdbCfgName(1 /*true*/);
    NdbAutoPtr<char> tmp_aptr(buf);
joreland@mysql.com's avatar
joreland@mysql.com committed
73
    if(readFile(buf, fopenError))
74 75 76 77 78 79 80 81
      return true;
    if (!fopenError)
      return false;
  }

  //5. Check Ndb.cfg in cwd
  {
    bool fopenError;
82 83
    char *buf= NdbConfig_NdbCfgName(0 /*false*/);
    NdbAutoPtr<char> tmp_aptr(buf);
joreland@mysql.com's avatar
joreland@mysql.com committed
84
    if(readFile(buf, fopenError))
85 86 87 88 89
      return true;
    if (!fopenError)
      return false;
  }

tomas@poseidon.bredbandsbolaget.se's avatar
tomas@poseidon.bredbandsbolaget.se committed
90
  //7. Check
91 92
  {
    char buf[256];
93
    snprintf(buf, sizeof(buf), "host=localhost:%s", NDB_BASE_PORT);
joreland@mysql.com's avatar
joreland@mysql.com committed
94
    if(readConnectString(buf))
95
      return true;
tomas@poseidon.bredbandsbolaget.se's avatar
tomas@poseidon.bredbandsbolaget.se committed
96
  }
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124

  setError(0, "");

  return false;
}

LocalConfig::~LocalConfig(){
}
  
void LocalConfig::setError(int lineNumber, const char * _msg) {
  error_line = lineNumber;
  strncpy(error_msg, _msg, sizeof(error_msg));
}

void LocalConfig::printError() const {
  ndbout << "Local configuration error"<< endl
	 << "Line: "<< error_line << ", " << error_msg << endl << endl;
}

void LocalConfig::printUsage() const {
  ndbout << "This node needs information on how to connect"<<endl
	 << "to the NDB Management Server."<<endl
	 << "The information can be supplied in one of the following ways:"
	 << endl;
    
  ndbout << "1. Put a Ndb.cfg file in the directory where you start"<<endl 
	 << "   the node. "<< endl
	 << "   Ex: Ndb.cfg" << endl
125
	 << "   | host=localhost:"<<NDB_BASE_PORT<<endl;
126 127 128 129
    
  ndbout << "2. Use the environment variable NDB_CONNECTSTRING to "<<endl
	 << "   provide this information." <<endl
	 << "   Ex: " << endl
130
	 << "   >export NDB_CONNECTSTRING=\"host=localhost:"<<NDB_BASE_PORT<<"\""
131 132 133
	 <<endl<<endl;
}
  
joreland@mysql.com's avatar
joreland@mysql.com committed
134
const char *nodeIdTokens[] = {
135 136 137 138 139
  "OwnProcessId %i",
  "nodeid=%i",
  0
};

joreland@mysql.com's avatar
joreland@mysql.com committed
140
const char *hostNameTokens[] = {
141 142 143 144 145 146 147
  "host://%[^:]:%i",
  "host=%[^:]:%i",
  "%[^:]:%i",
  "%s %i",
  0
};

joreland@mysql.com's avatar
joreland@mysql.com committed
148
const char *fileNameTokens[] = {
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
  "file://%s",
  "file=%s",
  0
};

bool
LocalConfig::parseNodeId(const char * buf){
  for(int i = 0; nodeIdTokens[i] != 0; i++)
    if (sscanf(buf, nodeIdTokens[i], &_ownNodeId) == 1)
      return true;
  return false;
}

bool
LocalConfig::parseHostName(const char * buf){
164
  char tempString[1024];
165 166 167
  int port;
  for(int i = 0; hostNameTokens[i] != 0; i++) {
    if (sscanf(buf, hostNameTokens[i], tempString, &port) == 2) {
joreland@mysql.com's avatar
joreland@mysql.com committed
168 169 170 171 172
      MgmtSrvrId mgmtSrvrId;
      mgmtSrvrId.type = MgmId_TCP;
      mgmtSrvrId.name.assign(tempString);
      mgmtSrvrId.port = port;
      ids.push_back(mgmtSrvrId);
173 174 175 176 177 178 179 180
      return true;
    }
  }
  return false;
}

bool
LocalConfig::parseFileName(const char * buf){
181
  char tempString[1024];
182 183
  for(int i = 0; fileNameTokens[i] != 0; i++) {
    if (sscanf(buf, fileNameTokens[i], tempString) == 1) {
joreland@mysql.com's avatar
joreland@mysql.com committed
184 185 186 187
      MgmtSrvrId mgmtSrvrId;
      mgmtSrvrId.type = MgmId_File;
      mgmtSrvrId.name.assign(tempString);
      ids.push_back(mgmtSrvrId);
188 189 190 191 192 193 194
      return true;
    }
  }
  return false;
}

bool
joreland@mysql.com's avatar
joreland@mysql.com committed
195
LocalConfig::parseString(const char * connectString, char *line){
196 197
  char * for_strtok;
  char * copy = strdup(connectString);
198
  NdbAutoPtr<char> tmp_aptr(copy);
199 200 201 202

  bool b_nodeId = false;
  bool found_other = false;

203 204
  for (char *tok = strtok_r(copy,";,",&for_strtok); tok != 0;
       tok = strtok_r(NULL, ";,", &for_strtok)) {
205 206 207 208 209 210 211 212 213 214
    if (tok[0] == '#') continue;

    if (!b_nodeId) // only one nodeid definition allowed
      if (b_nodeId = parseNodeId(tok))
	continue;
    if (found_other = parseHostName(tok))
      continue;
    if (found_other = parseFileName(tok))
      continue;
    
215 216 217
    if (line)
      snprintf(line, 150, "Unexpected entry: \"%s\"", tok);
    return false;
218 219
  }

joreland@mysql.com's avatar
joreland@mysql.com committed
220
  if (!found_other) {
221
    if (line)
joreland@mysql.com's avatar
joreland@mysql.com committed
222 223
      snprintf(line, 150, "Missing host/file name extry in \"%s\"", 
	       connectString);
224
    return false;
225 226
  }

227
  return true;
228 229
}

joreland@mysql.com's avatar
joreland@mysql.com committed
230
bool LocalConfig::readFile(const char * filename, bool &fopenError)
231 232 233 234 235 236 237 238 239 240 241 242 243
{
  char line[150], line2[150];
    
  fopenError = false;

  FILE * file = fopen(filename, "r");
  if(file == 0){
    snprintf(line, 150, "Unable to open local config file: %s", filename);
    setError(0, line);
    fopenError = true;
    return false;
  }

244
  unsigned int sz = 1024;
mronstrom@mysql.com's avatar
mronstrom@mysql.com committed
245
  char* theString = (char*)NdbMem_Allocate(sz);
246 247 248 249 250 251 252
  theString[0] = 0;

  fgets(theString, sz, file);
  while (fgets(line+1, 100, file)) {
    line[0] = ';';
    while (strlen(theString) + strlen(line) >= sz) {
      sz = sz*2;
mronstrom@mysql.com's avatar
mronstrom@mysql.com committed
253
      char *newString = (char*)NdbMem_Allocate(sz);
254 255 256 257 258 259 260
      strcpy(newString, theString);
      free(theString);
      theString = newString;
    }
    strcat(theString, line);
  }

joreland@mysql.com's avatar
joreland@mysql.com committed
261
  bool return_value = parseString(theString, line);
262 263 264 265 266 267 268 269 270 271 272 273

  if (!return_value) {
    snprintf(line2, 150, "Reading %s: %s", filename, line);
    setError(0,line2);
  }

  free(theString);
  fclose(file);
  return return_value;
}

bool
joreland@mysql.com's avatar
joreland@mysql.com committed
274
LocalConfig::readConnectString(const char * connectString){
275
  char line[150], line2[150];
joreland@mysql.com's avatar
joreland@mysql.com committed
276
  bool return_value = parseString(connectString, line);
277 278 279 280 281 282
  if (!return_value) {
    snprintf(line2, 150, "Reading NDB_CONNECTSTRING \"%s\": %s", connectString, line);
    setError(0,line2);
  }
  return return_value;
}
283 284

template class Vector<MgmtSrvrId>;