#At file:///home/msvensson/mysql/6.4/
3018 Magnus Svensson 2008-10-27 [merge]
Merge in WL#4350
removed:
storage/ndb/include/kernel/signaldata/ManagementServer.hpp
storage/ndb/src/mgmsrv/MgmtSrvrConfig.cpp
added:
storage/ndb/include/kernel/signaldata/ConfigChange.hpp
storage/ndb/src/common/debugger/signaldata/ApiVersion.cpp
storage/ndb/src/mgmsrv/ConfigManager.cpp
storage/ndb/src/mgmsrv/ConfigManager.hpp
storage/ndb/src/mgmsrv/ConfigSubscriber.hpp
storage/ndb/src/mgmsrv/DirIterator.cpp
storage/ndb/src/mgmsrv/DirIterator.hpp
storage/ndb/src/mgmsrv/MgmtThread.hpp
modified:
mysql-test/mysql-test-run.pl
mysql-test/suite/ndb/r/ndb_config.result
mysql-test/suite/ndb/r/ndb_config2.result
storage/ndb/include/kernel/BlockNumbers.h
storage/ndb/include/kernel/GlobalSignalNumbers.h
storage/ndb/include/kernel/signaldata/ApiVersion.hpp
storage/ndb/include/kernel/signaldata/SignalData.hpp
storage/ndb/include/mgmcommon/ConfigRetriever.hpp
storage/ndb/src/common/debugger/signaldata/CMakeLists.txt
storage/ndb/src/common/debugger/signaldata/Makefile.am
storage/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp
storage/ndb/src/common/debugger/signaldata/SignalNames.cpp
storage/ndb/src/common/mgmcommon/ConfigRetriever.cpp
storage/ndb/src/kernel/vm/Configuration.cpp
storage/ndb/src/mgmsrv/CMakeLists.txt
storage/ndb/src/mgmsrv/Config.cpp
storage/ndb/src/mgmsrv/Config.hpp
storage/ndb/src/mgmsrv/ConfigInfo.cpp
storage/ndb/src/mgmsrv/ConfigInfo.hpp
storage/ndb/src/mgmsrv/InitConfigFileParser.cpp
storage/ndb/src/mgmsrv/Makefile.am
storage/ndb/src/mgmsrv/MgmtSrvr.cpp
storage/ndb/src/mgmsrv/MgmtSrvr.hpp
storage/ndb/src/mgmsrv/Services.cpp
storage/ndb/src/mgmsrv/main.cpp
storage/ndb/src/ndbapi/ClusterMgr.cpp
storage/ndb/src/ndbapi/SignalSender.cpp
storage/ndb/src/ndbapi/SignalSender.hpp
storage/ndb/src/ndbapi/TransporterFacade.cpp
storage/ndb/src/ndbapi/TransporterFacade.hpp
storage/ndb/test/run-test/Makefile.am
=== modified file 'mysql-test/mysql-test-run.pl'
--- a/mysql-test/mysql-test-run.pl 2008-10-21 14:56:15 +0000
+++ b/mysql-test/mysql-test-run.pl 2008-10-27 11:13:34 +0000
@@ -2832,6 +2832,8 @@ sub ndb_mgmd_start ($) {
mtr_add_arg($args, "--core");
mtr_add_arg($args, "--nodaemon");
mtr_add_arg($args, "--config-file=%s", "$cluster->{'data_dir'}/config.ini");
+ mtr_add_arg($args, "--datadir=%s", "$cluster->{'data_dir'}");
+ mtr_add_arg($args, "--ndb-nodeid=%d", $cluster->{'nodes'} + 1);
my $path_ndb_mgmd_log= "$cluster->{'data_dir'}/\l$cluster->{'name'}_ndb_mgmd.log";
=== modified file 'mysql-test/suite/ndb/r/ndb_config.result'
--- a/mysql-test/suite/ndb/r/ndb_config.result 2008-09-13 16:15:54 +0000
+++ b/mysql-test/suite/ndb/r/ndb_config.result 2008-10-21 12:41:59 +0000
@@ -8,7 +8,7 @@ ndb_mgmd,5,localhost,, mysqld,6,localhos
ndb_mgmd,5,localhost mysqld,6, mysqld,7, mysqld,8, mysqld,9, mysqld,10, ndbd,1,localhost ndbd,2,localhost ndbd,3,localhost ndbd,4,localhost
ndb_mgmd,6,localhost mysqld,1, mysqld,7, mysqld,8, mysqld,9, mysqld,10, ndbd,2,localhost ndbd,3,localhost ndbd,4,localhost ndbd,5,localhost
ndb_mgmd,1,localhost ndb_mgmd,2,localhost mysqld,11, mysqld,12, mysqld,13, mysqld,14, mysqld,15, ndbd,3,localhost ndbd,4,localhost ndbd,5,localhost ndbd,6,localhost
-shm,3,4,35,3 shm,3,5,35,3 shm,3,6,35,3 shm,4,5,35,4 shm,4,6,35,4 shm,5,6,35,5 tcp,11,3,55,3 tcp,11,4,55,4 tcp,11,5,55,5 tcp,11,6,55,6 tcp,12,3,55,3 tcp,12,4,55,4 tcp,12,5,55,5 tcp,12,6,55,6 tcp,13,3,55,3 tcp,13,4,55,4 tcp,13,5,55,5 tcp,13,6,55,6 tcp,14,3,55,3 tcp,14,4,55,4 tcp,14,5,55,5 tcp,14,6,55,6 tcp,15,3,55,3 tcp,15,4,55,4 tcp,15,5,55,5 tcp,15,6,55,6 tcp,1,3,55,1 tcp,1,4,55,1 tcp,1,5,55,1 tcp,1,6,55,1 tcp,2,3,55,2 tcp,2,4,55,2 tcp,2,5,55,2 tcp,2,6,55,2
+shm,3,4,35,3 shm,3,5,35,3 shm,3,6,35,3 shm,4,5,35,4 shm,4,6,35,4 shm,5,6,35,5 tcp,11,3,55,3 tcp,11,4,55,4 tcp,11,5,55,5 tcp,11,6,55,6 tcp,12,3,55,3 tcp,12,4,55,4 tcp,12,5,55,5 tcp,12,6,55,6 tcp,13,3,55,3 tcp,13,4,55,4 tcp,13,5,55,5 tcp,13,6,55,6 tcp,14,3,55,3 tcp,14,4,55,4 tcp,14,5,55,5 tcp,14,6,55,6 tcp,15,3,55,3 tcp,15,4,55,4 tcp,15,5,55,5 tcp,15,6,55,6 tcp,1,3,55,1 tcp,1,4,55,1 tcp,1,5,55,1 tcp,1,6,55,1 tcp,2,3,55,2 tcp,2,4,55,2 tcp,2,5,55,2 tcp,2,6,55,2 tcp,1,2,55,2
3 1 2
3 1 2
=== modified file 'mysql-test/suite/ndb/r/ndb_config2.result'
--- a/mysql-test/suite/ndb/r/ndb_config2.result 2007-06-27 12:28:02 +0000
+++ b/mysql-test/suite/ndb/r/ndb_config2.result 2008-10-21 12:41:59 +0000
@@ -1 +1 @@
-shm,3,4,35,3 shm,3,5,35,3 shm,3,6,35,3 shm,4,5,35,4 shm,4,6,35,4 shm,5,6,35,5 tcp,11,3,55,3 tcp,11,4,55,4 tcp,11,5,55,5 tcp,11,6,55,6 tcp,12,3,55,3 tcp,12,4,55,4 tcp,12,5,55,5 tcp,12,6,55,6 tcp,13,3,55,3 tcp,13,4,55,4 tcp,13,5,55,5 tcp,13,6,55,6 tcp,14,3,55,3 tcp,14,4,55,4 tcp,14,5,55,5 tcp,14,6,55,6 tcp,15,3,55,3 tcp,15,4,55,4 tcp,15,5,55,5 tcp,15,6,55,6 tcp,1,3,55,1 tcp,1,4,55,1 tcp,1,5,55,1 tcp,1,6,55,1 tcp,2,3,55,2 tcp,2,4,55,2 tcp,2,5,55,2 tcp,2,6,55,2
+shm,3,4,35,3 shm,3,5,35,3 shm,3,6,35,3 shm,4,5,35,4 shm,4,6,35,4 shm,5,6,35,5 tcp,11,3,55,3 tcp,11,4,55,4 tcp,11,5,55,5 tcp,11,6,55,6 tcp,12,3,55,3 tcp,12,4,55,4 tcp,12,5,55,5 tcp,12,6,55,6 tcp,13,3,55,3 tcp,13,4,55,4 tcp,13,5,55,5 tcp,13,6,55,6 tcp,14,3,55,3 tcp,14,4,55,4 tcp,14,5,55,5 tcp,14,6,55,6 tcp,15,3,55,3 tcp,15,4,55,4 tcp,15,5,55,5 tcp,15,6,55,6 tcp,1,3,55,1 tcp,1,4,55,1 tcp,1,5,55,1 tcp,1,6,55,1 tcp,2,3,55,2 tcp,2,4,55,2 tcp,2,5,55,2 tcp,2,6,55,2 tcp,1,2,55,2
=== modified file 'storage/ndb/include/kernel/BlockNumbers.h'
--- a/storage/ndb/include/kernel/BlockNumbers.h 2008-10-05 07:12:42 +0000
+++ b/storage/ndb/include/kernel/BlockNumbers.h 2008-10-27 11:13:34 +0000
@@ -19,7 +19,7 @@
#include <kernel_types.h>
#include <RefConvert.hpp>
-/* 240 */
+/* 32768 */
#define MIN_API_BLOCK_NO 0x8000
/* 2047 */
@@ -28,6 +28,14 @@
/* 4002 */
#define API_CLUSTERMGR 0x0FA2
+/* Fixed block numbers in API */
+#define NO_API_FIXED_BLOCKS 1
+#define MIN_API_FIXED_BLOCK_NO (API_CLUSTERMGR+1)
+#define MGM_CONFIG_MAN MIN_API_FIXED_BLOCK_NO
+
+#define MAX_API_FIXED_BLOCK_NO (MIN_API_FIXED_BLOCK_NO + NO_API_FIXED_BLOCKS)
+
+
#define BACKUP 0xF4
#define DBTC 0xF5
#define DBDIH 0xF6
=== modified file 'storage/ndb/include/kernel/GlobalSignalNumbers.h'
--- a/storage/ndb/include/kernel/GlobalSignalNumbers.h 2008-10-05 07:14:37 +0000
+++ b/storage/ndb/include/kernel/GlobalSignalNumbers.h 2008-10-27 11:13:34 +0000
@@ -96,15 +96,19 @@ extern const GlobalSignalNumber NO_OF_SI
#define GSN_DBINFO_SCANCONF 42
#define GSN_DBINFO_SCANREF 43
#define GSN_DBINFO_TRANSID_AI 44
-/* 45 unused */
-/* 46 unused */
-/* 47 unused */
-/* 48 unused */
-/* 49 unused */
-/* 50 unused */
-/* 51 unused */
-/* 52 unused */
-/* 53 unused */
+
+#define GSN_CONFIG_CHANGE_REQ 45
+#define GSN_CONFIG_CHANGE_REF 46
+#define GSN_CONFIG_CHANGE_CONF 47
+
+#define GSN_CONFIG_CHANGE_IMPL_REQ 48
+#define GSN_CONFIG_CHANGE_IMPL_REF 49
+#define GSN_CONFIG_CHANGE_IMPL_CONF 50
+
+#define GSN_CONFIG_CHECK_REQ 51
+#define GSN_CONFIG_CHECK_REF 52
+#define GSN_CONFIG_CHECK_CONF 53
+
/* 54 unused */
/* 55 unused */
/* 56 unused */
=== modified file 'storage/ndb/include/kernel/signaldata/ApiVersion.hpp'
--- a/storage/ndb/include/kernel/signaldata/ApiVersion.hpp 2007-01-06 00:21:39 +0000
+++ b/storage/ndb/include/kernel/signaldata/ApiVersion.hpp 2008-10-24 12:51:04 +0000
@@ -16,19 +16,24 @@
#ifndef API_VERSION_HPP
#define API_VERSION_HPP
+#include "SignalData.hpp"
+
class ApiVersionReq {
/**
* Sender(s)
*/
- friend class MgmtSrv;
-
+ friend class MgmtSrvr;
+
/**
* Reciver(s)
*/
- friend class Qmgr;
-public:
+ friend class Qmgr;
+
+ friend bool printAPI_VERSION_REQ(FILE *, const Uint32 *, Uint32, Uint16);
+
STATIC_CONST( SignalLength = 4 );
- Uint32 senderRef;
+
+ Uint32 senderRef;
Uint32 nodeId; //api node id
Uint32 version; // Version of API node
Uint32 mysql_version; // MySQL version
@@ -41,14 +46,17 @@ class ApiVersionConf {
* Sender(s)
*/
friend class Qmgr;
-
+
/**
* Reciver(s)
*/
- friend class MgmtSrv;
-public:
+ friend class MgmtSrvr;
+
+ friend bool printAPI_VERSION_CONF(FILE *, const Uint32 *, Uint32, Uint16);
+
STATIC_CONST( SignalLength = 5 );
- Uint32 senderRef;
+
+ Uint32 senderRef;
Uint32 nodeId; //api node id
Uint32 version; // Version of API node
Uint32 inet_addr;
=== added file 'storage/ndb/include/kernel/signaldata/ConfigChange.hpp'
--- a/storage/ndb/include/kernel/signaldata/ConfigChange.hpp 1970-01-01 00:00:00 +0000
+++ b/storage/ndb/include/kernel/signaldata/ConfigChange.hpp 2008-10-21 12:41:59 +0000
@@ -0,0 +1,253 @@
+/* Copyright (C) 2008 Sun Microsystems, Inc.
+
+ 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; version 2 of the License.
+
+ 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 */
+
+#ifndef CONFIG_CHANGE_H
+#define CONFIG_CHANGE_H
+
+#include "SignalData.hpp"
+
+class ConfigChangeReq {
+ /**
+ * Sender
+ */
+ friend class MgmtSrvr;
+
+ /**
+ * Receiver
+ */
+ friend class ConfigManager;
+
+public:
+ STATIC_CONST( SignalLength = 1 );
+
+private:
+ Uint32 length; // Length of the config data in long signal
+};
+
+
+class ConfigChangeConf {
+ /**
+ * Sender
+ */
+ friend class ConfigManager;
+
+ /**
+ * Receiver
+ */
+ friend class MgmtSrvr;
+
+public:
+ STATIC_CONST( SignalLength = 1 );
+
+private:
+
+ Uint32 unused;
+};
+
+
+class ConfigChangeRef {
+ /**
+ * Sender
+ */
+ friend class ConfigManager;
+
+ /**
+ * Receiver
+ */
+ friend class MgmtSrvr;
+
+
+ enum ErrorCode {
+ OK = 0,
+ ConfigChangeOnGoing = 1,
+ NotMaster = 2,
+ NoConfigData = 3,
+ ConfigChangeAborted = 4,
+ FailedToStart = 5,
+ SetGenerationFailed = 10,
+ PrepareFailed = 11,
+ IllegalConfigChange = 13,
+ FailedToUnpack = 14,
+ InvalidGeneration = 15,
+ InvalidConfigName = 16,
+ IllegalState = 17,
+ IllegalInitialGeneration = 18,
+ DifferentInitial = 19,
+ NotAllStarted = 20
+ } ;
+
+public:
+ STATIC_CONST( SignalLength = 1 );
+
+ static const char* errorMessage(Uint32 error) {
+ switch (error){
+ case NoConfigData:
+ return "No config data in signal";
+ case ConfigChangeAborted:
+ return "Config change was aborted";
+ case FailedToStart:
+ return "Failed to start config change";
+ case SetGenerationFailed:
+ return "setGeneration failed";
+ case FailedToUnpack:
+ return "Failed to unpack the configuration";
+ case IllegalConfigChange:
+ return "Illegal config change";
+
+ default:
+ return "ConfigChangeRef, unknown error";
+ }
+ }
+
+private:
+
+ Uint32 errorCode;
+};
+
+
+class ConfigChangeImplReq {
+ /**
+ * Receiver and sender
+ */
+ friend class ConfigManager;
+
+ enum RequestType {
+ Prepare,
+ Commit,
+ Abort
+ };
+
+public:
+ STATIC_CONST( SignalLength = 3 );
+
+private:
+
+ Uint32 requestType;
+ Uint32 initial; // Valid when requestType = Prepare
+ Uint32 length; // Length of the config data in long signal
+};
+
+
+class ConfigChangeImplConf {
+ /**
+ * Receiver and sender
+ */
+ friend class ConfigManager;
+
+public:
+ STATIC_CONST( SignalLength = 1 );
+
+private:
+
+ Uint32 requestType;
+};
+
+
+class ConfigChangeImplRef {
+ /**
+ * Receiver and sender
+ */
+ friend class ConfigManager;
+
+public:
+ STATIC_CONST( SignalLength = 1 );
+
+private:
+
+ Uint32 errorCode;
+};
+
+
+class ConfigCheckReq {
+ /**
+ * Sender
+ */
+ friend class MgmtSrvr;
+
+ /**
+ * Receiver
+ */
+ friend class ConfigManager;
+
+public:
+ STATIC_CONST( SignalLength = 2 );
+
+private:
+ Uint32 state;
+ Uint32 generation;
+};
+
+
+class ConfigCheckConf {
+ /**
+ * Sender
+ */
+ friend class ConfigManager;
+
+ /**
+ * Receiver
+ */
+ friend class MgmtSrvr;
+
+public:
+ STATIC_CONST( SignalLength = 2 );
+
+private:
+
+ Uint32 state;
+ Uint32 generation;
+};
+
+
+class ConfigCheckRef {
+ /**
+ * Sender
+ */
+ friend class ConfigManager;
+
+ /**
+ * Receiver
+ */
+ friend class MgmtSrvr;
+
+ enum ErrorCode {
+ WrongState = 1,
+ WrongGeneration = 2
+ };
+
+ static const char* errorMessage(Uint32 error) {
+ switch (error){
+ case WrongState:
+ return "Wrong state";
+ case WrongGeneration:
+ return "Wrong generation";
+
+ default:
+ return "ConfigCheckRef, unknown error";
+ }
+ }
+
+public:
+ STATIC_CONST( SignalLength = 5 );
+private:
+ Uint32 error;
+ Uint32 generation;
+ Uint32 expected_generation;
+ Uint32 state;
+ Uint32 expected_state;
+};
+
+
+#endif
=== removed file 'storage/ndb/include/kernel/signaldata/ManagementServer.hpp'
--- a/storage/ndb/include/kernel/signaldata/ManagementServer.hpp 2006-12-23 19:20:40 +0000
+++ b/storage/ndb/include/kernel/signaldata/ManagementServer.hpp 1970-01-01 00:00:00 +0000
@@ -1,86 +0,0 @@
-/* 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; version 2 of the License.
-
- 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 */
-
-#ifndef MANAGEMENTSERVER_HPP
-#define MANAGEMENTSERVER_HPP
-
-#include "SignalData.hpp"
-
-/**
- * Request to lock configuration
- */
-class MgmLockConfigReq {
- friend class MgmtSrvr;
-
-public:
- STATIC_CONST( SignalLength = 1 );
-
-private:
- Uint32 newConfigGeneration;
-};
-
-/**
- * Confirm configuration lock
- */
-class MgmLockConfigRep {
- friend class MgmtSrvr;
-public:
- STATIC_CONST( SignalLength = 1 );
-
- /* Error codes */
- enum ErrorCode {
- OK,
- UNKNOWN_ERROR,
- GENERATION_MISMATCH,
- ALREADY_LOCKED
- };
-
-private:
- Uint32 errorCode;
-};
-
-/**
- * Unlock configuration
- */
-class MgmUnlockConfigReq {
- friend class MgmtSrvr;
-
-public:
- STATIC_CONST( SignalLength = 1 );
-
-private:
- Uint32 commitConfig;
-};
-
-/**
- * Confirm config unlock
- */
-class MgmUnlockConfigRep {
- friend class MgmtSrvr;
-public:
- STATIC_CONST( SignalLength = 1 );
-
- /* Error codes */
- enum ErrorCode {
- OK,
- UNKNOWN_ERROR,
- NOT_LOCKED
- };
-
-private:
- Uint32 errorCode;
-};
-
-#endif /* !MANAGEMENTSERVER_HPP */
=== modified file 'storage/ndb/include/kernel/signaldata/SignalData.hpp'
--- a/storage/ndb/include/kernel/signaldata/SignalData.hpp 2007-12-25 16:34:29 +0000
+++ b/storage/ndb/include/kernel/signaldata/SignalData.hpp 2008-10-24 12:51:04 +0000
@@ -273,4 +273,7 @@ GSN_PRINT_SIGNATURE(printBUILD_INDX_IMPL
GSN_PRINT_SIGNATURE(printBUILD_INDX_IMPL_CONF);
GSN_PRINT_SIGNATURE(printBUILD_INDX_IMPL_REF);
+GSN_PRINT_SIGNATURE(printAPI_VERSION_REQ);
+GSN_PRINT_SIGNATURE(printAPI_VERSION_CONF);
+
#endif
=== modified file 'storage/ndb/include/mgmcommon/ConfigRetriever.hpp'
--- a/storage/ndb/include/mgmcommon/ConfigRetriever.hpp 2007-03-22 11:35:31 +0000
+++ b/storage/ndb/include/mgmcommon/ConfigRetriever.hpp 2008-10-24 10:06:10 +0000
@@ -34,7 +34,8 @@ public:
int do_connect(int no_retries, int retry_delay_in_seconds, int verbose);
int disconnect();
-
+ bool is_connected();
+
/**
* Get configuration for current node.
*
@@ -90,9 +91,10 @@ private:
CR_RETRY = 2
};
ErrorType latestErrorType;
-
+
void setError(ErrorType, const char * errorMsg);
-
+ void setError(ErrorType, BaseString err);
+
Uint32 _ownNodeId;
bool m_end_session;
=== added file 'storage/ndb/src/common/debugger/signaldata/ApiVersion.cpp'
--- a/storage/ndb/src/common/debugger/signaldata/ApiVersion.cpp 1970-01-01 00:00:00 +0000
+++ b/storage/ndb/src/common/debugger/signaldata/ApiVersion.cpp 2008-10-24 12:51:04 +0000
@@ -0,0 +1,50 @@
+/* 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; version 2 of the License.
+
+ 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 <signaldata/ApiVersion.hpp>
+#include <RefConvert.hpp>
+
+bool
+printAPI_VERSION_REQ(FILE * output,
+ const Uint32 * theData,
+ Uint32 len,
+ Uint16 recBlockNo){
+
+ ApiVersionReq * sig = (ApiVersionReq *)&theData[0];
+
+ fprintf(output,
+ " senderRef: (node: %d, block: %d), nodeId: %d\n" \
+ " version: %d, mysql_version: %d\n",
+ refToNode(sig->senderRef), refToBlock(sig->senderRef),
+ sig->nodeId, sig->version, sig->mysql_version);
+ return true;
+}
+
+bool
+printAPI_VERSION_CONF(FILE * output,
+ const Uint32 * theData,
+ Uint32 len,
+ Uint16 recBlockNo){
+
+ ApiVersionConf * sig = (ApiVersionConf *)&theData[0];
+
+ fprintf(output,
+ " senderRef: (node: %d, block: %d), nodeId: %d\n" \
+ " version: %d, mysql_version: %d, inet_addr: %d\n",
+ refToNode(sig->senderRef), refToBlock(sig->senderRef),
+ sig->nodeId, sig->version, sig->mysql_version, sig->inet_addr);
+ return true;
+}
=== modified file 'storage/ndb/src/common/debugger/signaldata/CMakeLists.txt'
--- a/storage/ndb/src/common/debugger/signaldata/CMakeLists.txt 2008-08-22 00:22:44 +0000
+++ b/storage/ndb/src/common/debugger/signaldata/CMakeLists.txt 2008-10-24 12:51:04 +0000
@@ -44,5 +44,5 @@ ADD_LIBRARY(ndbsignaldata STATIC
SumaImpl.cpp NdbSttor.cpp CreateFragmentation.cpp
UtilLock.cpp TuxMaint.cpp AccLock.cpp
LqhTrans.cpp ReadNodesConf.cpp CntrStart.cpp
- ScanFrag.cpp )
+ ScanFrag.cpp ApiVersion.cpp)
=== modified file 'storage/ndb/src/common/debugger/signaldata/Makefile.am'
--- a/storage/ndb/src/common/debugger/signaldata/Makefile.am 2008-08-26 14:20:06 +0000
+++ b/storage/ndb/src/common/debugger/signaldata/Makefile.am 2008-10-24 12:51:04 +0000
@@ -45,7 +45,7 @@ libsignaldataprint_la_SOURCES = \
CreateTab.cpp CreateTable.cpp DropTable.cpp \
CreateTrigImpl.cpp DropTrigImpl.cpp \
CreateIndxImpl.cpp DropIndxImpl.cpp AlterIndxImpl.cpp \
- BuildIndx.cpp BuildIndxImpl.cpp
+ BuildIndx.cpp BuildIndxImpl.cpp ApiVersion.cpp
include $(top_srcdir)/storage/ndb/config/common.mk.am
include $(top_srcdir)/storage/ndb/config/type_ndbapi.mk.am
=== modified file 'storage/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp'
--- a/storage/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp 2008-02-06 20:10:07 +0000
+++ b/storage/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp 2008-10-24 12:51:04 +0000
@@ -244,6 +244,9 @@ SignalDataPrintFunctions[] = {
,{ GSN_BUILD_INDX_IMPL_CONF, printBUILD_INDX_IMPL_CONF }
,{ GSN_BUILD_INDX_IMPL_REF, printBUILD_INDX_IMPL_REF }
+ ,{ GSN_API_VERSION_REQ, printAPI_VERSION_REQ }
+ ,{ GSN_API_VERSION_CONF, printAPI_VERSION_CONF }
+
,{ 0, 0 }
};
=== modified file 'storage/ndb/src/common/debugger/signaldata/SignalNames.cpp'
--- a/storage/ndb/src/common/debugger/signaldata/SignalNames.cpp 2008-09-12 12:55:29 +0000
+++ b/storage/ndb/src/common/debugger/signaldata/SignalNames.cpp 2008-10-21 12:41:59 +0000
@@ -709,5 +709,19 @@ const GsnName SignalNames [] = {
,{ GSN_DROP_NODEGROUP_IMPL_REQ, "DROP_NODEGROUP_IMPL_REQ" }
,{ GSN_DROP_NODEGROUP_IMPL_CONF, "DROP_NODEGROUP_IMPL_CONF" }
,{ GSN_DROP_NODEGROUP_IMPL_REF, "DROP_NODEGROUP_IMPL_REF" }
+
+ ,{ GSN_CONFIG_CHECK_REQ, "CONFIG_CHECK_REQ" }
+ ,{ GSN_CONFIG_CHECK_REF, "CONFIG_CHECK_REF" }
+ ,{ GSN_CONFIG_CHECK_CONF, "CONFIG_CHECK_CONF" }
+
+ ,{ GSN_CONFIG_CHANGE_REQ, "CONFIG_CHANGE_REQ" }
+ ,{ GSN_CONFIG_CHANGE_REF, "CONFIG_CHANGE_REF" }
+ ,{ GSN_CONFIG_CHANGE_CONF, "CONFIG_CHANGE_CONF" }
+
+ ,{ GSN_CONFIG_CHANGE_IMPL_REQ, "CONFIG_CHANGE_IMPL_REQ" }
+ ,{ GSN_CONFIG_CHANGE_IMPL_REF, "CONFIG_CHANGE_IMPL_REF" }
+ ,{ GSN_CONFIG_CHANGE_IMPL_CONF, "CONFIG_CHANGE_IMPL_CONF" }
+
+
};
const unsigned short NO_OF_SIGNAL_NAMES = sizeof(SignalNames)/sizeof(GsnName);
=== modified file 'storage/ndb/src/common/mgmcommon/ConfigRetriever.cpp'
--- a/storage/ndb/src/common/mgmcommon/ConfigRetriever.cpp 2008-06-10 20:06:47 +0000
+++ b/storage/ndb/src/common/mgmcommon/ConfigRetriever.cpp 2008-10-24 10:06:10 +0000
@@ -29,10 +29,7 @@
#include <Properties.hpp>
#include <socket_io.h>
-#include <NdbConfig.h>
-#include <NdbAutoPtr.hpp>
-
#include <mgmapi.h>
#include <mgmapi_config_parameters.h>
#include <mgmapi_configuration.hpp>
@@ -48,6 +45,9 @@ ConfigRetriever::ConfigRetriever(const c
int timeout_ms)
{
DBUG_ENTER("ConfigRetriever::ConfigRetriever");
+ DBUG_PRINT("enter", ("%s, version: %d, node_type: %d, bind: %s, timeout: %d",
+ _connect_string, version, node_type,
+ _bindaddress, timeout_ms));
m_version = version;
m_node_type = node_type;
@@ -137,6 +137,12 @@ ConfigRetriever::disconnect()
return ndb_mgm_disconnect(m_handle);
}
+bool
+ConfigRetriever::is_connected(void)
+{
+ return (ndb_mgm_is_connected(m_handle) != 0);
+}
+
//****************************************************************************
//****************************************************************************
//****************************************************************************
@@ -177,49 +183,45 @@ ConfigRetriever::getConfig(NdbMgmHandle
}
ndb_mgm_configuration *
-ConfigRetriever::getConfig(const char * filename){
-#ifndef NDB_WIN32
-
- struct stat sbuf;
- const int res = stat(filename, &sbuf);
- if(res != 0){
- char buf[255];
- BaseString::snprintf(buf, sizeof(buf), "Could not find file: \"%s\"", filename);
- setError(CR_ERROR, buf);
+ConfigRetriever::getConfig(const char * filename)
+{
+ if (access(filename, F_OK))
+ {
+ BaseString err;
+ err.assfmt("Could not find file: '%s'", filename);
+ setError(CR_ERROR, err);
return 0;
}
- const Uint32 bytes = sbuf.st_size;
-
- Uint32 * buf2 = new Uint32[bytes/4+1];
-
+
FILE * f = fopen(filename, "rb");
- if(f == 0){
+ if(f == 0)
+ {
setError(CR_ERROR, "Failed to open file");
- delete []buf2;
return 0;
}
- Uint32 sz = fread(buf2, 1, bytes, f);
- fclose(f);
- if(sz != bytes){
- setError(CR_ERROR, "Failed to read file");
- delete []buf2;
- return 0;
+
+ size_t read_sz;
+ char read_buf[512];
+ UtilBuffer config_buf;
+ while ((read_sz = fread(read_buf, 1, sizeof(read_buf), f)) != 0)
+ {
+ if (config_buf.append(read_buf, read_sz) != 0)
+ {
+ setError(CR_ERROR, "Out of memory when appending read data");
+ fclose(f);
+ return 0;
+ }
}
-
+ fclose(f);
+
ConfigValuesFactory cvf;
- if(!cvf.unpack(buf2, bytes)){
- char buf[255];
- BaseString::snprintf(buf, sizeof(buf), "Error while unpacking");
- setError(CR_ERROR, buf);
- delete []buf2;
+ if(!cvf.unpack(config_buf))
+ {
+ setError(CR_ERROR, "Error while unpacking");
return 0;
}
- delete [] buf2;
- return (ndb_mgm_configuration*)cvf.m_cfg;
-#else
- return 0;
-#endif
-}
+ return (ndb_mgm_configuration*)cvf.getConfigValues();
+}
void
ConfigRetriever::setError(ErrorType et, const char * s){
@@ -228,6 +230,11 @@ ConfigRetriever::setError(ErrorType et,
}
void
+ConfigRetriever::setError(ErrorType et, BaseString err){
+ setError(et, err.c_str());
+}
+
+void
ConfigRetriever::resetError(){
setError(CR_NO_ERROR,0);
}
@@ -243,65 +250,57 @@ ConfigRetriever::getErrorString(){
return errorString.c_str();
}
-bool
-ConfigRetriever::verifyConfig(const struct ndb_mgm_configuration * conf, Uint32 nodeid){
+bool
+ConfigRetriever::verifyConfig(const struct ndb_mgm_configuration * conf,
+ Uint32 nodeid)
+{
char buf[255];
- ndb_mgm_configuration_iterator * it;
- it = ndb_mgm_create_configuration_iterator((struct ndb_mgm_configuration *)conf,
- CFG_SECTION_NODE);
+ ndb_mgm_configuration_iterator it(* conf, CFG_SECTION_NODE);
- if(it == 0){
- BaseString::snprintf(buf, 255, "Unable to create config iterator");
- setError(CR_ERROR, buf);
- return false;
-
- }
- NdbAutoPtr<ndb_mgm_configuration_iterator> ptr(it);
-
- if(ndb_mgm_find(it, CFG_NODE_ID, nodeid) != 0){
+ if(it.find(CFG_NODE_ID, nodeid)){
BaseString::snprintf(buf, 255, "Unable to find node with id: %d", nodeid);
setError(CR_ERROR, buf);
return false;
}
-
+
const char * hostname;
- if(ndb_mgm_get_string_parameter(it, CFG_NODE_HOST, &hostname)){
- BaseString::snprintf(buf, 255, "Unable to get hostname(%d) from config",CFG_NODE_HOST);
+ if(it.get(CFG_NODE_HOST, &hostname)){
+ BaseString::snprintf(buf, 255, "Unable to get hostname(%d) from config",
+ CFG_NODE_HOST);
setError(CR_ERROR, buf);
return false;
}
- const char * datadir;
- if(!ndb_mgm_get_string_parameter(it, CFG_NODE_DATADIR, &datadir)){
- NdbConfig_SetPath(datadir);
- }
-
if (hostname && hostname[0] != 0 &&
!SocketServer::tryBind(0,hostname)) {
- BaseString::snprintf(buf, 255, "Config hostname(%s) don't match a local interface,"
- " tried to bind, error = %d - %s",
- hostname, errno, strerror(errno));
+ BaseString::snprintf(buf, 255,
+ "Config hostname: %s don't match a local "
+ "interface, tried to bind, error: %d '%s'",
+ hostname, errno, strerror(errno));
setError(CR_ERROR, buf);
return false;
}
unsigned int _type;
- if(ndb_mgm_get_int_parameter(it, CFG_TYPE_OF_SECTION, &_type)){
+ if(it.get(CFG_TYPE_OF_SECTION, &_type)){
BaseString::snprintf(buf, 255, "Unable to get type of node(%d) from config",
- CFG_TYPE_OF_SECTION);
+ CFG_TYPE_OF_SECTION);
setError(CR_ERROR, buf);
return false;
}
-
+
if(_type != m_node_type){
const char *type_s, *alias_s, *type_s2, *alias_s2;
- alias_s= ndb_mgm_get_node_type_alias_string((enum ndb_mgm_node_type)m_node_type,
- &type_s);
- alias_s2= ndb_mgm_get_node_type_alias_string((enum ndb_mgm_node_type)_type,
- &type_s2);
- BaseString::snprintf(buf, 255, "This node type %s(%s) and config "
- "node type %s(%s) don't match for nodeid %d",
+ alias_s=
+ ndb_mgm_get_node_type_alias_string((enum ndb_mgm_node_type)m_node_type,
+ &type_s);
+ alias_s2=
+ ndb_mgm_get_node_type_alias_string((enum ndb_mgm_node_type)_type,
+ &type_s2);
+ BaseString::snprintf(buf, 255,
+ "This node type %s(%s) and config "
+ "node type %s(%s) don't match for nodeid %d",
alias_s, type_s, alias_s2, type_s2, nodeid);
setError(CR_ERROR, buf);
return false;
@@ -347,6 +346,7 @@ ConfigRetriever::verifyConfig(const stru
}
}
}
+
return true;
}
=== modified file 'storage/ndb/src/kernel/vm/Configuration.cpp'
--- a/storage/ndb/src/kernel/vm/Configuration.cpp 2008-08-21 06:31:25 +0000
+++ b/storage/ndb/src/kernel/vm/Configuration.cpp 2008-10-21 12:41:59 +0000
@@ -26,6 +26,7 @@
#include <NdbMem.h>
#include <NdbOut.hpp>
#include <WatchDog.hpp>
+#include <NdbConfig.h>
#include <mgmapi_configuration.hpp>
#include <mgmapi_config_parameters_debug.h>
@@ -338,6 +339,13 @@ Configuration::fetch_configuration(){
"StopOnError missing");
}
+ const char * datadir;
+ if(iter.get(CFG_NODE_DATADIR, &datadir)){
+ ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, "Invalid configuration fetched",
+ "DataDir missing");
+ }
+ NdbConfig_SetPath(datadir);
+
m_mgmds.clear();
for(ndb_mgm_first(&iter); ndb_mgm_valid(&iter); ndb_mgm_next(&iter))
{
=== modified file 'storage/ndb/src/mgmsrv/CMakeLists.txt'
--- a/storage/ndb/src/mgmsrv/CMakeLists.txt 2008-08-20 13:22:29 +0000
+++ b/storage/ndb/src/mgmsrv/CMakeLists.txt 2008-10-24 12:41:10 +0000
@@ -41,6 +41,6 @@ ADD_EXECUTABLE(ndb_mgmd
MgmtSrvr.cpp
main.cpp
Services.cpp
- MgmtSrvrConfig.cpp
- ${CMAKE_SOURCE_DIR}/sql/nt_servc.cc)
+ ConfigManager.cpp
+ DirIterator.cpp)
TARGET_LINK_LIBRARIES(ndb_mgmd ndbconf)
=== modified file 'storage/ndb/src/mgmsrv/Config.cpp'
--- a/storage/ndb/src/mgmsrv/Config.cpp 2008-09-16 09:37:22 +0000
+++ b/storage/ndb/src/mgmsrv/Config.cpp 2008-10-21 12:41:59 +0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 MySQL AB
+/* Copyright (C) 2003-2008 MySQL AB, 2008 Sun Microsystems, Inc.
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
@@ -19,14 +19,12 @@
#include <NdbOut.hpp>
#include "ConfigInfo.hpp"
-
static void require(bool b)
{
if (!b)
abort();
}
-
Config::Config(struct ndb_mgm_configuration *config_values) :
m_configValues(config_values)
{
@@ -38,6 +36,18 @@ Config::Config(ConfigValues *config_valu
{
}
+Config::Config(const Config* conf)
+{
+ // TODO Magnus, improve copy constructor
+ // to not use pack/unpack
+ assert(conf);
+ UtilBuffer buf;
+ conf->pack(buf);
+ ConfigValuesFactory cvf;
+ cvf.unpack(buf);
+ m_configValues= (struct ndb_mgm_configuration*)cvf.getConfigValues();
+}
+
Config::~Config() {
if(m_configValues != 0){
@@ -110,29 +120,44 @@ Config::getGeneration() const
}
+const char*
+Config::getName() const
+{
+ const char* name;
+ ConfigIter iter(this, CFG_SECTION_SYSTEM);
+
+ if (iter.get(CFG_SYS_NAME, &name))
+ return 0;
+
+ return name;
+}
+
bool
Config::setValue(Uint32 section, Uint32 section_no,
Uint32 id, Uint32 new_val)
{
ConfigValues::Iterator iter(m_configValues->m_config);
- if (iter.openSection(section, section_no)){
- if (!iter.set(id, new_val))
- return false;
- }
- else
- {
- ConfigValuesFactory cf(&m_configValues->m_config);
- if (!cf.openSection(section, section_no))
- return false;
- if (!cf.put(CFG_TYPE_OF_SECTION, section))
- return false;
- if (!cf.put(id, new_val))
- return false;
- cf.closeSection();
+ if (!iter.openSection(section, section_no))
+ return false;
- m_configValues= (struct ndb_mgm_configuration*)cf.getConfigValues();
- }
+ if (!iter.set(id, new_val))
+ return false;
+
+ return true;
+}
+
+
+bool
+Config::setValue(Uint32 section, Uint32 section_no,
+ Uint32 id, const char* new_val)
+{
+ ConfigValues::Iterator iter(m_configValues->m_config);
+ if (!iter.openSection(section, section_no))
+ return false;
+
+ if (!iter.set(id, new_val))
+ return false;
return true;
}
@@ -147,6 +172,15 @@ Config::setGeneration(Uint32 new_gen)
}
+bool
+Config::setName(const char* new_name)
+{
+ return setValue(CFG_SECTION_SYSTEM, 0,
+ CFG_SYS_NAME,
+ new_name);
+}
+
+
Uint32
Config::pack(UtilBuffer& buf) const
{
@@ -168,7 +202,6 @@ add_diff(const char* name, const char* k
Properties& diff,
const char* value_name, Properties* value)
{
-
Properties *section;
// Create a new section if it did not exist
if (!diff.getCopy(key, §ion)){
@@ -187,7 +220,8 @@ add_diff(const char* name, const char* k
require(value->get("Type", &type));
// Add the value to the section if not already added
- if (!section->put(value_name, value))
+ require(value->put("Name", value_name));
+ if (!section->put("Value", value))
require(section->getPropertiesErrno() ==
E_PROPERTIES_ELEMENT_ALREADY_EXISTS);
@@ -537,6 +571,7 @@ Config::diff2str(const Properties& diff_
Uint32 type;
require(what->get("Type", &type));
+ require(what->get("Name", &name));
switch (type) {
case DT_DIFF:
{
=== modified file 'storage/ndb/src/mgmsrv/Config.hpp'
--- a/storage/ndb/src/mgmsrv/Config.hpp 2008-09-16 09:37:22 +0000
+++ b/storage/ndb/src/mgmsrv/Config.hpp 2008-10-21 12:41:59 +0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 MySQL AB
+/* Copyright (C) 2003-2008 MySQL AB, 2008 Sun Microsystems, Inc.
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
@@ -33,6 +33,7 @@ class Config {
public:
Config(struct ndb_mgm_configuration *config_values = NULL);
Config(ConfigValues* config_values);
+ Config(const Config*);
virtual ~Config();
void print() const;
@@ -45,6 +46,12 @@ public:
bool setGeneration(Uint32);
/*
+ Returns name of the config
+ */
+ const char* getName() const;
+ bool setName(const char* new_name);
+
+ /*
Pack the config into a UtilBuffer and return it's size in bytes
*/
Uint32 pack(UtilBuffer&) const;
@@ -80,7 +87,9 @@ public:
private:
bool setValue(Uint32 section, Uint32 section_no,
- Uint32 id, Uint32 new_gen);
+ Uint32 id, Uint32 new_val);
+ bool setValue(Uint32 section, Uint32 section_no,
+ Uint32 id, const char* new_val);
bool illegal_change(const Properties&) const;
bool equal(const Properties&) const;
=== modified file 'storage/ndb/src/mgmsrv/ConfigInfo.cpp'
--- a/storage/ndb/src/mgmsrv/ConfigInfo.cpp 2008-09-17 13:23:21 +0000
+++ b/storage/ndb/src/mgmsrv/ConfigInfo.cpp 2008-10-21 12:41:59 +0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 MySQL AB
+/* Copyright (C) 2003-2008 MySQL AB, 2008 Sun Microsystems, Inc.
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
@@ -191,6 +191,9 @@ const int ConfigInfo::m_NoOfRules = size
/****************************************************************************
* Config Rules declarations
****************************************************************************/
+static bool add_system_section(Vector<ConfigInfo::ConfigRuleSection>§ions,
+ struct InitConfigFileParser::Context &ctx,
+ const char * rule_data);
static bool sanity_checks(Vector<ConfigInfo::ConfigRuleSection>§ions,
struct InitConfigFileParser::Context &ctx,
const char * rule_data);
@@ -211,11 +214,12 @@ static bool saveSectionsInConfigValues(V
const ConfigInfo::ConfigRule
ConfigInfo::m_ConfigRules[] = {
+ { add_system_section, 0 },
{ sanity_checks, 0 },
{ add_node_connections, 0 },
{ set_connection_priorities, 0 },
{ check_node_vs_replicas, 0 },
- { saveSectionsInConfigValues, "Node,Connection" },
+ { saveSectionsInConfigValues, "SYSTEM,Node,Connection" },
{ 0, 0 }
};
@@ -348,6 +352,10 @@ const ConfigInfo::ParamInfo ConfigInfo::
"0",
STR_VALUE(MAX_INT_RNIL) },
+ /***************************************************************************
+ * DB
+ ***************************************************************************/
+
{
CFG_SYS_CONFIG_GENERATION,
"ConfigGenerationNumber",
@@ -407,10 +415,7 @@ const ConfigInfo::ParamInfo ConfigInfo::
"false",
"false",
"true"},
-
- /***************************************************************************
- * DB
- ***************************************************************************/
+
{
CFG_SECTION_NODE,
DB_TOKEN,
@@ -1817,7 +1822,7 @@ const ConfigInfo::ParamInfo ConfigInfo::
ConfigInfo::CI_USED,
false,
ConfigInfo::CI_STRING,
- MYSQLCLUSTERDIR,
+ "",
0, 0 },
{
@@ -3237,8 +3242,6 @@ transformSystem(InitConfigFileParser::Co
return false;
}
- ndbout << "transformSystem " << name << endl;
-
BaseString::snprintf(ctx.pname, sizeof(ctx.pname), "SYSTEM_%s", name);
return true;
@@ -3976,6 +3979,42 @@ saveInConfigValues(InitConfigFileParser:
return true;
}
+
+static bool
+add_system_section(Vector<ConfigInfo::ConfigRuleSection>§ions,
+ struct InitConfigFileParser::Context &ctx,
+ const char * rule_data)
+{
+ if (!ctx.m_userProperties.contains("SYSTEM")) {
+ ConfigInfo::ConfigRuleSection s;
+
+ // Generate a unique name for this new cluster
+ time_t now = ::time((time_t*)NULL);
+ struct tm* tm_now = ::localtime(&now);
+
+ char name_buf[18];
+ BaseString::snprintf(name_buf, sizeof(name_buf),
+ "MC_%d%.2d%.2d%.2d%.2d%.2d",
+ tm_now->tm_year + 1900,
+ tm_now->tm_mon + 1,
+ tm_now->tm_mday,
+ tm_now->tm_hour,
+ tm_now->tm_min,
+ tm_now->tm_sec);
+
+ s.m_sectionType = BaseString("SYSTEM");
+ s.m_sectionData = new Properties(true);
+ s.m_sectionData->put("Name", name_buf);
+ s.m_sectionData->put("Type", "SYSTEM");
+
+ // ndbout_c("Generated new SYSTEM section with name '%s'", name_buf);
+
+ sections.push_back(s);
+ }
+ return true;
+}
+
+
static bool
sanity_checks(Vector<ConfigInfo::ConfigRuleSection>§ions,
struct InitConfigFileParser::Context &ctx,
@@ -4161,6 +4200,7 @@ add_node_connections(Vector<ConfigInfo::
Uint32 nodeId1, nodeId2, dummy;
+ // DB -> DB
for (i= 0; p_db_nodes.get("", i, &nodeId1); i++){
for (Uint32 j= i+1;; j++){
if(!p_db_nodes.get("", j, &nodeId2)) break;
@@ -4172,6 +4212,7 @@ add_node_connections(Vector<ConfigInfo::
}
}
+ // API -> DB
for (i= 0; p_api_nodes.get("", i, &nodeId1); i++){
if(!p_connections.get("", nodeId1, &dummy)) {
for (Uint32 j= 0;; j++){
@@ -4182,6 +4223,7 @@ add_node_connections(Vector<ConfigInfo::
}
}
+ // MGM -> DB
for (i= 0; p_mgm_nodes.get("", i, &nodeId1); i++){
if(!p_connections.get("", nodeId1, &dummy)) {
for (Uint32 j= 0;; j++){
@@ -4191,7 +4233,19 @@ add_node_connections(Vector<ConfigInfo::
}
}
}
-
+
+ // MGM -> MGM
+ for (i= 0; p_mgm_nodes.get("", i, &nodeId1); i++){
+ for (Uint32 j= i+1;; j++){
+ if(!p_mgm_nodes.get("", j, &nodeId2)) break;
+ if(!p_connections2.get("", nodeId1+nodeId2<<16, &dummy))
+ {
+ if (!add_a_connection(sections,ctx,nodeId1,nodeId2,0))
+ goto err;
+ }
+ }
+ }
+
DBUG_RETURN(true);
err:
DBUG_RETURN(false);
=== modified file 'storage/ndb/src/mgmsrv/ConfigInfo.hpp'
--- a/storage/ndb/src/mgmsrv/ConfigInfo.hpp 2008-07-25 10:02:59 +0000
+++ b/storage/ndb/src/mgmsrv/ConfigInfo.hpp 2008-10-21 12:41:59 +0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 MySQL AB
+/* Copyright (C) 2003-2008 MySQL AB, 2008 Sun Microsystems, Inc.
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
=== added file 'storage/ndb/src/mgmsrv/ConfigManager.cpp'
--- a/storage/ndb/src/mgmsrv/ConfigManager.cpp 1970-01-01 00:00:00 +0000
+++ b/storage/ndb/src/mgmsrv/ConfigManager.cpp 2008-10-24 12:41:10 +0000
@@ -0,0 +1,1557 @@
+/* Copyright (C) 2008 Sun Microsystems, Inc.
+
+ 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; version 2 of the License.
+
+ 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 "ConfigManager.hpp"
+#include "MgmtSrvr.hpp"
+
+#include <NdbConfig.h>
+
+#include <SignalSender.hpp>
+#include <NdbApiSignal.hpp>
+#include <signaldata/NFCompleteRep.hpp>
+#include <signaldata/NodeFailRep.hpp>
+#include <signaldata/ApiRegSignalData.hpp>
+#include <ndb_version.h>
+
+
+#ifdef VM_TRACE
+#define require(v) assert(v)
+#else
+static void
+require(bool v)
+{
+ if (!v)
+ abort();
+}
+#endif
+
+extern "C" const char* opt_connect_str;
+
+ConfigManager::ConfigManager(const MgmtSrvr::MgmtOpts& opts) :
+ MgmtThread("ConfigManager"),
+ m_opts(opts),
+ m_facade(NULL),
+ m_config_mutex(NULL),
+ m_config(NULL),
+ m_new_config(NULL),
+ m_config_retriever(opt_connect_str,
+ NDB_VERSION,
+ NDB_MGM_NODE_TYPE_MGM,
+ opts.bind_address),
+ m_config_change_state(CCS_IDLE),
+ m_config_state(CS_UNINITIALIZED),
+ m_previous_state(CS_UNINITIALIZED),
+ m_client_ref(RNIL),
+ m_prepared_config(NULL),
+ m_node_id(0),
+ m_datadir(NULL)
+{
+}
+
+
+ConfigManager::~ConfigManager()
+{
+ delete m_config;
+ delete m_new_config;
+ delete m_prepared_config;
+ NdbMutex_Destroy(m_config_mutex);
+}
+
+
+
+bool
+ConfigManager::init_nodeid(void)
+{
+ DBUG_ENTER("ConfigManager::init_nodeid");
+
+ NodeId nodeid= m_config_retriever.get_configuration_nodeid();
+ DBUG_PRINT("info", ("nodeid: %d", nodeid));
+
+ if (nodeid)
+ {
+ // Nodeid was specifed on command line or in NDB_CONNECTSTRING
+ m_node_id= nodeid;
+ DBUG_RETURN(true);
+ }
+
+#if 0
+ // We _could_ try connecting to other running mgmd(s)
+ // and fetch our nodeid. But, that introduces a dependency
+ // that is not beneficial for a shared nothing cluster, since
+ // it might only work when other mgmd(s) are started. If all
+ // mgmd(s) is down it would require manual intervention.
+ // Better to require the node id to always be specified
+ // on the command line(or some other "local" magic by
+ // examining --datadir)
+
+ // Try to alloc nodeid from other mgmd
+ char buf[128];
+ g_eventLogger->info("Trying to get nodeid from other mgmd(s) "\
+ "using '%s'...",
+ m_config_retriever.get_connectstring(buf, sizeof(buf)));
+
+ if (m_config_retriever.do_connect(3, /* retry */
+ 1, /* delay */
+ 0 /* verbose */) == 0)
+ {
+ g_eventLogger->info("Connected...");
+
+ nodeid = m_config_retriever.allocNodeId(3, /* retry */
+ 1 /* delay */);
+ if (nodeid == 0)
+ {
+ // Failed to alloc nodeid from other mgmd
+ g_eventLogger->error(m_config_retriever.getErrorString());
+ DBUG_RETURN(false);
+ }
+ }
+#endif
+
+ g_eventLogger->error("Could not determine which nodeid to use for "\
+ "this node. Specify it with --ndb-nodeid=<nodeid> "\
+ "on command line");
+ DBUG_RETURN(false);
+}
+
+
+bool
+ConfigManager::init(void)
+{
+ DBUG_ENTER("ConfigManager::init");
+
+ m_config_mutex = NdbMutex_Create();
+ if (!m_config_mutex)
+ {
+ g_eventLogger->error("Failed to create mutex in ConfigManager!");
+ DBUG_RETURN(false);
+ }
+
+ require(m_config_state == CS_UNINITIALIZED);
+
+ if (m_config_retriever.hasError())
+ {
+ g_eventLogger->error(m_config_retriever.getErrorString());
+ DBUG_RETURN(false);
+ }
+
+ // Check datadir
+ if (m_opts.datadir)
+ {
+ // Specified on commmand line
+ if (access(m_opts.datadir, F_OK))
+ {
+ g_eventLogger->error("Directory '%s' specified with --datadir " \
+ "does not exist", m_opts.datadir);
+ DBUG_RETURN(false);
+ }
+ m_datadir= m_opts.datadir;
+ }
+ else
+ {
+ // Compiled in path MYSQLCLUSTERDIR
+ if (access(MYSQLCLUSTERDIR, F_OK))
+ {
+ g_eventLogger->error("The default data directory '%s' " \
+ "does not exist. Either create it or " \
+ "specify a different directory with " \
+ "--datadir=<path>",
+ MYSQLCLUSTERDIR);
+ DBUG_RETURN(false);
+ }
+ m_datadir= MYSQLCLUSTERDIR;
+ }
+ DBUG_PRINT("info", ("datadir: %s", m_datadir));
+
+ if (!init_nodeid())
+ DBUG_RETURN(false);
+
+ BaseString config_bin_name;
+ if (saved_config_exists(config_bin_name))
+ {
+ Config* conf = NULL;
+ if (!(conf = load_saved_config(config_bin_name)))
+ DBUG_RETURN(false);
+
+ if (!config_ok(conf))
+ DBUG_RETURN(false);
+
+ set_config(conf);
+ m_config_state = CS_CONFIRMED;
+
+ if (m_opts.mycnf || m_opts.config_filename)
+ {
+ Config* new_conf = NULL;
+ if (m_opts.mycnf && (new_conf = load_init_mycnf()) == NULL)
+ {
+ g_eventLogger->error("Could not load configuration from 'my.cnf'");
+ DBUG_RETURN(false);
+ }
+ else if (m_opts.config_filename &&
+ (new_conf = load_init_config(m_opts.config_filename)) == NULL)
+ {
+ g_eventLogger->error("Could not load configuration from '%s'",
+ m_opts.config_filename);
+ DBUG_RETURN(false);
+ }
+
+ /* Copy the necessary values from old to new config */
+ if (!new_conf->setGeneration(m_config->getGeneration()))
+ {
+ g_eventLogger->error("Failed to copy generation from old config");
+ DBUG_RETURN(false);
+ }
+
+ if (!new_conf->setName(m_config->getName()))
+ {
+ g_eventLogger->error("Failed to copy name from old config");
+ DBUG_RETURN(false);
+ }
+
+ /* Check if config has changed */
+ if (!m_config->equal(new_conf))
+ {
+ /* Loaded config is different */
+ BaseString buf;
+ g_eventLogger->info("Detected change of %s on disk, will try to " \
+ "set it when all ndb_mgmd(s) started. " \
+ "This is the actual diff:\n%s",
+ m_opts.mycnf ? "my.cnf" : m_opts.config_filename,
+ m_config->diff2str(new_conf, buf));
+ m_new_config= new_conf;
+ }
+ else
+ {
+ /* Loaded config was equal to current */
+ g_eventLogger->info("Config equal!");
+ delete new_conf;
+ }
+ }
+ }
+ else
+ {
+ if (m_opts.mycnf || m_opts.config_filename)
+ {
+ Config* conf = NULL;
+ if (m_opts.mycnf && (conf = load_init_mycnf()) == NULL)
+ {
+ g_eventLogger->error("Could not load configuration from 'my.cnf'");
+ DBUG_RETURN(false);
+ }
+ else if (m_opts.config_filename &&
+ (conf = load_init_config(m_opts.config_filename)) == NULL)
+ {
+ g_eventLogger->error("Could not load initial configuration from '%s'",
+ m_opts.config_filename);
+ DBUG_RETURN(false);
+ }
+
+ if (!config_ok(conf))
+ DBUG_RETURN(false);
+
+ /* Use the initial config for now */
+ set_config(conf);
+
+ g_eventLogger->info("Got initial configuration from '%s', will try " \
+ "to set it when all ndb_mgmd(s) started",
+ m_opts.mycnf ? "my.cnf" : m_opts.config_filename);
+ m_new_config = new Config(conf); // Copy config
+ m_config_state = CS_INITIAL;
+ }
+ else
+ {
+ Config* conf = NULL;
+ if (!(conf = fetch_config()))
+ {
+ g_eventLogger->error("Could not fetch config!");
+ DBUG_RETURN(false);
+ }
+
+ if (!config_ok(conf))
+ DBUG_RETURN(false);
+
+ /* Use the fetched config for now */
+ set_config(conf);
+ m_new_config = new Config(conf); // Copy config
+
+ if (m_config->getGeneration() == 0)
+ {
+ g_eventLogger->info("Fetched initial configuration, " \
+ "generation: %d, name: '%s'. "\
+ "Will try to set it when all ndb_mgmd(s) started",
+ m_config->getGeneration(), m_config->getName());
+ m_config_state= CS_INITIAL;
+ }
+ else
+ {
+ g_eventLogger->info("Fetched confirmed configuration, " \
+ "generation: %d, name: '%s'. " \
+ "Trying to write it to disk...",
+ m_config->getGeneration(), m_config->getName());
+ if (!prepareConfigChange(m_config))
+ {
+ abortConfigChange();
+ g_eventLogger->error("Failed to write the fetched config to disk");
+ DBUG_RETURN(false);
+ }
+ commitConfigChange();
+ m_config_state = CS_CONFIRMED;
+ g_eventLogger->info("The fetched configuration has been saved!");
+ }
+ }
+ }
+
+ require(m_config_state != CS_UNINITIALIZED);
+ DBUG_RETURN(true);
+}
+
+
+bool
+ConfigManager::prepareConfigChange(const Config* config)
+{
+ if (m_prepared_config)
+ {
+ g_eventLogger->error("Can't prepare configuration change " \
+ "when already prepared");
+ return false;
+ }
+ Uint32 generation= config->getGeneration();
+ if (generation == 0)
+ {
+ g_eventLogger->error("Can't prepare configuration change for "\
+ "configuration with generation 0");
+ return false;
+ }
+
+ assert(m_node_id);
+ m_config_name.assfmt("%s/ndb_%u_config.bin.%u",
+ m_datadir, m_node_id, generation);
+ g_eventLogger->debug("Preparing configuration, generation: %d name: %s",
+ m_config_name.c_str());
+
+ /* Check file name is free */
+ if (access(m_config_name.c_str(), F_OK) == 0)
+ {
+ g_eventLogger->error("The file '%s' already exist while preparing",
+ m_config_name.c_str());
+ return false;
+ }
+
+ /* Pack the config */
+ UtilBuffer buf;
+ if(!config->pack(buf))
+ {
+ /* Failed to pack config */
+ g_eventLogger->error("Failed to pack configuration while preparing");
+ return false;
+ }
+
+ /* Write config to temporary file */
+ BaseString prep_config_name(m_config_name);
+ prep_config_name.append(".tmp");
+ FILE * f = fopen(prep_config_name.c_str(), IF_WIN("wbc", "w"));
+ if(f == NULL)
+ {
+ g_eventLogger->error("Failed to open file '%s' while preparing, errno: %d",
+ prep_config_name.c_str(), errno);
+ return false;
+ }
+
+ if(fwrite(buf.get_data(), 1, buf.length(), f) != (size_t)buf.length())
+ {
+ g_eventLogger->error("Failed to write file '%s' while preparing, errno: %d",
+ prep_config_name.c_str(), errno);
+ fclose(f);
+ unlink(prep_config_name.c_str());
+ return false;
+ }
+
+ if (fflush(f))
+ {
+ g_eventLogger->error("Failed to flush file '%s' while preparing, errno: %d",
+ prep_config_name.c_str(), errno);
+ fclose(f);
+ unlink(prep_config_name.c_str());
+ return false;
+ }
+
+#ifdef __WIN__
+ /*
+ File is opened with the commit flag "c" so
+ that the contents of the file buffer are written
+ directly to disk when fflush is called
+ */
+#else
+ if (fsync(fileno(f)))
+ {
+ g_eventLogger->error("Failed to sync file '%s' while preparing, errno: %d",
+ prep_config_name.c_str(), errno);
+ fclose(f);
+ unlink(prep_config_name.c_str());
+ return false;
+ }
+#endif
+ fclose(f);
+
+ m_prepared_config = new Config(config->m_configValues);
+ g_eventLogger->debug("Configuration prepared");
+
+ return true;
+}
+
+
+void
+ConfigManager::commitConfigChange(void)
+{
+ require(m_prepared_config);
+
+ /* Set new config locally and in all subscribers */
+ set_config(m_prepared_config);
+ m_prepared_config= NULL;
+
+ /* Rename file to real name */
+ require(m_config_name.length());
+ BaseString prep_config_name(m_config_name);
+ prep_config_name.append(".tmp");
+ if(rename(prep_config_name.c_str(), m_config_name.c_str()))
+ {
+ g_eventLogger->error("rename from '%s' to '%s' failed while committing, " \
+ "errno: %d",
+ prep_config_name.c_str(), m_config_name.c_str(),
+ errno);
+ // Crash and leave the prepared config file in place
+ abort();
+ }
+ m_config_name.clear();
+
+ g_eventLogger->info("Configuration %d commited", m_config->getGeneration());
+}
+
+
+void
+ConfigManager::set_config(Config* new_config)
+{
+ delete m_config;
+ m_config = new_config;
+
+ for (unsigned i = 0; i < m_subscribers.size(); i++)
+ m_subscribers[i]->config_changed(m_node_id, new_config);
+
+}
+
+
+int
+ConfigManager::add_config_change_subscriber(ConfigSubscriber* subscriber)
+{
+ return m_subscribers.push_back(subscriber);
+}
+
+
+bool
+ConfigManager::config_ok(const Config* conf)
+{
+ assert(m_node_id);
+ if (!m_config_retriever.verifyConfig(conf->m_configValues, m_node_id))
+ {
+ g_eventLogger->error(m_config_retriever.getErrorString());
+ return false;
+ }
+
+ // Check if --datadir is same as DataDir from config
+ assert(m_datadir);
+ ConfigIter iter(conf, CFG_SECTION_NODE);
+ require(iter.find(CFG_NODE_ID, m_node_id) == 0);
+
+ const char *datadir;
+ require(iter.get(CFG_NODE_DATADIR, &datadir) == 0);
+
+ if (strcmp(datadir, "") != 0 && // Not set -> empty string
+ strcmp(m_datadir, datadir) != 0) // Different
+ {
+ // Not same --datadir and DataDir
+ if (strcmp(m_datadir, MYSQLCLUSTERDIR) == 0 ||
+ strcmp(datadir, MYSQLCLUSTERDIR) == 0)
+ {
+ // Using the builtin default --datadir
+ g_eventLogger->error("The builtin data directory '%s' does " \
+ "not match DataDir=%s specified in " \
+ "configuation. Either specify --datadir=%s " \
+ "on command line or remove the DataDir=%s " \
+ "from configuration in order to use the " \
+ "builtin default.",
+ m_datadir, datadir, m_datadir, datadir);
+ return false;
+ }
+ else
+ {
+ // Using --datadir specified on command line
+ g_eventLogger->error("The data directory specified on command line " \
+ "with --datadir=%s does not match DataDir=%s " \
+ "specified in configuration. You need to " \
+ "change one of them.",
+ m_datadir, datadir);
+ return false;
+ }
+ }
+ NdbConfig_SetPath(m_datadir);
+
+ return true;
+}
+
+
+void
+ConfigManager::abortConfigChange(void)
+{
+ /* Should always succeed */
+
+ /* Remove the prepared file */
+ BaseString prep_config_name(m_config_name);
+ prep_config_name.append(".tmp");
+ unlink(prep_config_name.c_str());
+ m_config_name.clear();
+
+ delete m_prepared_config;
+ m_prepared_config= NULL;
+}
+
+
+
+void
+ConfigManager::sendConfigChangeImplRef(SignalSender& ss, NodeId nodeId,
+ ConfigChangeRef::ErrorCode error) const
+{
+ SimpleSignal ssig;
+ ConfigChangeImplRef* const ref =
+ CAST_PTR(ConfigChangeImplRef, ssig.getDataPtrSend());
+ ref->errorCode = error;
+
+ g_eventLogger->debug("Send CONFIG_CHANGE_IMPL_REF to node: %d, error: %d",
+ nodeId, error);
+
+ ss.sendSignal(nodeId, ssig,
+ MGM_CONFIG_MAN, GSN_CONFIG_CHANGE_IMPL_REF,
+ ConfigChangeImplRef::SignalLength);
+}
+
+
+
+void
+ConfigManager::execCONFIG_CHANGE_IMPL_REQ(SignalSender& ss, SimpleSignal* sig)
+{
+ NodeId nodeId = refToNode(sig->header.theSendersBlockRef);
+ const ConfigChangeImplReq * const req =
+ CAST_CONSTPTR(ConfigChangeImplReq, sig->getDataPtr());
+
+ g_eventLogger->debug("Got CONFIG_CHANGE_IMPL_REQ from node: %d, "\
+ "requestType: %d",
+ nodeId, req->requestType);
+
+ Guard g(m_config_mutex);
+
+ switch(req->requestType){
+ case ConfigChangeImplReq::Prepare:{
+ if (sig->header.m_noOfSections != 1)
+ {
+ sendConfigChangeImplRef(ss, nodeId, ConfigChangeRef::NoConfigData);
+ return;
+ }
+
+ ConfigValuesFactory cf;
+ if (!cf.unpack(sig->ptr[0].p, req->length))
+ {
+ sendConfigChangeImplRef(ss, nodeId, ConfigChangeRef::FailedToUnpack);
+ return;
+ }
+
+ Config* new_config = new Config(cf.getConfigValues());
+ Uint32 new_generation = new_config->getGeneration();
+ Uint32 curr_generation = m_config->getGeneration();
+ const char* new_name = new_config->getName();
+ const char* curr_name = m_config->getName();
+
+ if (m_config->illegal_change(new_config))
+ {
+ sendConfigChangeImplRef(ss, nodeId, ConfigChangeRef::IllegalConfigChange);
+ return;
+ }
+
+ if (req->initial)
+ {
+ // Check own state
+ if (m_config_state != CS_INITIAL)
+ {
+ g_eventLogger->warning("Refusing to start initial " \
+ "configuration change since this node " \
+ "is not in INITIAL state");
+ sendConfigChangeImplRef(ss, nodeId, ConfigChangeRef::IllegalState);
+ return;
+ }
+
+ // Check generation
+ if (new_generation != 0)
+ {
+ g_eventLogger->warning("Refusing to start initial " \
+ "configuration change since new " \
+ "generation is not 0 (new_generation: %d)",
+ new_generation);
+ sendConfigChangeImplRef(ss, nodeId,
+ ConfigChangeRef::IllegalInitialGeneration);
+ return;
+ }
+ new_generation = 1;
+
+ // Check config is equal to our initial config
+ {
+ Config new_config_copy(new_config);
+ require(new_config_copy.setName(new_name));
+ unsigned exclude[]= {CFG_SECTION_SYSTEM, 0};
+ if (!new_config_copy.equal(m_new_config, exclude))
+ {
+ BaseString buf;
+ g_eventLogger->warning("Refusing to start initial config " \
+ "change when nodes have different " \
+ "config\n" \
+ "This is the actual diff:\n%s",
+ new_config_copy.diff2str(m_new_config, buf));
+ sendConfigChangeImplRef(ss, nodeId,
+ ConfigChangeRef::DifferentInitial);
+ return;
+ }
+ }
+
+ /*
+ Scrap the m_new_config, it's been used to check that other node
+ started from equal initial config, now it's not needed anymore
+ */
+ delete m_new_config;
+ m_new_config = NULL;
+
+ }
+ else
+ {
+ if (new_generation == 0 ||
+ new_generation != curr_generation)
+ {
+ BaseString buf;
+ g_eventLogger->warning("Refusing to start config change " \
+ "requested by node with different " \
+ "generation: %d. Our generation: %d\n" \
+ "This is the actual diff:\n%s",
+ new_generation, curr_generation,
+ new_config->diff2str(m_config, buf));
+ sendConfigChangeImplRef(ss, nodeId, ConfigChangeRef::InvalidGeneration);
+ return;
+ }
+ new_generation++;
+
+ // Check same cluster name
+ if (strcmp(new_name, curr_name))
+ {
+ BaseString buf;
+ g_eventLogger->warning("Refusing to start config change " \
+ "requested by node with different " \
+ "name: '%s'. Our name: '%s'\n" \
+ "This is the actual diff:\n%s",
+ new_name, curr_name,
+ new_config->diff2str(m_config, buf));
+ sendConfigChangeImplRef(ss, nodeId, ConfigChangeRef::InvalidConfigName);
+ return;
+ }
+ }
+
+ // Set new generation
+ if(!new_config->setGeneration(new_generation))
+ {
+ g_eventLogger->error("Failed to set new generation to %d",
+ new_generation);
+ sendConfigChangeImplRef(ss, nodeId, ConfigChangeRef::SetGenerationFailed);
+ return;
+ }
+
+ if (!prepareConfigChange(new_config))
+ {
+ sendConfigChangeImplRef(ss, nodeId, ConfigChangeRef::PrepareFailed);
+ return;
+ }
+ break;
+ }
+
+ case ConfigChangeImplReq::Commit:
+ commitConfigChange();
+
+ // All nodes has agreed on config -> CONFIRMED
+ m_config_state = CS_CONFIRMED;
+
+ break;
+
+ case ConfigChangeImplReq::Abort:
+ abortConfigChange();
+ break;
+
+ default:
+ g_eventLogger->error("execCONFIG_CHANGE_IMPL_REQ: unhandled state");
+ abort();
+ break;
+ }
+
+ /* Send CONF */
+ SimpleSignal ssig;
+ ConfigChangeImplConf* const conf =
+ CAST_PTR(ConfigChangeImplConf, ssig.getDataPtrSend());
+ conf->requestType = req->requestType;
+
+ g_eventLogger->debug("Sending CONFIG_CHANGE_IMPL_CONF to node: %d",
+ nodeId);
+
+ ss.sendSignal(nodeId, ssig,
+ MGM_CONFIG_MAN,
+ GSN_CONFIG_CHANGE_IMPL_CONF,
+ ConfigChangeImplConf::SignalLength);
+}
+
+
+void
+ConfigManager::execCONFIG_CHANGE_IMPL_REF(SignalSender& ss, SimpleSignal* sig)
+{
+ NodeId nodeId = refToNode(sig->header.theSendersBlockRef);
+ g_eventLogger->debug("Got CONFIG_CHANGE_IMPL_REF from node: %d", nodeId);
+
+ const ConfigChangeImplRef * const ref =
+ CAST_CONSTPTR(ConfigChangeImplRef, sig->getDataPtr());
+ g_eventLogger->warning("Node %d refused configuration change, error: %d",
+ nodeId, ref->errorCode);
+
+ switch(m_config_change_state){
+
+ case CCS_PREPARING:{
+ /* Got ref while preparing */
+ m_config_change_state = CCS_ABORT;
+ m_waiting_for.clear(nodeId);
+ if (!m_waiting_for.isclear())
+ return;
+
+ /* Abort all other nodes */
+ SimpleSignal ssig;
+ ConfigChangeImplReq* const req =
+ CAST_PTR(ConfigChangeImplReq, ssig.getDataPtrSend());
+ req->requestType = ConfigChangeImplReq::Abort;
+
+ g_eventLogger->debug("Sending CONFIG_CHANGE_IMPL_REQ(abort) to node %d",
+ nodeId);
+ require(m_waiting_for.isclear());
+ m_waiting_for = ss.broadcastSignal(m_all_mgm, ssig,
+ MGM_CONFIG_MAN,
+ GSN_CONFIG_CHANGE_IMPL_REQ,
+ ConfigChangeImplReq::SignalLength);
+ if (m_waiting_for.isclear())
+ m_config_change_state = CCS_IDLE;
+ else
+ m_config_change_state = CCS_ABORTING;
+ break;
+ }
+
+ case CCS_COMITTING:
+ /* Got ref while comitting, impossible */
+ abort();
+ break;
+
+ case CCS_ABORT:{
+ /* Got ref(another) while already decided to abort */
+ m_waiting_for.clear(nodeId);
+ if (!m_waiting_for.isclear())
+ return;
+
+ /* Abort all other nodes */
+ SimpleSignal ssig;
+ ConfigChangeImplReq* const req =
+ CAST_PTR(ConfigChangeImplReq, ssig.getDataPtrSend());
+ req->requestType = ConfigChangeImplReq::Abort;
+
+ g_eventLogger->debug("Sending CONFIG_CHANGE_IMPL_REQ(abort) to node %d",
+ nodeId);
+ require(m_waiting_for.isclear());
+ m_waiting_for = ss.broadcastSignal(m_all_mgm, ssig,
+ MGM_CONFIG_MAN,
+ GSN_CONFIG_CHANGE_IMPL_REQ,
+ ConfigChangeImplReq::SignalLength);
+ if (m_waiting_for.isclear())
+ m_config_change_state = CCS_IDLE;
+ else
+ m_config_change_state = CCS_ABORTING;
+ break;
+ }
+
+ case CCS_ABORTING:
+ /* Got ref while aborting, impossible */
+ abort();
+ break;
+
+ default:
+ g_eventLogger->error("execCONFIG_CHANGE_IMPL_REF: unhandled state");
+ abort();
+ break;
+ }
+}
+
+
+void
+ConfigManager::execCONFIG_CHANGE_IMPL_CONF(SignalSender& ss, SimpleSignal* sig)
+{
+ NodeId nodeId = refToNode(sig->header.theSendersBlockRef);
+ const ConfigChangeImplConf * const conf =
+ CAST_CONSTPTR(ConfigChangeImplConf, sig->getDataPtr());
+ g_eventLogger->debug("Got CONFIG_CHANGE_IMPL_CONF from node %d", nodeId);
+
+ switch(m_config_change_state){
+ case CCS_PREPARING:{
+ require(conf->requestType == ConfigChangeImplReq::Prepare);
+ m_waiting_for.clear(nodeId);
+ if (!m_waiting_for.isclear())
+ return;
+
+ /* Send commit to all nodes */
+ SimpleSignal ssig;
+ ConfigChangeImplReq* const req =
+ CAST_PTR(ConfigChangeImplReq, ssig.getDataPtrSend());
+
+ req->requestType = ConfigChangeImplReq::Commit;
+
+ g_eventLogger->debug("Sending CONFIG_CHANGE_IMPL_REQ(commit)");
+ require(m_waiting_for.isclear());
+ m_waiting_for = ss.broadcastSignal(m_all_mgm, ssig,
+ MGM_CONFIG_MAN,
+ GSN_CONFIG_CHANGE_IMPL_REQ,
+ ConfigChangeImplReq::SignalLength);
+ if (m_waiting_for.isclear())
+ m_config_change_state = CCS_IDLE;
+ else
+ m_config_change_state = CCS_COMITTING;
+ break;
+ }
+
+ case CCS_COMITTING:{
+ require(conf->requestType == ConfigChangeImplReq::Commit);
+
+ m_waiting_for.clear(nodeId);
+ if (!m_waiting_for.isclear())
+ return;
+
+ require(m_client_ref != RNIL);
+ if (m_client_ref == ss.getOwnRef())
+ {
+ g_eventLogger->info("Config change completed! New generation: %d",
+ m_config->getGeneration());
+ }
+ else
+ {
+ /* Send CONF to requestor */
+ sendConfigChangeConf(ss, m_client_ref);
+ }
+ m_client_ref = RNIL;
+ m_config_change_state = CCS_IDLE;
+ break;
+ }
+
+ case CCS_ABORT:{
+ m_waiting_for.clear(nodeId);
+ if (!m_waiting_for.isclear())
+ return;
+
+ /* Abort all other nodes */
+ SimpleSignal ssig;
+ ConfigChangeImplReq* const req =
+ CAST_PTR(ConfigChangeImplReq, ssig.getDataPtrSend());
+ req->requestType = ConfigChangeImplReq::Abort;
+
+ g_eventLogger->debug("Sending CONFIG_CHANGE_IMPL_REQ(abort)");
+ require(m_waiting_for.isclear());
+ m_waiting_for = ss.broadcastSignal(m_all_mgm, ssig,
+ MGM_CONFIG_MAN,
+ GSN_CONFIG_CHANGE_IMPL_REQ,
+ ConfigChangeImplReq::SignalLength);
+ if (m_waiting_for.isclear())
+ m_config_change_state = CCS_IDLE;
+ else
+ m_config_change_state = CCS_ABORTING;
+ break;
+ }
+
+ case CCS_ABORTING:{
+ m_waiting_for.clear(nodeId);
+ if (!m_waiting_for.isclear())
+ return;
+
+ require(m_client_ref != RNIL);
+ if (m_client_ref == ss.getOwnRef())
+ {
+ g_eventLogger->error("Config change failed!");
+ exit(1);
+ }
+ else
+ {
+ /* Send ref to the requestor */
+ sendConfigChangeRef(ss, m_client_ref,
+ ConfigChangeRef::ConfigChangeAborted);
+ }
+ m_client_ref = RNIL;
+ m_config_change_state = CCS_IDLE;
+ break;
+ }
+
+ default:
+ g_eventLogger->error("execCONFIG_CHANGE_IMPL_CONF: unhandled state");
+ abort();
+ break;
+ }
+}
+
+
+void
+ConfigManager::sendConfigChangeRef(SignalSender& ss, BlockReference to,
+ ConfigChangeRef::ErrorCode error) const
+{
+ NodeId nodeId = refToNode(to);
+ SimpleSignal ssig;
+ ConfigChangeRef* const ref =
+ CAST_PTR(ConfigChangeRef, ssig.getDataPtrSend());
+ ref->errorCode = error;
+
+ g_eventLogger->debug("Send CONFIG_CHANGE_REF to node: %d, error: %d",
+ nodeId, error);
+
+ ss.sendSignal(nodeId, ssig, refToBlock(to),
+ GSN_CONFIG_CHANGE_REF, ConfigChangeRef::SignalLength);
+}
+
+
+void
+ConfigManager::sendConfigChangeConf(SignalSender& ss, BlockReference to) const
+{
+ NodeId nodeId = refToNode(to);
+ SimpleSignal ssig;
+
+ g_eventLogger->debug("Send CONFIG_CHANGE_CONF to node: %d", nodeId);
+
+ ss.sendSignal(nodeId, ssig, refToBlock(to),
+ GSN_CONFIG_CHANGE_CONF, ConfigChangeConf::SignalLength);
+}
+
+
+void
+ConfigManager::startInitConfigChange(SignalSender& ss)
+{
+ require(m_config_state == CS_INITIAL);
+ g_eventLogger->info("Starting initial configuration change");
+ m_client_ref = ss.getOwnRef();
+ sendConfigChangeImplReq(ss, m_new_config);
+}
+
+
+void
+ConfigManager::startNewConfigChange(SignalSender& ss)
+{
+ require(m_config_state == CS_CONFIRMED);
+ g_eventLogger->info("Starting configuration change, generation: %d",
+ m_new_config->getGeneration());
+ m_client_ref = ss.getOwnRef();
+ sendConfigChangeImplReq(ss, m_new_config);
+
+ /* The new config has been sent and can now be discarded */
+ delete m_new_config;
+ m_new_config = NULL;
+}
+
+
+void
+ConfigManager::sendConfigChangeImplReq(SignalSender& ss, const Config* conf)
+{
+ require(m_client_ref != RNIL);
+
+ /* Send prepare to all MGM nodes */
+ SimpleSignal ssig;
+
+ UtilBuffer buf;
+ conf->pack(buf);
+ ssig.ptr[0].p = (Uint32*)buf.get_data();
+ ssig.ptr[0].sz = (buf.length() + 3) / 4;
+ ssig.header.m_noOfSections = 1;
+
+ ConfigChangeImplReq* const req =
+ CAST_PTR(ConfigChangeImplReq, ssig.getDataPtrSend());
+ req->requestType = ConfigChangeImplReq::Prepare;
+ req->initial = (m_config_state == CS_INITIAL);
+ req->length = buf.length();
+
+ g_eventLogger->debug("Sending CONFIG_CHANGE_IMPL_REQ(prepare)");
+
+ require(m_waiting_for.isclear());
+ m_waiting_for = ss.broadcastSignal(m_all_mgm, ssig,
+ MGM_CONFIG_MAN,
+ GSN_CONFIG_CHANGE_IMPL_REQ,
+ ConfigChangeImplReq::SignalLength);
+ if (!m_waiting_for.isclear())
+ m_config_change_state = CCS_ABORT;
+ else
+ require(m_config_change_state == CCS_IDLE);
+ m_config_change_state = CCS_PREPARING;
+}
+
+
+void
+ConfigManager::execCONFIG_CHANGE_REQ(SignalSender& ss, SimpleSignal* sig)
+{
+ BlockReference from = sig->header.theSendersBlockRef;
+ const ConfigChangeReq * const req =
+ CAST_CONSTPTR(ConfigChangeReq, sig->getDataPtr());
+
+ if (!m_started.equal(m_all_mgm)) // Not all started
+ {
+ sendConfigChangeRef(ss, from, ConfigChangeRef::NotAllStarted);
+ return;
+ }
+
+ if (m_all_mgm.find(0) != m_facade->ownId()) // Not the master
+ {
+ sendConfigChangeRef(ss, from, ConfigChangeRef::NotMaster);
+ return;
+ }
+
+ if (m_config_change_state != CCS_IDLE)
+ {
+ sendConfigChangeRef(ss, from, ConfigChangeRef::ConfigChangeOnGoing);
+ return;
+ }
+
+ if (sig->header.m_noOfSections != 1)
+ {
+ sendConfigChangeRef(ss, from, ConfigChangeRef::NoConfigData);
+ return;
+ }
+
+ ConfigValuesFactory cf;
+ if (!cf.unpack(sig->ptr[0].p, req->length))
+ {
+ sendConfigChangeRef(ss, from, ConfigChangeRef::FailedToUnpack);
+ return;
+ }
+
+ Config new_config(cf.getConfigValues());
+ if (!config_ok(&new_config))
+ {
+ g_eventLogger->warning("Refusing to start config change, the config "\
+ "is not ok");
+ sendConfigChangeRef(ss, from, ConfigChangeRef::FailedToUnpack);
+ return;
+ }
+
+ m_client_ref = from;
+ sendConfigChangeImplReq(ss, &new_config);
+ return;
+}
+
+
+void
+ConfigManager::execCONFIG_CHECK_REQ(SignalSender& ss, SimpleSignal* sig)
+{
+ Guard g(m_config_mutex);
+ BlockReference from = sig->header.theSendersBlockRef;
+ NodeId nodeId = refToNode(from);
+ const ConfigCheckReq * const req =
+ CAST_CONSTPTR(ConfigCheckReq, sig->getDataPtr());
+
+ Uint32 other_generation = req->generation;
+ ConfigState other_state = (ConfigState)req->state;
+
+ Uint32 generation = m_config->getGeneration();
+
+ g_eventLogger->debug("Got CONFIG_CHECK_REQ from node: %d. " \
+ "generation: %d, other_generation: %d, " \
+ "our state: %d, other state: %d",
+ generation, other_generation,
+ m_config_state, other_state, nodeId);
+
+ switch (m_config_state)
+ {
+ default:
+ case CS_UNINITIALIZED:
+ g_eventLogger->error("execCONFIG_CHECK_REQ: unhandled state");
+ abort();
+ break;
+
+ case CS_INITIAL:
+ if (other_state != CS_INITIAL)
+ {
+ g_eventLogger->error("Other node are not in INITIAL");
+ exit(1);
+ }
+
+ require(generation == 0);
+ if (other_generation != generation)
+ {
+ g_eventLogger->warning("Refusing other node, it has different " \
+ "generation: %d, expected: %d",
+ other_generation, generation);
+ sendConfigCheckRef(ss, from, ConfigCheckRef::WrongGeneration,
+ generation, other_generation,
+ m_config_state, other_state);
+ return;
+ }
+ break;
+
+ case CS_CONFIRMED:
+ if (other_state != CS_CONFIRMED)
+ {
+ g_eventLogger->warning("Refusing other node, it's in different " \
+ "state: %d, expected: %d",
+ other_state, m_config_state);
+ sendConfigCheckRef(ss, from, ConfigCheckRef::WrongState,
+ generation, other_generation,
+ m_config_state, other_state);
+ return;
+ }
+
+ if (other_generation == generation)
+ {
+ ;// OK
+ }
+ else if (other_generation < generation)
+ {
+ g_eventLogger->warning("Refusing other node, it has lower " \
+ " generation: %d, expected: %d",
+ other_generation, generation);
+ sendConfigCheckRef(ss, from, ConfigCheckRef::WrongGeneration,
+ generation, other_generation,
+ m_config_state, other_state);
+ return;
+ }
+ else
+ {
+ g_eventLogger->error("Other node has higher generation: %d, this " \
+ "node is out of sync with generation: %d",
+ other_generation, generation);
+ exit(1);
+ }
+
+ break;
+ }
+
+ sendConfigCheckConf(ss, from);
+ return;
+}
+
+
+void
+ConfigManager::sendConfigCheckReq(SignalSender& ss, NodeBitmask to)
+{
+ SimpleSignal ssig;
+ ConfigCheckReq* const req =
+ CAST_PTR(ConfigCheckReq, ssig.getDataPtrSend());
+ req->state = m_config_state;
+ req->generation = m_config->getGeneration();
+
+ BaseString buf("Sending CONFIG_CHECK_REQ to node(s) ");
+ unsigned i = 0;
+ while((i = to.find(i+1)) != NodeBitmask::NotFound)
+ buf.appfmt("%d ", i);
+ g_eventLogger->debug(buf);
+
+ require(m_waiting_for.isclear());
+ m_waiting_for = ss.broadcastSignal(to, ssig, MGM_CONFIG_MAN,
+ GSN_CONFIG_CHECK_REQ,
+ ConfigCheckReq::SignalLength);
+}
+
+
+void
+ConfigManager::sendConfigCheckRef(SignalSender& ss, BlockReference to,
+ ConfigCheckRef::ErrorCode error,
+ Uint32 generation,
+ Uint32 other_generation,
+ ConfigState state,
+ ConfigState other_state) const
+{
+ NodeId nodeId = refToNode(to);
+ SimpleSignal ssig;
+ ConfigCheckRef* const ref =
+ CAST_PTR(ConfigCheckRef, ssig.getDataPtrSend());
+ ref->error = error;
+ ref->generation = other_generation;
+ ref->expected_generation = generation;
+ ref->state = other_state;
+ ref->expected_state = state;
+
+ g_eventLogger->debug("Send CONFIG_CHECK_REF with error: %d to node: %d",
+ error, nodeId);
+
+ ss.sendSignal(nodeId, ssig, MGM_CONFIG_MAN,
+ GSN_CONFIG_CHECK_REF, ConfigCheckReq::SignalLength);
+}
+
+
+void
+ConfigManager::sendConfigCheckConf(SignalSender& ss, BlockReference to) const
+{
+ NodeId nodeId = refToNode(to);
+ SimpleSignal ssig;
+ ConfigCheckConf* const conf =
+ CAST_PTR(ConfigCheckConf, ssig.getDataPtrSend());
+ conf->state = m_config_state;
+ conf->generation = m_config->getGeneration();
+
+ g_eventLogger->debug("Send CONFIG_CHECK_CONF to node: %d", nodeId);
+
+ ss.sendSignal(nodeId, ssig, MGM_CONFIG_MAN,
+ GSN_CONFIG_CHECK_CONF, ConfigCheckReq::SignalLength);
+}
+
+
+void
+ConfigManager::execCONFIG_CHECK_CONF(SignalSender& ss, SimpleSignal* sig)
+{
+ BlockReference from = sig->header.theSendersBlockRef;
+ NodeId nodeId = refToNode(from);
+ m_waiting_for.clear(nodeId);
+ m_checked.set(nodeId);
+
+ g_eventLogger->debug("Got CONFIG_CHECK_CONF from node: %d",
+ nodeId);
+
+ return;
+}
+
+
+void
+ConfigManager::execCONFIG_CHECK_REF(SignalSender& ss, SimpleSignal* sig)
+{
+ BlockReference from = sig->header.theSendersBlockRef;
+ NodeId nodeId = refToNode(from);
+
+ const ConfigCheckRef* const ref =
+ CAST_CONSTPTR(ConfigCheckRef, sig->getDataPtr());
+
+ g_eventLogger->error("Got CONFIG_CHECK_REF from node %d, " \
+ "error: %d, message: '%s'\n" \
+ "generation: %d, expected generation: %d\n"\
+ "state: %d, expected state: %d",
+ nodeId, ref->error,
+ ConfigCheckRef::errorMessage(ref->error),
+ ref->generation, ref->expected_generation,
+ ref->state, ref->expected_state);
+ exit(1);
+}
+
+
+void
+ConfigManager::run()
+{
+ assert(m_facade);
+ SignalSender ss(m_facade, MGM_CONFIG_MAN);
+ ss.lock();
+
+ ss.getNodes(m_all_mgm, NodeInfo::MGM);
+
+ m_started.set(m_facade->ownId());
+
+ while (!is_stopped())
+ {
+
+ if (m_config_change_state == CCS_IDLE)
+ {
+ bool print_state = false;
+ if (m_previous_state != m_config_state)
+ {
+ print_state = true;
+ m_previous_state = m_config_state;
+ }
+
+ /*
+ Check if it's necessary to start something to get
+ out of the current state
+ */
+ switch (m_config_state){
+
+ case CS_UNINITIALIZED:
+ abort();
+ break;
+
+ case CS_INITIAL:
+ /*
+ INITIAL => CONFIRMED
+ When all mgm nodes has been started and checked that they
+ are also in INITIAL, the node with the lowest node id
+ will start an initial config change. When completed
+ all nodes will be in CONFIRMED
+ */
+
+ if (print_state)
+ ndbout_c("==INITIAL==");
+
+ if (m_new_config && // Updated config.ini was found
+ m_started.equal(m_all_mgm) && // All mgmd started
+ m_checked.equal(m_started) && // All nodes checked
+ m_all_mgm.find(0) == m_facade->ownId()) // Lowest nodeid
+ {
+ startInitConfigChange(ss);
+ }
+ break;
+
+ case CS_CONFIRMED:
+ if (print_state)
+ ndbout_c("==CONFIRMED==");
+
+ if (m_new_config && // Updated config.ini was found
+ m_started.equal(m_all_mgm) && // All mgmd started
+ m_checked.equal(m_started)) // All nodes checked
+ {
+ startNewConfigChange(ss);
+ }
+
+ break;
+
+ default:
+ break;
+ }
+
+ // Send CHECK_CONFIG to all nodes not yet checked
+ if (m_waiting_for.isclear() && // Nothing else ongoing
+ !m_checked.equal(m_started)) // Some nodes have not been checked
+ {
+ NodeBitmask not_checked;
+ not_checked.assign(m_started);
+ not_checked.bitANDC(m_checked);
+ sendConfigCheckReq(ss, not_checked);
+ }
+ }
+
+
+ SimpleSignal *sig = ss.waitFor((Uint32)1000);
+ if (!sig)
+ continue;
+
+ switch (sig->readSignalNumber()) {
+
+ case GSN_CONFIG_CHANGE_REQ:
+ execCONFIG_CHANGE_REQ(ss, sig);
+ break;
+
+ case GSN_CONFIG_CHANGE_IMPL_REQ:
+ execCONFIG_CHANGE_IMPL_REQ(ss, sig);
+ break;
+
+ case GSN_CONFIG_CHANGE_IMPL_REF:
+ execCONFIG_CHANGE_IMPL_REF(ss, sig);
+ break;
+
+ case GSN_CONFIG_CHANGE_IMPL_CONF:
+ execCONFIG_CHANGE_IMPL_CONF(ss, sig);
+ break;
+
+ case GSN_NF_COMPLETEREP:{
+ const NFCompleteRep * const rep =
+ CAST_CONSTPTR(NFCompleteRep, sig->getDataPtr());
+ NodeId nodeId= rep->failedNodeId;
+
+ if (m_all_mgm.get(nodeId)) // Not mgm node
+ break;
+
+ ndbout_c("Node %d failed", nodeId);
+ m_started.clear(nodeId);
+ m_checked.clear(nodeId);
+
+ if (m_config_change_state != CCS_IDLE)
+ {
+ g_eventLogger->info("Node %d failed during config change!!",
+ nodeId);
+ // TODO start take over of config change protocol
+ }
+ break;
+ }
+
+ case GSN_NODE_FAILREP:
+ // ignore, NF_COMPLETEREP will come
+ break;
+
+ case GSN_API_REGCONF:{
+ NodeId nodeId = refToNode(sig->header.theSendersBlockRef);
+ if (m_all_mgm.get(nodeId) && // Is a mgm node
+ !m_started.get(nodeId)) // Not already marked as started
+ {
+ g_eventLogger->info("Node %d connected", nodeId);
+ m_started.set(nodeId);
+ }
+ break;
+ }
+
+ case GSN_CONFIG_CHECK_REQ:
+ execCONFIG_CHECK_REQ(ss, sig);
+ break;
+
+ case GSN_CONFIG_CHECK_REF:
+ execCONFIG_CHECK_REF(ss, sig);
+ break;
+
+ case GSN_CONFIG_CHECK_CONF:
+ execCONFIG_CHECK_CONF(ss, sig);
+ break;
+
+ default:
+ sig->print();
+ g_eventLogger->error("Unknown signal received. SignalNumber: "
+ "%i from (%d, 0x%x)",
+ sig->readSignalNumber(),
+ refToNode(sig->header.theSendersBlockRef),
+ refToBlock(sig->header.theSendersBlockRef));
+ abort();
+ break;
+ }
+ }
+}
+
+
+#include "InitConfigFileParser.hpp"
+
+Config*
+ConfigManager::load_init_config(const char* config_filename)
+{
+ InitConfigFileParser parser;
+ g_eventLogger->info("Reading cluster configuration from '%s'",
+ config_filename);
+ return parser.parseConfig(config_filename);
+}
+
+
+Config*
+ConfigManager::load_init_mycnf(void)
+{
+ InitConfigFileParser parser;
+ g_eventLogger->info("Reading cluster configuration using my.cnf");
+ return parser.parse_mycnf();
+}
+
+
+Config*
+ConfigManager::fetch_config(void)
+{
+ DBUG_ENTER("ConfigManager::fetch_config");
+
+ /* Loop until config loaded from other mgmd(s) */
+ char buf[128];
+ g_eventLogger->info("Trying to get configuration from other mgmd(s) "\
+ "using '%s'...",
+ m_config_retriever.get_connectstring(buf, sizeof(buf)));
+
+ if (!m_config_retriever.is_connected())
+ {
+
+ if (m_config_retriever.do_connect(-1 /* retry */,
+ 1 /* delay */,
+ 0 /* verbose */) != 0)
+ {
+ g_eventLogger->error("INTERNAL ERROR: Inifinite wait for connect " \
+ "returned!");
+ abort();
+ }
+ g_eventLogger->info("Connected...");
+
+ }
+
+ // read config from other management server
+ ndb_mgm_configuration * tmp =
+ m_config_retriever.getConfig(m_config_retriever.get_mgmHandle());
+ if (tmp == NULL) {
+ g_eventLogger->error(m_config_retriever.getErrorString());
+ DBUG_RETURN(false);
+ }
+
+ DBUG_RETURN(new Config(tmp));
+}
+
+
+#include "DirIterator.hpp"
+
+bool
+ConfigManager::saved_config_exists(BaseString& config_name) const
+{
+ DirIterator iter;
+
+ if (iter.open(m_datadir) != 0)
+ return false;
+
+ const char* name;
+ unsigned nodeid;
+ char extra; // Avoid matching ndb_2_config.bin.2.tmp
+ unsigned version, max_version= 0;
+ while ((name= iter.next_file()) != NULL)
+ {
+ if (sscanf(name,
+ "ndb_%u_config.bin.%u%c",
+ &nodeid, &version, &extra) == 2)
+ {
+ // ndbout_c("match: %s", name);
+
+ if (nodeid != m_node_id)
+ continue;
+
+ if (version>max_version)
+ max_version= version;
+ }
+ }
+
+ if (max_version == 0)
+ return false;
+
+ config_name.assfmt("%s%sndb_%u_config.bin.%u",
+ m_datadir, DIR_SEPARATOR, m_node_id, max_version);
+ return true;
+}
+
+
+Config*
+ConfigManager::load_saved_config(const BaseString& config_name)
+{
+ struct ndb_mgm_configuration * tmp =
+ m_config_retriever.getConfig(config_name.c_str());
+ if(tmp == NULL)
+ {
+ g_eventLogger->error("Failed to load config from '%s', error: '%s'",
+ config_name.c_str(),
+ m_config_retriever.getErrorString());
+ return NULL;
+ }
+
+ g_eventLogger->info("Loaded config from '%s'", config_name.c_str());
+ Config* conf = new Config(tmp);
+ if (conf == NULL)
+ g_eventLogger->error("Failed to load config, out of memory");
+ return conf;
+}
+
+
+bool
+ConfigManager::get_packed_config(UtilBuffer& pack_buf)
+{
+ Guard g(m_config_mutex);
+
+ /* Only allow the config to be exported if it's been confirmed */
+ if (m_config_state != CS_CONFIRMED)
+ return false;
+
+ require(m_config);
+ return m_config->pack(pack_buf);
+}
+
+
+template class Vector<ConfigSubscriber*>;
+
=== added file 'storage/ndb/src/mgmsrv/ConfigManager.hpp'
--- a/storage/ndb/src/mgmsrv/ConfigManager.hpp 1970-01-01 00:00:00 +0000
+++ b/storage/ndb/src/mgmsrv/ConfigManager.hpp 2008-10-21 12:41:59 +0000
@@ -0,0 +1,153 @@
+/* Copyright (C) 2008 Sun Microsystems, Inc.
+
+ 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; version 2 of the License.
+
+ 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 */
+
+#ifndef ConfigManager_H
+#define ConfigManager_H
+
+#include "MgmtThread.hpp"
+#include "Config.hpp"
+#include "ConfigSubscriber.hpp"
+#include "MgmtSrvr.hpp"
+
+#include <ConfigRetriever.hpp>
+
+#include <SignalSender.hpp>
+#include <NodeBitmask.hpp>
+
+#include <signaldata/ConfigChange.hpp>
+
+class ConfigManager : public MgmtThread {
+ const MgmtSrvr::MgmtOpts& m_opts;
+ TransporterFacade* m_facade;
+
+ NdbMutex *m_config_mutex;
+ const Config * m_config;
+ const Config * m_new_config;
+
+ ConfigRetriever m_config_retriever;
+
+ enum ConfigChangeState {
+ CCS_IDLE,
+ CCS_PREPARING,
+ CCS_COMITTING,
+ CCS_ABORT,
+ CCS_ABORTING
+ } m_config_change_state;
+
+ enum ConfigState {
+ CS_UNINITIALIZED,
+
+ CS_INITIAL, // Initial config.ini, ie. no config.bin.X found
+
+ CS_CONFIRMED, // Started and all agreed
+ CS_FORCED // Forced start
+ };
+
+ ConfigState m_config_state;
+ ConfigState m_previous_state;
+
+ BlockReference m_client_ref;
+ BaseString m_config_name;
+ Config* m_prepared_config;
+
+ NodeBitmask m_all_mgm;
+ NodeBitmask m_started;
+ NodeBitmask m_waiting_for;
+ NodeBitmask m_checked;
+
+ NodeId m_node_id;
+
+ const char* m_datadir;
+
+ /* Functions used from 'init' */
+ Config* load_init_config(const char*);
+ Config* load_init_mycnf(void);
+ Config* fetch_config(void);
+ bool save_config(const Config* conf);
+ bool save_config(void);
+ bool saved_config_exists(BaseString& config_name) const;
+ Config* load_saved_config(const BaseString& config_name);
+ bool init_nodeid(void);
+
+ /* Set the new config and inform subscribers */
+ void set_config(Config* config);
+ Vector<ConfigSubscriber*> m_subscribers;
+
+ /* Check config is ok */
+ bool config_ok(const Config* conf);
+
+ /* Functions for writing config.bin to disk */
+ bool prepareConfigChange(const Config* config);
+ void commitConfigChange();
+ void abortConfigChange();
+
+ /* Functions for starting config change from ConfigManager */
+ void startInitConfigChange(SignalSender& ss);
+ void startNewConfigChange(SignalSender& ss);
+
+ /* CONFIG_CHANGE - controlling config change from other node */
+ void execCONFIG_CHANGE_REQ(SignalSender& ss, SimpleSignal* sig);
+ void execCONFIG_CHANGE_REF(SignalSender& ss, SimpleSignal* sig);
+ void sendConfigChangeRef(SignalSender& ss, BlockReference,
+ ConfigChangeRef::ErrorCode) const;
+ void sendConfigChangeConf(SignalSender& ss, BlockReference) const;
+
+ /*
+ CONFIG_CHANGE_IMPL - protocol for starting config change
+ between nodes
+ */
+ void execCONFIG_CHANGE_IMPL_REQ(SignalSender& ss, SimpleSignal* sig);
+ void execCONFIG_CHANGE_IMPL_REF(SignalSender& ss, SimpleSignal* sig);
+ void execCONFIG_CHANGE_IMPL_CONF(SignalSender& ss, SimpleSignal* sig);
+ void sendConfigChangeImplRef(SignalSender& ss, NodeId nodeId,
+ ConfigChangeRef::ErrorCode) const;
+ void sendConfigChangeImplReq(SignalSender& ss, const Config* conf);
+
+ /*
+ CONFIG_CHECK - protocol for exchanging and checking config state
+ between nodes
+ */
+ void execCONFIG_CHECK_REQ(SignalSender& ss, SimpleSignal* sig);
+ void execCONFIG_CHECK_CONF(SignalSender& ss, SimpleSignal* sig);
+ void execCONFIG_CHECK_REF(SignalSender& ss, SimpleSignal* sig);
+ void sendConfigCheckReq(SignalSender& ss, NodeBitmask to);
+ void sendConfigCheckRef(SignalSender& ss, BlockReference to,
+ ConfigCheckRef::ErrorCode,
+ Uint32, Uint32, ConfigState, ConfigState) const;
+ void sendConfigCheckConf(SignalSender& ss, BlockReference to) const;
+
+public:
+ ConfigManager(const MgmtSrvr::MgmtOpts&);
+ virtual ~ConfigManager();
+ bool init();
+ void set_facade(TransporterFacade* facade) { m_facade= facade; };
+ virtual void run();
+
+
+ /*
+ Installs subscriber that will be notified when
+ config has changed
+ */
+ int add_config_change_subscriber(ConfigSubscriber*);
+
+ /*
+ Retrieve the current configuration in packed format
+ */
+ bool get_packed_config(UtilBuffer& pack_buf);
+};
+
+
+
+#endif
=== added file 'storage/ndb/src/mgmsrv/ConfigSubscriber.hpp'
--- a/storage/ndb/src/mgmsrv/ConfigSubscriber.hpp 1970-01-01 00:00:00 +0000
+++ b/storage/ndb/src/mgmsrv/ConfigSubscriber.hpp 2008-10-21 12:41:59 +0000
@@ -0,0 +1,26 @@
+/* Copyright (C) 2008 Sun Microsystems, Inc.
+
+ 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; version 2 of the License.
+
+ 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 */
+
+#ifndef ConfigSubscriber_H
+#define ConfigSubscriber_H
+
+
+class ConfigSubscriber {
+public:
+ virtual void config_changed(NodeId, const class Config*)= 0;
+ virtual ~ConfigSubscriber() {};
+};
+
+#endif
=== added file 'storage/ndb/src/mgmsrv/DirIterator.cpp'
--- a/storage/ndb/src/mgmsrv/DirIterator.cpp 1970-01-01 00:00:00 +0000
+++ b/storage/ndb/src/mgmsrv/DirIterator.cpp 2008-10-24 12:41:10 +0000
@@ -0,0 +1,122 @@
+/* Copyright (C) 2008 Sun Microsystems, Inc.
+
+ 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; version 2 of the License.
+
+ 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 "DirIterator.hpp"
+#include <stdio.h>
+
+#ifndef __WIN__
+
+#include <dirent.h>
+
+class DirIteratorImpl {
+ DIR* m_dirp;
+
+public:
+ DirIteratorImpl():
+ m_dirp(NULL) {};
+
+ ~DirIteratorImpl() {
+ closedir(m_dirp);
+ }
+
+ int open(const char* path){
+ if ((m_dirp = opendir(path)) == NULL){
+ return -1;
+ }
+ return 0;
+ }
+
+ const char* next_file(void){
+ struct dirent* dp;
+ while ((dp = readdir(m_dirp)) != NULL &&
+ dp->d_type != DT_REG)
+ ;
+ return dp ? dp->d_name : NULL;
+ }
+};
+
+#else
+
+#include <BaseString.hpp>
+
+class DirIteratorImpl {
+ bool m_first;
+ WIN32_FIND_DATA m_find_data;
+ HANDLE m_find_handle;
+
+ bool is_dir(const WIN32_FIND_DATA find_data) const {
+ return (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
+ }
+
+public:
+ DirIteratorImpl():
+ m_first(true),
+ m_find_handle(INVALID_HANDLE_VALUE) {};
+
+ ~DirIteratorImpl() {
+ FindClose(m_find_handle);
+ }
+
+ int open(const char* path){
+ BaseString path_buf;
+ path_buf.assfmt("%s\\*", path);
+ m_find_handle = FindFirstFile(path_buf.c_str(), &m_find_data);
+ if(m_find_handle == INVALID_HANDLE_VALUE)
+ {
+ if (GetLastError() == ERROR_FILE_NOT_FOUND)
+ m_first= false; // Will do a seek in 'next_file' and return NULL
+ else
+ return -1;
+ }
+ return 0;
+ }
+
+ const char* next_file(void){
+ while(m_first || FindNextFile(m_find_handle, &m_find_data))
+ {
+ m_first= false;
+
+ if (!is_dir(m_find_data))
+ return m_find_data.cFileName;
+ }
+ return NULL;
+ }
+
+};
+
+#endif
+
+
+DirIterator::DirIterator() :
+ m_impl(*new DirIteratorImpl())
+{
+};
+
+DirIterator::~DirIterator()
+{
+ delete &m_impl;
+}
+
+
+int DirIterator::open(const char* path)
+{
+ return m_impl.open(path);
+}
+
+const char* DirIterator::next_file(void)
+{
+ return m_impl.next_file();
+}
+
=== added file 'storage/ndb/src/mgmsrv/DirIterator.hpp'
--- a/storage/ndb/src/mgmsrv/DirIterator.hpp 1970-01-01 00:00:00 +0000
+++ b/storage/ndb/src/mgmsrv/DirIterator.hpp 2008-10-24 12:41:10 +0000
@@ -0,0 +1,29 @@
+/* Copyright (C) 2008 Sun Microsystems, Inc.
+
+ 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; version 2 of the License.
+
+ 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 */
+
+#ifndef DirIterator_HPP
+#define DirIterator_HPP
+
+class DirIterator {
+ class DirIteratorImpl& m_impl;
+public:
+ DirIterator();
+ ~DirIterator();
+
+ int open(const char* path);
+ const char* next_file(void);
+};
+
+#endif
=== modified file 'storage/ndb/src/mgmsrv/InitConfigFileParser.cpp'
--- a/storage/ndb/src/mgmsrv/InitConfigFileParser.cpp 2008-09-12 12:55:29 +0000
+++ b/storage/ndb/src/mgmsrv/InitConfigFileParser.cpp 2008-10-21 12:41:59 +0000
@@ -212,10 +212,8 @@ InitConfigFileParser::run_config_rules(C
strncat(tmpLine, system, MAX_LINE_LENGTH);
strncat(tmpLine, ":NoOfConnections", MAX_LINE_LENGTH);
ctx.m_config->put(tmpLine, nExtConnections);
-
- Config * ret = new Config();
- ret->m_configValues = (struct ndb_mgm_configuration*)ctx.m_configValues.getConfigValues();
- return ret;
+
+ return new Config(ctx.m_configValues.getConfigValues());
}
//****************************************************************************
=== modified file 'storage/ndb/src/mgmsrv/Makefile.am'
--- a/storage/ndb/src/mgmsrv/Makefile.am 2008-10-06 06:53:04 +0000
+++ b/storage/ndb/src/mgmsrv/Makefile.am 2008-10-27 11:13:34 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2004-2006 MySQL AB
+# Copyright (C) 2004-2008 MySQL AB, 2008 Sun Microsystems, Inc.
#
# 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
@@ -18,8 +18,7 @@ EXTRA_DIST = CMakeLists.txt
MYSQLDATAdir = $(localstatedir)
MYSQLSHAREdir = $(pkgdatadir)
MYSQLBASEdir= $(prefix)
-#MYSQLCLUSTERdir= $(prefix)/mysql-cluster
-MYSQLCLUSTERdir= .
+MYSQLCLUSTERdir= $(prefix)/mysql-cluster
ndbbin_PROGRAMS = ndb_mgmd
@@ -27,12 +26,12 @@ ndb_mgmd_SOURCES = \
MgmtSrvr.cpp \
main.cpp \
Services.cpp \
- MgmtSrvrConfig.cpp \
ConfigInfo.cpp \
InitConfigFileParser.cpp \
Config.cpp \
- mgm_ndbinfo.cpp
-
+ mgm_ndbinfo.cpp \
+ ConfigManager.cpp \
+ DirIterator.cpp
noinst_PROGRAMS = testConfig
=== modified file 'storage/ndb/src/mgmsrv/MgmtSrvr.cpp'
--- a/storage/ndb/src/mgmsrv/MgmtSrvr.cpp 2008-10-08 14:31:38 +0000
+++ b/storage/ndb/src/mgmsrv/MgmtSrvr.cpp 2008-10-27 11:13:34 +0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 MySQL AB
+/* Copyright (C) 2003-2008 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
@@ -14,11 +14,11 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <ndb_global.h>
-#include <my_pthread.h>
#include "MgmtSrvr.hpp"
#include "ndb_mgmd_error.h"
#include "Services.hpp"
+#include "ConfigManager.hpp"
#include <NdbOut.hpp>
#include <NdbApiSignal.hpp>
@@ -56,7 +56,6 @@
#include <mgmapi.h>
#include <mgmapi_configuration.hpp>
#include <mgmapi_config_parameters.h>
-#include <m_string.h>
#include <SignalSender.hpp>
@@ -89,6 +88,7 @@ static void require(bool v)
}
}
+
void *
MgmtSrvr::logLevelThread_C(void* m)
{
@@ -262,11 +262,9 @@ MgmtSrvr::MgmtSrvr(const MgmtOpts& opts,
_blockNumber(-1),
_ownNodeId(0),
m_port(0),
- m_config_retriever(connect_str,
- NDB_VERSION,
- NDB_MGM_NODE_TYPE_MGM),
+ m_local_config(NULL),
_ownReference(0),
- _config(NULL),
+ m_config_manager(NULL),
theFacade(NULL),
_isStopThread(false),
_logLevelThreadSleep(500),
@@ -276,9 +274,9 @@ MgmtSrvr::MgmtSrvr(const MgmtOpts& opts,
{
DBUG_ENTER("MgmtSrvr::MgmtSrvr");
- m_configMutex = NdbMutex_Create();
+ m_local_config_mutex= NdbMutex_Create();
m_node_id_mutex = NdbMutex_Create();
- if (!m_configMutex || !m_node_id_mutex)
+ if (!m_local_config_mutex || !m_node_id_mutex)
{
g_eventLogger->error("Failed to create MgmtSrvr mutexes");
require(false);
@@ -314,67 +312,66 @@ MgmtSrvr::init()
{
DBUG_ENTER("MgmtSrvr::init");
- if (m_opts.mycnf || m_opts.config_filename)
+
+ if (!(m_config_manager= new ConfigManager(m_opts)))
{
- Config* conf= NULL;
- if (m_opts.mycnf && (conf= load_init_mycnf()) == NULL)
- {
- g_eventLogger->error("Could not load config from 'my.cnf'");
- DBUG_RETURN(false);
- }
- else if (m_opts.config_filename && (conf= load_init_config()) == NULL)
- {
- g_eventLogger->error("Could not load initial config from '%s'",
- m_opts.config_filename);
- DBUG_RETURN(false);
- }
- setConfig(conf);
+ g_eventLogger->error("Failed to create ConfigManager");
+ DBUG_RETURN(false);
}
- else
+
+ if (m_config_manager->add_config_change_subscriber(this) < 0)
{
- if (fetch_config())
- {
- g_eventLogger->error("Could not fetch config");
- DBUG_RETURN(false);
- }
+ g_eventLogger->error("Failed to add MgmtSrvr as config change subscriber");
+ DBUG_RETURN(false);
}
- if (m_opts.print_full_config)
+ if (!m_config_manager->init())
{
- print_config();
DBUG_RETURN(false);
}
- if (_ownNodeId == 0)
+ /* 'config_changed' should have been called from 'init' */
+ require(m_local_config);
+
+ if (m_opts.print_full_config)
{
- _ownNodeId= m_config_retriever.get_configuration_nodeid();
+ Guard g(m_local_config_mutex);
+ m_local_config->print();
+ DBUG_RETURN(false);
+ }
- int error_code;
- BaseString error_string;
- if (!alloc_node_id(&_ownNodeId, NDB_MGM_NODE_TYPE_MGM,
- 0, 0, error_code, error_string, 0))
- {
- g_eventLogger->error("Unable to obtain requested nodeid, error: '%s'",
- error_string.c_str());
- DBUG_RETURN(false);
- }
+ assert(_ownNodeId);
- if (!m_config_retriever.verifyConfig(_config->m_configValues,
- _ownNodeId))
- {
- g_eventLogger->error(m_config_retriever.getErrorString());
- DBUG_RETURN(false);
- }
+ /* Reserve the node id with ourself */
+ NodeId nodeId= _ownNodeId;
+ int error_code;
+ BaseString error_string;
+ if (!alloc_node_id(&nodeId, NDB_MGM_NODE_TYPE_MGM,
+ 0, /* client_addr */
+ 0, /* client_addr_len */
+ error_code, error_string,
+ 0 /* log_event */ ))
+ {
+ g_eventLogger->error("INTERNAL ERROR: Could not allocate nodeid: %d, " \
+ "error: %d, '%s'",
+ _ownNodeId, error_code, error_string.c_str());
+ DBUG_RETURN(false);
}
- setClusterLog();
+ if (nodeId != _ownNodeId)
+ {
+ g_eventLogger->error("INTERNAL ERROR: Nodeid %d allocated " \
+ "when %d was requested",
+ nodeId, _ownNodeId);
+ DBUG_RETURN(false);
+ }
DBUG_RETURN(true);
}
bool
-MgmtSrvr::start_transporter()
+MgmtSrvr::start_transporter(const Config* config)
{
DBUG_ENTER("MgmtSrvr::start_transporter");
@@ -386,7 +383,7 @@ MgmtSrvr::start_transporter()
}
if (theFacade->start_instance(_ownNodeId,
- _config->m_configValues) < 0)
+ config->m_configValues) < 0)
{
g_eventLogger->error("Failed to start transporter");
delete theFacade;
@@ -428,15 +425,14 @@ MgmtSrvr::start_transporter()
bool
-MgmtSrvr::start_mgm_service()
+MgmtSrvr::start_mgm_service(const Config* config)
{
DBUG_ENTER("MgmtSrvr::start_mgm_service");
assert(m_port == 0);
{
// Find the portnumber to use for mgm service
- Guard g(m_configMutex);
- ConfigIter iter(_config, CFG_SECTION_NODE);
+ ConfigIter iter(config, CFG_SECTION_NODE);
if(iter.find(CFG_NODE_ID, _ownNodeId) != 0){
g_eventLogger->error("Could not find node %d in config", _ownNodeId);
@@ -529,15 +525,17 @@ MgmtSrvr::start()
{
DBUG_ENTER("MgmtSrvr::start");
+ Guard g(m_local_config_mutex);
+
/* Start transporter */
- if(!start_transporter())
+ if(!start_transporter(m_local_config))
{
g_eventLogger->error("Failed to start transporter!");
DBUG_RETURN(false);
}
/* Start mgm service */
- if (!start_mgm_service())
+ if (!start_mgm_service(m_local_config))
{
g_eventLogger->error("Failed to start mangement service!");
DBUG_RETURN(false);
@@ -550,6 +548,14 @@ MgmtSrvr::start()
DBUG_RETURN(false);
}
+ /* Start config manager */
+ m_config_manager->set_facade(theFacade);
+ if (!m_config_manager->start())
+ {
+ g_eventLogger->error("Failed to start ConfigManager");
+ DBUG_RETURN(false);
+ }
+
/* Loglevel thread */
assert(_isStopThread == false);
_logLevelThread = NdbThread_Create(logLevelThread_C,
@@ -563,7 +569,7 @@ MgmtSrvr::start()
void
-MgmtSrvr::setClusterLog(void)
+MgmtSrvr::setClusterLog(const Config* config)
{
BaseString logdest;
@@ -571,7 +577,8 @@ MgmtSrvr::setClusterLog(void)
// Get log destination from config
DBUG_ASSERT(_ownNodeId);
- ConfigIter iter(_config, CFG_SECTION_NODE);
+
+ ConfigIter iter(config, CFG_SECTION_NODE);
require(iter.find(CFG_NODE_ID, _ownNodeId) == 0);
const char *value;
@@ -607,15 +614,26 @@ MgmtSrvr::setClusterLog(void)
void
-MgmtSrvr::setConfig(Config* conf)
+MgmtSrvr::config_changed(NodeId node_id, const Config* new_config)
{
- DBUG_ENTER("MgmtSrvr::setConfig");
- Guard g(m_configMutex);
+ DBUG_ENTER("MgmtSrvr::config_changed");
+
+ Guard g(m_local_config_mutex);
+
+ // Don't allow nodeid to change, once it's been set
+ require(_ownNodeId == 0 || _ownNodeId == node_id);
- _config= conf;
+ _ownNodeId= node_id;
+
+ // TODO Magnus, Copy information about dynamic ports from
+ // new to old or save that info elsewhere
+
+ delete m_local_config;
+ m_local_config= new Config(new_config); // Copy
+ require(m_local_config);
/* Rebuild node arrays */
- ConfigIter iter(_config, CFG_SECTION_NODE);
+ ConfigIter iter(m_local_config, CFG_SECTION_NODE);
for(Uint32 i = 0; i<MAX_NODES; i++) {
m_connect_address[i].s_addr= 0;
@@ -648,13 +666,32 @@ MgmtSrvr::setConfig(Config* conf)
}
+ setClusterLog(m_local_config);
+
+ // TODO Magnus, Reload ClusterMgr::theNodes
+
DBUG_VOID_RETURN;
}
+bool
+MgmtSrvr::getPackedConfig(UtilBuffer& pack_buf)
+{
+ return m_config_manager->get_packed_config(pack_buf);
+}
+
+
MgmtSrvr::~MgmtSrvr()
{
+ /* Stop config manager */
+ if (m_config_manager != 0)
+ {
+ m_config_manager->stop();
+ delete m_config_manager;
+ m_config_manager= 0;
+ }
+
/* Stop log level thread */
void* res = 0;
_isStopThread = true;
@@ -677,10 +714,10 @@ MgmtSrvr::~MgmtSrvr()
theFacade = 0;
}
- delete _config;
+ delete m_local_config;
+ NdbMutex_Destroy(m_local_config_mutex);
NdbMutex_Destroy(m_node_id_mutex);
- NdbMutex_Destroy(m_configMutex);
}
@@ -701,13 +738,16 @@ int MgmtSrvr::okToSendTo(NodeId nodeId,
return NO_CONTACT_WITH_PROCESS;
}
-void report_unknown_signal(SimpleSignal *signal)
+void
+MgmtSrvr::report_unknown_signal(SimpleSignal *signal)
{
+ signal->print();
g_eventLogger->error("Unknown signal received. SignalNumber: "
- "%i from (%d, %x)",
+ "%i from (%d, 0x%x)",
signal->readSignalNumber(),
refToNode(signal->header.theSendersBlockRef),
refToBlock(signal->header.theSendersBlockRef));
+ assert(false);
}
/*****************************************************************************
@@ -754,8 +794,8 @@ MgmtSrvr::versionNode(int nodeId, Uint32
mysql_version = NDB_MYSQL_VERSION_D;
if(!*address)
{
- ndb_mgm_configuration_iterator
- iter(*_config->m_configValues, CFG_SECTION_NODE);
+ Guard g(m_local_config_mutex);
+ ConfigIter iter(m_local_config, CFG_SECTION_NODE);
unsigned tmp= 0;
for(iter.first();iter.valid();iter.next())
{
@@ -786,9 +826,10 @@ MgmtSrvr::versionNode(int nodeId, Uint32
return 0;
}
-int
-MgmtSrvr::sendVersionReq(int v_nodeId,
- Uint32 &version,
+
+int
+MgmtSrvr::sendVersionReq(int v_nodeId,
+ Uint32 &version,
Uint32& mysql_version,
const char **address)
{
@@ -799,49 +840,38 @@ MgmtSrvr::sendVersionReq(int v_nodeId,
ApiVersionReq* req = CAST_PTR(ApiVersionReq, ssig.getDataPtrSend());
req->senderRef = ss.getOwnRef();
req->nodeId = v_nodeId;
- ssig.set(ss, TestOrd::TraceAPI, QMGR, GSN_API_VERSION_REQ,
- ApiVersionReq::SignalLength);
+ ssig.set(ss, TestOrd::TraceAPI, QMGR,
+ GSN_API_VERSION_REQ, ApiVersionReq::SignalLength);
- int do_send = 1;
NodeId nodeId;
-
- while (1)
+ int do_send = 1;
+ while(true)
{
if (do_send)
{
- bool next;
- nodeId = 0;
-
- while((next = getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)) == true &&
- okToSendTo(nodeId, true) != 0);
-
- const ClusterMgr::Node &node=
- theFacade->theClusterMgr->getNodeInfo(nodeId);
- if(next && node.m_state.startLevel != NodeState::SL_STARTED)
+ nodeId = ss.get_an_alive_node();
+ if (nodeId == 0)
{
- NodeId tmp=nodeId;
- while((next = getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)) == true &&
- okToSendTo(nodeId, true) != 0);
- if(!next)
- nodeId= tmp;
+ return NO_CONTACT_WITH_DB_NODES;
}
- if(!next) return NO_CONTACT_WITH_DB_NODES;
-
- if (ss.sendSignal(nodeId, &ssig) != SEND_OK) {
- return SEND_OR_RECEIVE_FAILED;
+ if (ss.sendSignal(nodeId, &ssig) != SEND_OK)
+ {
+ return SEND_OR_RECEIVE_FAILED;
}
+
do_send = 0;
}
SimpleSignal *signal = ss.waitFor();
- int gsn = signal->readSignalNumber();
- switch (gsn) {
+ switch (signal->readSignalNumber()) {
case GSN_API_VERSION_CONF: {
- const ApiVersionConf * const conf =
+ const ApiVersionConf * const conf =
CAST_CONSTPTR(ApiVersionConf, signal->getDataPtr());
+
assert((int) conf->nodeId == v_nodeId);
+
version = conf->version;
mysql_version = conf->mysql_version;
if (version < NDBD_SPLIT_VERSION)
@@ -849,8 +879,10 @@ MgmtSrvr::sendVersionReq(int v_nodeId,
struct in_addr in;
in.s_addr= conf->inet_addr;
*address= inet_ntoa(in);
+
return 0;
}
+
case GSN_NF_COMPLETEREP:{
const NFCompleteRep * const rep =
CAST_CONSTPTR(NFCompleteRep, signal->getDataPtr());
@@ -858,6 +890,7 @@ MgmtSrvr::sendVersionReq(int v_nodeId,
do_send = 1; // retry with other node
continue;
}
+
case GSN_NODE_FAILREP:{
const NodeFailRep * const rep =
CAST_CONSTPTR(NodeFailRep, signal->getDataPtr());
@@ -865,16 +898,23 @@ MgmtSrvr::sendVersionReq(int v_nodeId,
do_send = 1; // retry with other node
continue;
}
+
+ case GSN_API_REGCONF:
+ // Ignore
+ continue;
+
default:
report_unknown_signal(signal);
return SEND_OR_RECEIVE_FAILED;
}
- break;
- } // while(1)
+ }
- return 0;
+ // Should never come here
+ require(false);
+ return -1;
}
+
int MgmtSrvr::sendStopMgmd(NodeId nodeId,
bool abort,
bool stop,
@@ -887,18 +927,16 @@ int MgmtSrvr::sendStopMgmd(NodeId nodeId
BaseString connect_string;
{
- Guard g(m_configMutex);
+ Guard g(m_local_config_mutex);
{
- ndb_mgm_configuration_iterator
- iter(* _config->m_configValues, CFG_SECTION_NODE);
+ ConfigIter iter(m_local_config, CFG_SECTION_NODE);
if(iter.first()) return SEND_OR_RECEIVE_FAILED;
if(iter.find(CFG_NODE_ID, nodeId)) return SEND_OR_RECEIVE_FAILED;
if(iter.get(CFG_NODE_HOST, &hostname)) return SEND_OR_RECEIVE_FAILED;
}
{
- ndb_mgm_configuration_iterator
- iter(* _config->m_configValues, CFG_SECTION_NODE);
+ ConfigIter iter(m_local_config, CFG_SECTION_NODE);
if(iter.first()) return SEND_OR_RECEIVE_FAILED;
if(iter.find(CFG_NODE_ID, nodeId)) return SEND_OR_RECEIVE_FAILED;
@@ -906,6 +944,7 @@ int MgmtSrvr::sendStopMgmd(NodeId nodeId
}
if( strlen(hostname) == 0 )
return SEND_OR_RECEIVE_FAILED;
+
}
connect_string.assfmt("%s:%u",hostname,port);
@@ -1179,6 +1218,8 @@ int MgmtSrvr::sendSTOP_REQ(const Vector<
stoppedNodes.bitOR(mask);
break;
}
+ case GSN_API_REGCONF:
+ break;
default:
report_unknown_signal(signal);
#ifdef VM_TRACE
@@ -1503,6 +1544,7 @@ MgmtSrvr::exitSingleUser(int * stopCount
SimpleSignal ssig;
ResumeReq* const resumeReq =
CAST_PTR(ResumeReq, ssig.getDataPtrSend());
+
ssig.set(ss,TestOrd::TraceAPI, NDBCNTR, GSN_RESUME_REQ,
ResumeReq::SignalLength);
resumeReq->senderData = 12;
@@ -1739,6 +1781,8 @@ MgmtSrvr::setEventReportingLevelImpl(int
nodes.clear(rep->failedNodeId);
break;
}
+ case GSN_API_REGCONF:
+ break;
default:
report_unknown_signal(signal);
return SEND_OR_RECEIVE_FAILED;
@@ -1803,6 +1847,7 @@ MgmtSrvr::insertError(int nodeId, int er
return ss.sendSignal(nodeId, &ssig) == SEND_OK ? 0 : SEND_OR_RECEIVE_FAILED;
}
+
int
MgmtSrvr::startSchemaTrans(SignalSender& ss, NodeId & out_nodeId,
Uint32 transId, Uint32 & out_transKey)
@@ -1872,6 +1917,8 @@ retry:
}
break;
}
+ case GSN_API_REGCONF:
+ break;
default:
report_unknown_signal(signal);
return SEND_OR_RECEIVE_FAILED;
@@ -1928,6 +1975,8 @@ MgmtSrvr::endSchemaTrans(SignalSender& s
}
break;
}
+ case GSN_API_REGCONF:
+ break;
default:
report_unknown_signal(signal);
return SEND_OR_RECEIVE_FAILED;
@@ -2019,6 +2068,8 @@ MgmtSrvr::createNodegroup(int *nodes, in
}
break;
}
+ case GSN_API_REGCONF:
+ break;
default:
report_unknown_signal(signal);
return SEND_OR_RECEIVE_FAILED;
@@ -2091,6 +2142,8 @@ MgmtSrvr::dropNodegroup(int ng)
}
break;
}
+ case GSN_API_REGCONF:
+ break;
default:
report_unknown_signal(signal);
return SEND_OR_RECEIVE_FAILED;
@@ -2372,10 +2425,6 @@ MgmtSrvr::handleReceivedSignal(NdbApiSig
int gsn = signal->readSignalNumber();
switch (gsn) {
- case GSN_EVENT_SUBSCRIBE_CONF:
- break;
- case GSN_EVENT_SUBSCRIBE_REF:
- break;
case GSN_EVENT_REP:
{
eventReport(signal->getDataPtr(), signal->getLength());
@@ -2390,6 +2439,8 @@ MgmtSrvr::handleReceivedSignal(NdbApiSig
case GSN_TAMPER_ORD:
ndbout << "TAMPER ORD" << endl;
break;
+ case GSN_API_REGCONF:
+ break;
case GSN_DBINFO_SCANREQ:
execDBINFO_SCANREQ(signal);
@@ -2397,10 +2448,11 @@ MgmtSrvr::handleReceivedSignal(NdbApiSig
default:
g_eventLogger->error("Unknown signal received. SignalNumber: "
- "%i from (%d, %x)",
+ "%i from (%d, 0x%x)",
gsn,
refToNode(signal->theSendersBlockRef),
refToBlock(signal->theSendersBlockRef));
+ assert(false);
}
}
@@ -2482,7 +2534,7 @@ const char *MgmtSrvr::get_connect_addres
void
MgmtSrvr::get_connected_nodes(NodeBitmask &connected_nodes) const
{
- if (theFacade && theFacade->theClusterMgr)
+ if (theFacade && theFacade->theClusterMgr)
{
for(Uint32 i = 0; i < MAX_NDB_NODES; i++)
{
@@ -2583,6 +2635,8 @@ MgmtSrvr::alloc_node_id_req(NodeId free_
// ignore NF_COMPLETEREP will come
continue;
}
+ case GSN_API_REGCONF:
+ break;
default:
report_unknown_signal(signal);
return SEND_OR_RECEIVE_FAILED;
@@ -2629,15 +2683,8 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
int r_config_addr= -1;
unsigned type_c= 0;
- if(NdbMutex_Lock(m_configMutex))
- {
- // should not happen
- error_string.appfmt("unable to lock configuration mutex");
- error_code = NDB_MGM_ALLOCID_ERROR;
- DBUG_RETURN(false);
- }
- ndb_mgm_configuration_iterator
- iter(* _config->m_configValues, CFG_SECTION_NODE);
+ NdbMutex_Lock(m_local_config_mutex);
+ ConfigIter iter(m_local_config, CFG_SECTION_NODE);
for(iter.first(); iter.valid(); iter.next()) {
unsigned tmp= 0;
if(iter.get(CFG_NODE_ID, &tmp)) require(false);
@@ -2704,7 +2751,7 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
"Suggest specifying node id in connectstring,\n"
"or specifying unique host names in config file.",
id_found, tmp);
- NdbMutex_Unlock(m_configMutex);
+ NdbMutex_Unlock(m_local_config_mutex);
error_code = NDB_MGM_ALLOCID_CONFIG_MISMATCH;
DBUG_RETURN(false);
}
@@ -2714,13 +2761,13 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
"or specifying unique host names in config file,\n"
"or specifying just one mgmt server in config file.",
tmp);
- NdbMutex_Unlock(m_configMutex);
+ NdbMutex_Unlock(m_local_config_mutex);
error_code = NDB_MGM_ALLOCID_CONFIG_MISMATCH;
DBUG_RETURN(false);
}
id_found= tmp; // mgmt server matched, check for more matches
}
- NdbMutex_Unlock(m_configMutex);
+ NdbMutex_Unlock(m_local_config_mutex);
if (id_found && client_addr != 0)
{
@@ -2986,12 +3033,12 @@ MgmtSrvr::startBackup(Uint32& backupId,
BlockNumber backupBlockNo = numberToBlock(BACKUP, 1);
if(input_backupId > 0)
{
- ssig.set(ss, TestOrd::TraceAPI, backupBlockNo, GSN_BACKUP_REQ,
+ ssig.set(ss, TestOrd::TraceAPI, backupBlockNo, GSN_BACKUP_REQ,
BackupReq::SignalLength);
req->inputBackupId = input_backupId;
}
else
- ssig.set(ss, TestOrd::TraceAPI, backupBlockNo, GSN_BACKUP_REQ,
+ ssig.set(ss, TestOrd::TraceAPI, BACKUP, GSN_BACKUP_REQ,
BackupReq::SignalLength - 1);
req->senderData = 19;
@@ -3109,6 +3156,8 @@ MgmtSrvr::startBackup(Uint32& backupId,
// master node will report aborted backup
break;
}
+ case GSN_API_REGCONF:
+ break;
default:
report_unknown_signal(signal);
return SEND_OR_RECEIVE_FAILED;
@@ -3199,50 +3248,44 @@ MgmtSrvr::Allocated_resources::get_nodei
int
MgmtSrvr::setDbParameter(int node, int param, const char * value,
- BaseString& msg){
+ BaseString& msg)
+{
- if(NdbMutex_Lock(m_configMutex))
- return -1;
+ Guard g(m_local_config_mutex);
/**
* Check parameter
*/
- ndb_mgm_configuration_iterator
- iter(* _config->m_configValues, CFG_SECTION_NODE);
+ ConfigIter iter(m_local_config, CFG_SECTION_NODE);
if(iter.first() != 0){
msg.assign("Unable to find node section (iter.first())");
- NdbMutex_Unlock(m_configMutex);
return -1;
}
-
+
Uint32 type = NODE_TYPE_DB + 1;
if(node != 0){
if(iter.find(CFG_NODE_ID, node) != 0){
msg.assign("Unable to find node (iter.find())");
- NdbMutex_Unlock(m_configMutex);
return -1;
}
if(iter.get(CFG_TYPE_OF_SECTION, &type) != 0){
msg.assign("Unable to get node type(iter.get(CFG_TYPE_OF_SECTION))");
- NdbMutex_Unlock(m_configMutex);
return -1;
}
} else {
do {
if(iter.get(CFG_TYPE_OF_SECTION, &type) != 0){
msg.assign("Unable to get node type(iter.get(CFG_TYPE_OF_SECTION))");
- NdbMutex_Unlock(m_configMutex);
return -1;
}
if(type == NODE_TYPE_DB)
break;
} while(iter.next() == 0);
}
-
+
if(type != NODE_TYPE_DB){
msg.assfmt("Invalid node type or no such node (%d %d)",
type, NODE_TYPE_DB);
- NdbMutex_Unlock(m_configMutex);
return -1;
}
@@ -3256,7 +3299,7 @@ MgmtSrvr::setDbParameter(int node, int p
val_32 = atoi(value);
break;
}
-
+
p_type++;
if(iter.get(param, &val_64) == 0){
val_64 = strtoll(value, 0, 10);
@@ -3268,23 +3311,22 @@ MgmtSrvr::setDbParameter(int node, int p
break;
}
msg.assign("Could not get parameter");
- NdbMutex_Unlock(m_configMutex);
return -1;
} while(0);
-
+
bool res = false;
do {
int ret = iter.get(CFG_TYPE_OF_SECTION, &type);
assert(ret == 0);
-
+
if(type != NODE_TYPE_DB)
continue;
-
+
Uint32 node;
ret = iter.get(CFG_NODE_ID, &node);
assert(ret == 0);
-
- ConfigValues::Iterator i2(_config->m_configValues->m_config,
+
+ ConfigValues::Iterator i2(m_local_config->m_configValues->m_config,
iter.m_config);
switch(p_type){
case 0:
@@ -3306,30 +3348,25 @@ MgmtSrvr::setDbParameter(int node, int p
} while(node == 0 && iter.next() == 0);
msg.assign("Success");
- NdbMutex_Unlock(m_configMutex);
return 0;
}
+
+
int
MgmtSrvr::setConnectionDbParameter(int node1,
int node2,
int param,
int value,
- BaseString& msg){
- Uint32 current_value,new_value;
-
+ BaseString& msg)
+{
DBUG_ENTER("MgmtSrvr::setConnectionDbParameter");
- if(NdbMutex_Lock(m_configMutex))
- {
- DBUG_RETURN(-1);
- }
-
- ndb_mgm_configuration_iterator
- iter(* _config->m_configValues, CFG_SECTION_CONNECTION);
+ Uint32 current_value,new_value;
+ Guard g(m_local_config_mutex);
+ ConfigIter iter(m_local_config, CFG_SECTION_CONNECTION);
if(iter.first() != 0){
msg.assign("Unable to find connection section (iter.first())");
- NdbMutex_Unlock(m_configMutex);
DBUG_RETURN(-1);
}
@@ -3343,33 +3380,32 @@ MgmtSrvr::setConnectionDbParameter(int n
}
if(!iter.valid()) {
msg.assign("Unable to find connection between nodes");
- NdbMutex_Unlock(m_configMutex);
DBUG_RETURN(-2);
}
-
+
if(iter.get(param, ¤t_value) != 0) {
msg.assign("Unable to get current value of parameter");
- NdbMutex_Unlock(m_configMutex);
DBUG_RETURN(-3);
}
- ConfigValues::Iterator i2(_config->m_configValues->m_config,
+ ConfigValues::Iterator i2(m_local_config->m_configValues->m_config,
iter.m_config);
if(i2.set(param, (unsigned)value) == false) {
msg.assign("Unable to set new value of parameter");
- NdbMutex_Unlock(m_configMutex);
DBUG_RETURN(-4);
}
-
+
+ // TODO Magnus, in theory this new config should be saved on
+ // nodes, but it's probably a better idea to save this
+ // dynamic information elsewhere instead.
+
if(iter.get(param, &new_value) != 0) {
msg.assign("Unable to get parameter after setting it.");
- NdbMutex_Unlock(m_configMutex);
DBUG_RETURN(-5);
}
msg.assfmt("%u -> %u",current_value,new_value);
- NdbMutex_Unlock(m_configMutex);
DBUG_RETURN(1);
}
@@ -3379,20 +3415,15 @@ MgmtSrvr::getConnectionDbParameter(int n
int node2,
int param,
int *value,
- BaseString& msg){
- DBUG_ENTER("MgmtSrvr::getConnectionDbParameter");
-
- if(NdbMutex_Lock(m_configMutex))
- {
- DBUG_RETURN(-1);
- }
+ BaseString& msg)
+{
- ndb_mgm_configuration_iterator
- iter(* _config->m_configValues, CFG_SECTION_CONNECTION);
+ DBUG_ENTER("MgmtSrvr::getConnectionDbParameter");
+ Guard g(m_local_config_mutex);
+ ConfigIter iter(m_local_config, CFG_SECTION_CONNECTION);
if(iter.first() != 0){
msg.assign("Unable to find connection section (iter.first())");
- NdbMutex_Unlock(m_configMutex);
DBUG_RETURN(-1);
}
@@ -3406,21 +3437,20 @@ MgmtSrvr::getConnectionDbParameter(int n
}
if(!iter.valid()) {
msg.assign("Unable to find connection between nodes");
- NdbMutex_Unlock(m_configMutex);
DBUG_RETURN(-1);
}
-
+
if(iter.get(param, (Uint32*)value) != 0) {
msg.assign("Unable to get current value of parameter");
- NdbMutex_Unlock(m_configMutex);
DBUG_RETURN(-1);
}
msg.assfmt("%d",*value);
- NdbMutex_Unlock(m_configMutex);
+
DBUG_RETURN(1);
}
+
void MgmtSrvr::transporter_connect(NDB_SOCKET_TYPE sockfd)
{
if (theFacade->get_registry()->connect_server(sockfd))
=== modified file 'storage/ndb/src/mgmsrv/MgmtSrvr.hpp'
--- a/storage/ndb/src/mgmsrv/MgmtSrvr.hpp 2008-10-07 06:47:09 +0000
+++ b/storage/ndb/src/mgmsrv/MgmtSrvr.hpp 2008-10-27 11:13:34 +0000
@@ -17,9 +17,9 @@
#define MgmtSrvr_H
#include "Config.hpp"
-#include <mgmapi.h>
+#include "ConfigSubscriber.hpp"
-#include <ConfigRetriever.hpp>
+#include <mgmapi.h>
#include <Vector.hpp>
#include <NodeBitmask.hpp>
#include <ndb_version.h>
@@ -70,8 +70,8 @@ public:
@class MgmtSrvr
@brief Main class for the management server.
*/
-class MgmtSrvr {
-
+class MgmtSrvr : private ConfigSubscriber {
+
public:
// some compilers need all of this
class Allocated_resources;
@@ -130,6 +130,7 @@ public:
const char* bind_address;
int no_nodeid_checks;
int print_full_config;
+ const char* datadir;
};
MgmtSrvr(); // Not implemented
@@ -139,21 +140,10 @@ public:
~MgmtSrvr();
/*
- To be called after constructor. Loads configuration
- from disk or fetches it from other server
- */
+ To be called after constructor.
+ */
bool init();
-private:
- /* Functions used from 'init' */
- Config* load_init_config(void);
- Config* load_init_mycnf(void);
- bool fetch_config(void);
- bool save_config(const Config* conf);
- bool save_config(void);
-
-public:
-
/*
To be called after 'init', starts up the services
this server will expose
@@ -161,16 +151,14 @@ public:
bool start(void);
private:
/* Functions used from 'start' */
- bool start_transporter(void);
- bool start_mgm_service(void);
+ bool start_transporter(const Config*);
+ bool start_mgm_service(const Config*);
bool connect_to_self(void);
public:
NodeId getOwnNodeId() const {return _ownNodeId;};
- void print_config() { _config->print(); };
-
/**
* Get status on a node.
* address may point to a common area (e.g. from inet_addr)
@@ -205,15 +193,6 @@ public:
int shutdownDB(int * cnt = 0, bool abort = false);
/**
- * print version info about a node
- *
- * @param processId: Id of the DB process to stop
- * @return 0 if succeeded, otherwise: as stated above, plus:
- */
- int versionNode(int nodeId, Uint32 &version, Uint32 &mysql_version,
- const char **address);
-
- /**
* Maintenance on the system
*/
int enterSingleUser(int * cnt = 0, Uint32 singleuserNodeId = 0);
@@ -390,13 +369,9 @@ public:
*/
const char* getErrorText(int errorCode, char *buf, int buf_sz);
- /**
- * Get configuration
- */
- const Config * getConfig() const;
private:
- void setConfig(Config* conf);
- void setClusterLog(void);
+ void config_changed(NodeId, const Config*);
+ void setClusterLog(const Config* conf);
public:
/**
@@ -429,6 +404,12 @@ public:
private:
+ int versionNode(int nodeId, Uint32 &version,
+ Uint32 &mysql_version, const char **address);
+
+ int sendVersionReq(int processId, Uint32 &version,
+ Uint32& mysql_version, const char **address);
+
int sendStopMgmd(NodeId nodeId,
bool abort,
bool stop,
@@ -483,15 +464,17 @@ private:
NodeId _ownNodeId;
Uint32 m_port;
SocketServer m_socket_server;
- ConfigRetriever m_config_retriever;
Vector<BaseString> m_ndbinfo_table_names;
Vector< Vector<Uint32> > m_ndbinfo_column_types;
Vector< Vector<BaseString> > m_ndbinfo_column_names;
- BlockReference _ownReference;
- NdbMutex *m_configMutex;
- const Config * _config;
+ NdbMutex* m_local_config_mutex;
+ const Config* m_local_config;
+
+ BlockReference _ownReference;
+
+ class ConfigManager* m_config_manager;
NodeBitmask m_reserved_nodes;
struct in_addr m_connect_address[MAX_NODES];
@@ -529,8 +512,6 @@ private:
class TransporterFacade * theFacade;
- int sendVersionReq( int processId, Uint32 &version, Uint32& mysql_version,
- const char **address);
int translateStopRef(Uint32 errCode);
bool _isStopThread;
@@ -552,12 +533,17 @@ private:
struct NdbThread* _logLevelThread;
static void *logLevelThread_C(void *);
void logLevelThreadRun();
+
+ void report_unknown_signal(SimpleSignal *signal);
+
+
+public:
+ /*
+ Get packed copy of configuration in the supplied buffer
+ */
+ bool getPackedConfig(UtilBuffer& pack_buf);
+
};
-inline
-const Config *
-MgmtSrvr::getConfig() const {
- return _config;
-}
#endif // MgmtSrvr_H
=== removed file 'storage/ndb/src/mgmsrv/MgmtSrvrConfig.cpp'
--- a/storage/ndb/src/mgmsrv/MgmtSrvrConfig.cpp 2008-08-04 21:01:04 +0000
+++ b/storage/ndb/src/mgmsrv/MgmtSrvrConfig.cpp 1970-01-01 00:00:00 +0000
@@ -1,81 +0,0 @@
-/* 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; version 2 of the License.
-
- 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 "MgmtSrvr.hpp"
-#include <InitConfigFileParser.hpp>
-#include <ConfigRetriever.hpp>
-#include <NdbSleep.h>
-
-
-Config*
-MgmtSrvr::load_init_config(void)
-{
- InitConfigFileParser parser;
- g_eventLogger->info("Reading cluster configuration from '%s'",
- m_opts.config_filename);
- return parser.parseConfig(m_opts.config_filename);
-}
-
-
-Config*
-MgmtSrvr::load_init_mycnf(void)
-{
- InitConfigFileParser parser;
- g_eventLogger->info("Reading cluster configuration using my.cnf");
- return parser.parse_mycnf();
-}
-
-
-bool
-MgmtSrvr::fetch_config(void)
-{
- char buf[128];
- DBUG_ENTER("MgmtSrvr::fetch_config");
- assert(_config == NULL);
-
- /* Loop until config loaded from other mgmd(s) */
- g_eventLogger->info("Trying to get configuration from other mgmd(s)"\
- "using '%.128s'...",
- m_config_retriever.get_connectstring(buf, sizeof(buf)));
-
-
- int retry= 0, delay= 0, verbose= 1;
- while (m_config_retriever.do_connect(retry, delay, verbose) != 0) {
- g_eventLogger->info("Waiting for connection to other mgmd(s)...");
- NdbSleep_SecSleep(1);
- }
- g_eventLogger->info("Connected...");
-
- // "login" and alloc node id from the other mgmd
- _ownNodeId= m_config_retriever.allocNodeId(retry, delay);
- if (_ownNodeId == 0) {
- g_eventLogger->error(m_config_retriever.getErrorString());
- DBUG_RETURN(false);
- }
-
- // read config from other managent server
- struct ndb_mgm_configuration * tmp = m_config_retriever.getConfig();
- if (tmp == NULL) {
- g_eventLogger->error(m_config_retriever.getErrorString());
- DBUG_RETURN(false);
- }
-
- setConfig(new Config(tmp));
-
- DBUG_RETURN(true);
-}
-
-
-
=== added file 'storage/ndb/src/mgmsrv/MgmtThread.hpp'
--- a/storage/ndb/src/mgmsrv/MgmtThread.hpp 1970-01-01 00:00:00 +0000
+++ b/storage/ndb/src/mgmsrv/MgmtThread.hpp 2008-10-21 12:41:59 +0000
@@ -0,0 +1,73 @@
+/* Copyright (C) 2008 Sun Microsystems, Inc.
+
+ 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; version 2 of the License.
+
+ 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 */
+
+#ifndef MgmtThread_H
+#define MgmtThread_H
+
+#include <ndb_global.h>
+#include <NdbThread.h>
+
+class MgmtThread {
+ bool m_running;
+ const char* m_name;
+ size_t m_stack_size;
+ NDB_THREAD_PRIO m_thread_prio;
+ struct NdbThread* m_thread;
+
+ static void* run_C(void* t) {
+ MgmtThread *thread = (MgmtThread*)t;
+ thread->run();
+ return 0;
+ }
+public:
+ MgmtThread(); // Not implemented
+ MgmtThread(const MgmtThread&); // Not implemented
+ MgmtThread(const char* name,
+ size_t stack_size= 32768,
+ NDB_THREAD_PRIO thread_prio= NDB_THREAD_PRIO_LOW) :
+ m_running(true),
+ m_name(name),
+ m_stack_size(stack_size),
+ m_thread_prio(thread_prio),
+ m_thread(NULL){
+ };
+ virtual ~MgmtThread() {
+ if (m_thread)
+ stop();
+ };
+
+ virtual void run()= 0;
+ bool start(){
+ assert(m_running);
+ m_thread = NdbThread_Create(run_C, (void**)this, m_stack_size,
+ m_name, m_thread_prio);
+ return (m_thread != NULL);
+ }
+ bool stop(){
+ void* res = 0;
+ if (!m_thread)
+ return false;
+
+ m_running= false;
+
+ NdbThread_WaitFor(m_thread, &res);
+ NdbThread_Destroy(&m_thread);
+ return true;
+
+ }
+ bool is_stopped() { return !m_running; };
+};
+
+#endif
=== modified file 'storage/ndb/src/mgmsrv/Services.cpp'
--- a/storage/ndb/src/mgmsrv/Services.cpp 2008-10-08 09:33:48 +0000
+++ b/storage/ndb/src/mgmsrv/Services.cpp 2008-10-27 11:13:34 +0000
@@ -620,14 +620,6 @@ MgmApiSession::getConfig(Parser_t::Conte
args.get("version", &version);
args.get("node", &node);
- const Config *conf = m_mgmsrv.getConfig();
- if(conf == NULL) {
- m_output->println("get config reply");
- m_output->println("result: Could not fetch configuration");
- m_output->println("");
- return;
- }
-
if(node != 0){
bool compatible;
switch (m_mgmsrv.getNodeType(node)) {
@@ -653,16 +645,19 @@ MgmApiSession::getConfig(Parser_t::Conte
return;
}
}
-
- NdbMutex_Lock(m_mgmsrv.m_configMutex);
- const ConfigValues * cfg = &conf->m_configValues->m_config;
-
- UtilBuffer src;
- cfg->pack(src);
- NdbMutex_Unlock(m_mgmsrv.m_configMutex);
-
- char *tmp_str = (char *) malloc(base64_needed_encoded_length(src.length()));
- (void) base64_encode(src.get_data(), src.length(), tmp_str);
+
+ UtilBuffer packed;
+ if (!m_mgmsrv.getPackedConfig(packed))
+ {
+ m_output->println("get config reply");
+ m_output->println("result: Could not fetch configuration");
+ m_output->println("");
+ return;
+ }
+
+ char *tmp_str =
+ (char *) malloc(base64_needed_encoded_length(packed.length()));
+ (void) base64_encode(packed.get_data(), packed.length(), tmp_str);
SLEEP_ERROR_INSERTED(1);
@@ -2068,6 +2063,14 @@ void MgmApiSession::getNdbInfo(Parser_t:
return ;
}
+#if 0
+ // TODO Magnus, "get variables"
+ ndbout_c("NdbConfig_get_path(0): %s", NdbConfig_get_path(0));
+ ndbout_c("opt_ndb_connectstring: %s", opt_ndb_connectstring);
+ ndbout_c("NDB_CONNECTSTRING: %s", getenv("NDB_CONNECTSTRING"));
+ ndbout_c("datadir: %s", opts.datadir);
+#endif
+
template class MutexVector<int>;
template class Vector<ParserRow<MgmApiSession> const*>;
template class Vector<NDB_SOCKET_TYPE>;
=== modified file 'storage/ndb/src/mgmsrv/main.cpp'
--- a/storage/ndb/src/mgmsrv/main.cpp 2008-10-03 08:22:13 +0000
+++ b/storage/ndb/src/mgmsrv/main.cpp 2008-10-21 12:41:59 +0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 MySQL AB
+/* Copyright (C) 2003-2008 MySQL AB, 2008 Sun Microsystems, Inc.
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
@@ -115,6 +115,10 @@ static struct my_option my_long_options[
"Local bind address",
(uchar**) &opts.bind_address, (uchar**) &opts.bind_address, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ { "datadir", 256,
+ "Data directory for this node",
+ (uchar**) &opts.datadir, (uchar**) &opts.datadir, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
@@ -161,12 +165,14 @@ int main(int argc, char** argv)
exit(1);
}
- if (opts.mycnf == 0 && opts.config_filename == 0)
- {
- MY_STAT buf;
- if (my_stat("config.ini", &buf, MYF(0)) != NULL)
- opts.config_filename = "config.ini";
- }
+ /**
+ Install signal handler for SIGPIPE
+ Done in TransporterFacade as well.. what about Configretriever?
+ */
+#if !defined NDB_WIN32
+ signal(SIGPIPE, SIG_IGN);
+#endif
+
start:
g_eventLogger->info("NDB Cluster Management Server. %s", NDB_VERSION_STRING);
@@ -177,14 +183,6 @@ start:
exit(1);
}
- /**
- Install signal handler for SIGPIPE
- Done in TransporterFacade as well.. what about Configretriever?
- */
-#if !defined NDB_WIN32
- signal(SIGPIPE, SIG_IGN);
-#endif
-
/* Init mgm, load or fetch config */
if (!mgm->init()) {
delete mgm;
=== modified file 'storage/ndb/src/ndbapi/ClusterMgr.cpp'
--- a/storage/ndb/src/ndbapi/ClusterMgr.cpp 2008-08-21 06:33:53 +0000
+++ b/storage/ndb/src/ndbapi/ClusterMgr.cpp 2008-10-21 12:41:59 +0000
@@ -221,7 +221,6 @@ ClusterMgr::threadMain( ){
NdbApiSignal signal(numberToRef(API_CLUSTERMGR, theFacade.ownId()));
signal.theVerId_signalNumber = GSN_API_REGREQ;
- signal.theReceiversBlockNumber = QMGR;
signal.theTrace = 0;
signal.theLength = ApiRegReq::SignalLength;
@@ -280,6 +279,11 @@ ClusterMgr::threadMain( ){
theNode.hbCounter = 0;
}
+ if(theNode.m_info.m_type == NodeInfo::MGM)
+ signal.theReceiversBlockNumber = API_CLUSTERMGR;
+ else
+ signal.theReceiversBlockNumber = QMGR;
+
#ifdef DEBUG_REG
ndbout_c("ClusterMgr: Sending API_REGREQ to node %d", (int)nodeId);
#endif
@@ -365,7 +369,8 @@ ClusterMgr::execAPI_REGREQ(const Uint32
conf->version = NDB_VERSION;
conf->mysql_version = NDB_MYSQL_VERSION_D;
conf->apiHeartbeatFrequency = node.hbFrequency;
- theFacade.sendSignalUnCond(&signal, nodeId);
+ if (theFacade.sendSignalUnCond(&signal, nodeId) == SEND_OK)
+ node.m_api_reg_conf= true;
}
void
=== modified file 'storage/ndb/src/ndbapi/SignalSender.cpp'
--- a/storage/ndb/src/ndbapi/SignalSender.cpp 2008-10-02 07:51:11 +0000
+++ b/storage/ndb/src/ndbapi/SignalSender.cpp 2008-10-27 11:13:34 +0000
@@ -18,6 +18,7 @@
#include <SignalLoggerManager.hpp>
#include <signaldata/NFCompleteRep.hpp>
#include <signaldata/NodeFailRep.hpp>
+#include <signaldata/TestOrd.hpp>
SimpleSignal::SimpleSignal(bool dealloc){
@@ -126,11 +127,6 @@ SignalSender::getOwnRef() const {
return numberToRef(m_blockNo, theFacade->ownId());
}
-Uint32
-SignalSender::getAliveNode() const{
- return theFacade->get_an_alive_node();
-}
-
const ClusterMgr::Node &
SignalSender::getNodeInfo(Uint16 nodeId) const {
return theFacade->theClusterMgr->getNodeInfo(nodeId);
@@ -141,6 +137,55 @@ SignalSender::getNoOfConnectedNodes() co
return theFacade->theClusterMgr->getNoOfConnectedNodes();
}
+
+void
+SignalSender::getNodes(NodeBitmask& mask,
+ NodeInfo::NodeType type)
+{
+ mask.clear();
+ for(Uint32 i = 0; i < MAX_NODES; i++)
+ {
+ const ClusterMgr::Node& node= getNodeInfo(i);
+ if(!node.defined)
+ continue;
+ if(type == NodeInfo::INVALID || // INVALID -> add all nodes to mask
+ node.m_info.getType() == type)
+ {
+ mask.set(i);
+ }
+ }
+}
+
+
+NodeBitmask
+SignalSender::broadcastSignal(NodeBitmask mask,
+ SimpleSignal& sig,
+ Uint16 recBlock, Uint16 gsn,
+ Uint32 len)
+{
+ sig.set(*this, TestOrd::TraceAPI, recBlock, gsn, len);
+
+ NodeBitmask result;
+ for(Uint32 i = 0; i < MAX_NODES; i++)
+ {
+ if(mask.get(i) && sendSignal(i, &sig) == SEND_OK)
+ result.set(i);
+ }
+ return result;
+}
+
+
+SendStatus
+SignalSender::sendSignal(Uint16 nodeId,
+ SimpleSignal& sig,
+ Uint16 recBlock, Uint16 gsn,
+ Uint32 len)
+{
+ sig.set(*this, TestOrd::TraceAPI, recBlock, gsn, len);
+ return sendSignal(nodeId, &sig);
+}
+
+
template<class T>
SimpleSignal *
SignalSender::waitFor(Uint32 timeOutMillis, T & t)
=== modified file 'storage/ndb/src/ndbapi/SignalSender.hpp'
--- a/storage/ndb/src/ndbapi/SignalSender.hpp 2008-09-17 13:23:21 +0000
+++ b/storage/ndb/src/ndbapi/SignalSender.hpp 2008-10-24 12:51:04 +0000
@@ -51,17 +51,28 @@ public:
int unlock();
Uint32 getOwnRef() const;
- Uint32 getAliveNode() const;
const ClusterMgr::Node &getNodeInfo(Uint16 nodeId) const;
Uint32 getNoOfConnectedNodes() const;
+ /*
+ Return bitmask of all defined nodes of a certain type
+ returns all defined nodes by default.
+ */
+ void getNodes(NodeBitmask& mask,
+ NodeInfo::NodeType type = NodeInfo::INVALID);
+
SendStatus sendSignal(Uint16 nodeId, const SimpleSignal *);
-
+ SendStatus sendSignal(Uint16 nodeId, SimpleSignal& sig,
+ Uint16 recBlock, Uint16 gsn, Uint32 len);
+ NodeBitmask broadcastSignal(NodeBitmask mask, SimpleSignal& sig,
+ Uint16 recBlock, Uint16 gsn, Uint32 len);
+
SimpleSignal * waitFor(Uint32 timeOutMillis = 0);
SimpleSignal * waitFor(Uint16 nodeId, Uint32 timeOutMillis = 0);
SimpleSignal * waitFor(Uint16 nodeId, Uint16 gsn, Uint32 timeOutMillis = 0);
- Uint32 get_an_alive_node() { return theFacade->get_an_alive_node(); }
+ Uint32 get_an_alive_node() const { return theFacade->get_an_alive_node(); }
+ Uint32 getAliveNode() const { return get_an_alive_node(); }
bool get_node_alive(NodeId n) const { return theFacade->get_node_alive(n); }
private:
=== modified file 'storage/ndb/src/ndbapi/TransporterFacade.cpp'
--- a/storage/ndb/src/ndbapi/TransporterFacade.cpp 2008-09-10 00:32:18 +0000
+++ b/storage/ndb/src/ndbapi/TransporterFacade.cpp 2008-10-27 09:19:44 +0000
@@ -312,9 +312,16 @@ TransporterFacade::deliver_signal(Signal
break;
case GSN_API_REGCONF:
+ {
clusterMgr->execAPI_REGCONF(theData);
+
+ // Distribute signal to all threads/blocks
+ NdbApiSignal tSignal(* header);
+ tSignal.setDataPtr(theData);
+ for_each(&tSignal, ptr);
break;
-
+ }
+
case GSN_API_REGREF:
clusterMgr->execAPI_REGREF(theData);
break;
@@ -386,6 +393,16 @@ TransporterFacade::deliver_signal(Signal
}
return;
+ } else if (tRecBlockNo >= MIN_API_FIXED_BLOCK_NO &&
+ tRecBlockNo <= MAX_API_FIXED_BLOCK_NO) {
+ Uint32 dynamic= m_fixed2dynamic[tRecBlockNo - MIN_API_FIXED_BLOCK_NO];
+ oe = m_threads.get(dynamic);
+ if (oe.m_object != 0 && oe.m_executeFunction != 0) {
+ NdbApiSignal tmpSignal(*header);
+ NdbApiSignal * tSignal = &tmpSignal;
+ tSignal->setDataPtr(theData);
+ (* oe.m_executeFunction) (oe.m_object, tSignal, ptr);
+ }//if
} else {
; // Ignore all other block numbers.
if(header->theVerId_signalNumber != GSN_API_REGREQ) {
@@ -701,6 +718,9 @@ TransporterFacade::TransporterFacade(Glo
m_batch_size= DEF_BATCH_SIZE;
m_max_trans_id = 0;
+ for (int i = 0; i < NO_API_FIXED_BLOCKS; i++)
+ m_fixed2dynamic[i]= RNIL;
+
theClusterMgr = new ClusterMgr(* this);
#ifdef API_TRACE
@@ -929,9 +949,20 @@ TransporterFacade::open(void* objRef,
int blockNo)
{
DBUG_ENTER("TransporterFacade::open");
- int r= m_threads.open(objRef, fun, statusFun, blockNo);
+ int r= m_threads.open(objRef, fun, statusFun);
if (r < 0)
DBUG_RETURN(r);
+
+ if (unlikely(blockNo != -1)){
+ // Using fixed block number, add fixed->dymamic mapping
+ Uint32 fixed_index= blockNo - MIN_API_FIXED_BLOCK_NO;
+
+ assert(blockNo >= MIN_API_FIXED_BLOCK_NO &&
+ fixed_index <= NO_API_FIXED_BLOCKS);
+
+ m_fixed2dynamic[fixed_index]= r;
+ }
+
#if 1
if (theOwnId > 0) {
(*statusFun)(objRef, numberToRef(r, theOwnId), true, true);
@@ -1644,14 +1675,14 @@ TransporterFacade::get_an_alive_node()
#endif
NodeId i;
for (i = theStartNodeId; i < MAX_NDB_NODES; i++) {
- if (get_node_alive(i)){
+ if (getIsDbNode(i) && get_node_alive(i)){
DBUG_PRINT("info", ("Node %d is alive", i));
theStartNodeId = ((i + 1) % MAX_NDB_NODES);
DBUG_RETURN(i);
}
}
for (i = 1; i < theStartNodeId; i++) {
- if (get_node_alive(i)){
+ if (getIsDbNode(i) && get_node_alive(i)){
DBUG_PRINT("info", ("Node %d is alive", i));
theStartNodeId = ((i + 1) % MAX_NDB_NODES);
DBUG_RETURN(i);
@@ -1686,8 +1717,7 @@ TransporterFacade::ThreadData::expand(Ui
int
TransporterFacade::ThreadData::open(void* objRef,
ExecuteFunction fun,
- NodeStatusFunction fun2,
- int blockNo)
+ NodeStatusFunction fun2)
{
Uint32 nextFree = m_firstFree;
@@ -1695,41 +1725,16 @@ TransporterFacade::ThreadData::open(void
return -1;
}
- Object_Execute oe = { objRef , fun };
-
- if (unlikely(blockNo >= 0)) {
- // Open block with fixed number
- Uint32 index= numberToIndex(blockNo);
-
- if(index > m_statusNext.size()){
- expand(index - m_statusNext.size());
- }
-
- m_use_cnt++;
-
- // Single linked free list, relink the previous one that points to this
- for(Uint32 i = 0; i < m_statusNext.size(); i++){
- if (m_statusNext[i] == index){
- m_statusNext[i]= m_statusNext[index];
- break;
- }
- }
-
- m_statusNext[index] = INACTIVE;
- m_objectExecute[index] = oe;
- m_statusFunction[index] = fun2;
-
- return indexToNumber(index);
- }
-
if(nextFree == END_OF_LIST){
expand(10);
nextFree = m_firstFree;
}
-
+
m_use_cnt++;
m_firstFree = m_statusNext[nextFree];
+ Object_Execute oe = { objRef , fun };
+
m_statusNext[nextFree] = INACTIVE;
m_objectExecute[nextFree] = oe;
m_statusFunction[nextFree] = fun2;
@@ -1950,6 +1955,18 @@ SignalSender::sendSignal(Uint16 nodeId,
signalLogger.flushSignalLog();
}
#endif
+
+ if (nodeId == theFacade->ownId())
+ {
+ SignalHeader tmp= s->header;
+ tmp.theSendersBlockRef = getOwnRef();
+ theFacade->deliver_signal(&tmp,
+ 1, // JBB
+ (Uint32*)&s->theData[0],
+ (LinearSectionPtr*)&s->ptr[0]);
+ return SEND_OK;
+ }
+
assert(getNodeInfo(nodeId).m_api_reg_conf == true ||
s->readSignalNumber() == GSN_API_REGREQ);
=== modified file 'storage/ndb/src/ndbapi/TransporterFacade.hpp'
--- a/storage/ndb/src/ndbapi/TransporterFacade.hpp 2008-08-26 14:05:01 +0000
+++ b/storage/ndb/src/ndbapi/TransporterFacade.hpp 2008-10-21 12:41:59 +0000
@@ -283,7 +283,7 @@ private:
Vector<Object_Execute> m_objectExecute;
Vector<NodeStatusFunction> m_statusFunction;
- int open(void* objRef, ExecuteFunction, NodeStatusFunction, int);
+ int open(void* objRef, ExecuteFunction, NodeStatusFunction);
int close(int number);
void expand(Uint32 size);
@@ -303,7 +303,8 @@ private:
return (m_statusNext[index] & (1 << 16)) != 0;
}
} m_threads;
-
+
+ Uint32 m_fixed2dynamic[NO_API_FIXED_BLOCKS];
Uint32 m_max_trans_id;
Uint32 m_fragmented_signal_id;
=== modified file 'storage/ndb/test/run-test/Makefile.am'
--- a/storage/ndb/test/run-test/Makefile.am 2008-08-28 12:23:34 +0000
+++ b/storage/ndb/test/run-test/Makefile.am 2008-10-21 12:41:59 +0000
@@ -42,7 +42,6 @@ LDADD_LOC = $(top_builddir)/storage/ndb/
atrt_CXXFLAGS = -I$(top_srcdir)/ndb/src/mgmapi \
-I$(top_srcdir)/ndb/src/mgmsrv \
-I$(top_srcdir)/ndb/include/mgmcommon \
- -DMYSQLCLUSTERDIR="\"\"" \
-DDEFAULT_PREFIX="\"$(prefix)\""
atrt_LDFLAGS = -static @ndb_bin_am_ldflags@
| Thread |
|---|
| • bzr commit into mysql-5.1 branch (msvensson:3018) WL#4350 | Magnus Svensson | 27 Oct |