mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
removed different CFG_ defined for connection host names
added support for setting up multiple interfaces correct connect address for mgmt server bug, -l flag would be interpreted as connectstring added flag to remove all node id checks changed automatic allocation of ports somewhat ndb/include/mgmapi/mgmapi_config_parameters.h: removed different CFG_ defined for connection host names ndb/include/transporter/TransporterRegistry.hpp: added support for setting up multiple interfaces ndb/src/common/mgmcommon/ConfigRetriever.cpp: removed different CFG_ defined for connection host names ndb/src/common/mgmcommon/IPCConfig.cpp: added support for setting up multiple interfaces ndb/src/common/portlib/NdbTCP.cpp: added debug printouts ndb/src/common/transporter/TransporterRegistry.cpp: added support for setting up multiple interfaces ndb/src/common/util/SocketServer.cpp: added my_thread init to enable debug printouts ndb/src/mgmclient/CommandInterpreter.cpp: shortened lines ndb/src/mgmsrv/ConfigInfo.cpp: removed different CFG_ defined for connection host names changed automatic allocation of ports somewhat ndb/src/mgmsrv/MgmtSrvr.cpp: correct connect address for mgmt server ndb/src/mgmsrv/Services.cpp: shoretened lines ndb/src/mgmsrv/main.cpp: bug, -l flag would be interpreted as connectstring added flag to remove all node id checks
This commit is contained in:
@ -104,9 +104,9 @@
|
||||
#define CFG_CONNECTION_NODE_1_SYSTEM 404
|
||||
#define CFG_CONNECTION_NODE_2_SYSTEM 405
|
||||
#define CFG_CONNECTION_SERVER_PORT 406
|
||||
#define CFG_CONNECTION_HOSTNAME_1 407
|
||||
#define CFG_CONNECTION_HOSTNAME_2 408
|
||||
|
||||
#define CFG_TCP_HOSTNAME_1 450
|
||||
#define CFG_TCP_HOSTNAME_2 451
|
||||
#define CFG_TCP_SERVER 452
|
||||
#define CFG_TCP_SEND_BUFFER_SIZE 454
|
||||
#define CFG_TCP_RECEIVE_BUFFER_SIZE 455
|
||||
@ -128,8 +128,6 @@
|
||||
#define CFG_SCI_NODE2_ADAPTER0 555
|
||||
#define CFG_SCI_NODE2_ADAPTER1 556
|
||||
|
||||
#define CFG_OSE_HOSTNAME_1 600
|
||||
#define CFG_OSE_HOSTNAME_2 601
|
||||
#define CFG_OSE_PRIO_A_SIZE 602
|
||||
#define CFG_OSE_PRIO_B_SIZE 603
|
||||
#define CFG_OSE_RECEIVE_ARRAY_SIZE 604
|
||||
|
@ -218,15 +218,18 @@ public:
|
||||
void printState();
|
||||
#endif
|
||||
|
||||
unsigned short m_service_port;
|
||||
|
||||
class Transporter_interface {
|
||||
public:
|
||||
unsigned short m_service_port;
|
||||
const char *m_interface;
|
||||
};
|
||||
Vector<Transporter_interface> m_transporter_interface;
|
||||
void add_transporter_interface(const char *interface, unsigned short port);
|
||||
protected:
|
||||
|
||||
private:
|
||||
void * callbackObj;
|
||||
|
||||
TransporterService *m_transporter_service;
|
||||
char *m_interface_name;
|
||||
struct NdbThread *m_start_clients_thread;
|
||||
bool m_run_start_clients_thread;
|
||||
|
||||
|
@ -344,7 +344,7 @@ ConfigRetriever::verifyConfig(const struct ndb_mgm_configuration * conf, Uint32
|
||||
const char * name;
|
||||
struct in_addr addr;
|
||||
BaseString tmp;
|
||||
if(!iter.get(CFG_TCP_HOSTNAME_1, &name) && strlen(name)){
|
||||
if(!iter.get(CFG_CONNECTION_HOSTNAME_1, &name) && strlen(name)){
|
||||
if(Ndb_getInAddr(&addr, name) != 0){
|
||||
tmp.assfmt("Unable to lookup/illegal hostname %s, "
|
||||
"connection from node %d to node %d",
|
||||
@ -354,7 +354,7 @@ ConfigRetriever::verifyConfig(const struct ndb_mgm_configuration * conf, Uint32
|
||||
}
|
||||
}
|
||||
|
||||
if(!iter.get(CFG_TCP_HOSTNAME_2, &name) && strlen(name)){
|
||||
if(!iter.get(CFG_CONNECTION_HOSTNAME_2, &name) && strlen(name)){
|
||||
if(Ndb_getInAddr(&addr, name) != 0){
|
||||
tmp.assfmt("Unable to lookup/illegal hostname %s, "
|
||||
"connection from node %d to node %d",
|
||||
|
@ -345,18 +345,27 @@ IPCConfig::configureTransporters(Uint32 nodeId,
|
||||
const class ndb_mgm_configuration & config,
|
||||
class TransporterRegistry & tr){
|
||||
|
||||
Uint32 noOfTransportersCreated= 0, server_port= 0;
|
||||
Uint32 noOfTransportersCreated= 0;
|
||||
ndb_mgm_configuration_iterator iter(config, CFG_SECTION_CONNECTION);
|
||||
|
||||
for(iter.first(); iter.valid(); iter.next()){
|
||||
|
||||
Uint32 nodeId1, nodeId2, remoteNodeId;
|
||||
const char * remoteHostName= 0, * localHostName= 0;
|
||||
if(iter.get(CFG_CONNECTION_NODE_1, &nodeId1)) continue;
|
||||
if(iter.get(CFG_CONNECTION_NODE_2, &nodeId2)) continue;
|
||||
|
||||
if(nodeId1 != nodeId && nodeId2 != nodeId) continue;
|
||||
remoteNodeId = (nodeId == nodeId1 ? nodeId2 : nodeId1);
|
||||
|
||||
{
|
||||
const char * host1= 0, * host2= 0;
|
||||
iter.get(CFG_CONNECTION_HOSTNAME_1, &host1);
|
||||
iter.get(CFG_CONNECTION_HOSTNAME_2, &host2);
|
||||
localHostName = (nodeId == nodeId1 ? host1 : host2);
|
||||
remoteHostName = (nodeId == nodeId1 ? host2 : host1);
|
||||
}
|
||||
|
||||
Uint32 sendSignalId = 1;
|
||||
Uint32 checksum = 1;
|
||||
if(iter.get(CFG_CONNECTION_SEND_SIGNAL_ID, &sendSignalId)) continue;
|
||||
@ -365,14 +374,10 @@ IPCConfig::configureTransporters(Uint32 nodeId,
|
||||
Uint32 type = ~0;
|
||||
if(iter.get(CFG_TYPE_OF_SECTION, &type)) continue;
|
||||
|
||||
Uint32 tmp_server_port= 0;
|
||||
if(iter.get(CFG_CONNECTION_SERVER_PORT, &tmp_server_port)) break;
|
||||
Uint32 server_port= 0;
|
||||
if(iter.get(CFG_CONNECTION_SERVER_PORT, &server_port)) break;
|
||||
if (nodeId <= nodeId1 && nodeId <= nodeId2) {
|
||||
if (server_port && server_port != tmp_server_port) {
|
||||
ndbout << "internal error in config setup of server ports line= " << __LINE__ << endl;
|
||||
exit(-1);
|
||||
}
|
||||
server_port= tmp_server_port;
|
||||
tr.add_transporter_interface(localHostName, server_port);
|
||||
}
|
||||
|
||||
switch(type){
|
||||
@ -388,7 +393,7 @@ IPCConfig::configureTransporters(Uint32 nodeId,
|
||||
if(iter.get(CFG_SHM_KEY, &conf.shmKey)) break;
|
||||
if(iter.get(CFG_SHM_BUFFER_MEM, &conf.shmSize)) break;
|
||||
|
||||
conf.port= tmp_server_port;
|
||||
conf.port= server_port;
|
||||
|
||||
if(!tr.createTransporter(&conf)){
|
||||
ndbout << "Failed to create SHM Transporter from: "
|
||||
@ -437,14 +442,10 @@ IPCConfig::configureTransporters(Uint32 nodeId,
|
||||
case CONNECTION_TYPE_TCP:{
|
||||
TCP_TransporterConfiguration conf;
|
||||
|
||||
const char * host1, * host2;
|
||||
if(iter.get(CFG_TCP_HOSTNAME_1, &host1)) break;
|
||||
if(iter.get(CFG_TCP_HOSTNAME_2, &host2)) break;
|
||||
|
||||
if(iter.get(CFG_TCP_SEND_BUFFER_SIZE, &conf.sendBufferSize)) break;
|
||||
if(iter.get(CFG_TCP_RECEIVE_BUFFER_SIZE, &conf.maxReceiveSize)) break;
|
||||
|
||||
conf.port= tmp_server_port;
|
||||
conf.port= server_port;
|
||||
const char * proxy;
|
||||
if (!iter.get(CFG_TCP_PROXY, &proxy)) {
|
||||
if (strlen(proxy) > 0 && nodeId2 == nodeId) {
|
||||
@ -455,8 +456,8 @@ IPCConfig::configureTransporters(Uint32 nodeId,
|
||||
|
||||
conf.localNodeId = nodeId;
|
||||
conf.remoteNodeId = remoteNodeId;
|
||||
conf.localHostName = (nodeId == nodeId1 ? host1 : host2);
|
||||
conf.remoteHostName = (nodeId == nodeId1 ? host2 : host1);
|
||||
conf.localHostName = localHostName;
|
||||
conf.remoteHostName = remoteHostName;
|
||||
conf.byteOrder = 0;
|
||||
conf.compression = 0;
|
||||
conf.checksum = checksum;
|
||||
@ -470,19 +471,15 @@ IPCConfig::configureTransporters(Uint32 nodeId,
|
||||
}
|
||||
case CONNECTION_TYPE_OSE:{
|
||||
OSE_TransporterConfiguration conf;
|
||||
|
||||
const char * host1, * host2;
|
||||
if(iter.get(CFG_OSE_HOSTNAME_1, &host1)) break;
|
||||
if(iter.get(CFG_OSE_HOSTNAME_2, &host2)) break;
|
||||
|
||||
|
||||
if(iter.get(CFG_OSE_PRIO_A_SIZE, &conf.prioASignalSize)) break;
|
||||
if(iter.get(CFG_OSE_PRIO_B_SIZE, &conf.prioBSignalSize)) break;
|
||||
if(iter.get(CFG_OSE_RECEIVE_ARRAY_SIZE, &conf.receiveBufferSize)) break;
|
||||
|
||||
conf.localNodeId = nodeId;
|
||||
conf.remoteNodeId = remoteNodeId;
|
||||
conf.localHostName = (nodeId == nodeId1 ? host1 : host2);
|
||||
conf.remoteHostName = (nodeId == nodeId1 ? host2 : host1);
|
||||
conf.localHostName = localHostName;
|
||||
conf.remoteHostName = remoteHostName;
|
||||
conf.byteOrder = 0;
|
||||
conf.compression = 0;
|
||||
conf.checksum = checksum;
|
||||
@ -502,9 +499,6 @@ IPCConfig::configureTransporters(Uint32 nodeId,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tr.m_service_port= server_port;
|
||||
|
||||
return noOfTransportersCreated;
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
|
||||
#include <ndb_global.h>
|
||||
#include <NdbMutex.h>
|
||||
#include <NdbTCP.h>
|
||||
|
||||
@ -27,22 +28,25 @@ static NdbMutex LOCK_gethostbyname = NDB_MUTEX_INITIALIZER;
|
||||
extern "C"
|
||||
int
|
||||
Ndb_getInAddr(struct in_addr * dst, const char *address) {
|
||||
DBUG_ENTER("Ndb_getInAddr");
|
||||
struct hostent * hostPtr;
|
||||
NdbMutex_Lock(&LOCK_gethostbyname);
|
||||
hostPtr = gethostbyname(address);
|
||||
if (hostPtr != NULL) {
|
||||
dst->s_addr = ((struct in_addr *) *hostPtr->h_addr_list)->s_addr;
|
||||
NdbMutex_Unlock(&LOCK_gethostbyname);
|
||||
return 0;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
NdbMutex_Unlock(&LOCK_gethostbyname);
|
||||
|
||||
/* Try it as aaa.bbb.ccc.ddd. */
|
||||
dst->s_addr = inet_addr(address);
|
||||
if (dst->s_addr != INADDR_NONE) {
|
||||
return 0;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
return -1;
|
||||
DBUG_PRINT("error",("inet_addr(%s) - %d - %s",
|
||||
address, errno, strerror(errno)));
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
@ -98,9 +98,8 @@ SocketServer::Session * TransporterService::newSession(NDB_SOCKET_TYPE sockfd)
|
||||
|
||||
TransporterRegistry::TransporterRegistry(void * callback,
|
||||
unsigned _maxTransporters,
|
||||
unsigned sizeOfLongSignalMemory) {
|
||||
|
||||
m_transporter_service= 0;
|
||||
unsigned sizeOfLongSignalMemory)
|
||||
{
|
||||
nodeIdSpecified = false;
|
||||
maxTransporters = _maxTransporters;
|
||||
sendCounter = 1;
|
||||
@ -150,7 +149,6 @@ TransporterRegistry::~TransporterRegistry() {
|
||||
delete[] theTransporters;
|
||||
delete[] performStates;
|
||||
delete[] ioStates;
|
||||
|
||||
#ifdef NDB_OSE_TRANSPORTER
|
||||
if(theOSEReceiver != NULL){
|
||||
theOSEReceiver->destroyPhantom();
|
||||
@ -1159,55 +1157,67 @@ TransporterRegistry::stop_clients()
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TransporterRegistry::add_transporter_interface(const char *interface, unsigned short port)
|
||||
{
|
||||
DBUG_ENTER("TransporterRegistry::add_transporter_interface");
|
||||
DBUG_PRINT("enter",("interface=%s, port= %d", interface, port));
|
||||
if (interface && strlen(interface) == 0)
|
||||
interface= 0;
|
||||
|
||||
for (unsigned i= 0; i < m_transporter_interface.size(); i++)
|
||||
{
|
||||
Transporter_interface &tmp= m_transporter_interface[i];
|
||||
if (port != tmp.m_service_port)
|
||||
continue;
|
||||
if (interface != 0 && tmp.m_interface != 0 &&
|
||||
strcmp(interface, tmp.m_interface) == 0)
|
||||
{
|
||||
DBUG_VOID_RETURN; // found match, no need to insert
|
||||
}
|
||||
if (interface == 0 && tmp.m_interface == 0)
|
||||
{
|
||||
DBUG_VOID_RETURN; // found match, no need to insert
|
||||
}
|
||||
}
|
||||
Transporter_interface t;
|
||||
t.m_service_port= port;
|
||||
t.m_interface= interface;
|
||||
m_transporter_interface.push_back(t);
|
||||
DBUG_PRINT("exit",("interface and port added"));
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
bool
|
||||
TransporterRegistry::start_service(SocketServer& socket_server)
|
||||
{
|
||||
#if 0
|
||||
for (int i= 0, n= 0; n < nTransporters; i++){
|
||||
Transporter * t = theTransporters[i];
|
||||
if (!t)
|
||||
continue;
|
||||
n++;
|
||||
if (t->isServer) {
|
||||
t->m_service = new TransporterService(new SocketAuthSimple("ndbd passwd"));
|
||||
if(!socket_server.setup(t->m_service, t->m_r_port, 0))
|
||||
{
|
||||
ndbout_c("Unable to setup transporter service port: %d!\n"
|
||||
"Please check if the port is already used,\n"
|
||||
"(perhaps a mgmt server is already running)",
|
||||
m_service_port);
|
||||
delete t->m_service;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (m_transporter_interface.size() > 0 && nodeIdSpecified != true)
|
||||
{
|
||||
ndbout_c("TransporterRegistry::startReceiving: localNodeId not specified");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m_service_port != 0) {
|
||||
|
||||
m_transporter_service = new TransporterService(new SocketAuthSimple("ndbd", "ndbd passwd"));
|
||||
|
||||
if (nodeIdSpecified != true) {
|
||||
ndbout_c("TransporterRegistry::startReceiving: localNodeId not specified");
|
||||
for (unsigned i= 0; i < m_transporter_interface.size(); i++)
|
||||
{
|
||||
Transporter_interface &t= m_transporter_interface[i];
|
||||
if (t.m_service_port == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
TransporterService *transporter_service =
|
||||
new TransporterService(new SocketAuthSimple("ndbd", "ndbd passwd"));
|
||||
if(!socket_server.setup(transporter_service,
|
||||
t.m_service_port, t.m_interface))
|
||||
{
|
||||
ndbout_c("Unable to setup transporter service port: %s:%d!\n"
|
||||
"Please check if the port is already used,\n"
|
||||
"(perhaps the node is already running)",
|
||||
t.m_interface ? t.m_interface : "*", t.m_service_port);
|
||||
delete transporter_service;
|
||||
return false;
|
||||
}
|
||||
|
||||
//m_interface_name = "ndbd";
|
||||
m_interface_name = 0;
|
||||
|
||||
if(!socket_server.setup(m_transporter_service, m_service_port, m_interface_name))
|
||||
{
|
||||
ndbout_c("Unable to setup transporter service port: %d!\n"
|
||||
"Please check if the port is already used,\n"
|
||||
"(perhaps a mgmt server is already running)",
|
||||
m_service_port);
|
||||
delete m_transporter_service;
|
||||
return false;
|
||||
}
|
||||
m_transporter_service->setTransporterRegistry(this);
|
||||
} else
|
||||
m_transporter_service= 0;
|
||||
|
||||
transporter_service->setTransporterRegistry(this);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1281,3 +1291,5 @@ NdbOut & operator <<(NdbOut & out, SignalHeader & sh){
|
||||
out << "trace: " << (int)sh.theTrace << endl;
|
||||
return out;
|
||||
}
|
||||
|
||||
template class Vector<TransporterRegistry::Transporter_interface>;
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
|
||||
#include <ndb_global.h>
|
||||
#include <my_pthread.h>
|
||||
|
||||
#include <SocketServer.hpp>
|
||||
|
||||
@ -83,7 +84,8 @@ bool
|
||||
SocketServer::setup(SocketServer::Service * service,
|
||||
unsigned short port,
|
||||
const char * intface){
|
||||
|
||||
DBUG_ENTER("SocketServer::setup");
|
||||
DBUG_PRINT("enter",("interface=%s, port=%d", intface, port));
|
||||
struct sockaddr_in servaddr;
|
||||
memset(&servaddr, 0, sizeof(servaddr));
|
||||
servaddr.sin_family = AF_INET;
|
||||
@ -92,36 +94,44 @@ SocketServer::setup(SocketServer::Service * service,
|
||||
|
||||
if(intface != 0){
|
||||
if(Ndb_getInAddr(&servaddr.sin_addr, intface))
|
||||
return false;
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
|
||||
const NDB_SOCKET_TYPE sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sock == NDB_INVALID_SOCKET) {
|
||||
return false;
|
||||
DBUG_PRINT("error",("socket() - %d - %s",
|
||||
errno, strerror(errno)));
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
|
||||
const int on = 1;
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
|
||||
(const char*)&on, sizeof(on)) == -1) {
|
||||
DBUG_PRINT("error",("getsockopt() - %d - %s",
|
||||
errno, strerror(errno)));
|
||||
NDB_CLOSE_SOCKET(sock);
|
||||
return false;
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
|
||||
if (bind(sock, (struct sockaddr*) &servaddr, sizeof(servaddr)) == -1) {
|
||||
DBUG_PRINT("error",("bind() - %d - %s",
|
||||
errno, strerror(errno)));
|
||||
NDB_CLOSE_SOCKET(sock);
|
||||
return false;
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
|
||||
if (listen(sock, m_maxSessions) == -1){
|
||||
DBUG_PRINT("error",("listen() - %d - %s",
|
||||
errno, strerror(errno)));
|
||||
NDB_CLOSE_SOCKET(sock);
|
||||
return false;
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
|
||||
ServiceInstance i;
|
||||
i.m_socket = sock;
|
||||
i.m_service = service;
|
||||
m_services.push_back(i);
|
||||
return true;
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
|
||||
void
|
||||
@ -177,8 +187,9 @@ void*
|
||||
socketServerThread_C(void* _ss){
|
||||
SocketServer * ss = (SocketServer *)_ss;
|
||||
|
||||
my_thread_init();
|
||||
ss->doRun();
|
||||
|
||||
my_thread_end();
|
||||
NdbThread_Exit(0);
|
||||
return 0;
|
||||
}
|
||||
@ -287,8 +298,10 @@ void*
|
||||
sessionThread_C(void* _sc){
|
||||
SocketServer::Session * si = (SocketServer::Session *)_sc;
|
||||
|
||||
my_thread_init();
|
||||
if(!transfer(si->m_socket)){
|
||||
si->m_stopped = true;
|
||||
my_thread_end();
|
||||
NdbThread_Exit(0);
|
||||
return 0;
|
||||
}
|
||||
@ -301,6 +314,7 @@ sessionThread_C(void* _sc){
|
||||
}
|
||||
|
||||
si->m_stopped = true;
|
||||
my_thread_end();
|
||||
NdbThread_Exit(0);
|
||||
return 0;
|
||||
}
|
||||
|
@ -673,8 +673,10 @@ CommandInterpreter::executeShutdown(char* parameters)
|
||||
if (mgm_id == 0)
|
||||
mgm_id= state->node_states[i].node_id;
|
||||
else {
|
||||
ndbout << "Unable to locate management server, shutdown manually with #STOP"
|
||||
ndbout << "Unable to locate management server, "
|
||||
<< "shutdown manually with <id> STOP"
|
||||
<< endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -721,11 +723,13 @@ const char *status_string(ndb_mgm_node_status status)
|
||||
|
||||
static void
|
||||
print_nodes(ndb_mgm_cluster_state *state, ndb_mgm_configuration_iterator *it,
|
||||
const char *proc_name, int no_proc, ndb_mgm_node_type type, int master_id)
|
||||
const char *proc_name, int no_proc, ndb_mgm_node_type type,
|
||||
int master_id)
|
||||
{
|
||||
int i;
|
||||
ndbout << "[" << proc_name
|
||||
<< "(" << ndb_mgm_get_node_type_string(type) << ")]\t" << no_proc << " node(s)" << endl;
|
||||
<< "(" << ndb_mgm_get_node_type_string(type) << ")]\t"
|
||||
<< no_proc << " node(s)" << endl;
|
||||
for(i=0; i < state->no_of_nodes; i++) {
|
||||
struct ndb_mgm_node_state *node_state= &(state->node_states[i]);
|
||||
if(node_state->node_type == type) {
|
||||
@ -733,7 +737,9 @@ print_nodes(ndb_mgm_cluster_state *state, ndb_mgm_configuration_iterator *it,
|
||||
ndbout << "id=" << node_id;
|
||||
if(node_state->version != 0) {
|
||||
const char *hostname= node_state->connect_address;
|
||||
if (hostname == 0 || strlen(hostname) == 0 || strcmp(hostname,"0.0.0.0") == 0)
|
||||
if (hostname == 0
|
||||
|| strlen(hostname) == 0
|
||||
|| strcmp(hostname,"0.0.0.0") == 0)
|
||||
ndbout << " ";
|
||||
else
|
||||
ndbout << "\t@" << hostname;
|
||||
@ -761,7 +767,8 @@ print_nodes(ndb_mgm_cluster_state *state, ndb_mgm_configuration_iterator *it,
|
||||
ndb_mgm_get_string_parameter(it, CFG_NODE_HOST, &config_hostname);
|
||||
if (config_hostname == 0 || config_hostname[0] == 0)
|
||||
config_hostname= "any host";
|
||||
ndbout << " (not connected, accepting connect from " << config_hostname << ")" << endl;
|
||||
ndbout << " (not connected, accepting connect from "
|
||||
<< config_hostname << ")" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1529,7 +1529,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
|
||||
},
|
||||
|
||||
{
|
||||
CFG_TCP_HOSTNAME_1,
|
||||
CFG_CONNECTION_HOSTNAME_1,
|
||||
"HostName1",
|
||||
"TCP",
|
||||
"Name/IP of computer on one side of the connection",
|
||||
@ -1540,7 +1540,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
|
||||
0, 0 },
|
||||
|
||||
{
|
||||
CFG_TCP_HOSTNAME_2,
|
||||
CFG_CONNECTION_HOSTNAME_2,
|
||||
"HostName2",
|
||||
"TCP",
|
||||
"Name/IP of computer on one side of the connection",
|
||||
@ -1935,7 +1935,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
|
||||
},
|
||||
|
||||
{
|
||||
CFG_OSE_HOSTNAME_1,
|
||||
CFG_CONNECTION_HOSTNAME_1,
|
||||
"HostName1",
|
||||
"OSE",
|
||||
"Name of computer on one side of the connection",
|
||||
@ -1946,7 +1946,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
|
||||
0, 0 },
|
||||
|
||||
{
|
||||
CFG_OSE_HOSTNAME_2,
|
||||
CFG_CONNECTION_HOSTNAME_2,
|
||||
"HostName2",
|
||||
"OSE",
|
||||
"Name of computer on one side of the connection",
|
||||
@ -2902,26 +2902,38 @@ fixPortNumber(InitConfigFileParser::Context & ctx, const char * data){
|
||||
DBUG_ENTER("fixPortNumber");
|
||||
|
||||
Uint32 id1= 0, id2= 0;
|
||||
const char *hostName1;
|
||||
const char *hostName2;
|
||||
require(ctx.m_currentSection->get("NodeId1", &id1));
|
||||
require(ctx.m_currentSection->get("NodeId2", &id2));
|
||||
require(ctx.m_currentSection->get("HostName1", &hostName1));
|
||||
require(ctx.m_currentSection->get("HostName2", &hostName2));
|
||||
DBUG_PRINT("info",("NodeId1=%d HostName1=\"%s\"",id1,hostName1));
|
||||
DBUG_PRINT("info",("NodeId2=%d HostName2=\"%s\"",id2,hostName2));
|
||||
|
||||
if (id1 > id2) {
|
||||
Uint32 tmp= id1;
|
||||
const char *tmp_name= hostName1;
|
||||
hostName1= hostName2;
|
||||
id1= id2;
|
||||
hostName2= tmp_name;
|
||||
id2= tmp;
|
||||
}
|
||||
|
||||
const Properties * node;
|
||||
require(ctx.m_config->get("Node", id1, &node));
|
||||
BaseString hostname;
|
||||
require(node->get("HostName", hostname));
|
||||
BaseString hostname(hostName1);
|
||||
// require(node->get("HostName", hostname));
|
||||
|
||||
if (hostname.c_str()[0] == 0) {
|
||||
ctx.reportError("Hostname required on nodeid %d since it will act as server.", id1);
|
||||
ctx.reportError("Hostname required on nodeid %d since it will "
|
||||
"act as server.", id1);
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
|
||||
Uint32 port= 0;
|
||||
if (!node->get("ServerPort", &port) && !ctx.m_userProperties.get("ServerPort_", id1, &port)) {
|
||||
if (!node->get("ServerPort", &port) &&
|
||||
!ctx.m_userProperties.get("ServerPort_", id1, &port)) {
|
||||
Uint32 adder= 0;
|
||||
{
|
||||
BaseString server_port_adder(hostname);
|
||||
@ -2932,7 +2944,8 @@ fixPortNumber(InitConfigFileParser::Context & ctx, const char * data){
|
||||
|
||||
Uint32 base= 0;
|
||||
if (!ctx.m_userProperties.get("ServerPortBase", &base)){
|
||||
if(!(ctx.m_userDefaults && ctx.m_userDefaults->get("PortNumber", &base)) &&
|
||||
if(!(ctx.m_userDefaults &&
|
||||
ctx.m_userDefaults->get("PortNumber", &base)) &&
|
||||
!ctx.m_systemDefaults->get("PortNumber", &base)) {
|
||||
base= strtoll(NDB_BASE_PORT,0,0)+2;
|
||||
// ctx.reportError("Cannot retrieve base port number");
|
||||
@ -2945,12 +2958,15 @@ fixPortNumber(InitConfigFileParser::Context & ctx, const char * data){
|
||||
}
|
||||
|
||||
if(ctx.m_currentSection->contains("PortNumber")) {
|
||||
ndbout << "PortNumber should no longer be specificied per connection, please remove from config. Will be changed to " << port << endl;
|
||||
ndbout << "PortNumber should no longer be specificied "
|
||||
<< "per connection, please remove from config. "
|
||||
<< "Will be changed to " << port << endl;
|
||||
ctx.m_currentSection->put("PortNumber", port, true);
|
||||
} else
|
||||
ctx.m_currentSection->put("PortNumber", port);
|
||||
|
||||
DBUG_PRINT("info", ("connection %d-%d port %d host %s", id1, id2, port, hostname.c_str()));
|
||||
DBUG_PRINT("info", ("connection %d-%d port %d host %s",
|
||||
id1, id2, port, hostname.c_str()));
|
||||
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
|
@ -62,6 +62,7 @@
|
||||
#endif
|
||||
|
||||
extern int global_flag_send_heartbeat_now;
|
||||
extern int g_no_nodeid_checks;
|
||||
|
||||
static
|
||||
void
|
||||
@ -591,9 +592,25 @@ MgmtSrvr::MgmtSrvr(NodeId nodeId,
|
||||
_props = NULL;
|
||||
|
||||
_ownNodeId= 0;
|
||||
char my_hostname[256];
|
||||
struct sockaddr_in tmp_addr;
|
||||
SOCKET_SIZE_TYPE addrlen= sizeof(tmp_addr);
|
||||
if (!g_no_nodeid_checks) {
|
||||
if (gethostname(my_hostname, sizeof(my_hostname))) {
|
||||
ndbout << "error: gethostname() - " << strerror(errno) << endl;
|
||||
exit(-1);
|
||||
}
|
||||
if (Ndb_getInAddr(&(((sockaddr_in*)&tmp_addr)->sin_addr),my_hostname)) {
|
||||
ndbout << "error: Ndb_getInAddr(" << my_hostname << ") - "
|
||||
<< strerror(errno) << endl;
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
NodeId tmp= nodeId;
|
||||
BaseString error_string;
|
||||
if (!alloc_node_id(&tmp, NDB_MGM_NODE_TYPE_MGM, 0, 0, error_string)){
|
||||
if (!alloc_node_id(&tmp, NDB_MGM_NODE_TYPE_MGM,
|
||||
(struct sockaddr *)&tmp_addr,
|
||||
&addrlen, error_string)){
|
||||
ndbout << "Unable to obtain requested nodeid: "
|
||||
<< error_string.c_str() << endl;
|
||||
exit(-1);
|
||||
@ -1020,36 +1037,38 @@ int
|
||||
MgmtSrvr::versionNode(int processId, bool abort,
|
||||
VersionCallback callback, void * anyData)
|
||||
{
|
||||
int version;
|
||||
|
||||
if(m_versionRec.inUse)
|
||||
return OPERATION_IN_PROGRESS;
|
||||
|
||||
m_versionRec.callback = callback;
|
||||
m_versionRec.inUse = true ;
|
||||
ClusterMgr::Node node;
|
||||
int version;
|
||||
if (getNodeType(processId) == NDB_MGM_NODE_TYPE_MGM) {
|
||||
if(m_versionRec.callback != 0)
|
||||
m_versionRec.callback(processId, NDB_VERSION, this,0);
|
||||
}
|
||||
|
||||
if (getNodeType(processId) == NDB_MGM_NODE_TYPE_NDB) {
|
||||
node = theFacade->theClusterMgr->getNodeInfo(processId);
|
||||
version = node.m_info.m_version;
|
||||
if(theFacade->theClusterMgr->getNodeInfo(processId).connected)
|
||||
if(m_versionRec.callback != 0)
|
||||
m_versionRec.callback(processId, version, this,0);
|
||||
else
|
||||
if(m_versionRec.callback != 0)
|
||||
m_versionRec.callback(processId, 0, this,0);
|
||||
|
||||
if (getOwnNodeId() == processId)
|
||||
{
|
||||
version= NDB_VERSION;
|
||||
}
|
||||
|
||||
if (getNodeType(processId) == NDB_MGM_NODE_TYPE_API) {
|
||||
else if (getNodeType(processId) == NDB_MGM_NODE_TYPE_NDB)
|
||||
{
|
||||
ClusterMgr::Node node= theFacade->theClusterMgr->getNodeInfo(processId);
|
||||
if(node.connected)
|
||||
version= node.m_info.m_version;
|
||||
else
|
||||
version= 0;
|
||||
}
|
||||
else if (getNodeType(processId) == NDB_MGM_NODE_TYPE_API ||
|
||||
getNodeType(processId) == NDB_MGM_NODE_TYPE_MGM)
|
||||
{
|
||||
return sendVersionReq(processId);
|
||||
}
|
||||
if(m_versionRec.callback != 0)
|
||||
m_versionRec.callback(processId, version, this,0);
|
||||
m_versionRec.inUse = false ;
|
||||
return 0;
|
||||
|
||||
m_versionRec.version[processId]= version;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
@ -1460,17 +1479,14 @@ MgmtSrvr::status(int processId,
|
||||
Uint32 * nodegroup,
|
||||
Uint32 * connectCount)
|
||||
{
|
||||
if (getNodeType(processId) == NDB_MGM_NODE_TYPE_API) {
|
||||
if (getNodeType(processId) == NDB_MGM_NODE_TYPE_API ||
|
||||
getNodeType(processId) == NDB_MGM_NODE_TYPE_MGM) {
|
||||
if(versionNode(processId, false,0,0) ==0)
|
||||
* version = m_versionRec.version[processId];
|
||||
else
|
||||
* version = 0;
|
||||
}
|
||||
|
||||
if (getNodeType(processId) == NDB_MGM_NODE_TYPE_MGM) {
|
||||
* version = NDB_VERSION;
|
||||
}
|
||||
|
||||
const ClusterMgr::Node node =
|
||||
theFacade->theClusterMgr->getNodeInfo(processId);
|
||||
|
||||
@ -2337,12 +2353,19 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
|
||||
SOCKET_SIZE_TYPE *client_addr_len,
|
||||
BaseString &error_string)
|
||||
{
|
||||
DBUG_ENTER("MgmtSrvr::alloc_node_id");
|
||||
DBUG_PRINT("enter", ("nodeid=%d, type=%d, client_addr=%d",
|
||||
*nodeId, type, client_addr));
|
||||
if (g_no_nodeid_checks) {
|
||||
if (*nodeId == 0) {
|
||||
error_string.appfmt("no-nodeid-ckecks set in manegment server.\n"
|
||||
"node id must be set explicitly in connectstring");
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
Guard g(&f_node_id_mutex);
|
||||
#if 0
|
||||
ndbout << "MgmtSrvr::getFreeNodeId type=" << type
|
||||
<< " *nodeid=" << *nodeId << endl;
|
||||
#endif
|
||||
|
||||
int no_mgm= 0;
|
||||
NodeBitmask connected_nodes(m_reserved_nodes);
|
||||
if (theFacade && theFacade->theClusterMgr) {
|
||||
for(Uint32 i = 0; i < MAX_NODES; i++)
|
||||
@ -2350,19 +2373,21 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
|
||||
const ClusterMgr::Node &node= theFacade->theClusterMgr->getNodeInfo(i);
|
||||
if (node.connected)
|
||||
connected_nodes.bitOR(node.m_state.m_connected_nodes);
|
||||
}
|
||||
} else if (getNodeType(i) == NDB_MGM_NODE_TYPE_MGM)
|
||||
no_mgm++;
|
||||
}
|
||||
|
||||
bool found_matching_id= false;
|
||||
bool found_matching_type= false;
|
||||
bool found_free_node= false;
|
||||
const char *config_hostname = 0;
|
||||
unsigned id_found= 0;
|
||||
const char *config_hostname= 0;
|
||||
struct in_addr config_addr= {0};
|
||||
int r_config_addr= -1;
|
||||
unsigned type_c= 0;
|
||||
|
||||
ndb_mgm_configuration_iterator iter(*(ndb_mgm_configuration *)_config->m_configValues,
|
||||
CFG_SECTION_NODE);
|
||||
ndb_mgm_configuration_iterator
|
||||
iter(*(ndb_mgm_configuration *)_config->m_configValues, CFG_SECTION_NODE);
|
||||
for(iter.first(); iter.valid(); iter.next()) {
|
||||
unsigned tmp= 0;
|
||||
if(iter.get(CFG_NODE_ID, &tmp)) abort();
|
||||
@ -2377,8 +2402,9 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
|
||||
continue;
|
||||
found_free_node= true;
|
||||
if(iter.get(CFG_NODE_HOST, &config_hostname)) abort();
|
||||
|
||||
if (config_hostname && config_hostname[0] != 0 && client_addr) {
|
||||
if (config_hostname && config_hostname[0] == 0)
|
||||
config_hostname= 0;
|
||||
else if (client_addr) {
|
||||
// check hostname compatability
|
||||
const void *tmp_in= &(((sockaddr_in*)client_addr)->sin_addr);
|
||||
if((r_config_addr= Ndb_getInAddr(&config_addr, config_hostname)) != 0
|
||||
@ -2388,8 +2414,9 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
|
||||
|| memcmp(&tmp_addr, tmp_in, sizeof(config_addr)) != 0) {
|
||||
// not localhost
|
||||
#if 0
|
||||
ndbout << "MgmtSrvr::getFreeNodeId compare failed for \"" << config_hostname
|
||||
<< "\" id=" << tmp << endl;
|
||||
ndbout << "MgmtSrvr::getFreeNodeId compare failed for \""
|
||||
<< config_hostname
|
||||
<< "\" id=" << tmp << endl;
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
@ -2405,22 +2432,59 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
|
||||
}
|
||||
}
|
||||
}
|
||||
*nodeId= tmp;
|
||||
if (client_addr)
|
||||
m_connect_address[tmp]= ((struct sockaddr_in *)client_addr)->sin_addr;
|
||||
else
|
||||
Ndb_getInAddr(&(m_connect_address[tmp]), "localhost");
|
||||
m_reserved_nodes.set(tmp);
|
||||
#if 0
|
||||
ndbout << "MgmtSrvr::getFreeNodeId found type=" << type
|
||||
<< " *nodeid=" << *nodeId << endl;
|
||||
#endif
|
||||
return true;
|
||||
if (*nodeId != 0 ||
|
||||
type != NDB_MGM_NODE_TYPE_MGM ||
|
||||
no_mgm == 1) { // any match is ok
|
||||
id_found= tmp;
|
||||
break;
|
||||
}
|
||||
if (id_found) { // mgmt server may only have one match
|
||||
error_string.appfmt("Ambiguous node id's %d and %d.\n"
|
||||
"Suggest specifying node id in connectstring,\n"
|
||||
"or specifying unique host names in config file.",
|
||||
id_found, tmp);
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
if (config_hostname == 0) {
|
||||
error_string.appfmt("Ambiguity for node id %d.\n"
|
||||
"Suggest specifying node id in connectstring,\n"
|
||||
"or specifying unique host names in config file,\n",
|
||||
"or specifying just one mgmt server in config file.",
|
||||
tmp);
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
id_found= tmp; // mgmt server matched, check for more matches
|
||||
}
|
||||
|
||||
if (id_found)
|
||||
{
|
||||
*nodeId= id_found;
|
||||
DBUG_PRINT("info", ("allocating node id %d",*nodeId));
|
||||
{
|
||||
int r= 0;
|
||||
if (client_addr)
|
||||
m_connect_address[id_found]=
|
||||
((struct sockaddr_in *)client_addr)->sin_addr;
|
||||
else if (config_hostname)
|
||||
r= Ndb_getInAddr(&(m_connect_address[id_found]), config_hostname);
|
||||
else {
|
||||
char name[256];
|
||||
r= gethostname(name, sizeof(name));
|
||||
if (r == 0) {
|
||||
name[sizeof(name)-1]= 0;
|
||||
r= Ndb_getInAddr(&(m_connect_address[id_found]), name);
|
||||
}
|
||||
}
|
||||
if (r)
|
||||
m_connect_address[id_found].s_addr= 0;
|
||||
}
|
||||
m_reserved_nodes.set(id_found);
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
|
||||
if (found_matching_type && !found_free_node) {
|
||||
// we have a temporary error which might be due to that we have got the latest
|
||||
// connect status from db-nodes. Force update.
|
||||
// we have a temporary error which might be due to that
|
||||
// we have got the latest connect status from db-nodes. Force update.
|
||||
global_flag_send_heartbeat_now= 1;
|
||||
}
|
||||
|
||||
@ -2429,7 +2493,8 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
|
||||
const char *alias, *str;
|
||||
alias= ndb_mgm_get_node_type_alias_string(type, &str);
|
||||
type_string.assfmt("%s(%s)", alias, str);
|
||||
alias= ndb_mgm_get_node_type_alias_string((enum ndb_mgm_node_type)type_c, &str);
|
||||
alias= ndb_mgm_get_node_type_alias_string((enum ndb_mgm_node_type)type_c,
|
||||
&str);
|
||||
type_c_string.assfmt("%s(%s)", alias, str);
|
||||
}
|
||||
|
||||
@ -2440,9 +2505,11 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
|
||||
error_string.appfmt("Connection done from wrong host ip %s.",
|
||||
inet_ntoa(((struct sockaddr_in *)(client_addr))->sin_addr));
|
||||
else
|
||||
error_string.appfmt("No free node id found for %s.", type_string.c_str());
|
||||
error_string.appfmt("No free node id found for %s.",
|
||||
type_string.c_str());
|
||||
else
|
||||
error_string.appfmt("No %s node defined in config file.", type_string.c_str());
|
||||
error_string.appfmt("No %s node defined in config file.",
|
||||
type_string.c_str());
|
||||
else
|
||||
error_string.append("No nodes defined in config file.");
|
||||
} else {
|
||||
@ -2451,19 +2518,23 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
|
||||
if (found_free_node) {
|
||||
// have to split these into two since inet_ntoa overwrites itself
|
||||
error_string.appfmt("Connection with id %d done from wrong host ip %s,",
|
||||
*nodeId, inet_ntoa(((struct sockaddr_in *)(client_addr))->sin_addr));
|
||||
*nodeId, inet_ntoa(((struct sockaddr_in *)
|
||||
(client_addr))->sin_addr));
|
||||
error_string.appfmt(" expected %s(%s).", config_hostname,
|
||||
r_config_addr ? "lookup failed" : inet_ntoa(config_addr));
|
||||
r_config_addr ?
|
||||
"lookup failed" : inet_ntoa(config_addr));
|
||||
} else
|
||||
error_string.appfmt("Id %d already allocated by another node.", *nodeId);
|
||||
error_string.appfmt("Id %d already allocated by another node.",
|
||||
*nodeId);
|
||||
else
|
||||
error_string.appfmt("Id %d configured as %s, connect attempted as %s.",
|
||||
*nodeId, type_c_string.c_str(), type_string.c_str());
|
||||
*nodeId, type_c_string.c_str(),
|
||||
type_string.c_str());
|
||||
else
|
||||
error_string.appfmt("No node defined with id=%d in config file.", *nodeId);
|
||||
error_string.appfmt("No node defined with id=%d in config file.",
|
||||
*nodeId);
|
||||
}
|
||||
|
||||
return false;
|
||||
DBUG_RETURN(false);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -418,7 +418,8 @@ MgmApiSession::get_nodeid(Parser_t::Context &,
|
||||
&addr, &addrlen, error_string)){
|
||||
const char *alias;
|
||||
const char *str;
|
||||
alias= ndb_mgm_get_node_type_alias_string((enum ndb_mgm_node_type)nodetype, &str);
|
||||
alias= ndb_mgm_get_node_type_alias_string((enum ndb_mgm_node_type)
|
||||
nodetype, &str);
|
||||
m_output->println(cmd);
|
||||
m_output->println("result: %s", error_string.c_str());
|
||||
m_output->println("");
|
||||
|
@ -82,6 +82,7 @@ struct MgmGlobals {
|
||||
SocketServer * socketServer;
|
||||
};
|
||||
|
||||
int g_no_nodeid_checks= 0;
|
||||
static MgmGlobals glob;
|
||||
|
||||
|
||||
@ -118,7 +119,9 @@ struct getargs args[] = {
|
||||
"Specify configuration file connect string (will default use Ndb.cfg if available)",
|
||||
"filename" },
|
||||
{ "interactive", 0, arg_flag, &glob.interactive,
|
||||
"Run interactive. Not supported but provided for testing purposes", "" },
|
||||
"Run interactive. Not supported but provided for testing purposes", "" },
|
||||
{ "no-nodeid-checks", 0, arg_flag, &g_no_nodeid_checks,
|
||||
"Do not provide any node id checks", "" },
|
||||
{ "nodaemon", 0, arg_flag, &glob.non_interactive,
|
||||
"Don't run as daemon, but don't read from stdin", "non-interactive" }
|
||||
};
|
||||
@ -336,17 +339,12 @@ MgmGlobals::~MgmGlobals(){
|
||||
* @fn readLocalConfig
|
||||
* @param glob : Global variables
|
||||
* @return true if success, false otherwise.
|
||||
*
|
||||
* How to get LOCAL CONFIGURATION FILE:
|
||||
* 1. Use local config file name (-l)
|
||||
* 2. Use environment NDB_HOME + Ndb.cfg
|
||||
* If NDB_HOME is not set this results in reading from local dir
|
||||
*/
|
||||
static bool
|
||||
readLocalConfig(){
|
||||
// Read local config file
|
||||
LocalConfig lc;
|
||||
if(!lc.init(glob.local_config_filename)){
|
||||
if(!lc.init(0,glob.local_config_filename)){
|
||||
lc.printError();
|
||||
return false;
|
||||
}
|
||||
@ -360,10 +358,6 @@ readLocalConfig(){
|
||||
* @fn readGlobalConfig
|
||||
* @param glob : Global variables
|
||||
* @return true if success, false otherwise.
|
||||
*
|
||||
* How to get the GLOBAL CONFIGURATION:
|
||||
* 1. Use config file name (this is a text file)(-c)
|
||||
* 2. Use name from line 2 of local config file, ex: file:///c/ndb/Ndb_cfg.bin
|
||||
*/
|
||||
static bool
|
||||
readGlobalConfig() {
|
||||
|
Reference in New Issue
Block a user