/* 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> LocalConfig::LocalConfig(){ ids = 0; size = 0; items = 0; error_line = 0; error_msg[0] = 0; } bool LocalConfig::init(bool onlyNodeId, const char *connectString, const char *fileName, const char *defaultConnectString) { /** * 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 if(connectString != 0) { if(readConnectString(connectString, onlyNodeId)){ return true; } return false; } //2. Check given filename if (fileName && strlen(fileName) > 0) { bool fopenError; if(readFile(fileName, fopenError, onlyNodeId)){ return true; } return false; } //3. Check environment variable char buf[255]; if(NdbEnv_GetEnv("NDB_CONNECTSTRING", buf, sizeof(buf)) && strlen(buf) != 0){ if(readConnectString(buf, onlyNodeId)){ return true; } return false; } //4. Check Ndb.cfg in NDB_HOME { bool fopenError; char buf[256]; if(readFile(NdbConfig_NdbCfgName(buf, sizeof(buf), 1 /*true*/), fopenError, onlyNodeId)){ return true; } if (!fopenError) return false; } //5. Check Ndb.cfg in cwd { bool fopenError; char buf[256]; if(readFile(NdbConfig_NdbCfgName(buf, sizeof(buf), 0 /*false*/), fopenError, onlyNodeId)){ return true; } if (!fopenError) return false; } //6. Check defaultConnectString if(defaultConnectString != 0) { if(readConnectString(defaultConnectString, onlyNodeId)){ return true; } return false; } setError(0, ""); return false; } LocalConfig::~LocalConfig(){ for(int i = 0; i<items; i++){ if(ids[i]->type == MgmId_TCP) free(ids[i]->data.tcp.remoteHost); else if(ids[i]->type == MgmId_File) free(ids[i]->data.file.filename); delete ids[i]; } if(ids != 0) delete[] ids; } void LocalConfig::add(MgmtSrvrId * i){ if(items == size){ MgmtSrvrId ** tmp = new MgmtSrvrId * [size+10]; if(ids != 0){ memcpy(tmp, ids, items*sizeof(MgmtSrvrId *)); delete []ids; } ids = tmp; } ids[items] = i; items++; } 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 << " | nodeid=11;host=localhost:2200"<<endl<<endl; ndbout << "2. Use the environment variable NDB_CONNECTSTRING to "<<endl << " provide this information." <<endl << " Ex: " << endl << " >export NDB_CONNECTSTRING=\"nodeid=11;host=localhost:2200\"" <<endl<<endl; } char *nodeIdTokens[] = { "OwnProcessId %i", "nodeid=%i", 0 }; char *hostNameTokens[] = { "host://%[^:]:%i", "host=%[^:]:%i", "%[^:]:%i", "%s %i", 0 }; char *fileNameTokens[] = { "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){ char tempString[100]; int port; for(int i = 0; hostNameTokens[i] != 0; i++) { if (sscanf(buf, hostNameTokens[i], tempString, &port) == 2) { MgmtSrvrId* mgmtSrvrId = new MgmtSrvrId(); mgmtSrvrId->type = MgmId_TCP; mgmtSrvrId->data.tcp.remoteHost = strdup(tempString); mgmtSrvrId->data.tcp.port = port; add(mgmtSrvrId); return true; } } return false; } bool LocalConfig::parseFileName(const char * buf){ char tempString[100]; for(int i = 0; fileNameTokens[i] != 0; i++) { if (sscanf(buf, fileNameTokens[i], tempString) == 1) { MgmtSrvrId* mgmtSrvrId = new MgmtSrvrId(); mgmtSrvrId->type = MgmId_File; mgmtSrvrId->data.file.filename = strdup(tempString); add(mgmtSrvrId); return true; } } return false; } bool LocalConfig::parseString(const char * connectString, bool onlyNodeId, char *line){ bool return_value = true; char * for_strtok; char * copy = strdup(connectString); bool b_nodeId = false; bool found_other = false; for (char *tok = strtok_r(copy,";",&for_strtok); tok != 0 && !(onlyNodeId && b_nodeId); tok = strtok_r(NULL, ";", &for_strtok)) { if (tok[0] == '#') continue; if (!b_nodeId) // only one nodeid definition allowed if (b_nodeId = parseNodeId(tok)) continue; if (onlyNodeId) continue; if (found_other = parseHostName(tok)) continue; if (found_other = parseFileName(tok)) continue; snprintf(line, 150, "Unexpected entry: \"%s\"", tok); return_value = false; break; } if (return_value && !onlyNodeId && !found_other) { return_value = false; snprintf(line, 150, "Missing host/file name extry in \"%s\"", connectString); } free(copy); return return_value; } bool LocalConfig::readFile(const char * filename, bool &fopenError, bool onlyNodeId) { 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; } int sz = 1024; char* theString = (char*)malloc(sz); theString[0] = 0; fgets(theString, sz, file); while (fgets(line+1, 100, file)) { line[0] = ';'; while (strlen(theString) + strlen(line) >= sz) { sz = sz*2; char *newString = (char*)malloc(sz); strcpy(newString, theString); free(theString); theString = newString; } strcat(theString, line); } bool return_value = parseString(theString, onlyNodeId, line); if (!return_value) { snprintf(line2, 150, "Reading %s: %s", filename, line); setError(0,line2); } free(theString); fclose(file); return return_value; } bool LocalConfig::readConnectString(const char * connectString, bool onlyNodeId){ char line[150], line2[150]; bool return_value = parseString(connectString, onlyNodeId, line); if (!return_value) { snprintf(line2, 150, "Reading NDB_CONNECTSTRING \"%s\": %s", connectString, line); setError(0,line2); } return return_value; }