Commit dba31904 authored by unknown's avatar unknown

Merge tulin@bk-internal.mysql.com:/home/bk/mysql-4.1

into poseidon.ndb.mysql.com:/home/tomas/mysql-4.1-new


tests/mysql_client_test.c:
  Auto merged
parents 951dacdc 2a48132e
...@@ -785,12 +785,14 @@ INSERT INTO t1 VALUES ...@@ -785,12 +785,14 @@ INSERT INTO t1 VALUES
(1,'blah','464','aaa','fkc1c9ilc20x0hgae7lx6j09','ERR','ERR Имри.Афимим.Аеимимримдмримрмрирор имримримримр имридм ирбднримрфмририримрфмфмим.Ад.Д имдимримрад.Адимримримрмдиримримримр м.Дадимфшьмримд им.Адимимрн имадми','ИМРИ.АФИМИМ.АЕИМИМРИМДМРИМРМРИРОР',3,'2005-06-01 17:30:43','1234567890'), (1,'blah','464','aaa','fkc1c9ilc20x0hgae7lx6j09','ERR','ERR Имри.Афимим.Аеимимримдмримрмрирор имримримримр имридм ирбднримрфмририримрфмфмим.Ад.Д имдимримрад.Адимримримрмдиримримримр м.Дадимфшьмримд им.Адимимрн имадми','ИМРИ.АФИМИМ.АЕИМИМРИМДМРИМРМРИРОР',3,'2005-06-01 17:30:43','1234567890'),
(2,'blah','464','aaa','haxpl2ilc20x00bj4tt2m5ti','11','11 g','G',3,'2005-06-02 22:43:10','1234567890'); (2,'blah','464','aaa','haxpl2ilc20x00bj4tt2m5ti','11','11 g','G',3,'2005-06-02 22:43:10','1234567890');
--disable_warnings
CREATE TABLE t2 ( CREATE TABLE t2 (
`msisdn` varchar(15) NOT NULL default '', `msisdn` varchar(15) NOT NULL default '',
`operator_id` int(11) NOT NULL default '0', `operator_id` int(11) NOT NULL default '0',
`created` datetime NOT NULL default '0000-00-00 00:00:00', `created` datetime NOT NULL default '0000-00-00 00:00:00',
UNIQUE KEY `PK_user` (`msisdn`) UNIQUE KEY `PK_user` (`msisdn`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--enable_warnings
INSERT INTO t2 VALUES ('1234567890',2,'2005-05-24 13:53:25'); INSERT INTO t2 VALUES ('1234567890',2,'2005-05-24 13:53:25');
......
...@@ -36,8 +36,16 @@ ...@@ -36,8 +36,16 @@
#define MAKE_VERSION(A,B,C) (((A) << 16) | ((B) << 8) | ((C) << 0)) #define MAKE_VERSION(A,B,C) (((A) << 16) | ((B) << 8) | ((C) << 0))
#define NDB_VERSION_D MAKE_VERSION(NDB_VERSION_MAJOR, NDB_VERSION_MINOR, NDB_VERSION_BUILD) #define NDB_VERSION_D MAKE_VERSION(NDB_VERSION_MAJOR, NDB_VERSION_MINOR, NDB_VERSION_BUILD)
#define NDB_VERSION_STRING_BUF_SZ 100
#define NDB_VERSION_STRING (getVersionString(NDB_VERSION, NDB_VERSION_STATUS)) #ifdef __cplusplus
extern "C"
#else
extern
#endif
char ndb_version_string_buf[NDB_VERSION_STRING_BUF_SZ];
#define NDB_VERSION_STRING (getVersionString(NDB_VERSION, NDB_VERSION_STATUS, \
ndb_version_string_buf, \
sizeof(ndb_version_string_buf)))
#define NDB_VERSION ndbGetOwnVersion() #define NDB_VERSION ndbGetOwnVersion()
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
#define NDB_NONBLOCK FNDELAY #define NDB_NONBLOCK FNDELAY
#define NDB_SOCKET_TYPE int #define NDB_SOCKET_TYPE int
#define NDB_INVALID_SOCKET -1 #define NDB_INVALID_SOCKET -1
#define NDB_CLOSE_SOCKET(x) close(x) #define _NDB_CLOSE_SOCKET(x) close(x)
/** /**
* socklen_t not defined in the header files of OSE * socklen_t not defined in the header files of OSE
...@@ -52,7 +52,7 @@ typedef int socklen_t; ...@@ -52,7 +52,7 @@ typedef int socklen_t;
#define EWOULDBLOCK WSAEWOULDBLOCK #define EWOULDBLOCK WSAEWOULDBLOCK
#define NDB_SOCKET_TYPE SOCKET #define NDB_SOCKET_TYPE SOCKET
#define NDB_INVALID_SOCKET INVALID_SOCKET #define NDB_INVALID_SOCKET INVALID_SOCKET
#define NDB_CLOSE_SOCKET(x) closesocket(x) #define _NDB_CLOSE_SOCKET(x) closesocket(x)
#else #else
...@@ -64,7 +64,7 @@ typedef int socklen_t; ...@@ -64,7 +64,7 @@ typedef int socklen_t;
#define NDB_NONBLOCK O_NONBLOCK #define NDB_NONBLOCK O_NONBLOCK
#define NDB_SOCKET_TYPE int #define NDB_SOCKET_TYPE int
#define NDB_INVALID_SOCKET -1 #define NDB_INVALID_SOCKET -1
#define NDB_CLOSE_SOCKET(x) ::close(x) #define _NDB_CLOSE_SOCKET(x) ::close(x)
#define InetErrno errno #define InetErrno errno
...@@ -89,6 +89,12 @@ extern "C" { ...@@ -89,6 +89,12 @@ extern "C" {
*/ */
int Ndb_getInAddr(struct in_addr * dst, const char *address); int Ndb_getInAddr(struct in_addr * dst, const char *address);
#ifdef DBUG_OFF
#define NDB_CLOSE_SOCKET(fd) _NDB_CLOSE_SOCKET(fd)
#else
int NDB_CLOSE_SOCKET(int fd);
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
......
...@@ -238,6 +238,8 @@ public: ...@@ -238,6 +238,8 @@ public:
}; };
Vector<Transporter_interface> m_transporter_interface; Vector<Transporter_interface> m_transporter_interface;
void add_transporter_interface(const char *interf, unsigned short port); void add_transporter_interface(const char *interf, unsigned short port);
struct in_addr get_connect_address(NodeId node_id) const;
protected: protected:
private: private:
......
...@@ -41,7 +41,13 @@ public: ...@@ -41,7 +41,13 @@ public:
protected: protected:
friend class SocketServer; friend class SocketServer;
friend void* sessionThread_C(void*); friend void* sessionThread_C(void*);
Session(NDB_SOCKET_TYPE sock): m_socket(sock){ m_stop = m_stopped = false;} Session(NDB_SOCKET_TYPE sock): m_socket(sock)
{
DBUG_ENTER("SocketServer::Session");
DBUG_PRINT("enter",("NDB_SOCKET: %d", m_socket));
m_stop = m_stopped = false;
DBUG_VOID_RETURN;
}
bool m_stop; // Has the session been ordered to stop? bool m_stop; // Has the session been ordered to stop?
bool m_stopped; // Has the session stopped? bool m_stopped; // Has the session stopped?
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
const char *opt_connect_str= 0;\ const char *opt_connect_str= 0;\
my_bool opt_ndb_optimized_node_selection my_bool opt_ndb_optimized_node_selection
bool opt_endinfo= 0;
my_bool opt_ndb_shm; my_bool opt_ndb_shm;
#define OPT_NDB_CONNECTSTRING 'c' #define OPT_NDB_CONNECTSTRING 'c'
...@@ -93,6 +94,7 @@ ndb_std_get_one_option(int optid, ...@@ -93,6 +94,7 @@ ndb_std_get_one_option(int optid,
{ {
DBUG_PUSH(argument); DBUG_PUSH(argument);
} }
opt_endinfo= 1;
break; break;
case 'V': case 'V':
ndb_std_print_version(); ndb_std_print_version();
......
...@@ -30,7 +30,8 @@ extern "C" { ...@@ -30,7 +30,8 @@ extern "C" {
Uint32 makeVersion(Uint32 major, Uint32 minor, Uint32 build); Uint32 makeVersion(Uint32 major, Uint32 minor, Uint32 build);
const char* getVersionString(Uint32 version, const char * status); const char* getVersionString(Uint32 version, const char * status,
char *buf, unsigned sz);
void ndbPrintVersion(); void ndbPrintVersion();
Uint32 ndbGetOwnVersion(); Uint32 ndbGetOwnVersion();
......
...@@ -31,6 +31,7 @@ LogHandler::LogHandler() : ...@@ -31,6 +31,7 @@ LogHandler::LogHandler() :
m_last_message[0]= 0; m_last_message[0]= 0;
m_last_log_time= 0; m_last_log_time= 0;
m_now= 0; m_now= 0;
m_last_level= (Logger::LoggerLevel)-1;
} }
LogHandler::~LogHandler() LogHandler::~LogHandler()
......
...@@ -47,6 +47,8 @@ ...@@ -47,6 +47,8 @@
ConfigRetriever::ConfigRetriever(const char * _connect_string, ConfigRetriever::ConfigRetriever(const char * _connect_string,
Uint32 version, Uint32 node_type) Uint32 version, Uint32 node_type)
{ {
DBUG_ENTER("ConfigRetriever::ConfigRetriever");
m_version = version; m_version = version;
m_node_type = node_type; m_node_type = node_type;
_ownNodeId= 0; _ownNodeId= 0;
...@@ -55,23 +57,26 @@ ConfigRetriever::ConfigRetriever(const char * _connect_string, ...@@ -55,23 +57,26 @@ ConfigRetriever::ConfigRetriever(const char * _connect_string,
if (m_handle == 0) { if (m_handle == 0) {
setError(CR_ERROR, "Unable to allocate mgm handle"); setError(CR_ERROR, "Unable to allocate mgm handle");
return; DBUG_VOID_RETURN;
} }
if (ndb_mgm_set_connectstring(m_handle, _connect_string)) if (ndb_mgm_set_connectstring(m_handle, _connect_string))
{ {
setError(CR_ERROR, ndb_mgm_get_latest_error_desc(m_handle)); setError(CR_ERROR, ndb_mgm_get_latest_error_desc(m_handle));
return; DBUG_VOID_RETURN;
} }
resetError(); resetError();
DBUG_VOID_RETURN;
} }
ConfigRetriever::~ConfigRetriever() ConfigRetriever::~ConfigRetriever()
{ {
DBUG_ENTER("ConfigRetriever::~ConfigRetriever");
if (m_handle) { if (m_handle) {
ndb_mgm_disconnect(m_handle); ndb_mgm_disconnect(m_handle);
ndb_mgm_destroy_handle(&m_handle); ndb_mgm_destroy_handle(&m_handle);
} }
DBUG_VOID_RETURN;
} }
Uint32 Uint32
...@@ -131,16 +136,14 @@ ConfigRetriever::getConfig() { ...@@ -131,16 +136,14 @@ ConfigRetriever::getConfig() {
} }
ndb_mgm_configuration * ndb_mgm_configuration *
ConfigRetriever::getConfig(NdbMgmHandle m_handle){ ConfigRetriever::getConfig(NdbMgmHandle m_handle)
{
ndb_mgm_configuration * conf = ndb_mgm_get_configuration(m_handle,m_version); ndb_mgm_configuration * conf = ndb_mgm_get_configuration(m_handle,m_version);
if(conf == 0){ if(conf == 0)
{
setError(CR_ERROR, ndb_mgm_get_latest_error_desc(m_handle)); setError(CR_ERROR, ndb_mgm_get_latest_error_desc(m_handle));
return 0; return 0;
} }
ndb_mgm_disconnect(m_handle);
return conf; return conf;
} }
......
...@@ -114,7 +114,10 @@ IPCConfig::addRemoteNodeId(NodeId nodeId){ ...@@ -114,7 +114,10 @@ IPCConfig::addRemoteNodeId(NodeId nodeId){
* Returns no of transporters configured * Returns no of transporters configured
*/ */
int int
IPCConfig::configureTransporters(TransporterRegistry * theTransporterRegistry){ IPCConfig::configureTransporters(TransporterRegistry * theTransporterRegistry)
{
DBUG_ENTER("IPCConfig::configureTransporters");
int noOfTransportersCreated = 0; int noOfTransportersCreated = 0;
Uint32 noOfConnections; Uint32 noOfConnections;
...@@ -276,7 +279,7 @@ IPCConfig::configureTransporters(TransporterRegistry * theTransporterRegistry){ ...@@ -276,7 +279,7 @@ IPCConfig::configureTransporters(TransporterRegistry * theTransporterRegistry){
continue; continue;
} }
} }
return noOfTransportersCreated; DBUG_RETURN(noOfTransportersCreated);
} }
/** /**
......
...@@ -23,33 +23,37 @@ ...@@ -23,33 +23,37 @@
NdbMutex* NdbMutex_Create(void) NdbMutex* NdbMutex_Create(void)
{ {
DBUG_ENTER("NdbMutex_Create");
NdbMutex* pNdbMutex; NdbMutex* pNdbMutex;
int result; int result;
pNdbMutex = (NdbMutex*)NdbMem_Allocate(sizeof(NdbMutex)); pNdbMutex = (NdbMutex*)NdbMem_Allocate(sizeof(NdbMutex));
DBUG_PRINT("info",("NdbMem_Allocate 0x%lx",pNdbMutex));
if (pNdbMutex == NULL) if (pNdbMutex == NULL)
return NULL; DBUG_RETURN(NULL);
result = pthread_mutex_init(pNdbMutex, NULL); result = pthread_mutex_init(pNdbMutex, NULL);
assert(result == 0); assert(result == 0);
return pNdbMutex; DBUG_RETURN(pNdbMutex);
} }
int NdbMutex_Destroy(NdbMutex* p_mutex) int NdbMutex_Destroy(NdbMutex* p_mutex)
{ {
DBUG_ENTER("NdbMutex_Destroy");
int result; int result;
if (p_mutex == NULL) if (p_mutex == NULL)
return -1; DBUG_RETURN(-1);
result = pthread_mutex_destroy(p_mutex); result = pthread_mutex_destroy(p_mutex);
free(p_mutex);
DBUG_PRINT("info",("NdbMem_Free 0x%lx",p_mutex));
NdbMem_Free(p_mutex);
return result; DBUG_RETURN(result);
} }
......
...@@ -54,6 +54,15 @@ Ndb_getInAddr(struct in_addr * dst, const char *address) { ...@@ -54,6 +54,15 @@ Ndb_getInAddr(struct in_addr * dst, const char *address) {
return -1; //DBUG_RETURN(-1); return -1; //DBUG_RETURN(-1);
} }
#ifndef DBUG_OFF
extern "C"
int NDB_CLOSE_SOCKET(int fd)
{
DBUG_PRINT("info", ("NDB_CLOSE_SOCKET(%d)", fd));
return _NDB_CLOSE_SOCKET(fd);
}
#endif
#if 0 #if 0
int int
Ndb_getInAddr(struct in_addr * dst, const char *address) { Ndb_getInAddr(struct in_addr * dst, const char *address) {
......
...@@ -56,6 +56,7 @@ ndb_thread_wrapper(void* _ss){ ...@@ -56,6 +56,7 @@ ndb_thread_wrapper(void* _ss){
void *ret; void *ret;
struct NdbThread * ss = (struct NdbThread *)_ss; struct NdbThread * ss = (struct NdbThread *)_ss;
ret= (* ss->func)(ss->object); ret= (* ss->func)(ss->object);
DBUG_POP();
NdbThread_Exit(ret); NdbThread_Exit(ret);
} }
/* will never be reached */ /* will never be reached */
...@@ -70,6 +71,7 @@ struct NdbThread* NdbThread_Create(NDB_THREAD_FUNC *p_thread_func, ...@@ -70,6 +71,7 @@ struct NdbThread* NdbThread_Create(NDB_THREAD_FUNC *p_thread_func,
const char* p_thread_name, const char* p_thread_name,
NDB_THREAD_PRIO thread_prio) NDB_THREAD_PRIO thread_prio)
{ {
DBUG_ENTER("NdbThread_Create");
struct NdbThread* tmpThread; struct NdbThread* tmpThread;
int result; int result;
pthread_attr_t thread_attr; pthread_attr_t thread_attr;
...@@ -77,11 +79,13 @@ struct NdbThread* NdbThread_Create(NDB_THREAD_FUNC *p_thread_func, ...@@ -77,11 +79,13 @@ struct NdbThread* NdbThread_Create(NDB_THREAD_FUNC *p_thread_func,
(void)thread_prio; /* remove warning for unused parameter */ (void)thread_prio; /* remove warning for unused parameter */
if (p_thread_func == NULL) if (p_thread_func == NULL)
return 0; DBUG_RETURN(NULL);
tmpThread = (struct NdbThread*)NdbMem_Allocate(sizeof(struct NdbThread)); tmpThread = (struct NdbThread*)NdbMem_Allocate(sizeof(struct NdbThread));
if (tmpThread == NULL) if (tmpThread == NULL)
return NULL; DBUG_RETURN(NULL);
DBUG_PRINT("info",("thread_name: %s", p_thread_name));
strnmov(tmpThread->thread_name,p_thread_name,sizeof(tmpThread->thread_name)); strnmov(tmpThread->thread_name,p_thread_name,sizeof(tmpThread->thread_name));
...@@ -108,16 +112,20 @@ struct NdbThread* NdbThread_Create(NDB_THREAD_FUNC *p_thread_func, ...@@ -108,16 +112,20 @@ struct NdbThread* NdbThread_Create(NDB_THREAD_FUNC *p_thread_func,
assert(result==0); assert(result==0);
pthread_attr_destroy(&thread_attr); pthread_attr_destroy(&thread_attr);
return tmpThread; DBUG_PRINT("exit",("ret: %lx", tmpThread));
DBUG_RETURN(tmpThread);
} }
void NdbThread_Destroy(struct NdbThread** p_thread) void NdbThread_Destroy(struct NdbThread** p_thread)
{ {
if (*p_thread != NULL){ DBUG_ENTER("NdbThread_Destroy");
if (*p_thread != NULL){
DBUG_PRINT("enter",("*p_thread: %lx", * p_thread));
free(* p_thread); free(* p_thread);
* p_thread = 0; * p_thread = 0;
} }
DBUG_VOID_RETURN;
} }
......
...@@ -74,6 +74,7 @@ Transporter::Transporter(TransporterRegistry &t_reg, ...@@ -74,6 +74,7 @@ Transporter::Transporter(TransporterRegistry &t_reg,
m_connected = false; m_connected = false;
m_timeOutMillis = 1000; m_timeOutMillis = 1000;
m_connect_address.s_addr= 0;
if (isServer) if (isServer)
m_socket_client= 0; m_socket_client= 0;
else else
...@@ -98,6 +99,13 @@ Transporter::connect_server(NDB_SOCKET_TYPE sockfd) { ...@@ -98,6 +99,13 @@ Transporter::connect_server(NDB_SOCKET_TYPE sockfd) {
DBUG_RETURN(true); // TODO assert(0); DBUG_RETURN(true); // TODO assert(0);
} }
{
struct sockaddr addr;
SOCKET_SIZE_TYPE addrlen= sizeof(addr);
int r= getpeername(sockfd, &addr, &addrlen);
m_connect_address= ((struct sockaddr_in *)&addr)->sin_addr;
}
bool res = connect_server_impl(sockfd); bool res = connect_server_impl(sockfd);
if(res){ if(res){
m_connected = true; m_connected = true;
...@@ -164,6 +172,13 @@ Transporter::connect_client() { ...@@ -164,6 +172,13 @@ Transporter::connect_client() {
g_eventLogger.warning("Unable to verify transporter compatability with node %d", nodeId); g_eventLogger.warning("Unable to verify transporter compatability with node %d", nodeId);
} }
{
struct sockaddr addr;
SOCKET_SIZE_TYPE addrlen= sizeof(addr);
int r= getpeername(sockfd, &addr, &addrlen);
m_connect_address= ((struct sockaddr_in *)&addr)->sin_addr;
}
bool res = connect_client_impl(sockfd); bool res = connect_client_impl(sockfd);
if(res){ if(res){
m_connected = true; m_connected = true;
......
...@@ -122,6 +122,7 @@ protected: ...@@ -122,6 +122,7 @@ protected:
private: private:
SocketClient *m_socket_client; SocketClient *m_socket_client;
struct in_addr m_connect_address;
protected: protected:
Uint32 getErrorCount(); Uint32 getErrorCount();
......
...@@ -51,6 +51,12 @@ extern int g_ndb_shm_signum; ...@@ -51,6 +51,12 @@ extern int g_ndb_shm_signum;
#include <EventLogger.hpp> #include <EventLogger.hpp>
extern EventLogger g_eventLogger; extern EventLogger g_eventLogger;
struct in_addr
TransporterRegistry::get_connect_address(NodeId node_id) const
{
return theTransporters[node_id]->m_connect_address;
}
SocketServer::Session * TransporterService::newSession(NDB_SOCKET_TYPE sockfd) SocketServer::Session * TransporterService::newSession(NDB_SOCKET_TYPE sockfd)
{ {
DBUG_ENTER("SocketServer::Session * TransporterService::newSession"); DBUG_ENTER("SocketServer::Session * TransporterService::newSession");
...@@ -70,7 +76,9 @@ SocketServer::Session * TransporterService::newSession(NDB_SOCKET_TYPE sockfd) ...@@ -70,7 +76,9 @@ SocketServer::Session * TransporterService::newSession(NDB_SOCKET_TYPE sockfd)
TransporterRegistry::TransporterRegistry(void * callback, TransporterRegistry::TransporterRegistry(void * callback,
unsigned _maxTransporters, unsigned _maxTransporters,
unsigned sizeOfLongSignalMemory) { unsigned sizeOfLongSignalMemory)
{
DBUG_ENTER("TransporterRegistry::TransporterRegistry");
nodeIdSpecified = false; nodeIdSpecified = false;
maxTransporters = _maxTransporters; maxTransporters = _maxTransporters;
...@@ -107,9 +115,13 @@ TransporterRegistry::TransporterRegistry(void * callback, ...@@ -107,9 +115,13 @@ TransporterRegistry::TransporterRegistry(void * callback,
theOSEReceiver = 0; theOSEReceiver = 0;
theOSEJunkSocketSend = 0; theOSEJunkSocketSend = 0;
theOSEJunkSocketRecv = 0; theOSEJunkSocketRecv = 0;
DBUG_VOID_RETURN;
} }
TransporterRegistry::~TransporterRegistry() { TransporterRegistry::~TransporterRegistry()
{
DBUG_ENTER("TransporterRegistry::~TransporterRegistry");
removeAll(); removeAll();
...@@ -129,6 +141,8 @@ TransporterRegistry::~TransporterRegistry() { ...@@ -129,6 +141,8 @@ TransporterRegistry::~TransporterRegistry() {
theOSEReceiver = 0; theOSEReceiver = 0;
} }
#endif #endif
DBUG_VOID_RETURN;
} }
void void
......
...@@ -141,7 +141,10 @@ split(char * buf, char ** name, char ** value){ ...@@ -141,7 +141,10 @@ split(char * buf, char ** name, char ** value){
bool bool
ParserImpl::run(Context * ctx, const class Properties ** pDst, ParserImpl::run(Context * ctx, const class Properties ** pDst,
volatile bool * stop) const { volatile bool * stop) const
{
DBUG_ENTER("ParserImpl::run");
* pDst = 0; * pDst = 0;
bool ownStop = false; bool ownStop = false;
if(stop == 0) if(stop == 0)
...@@ -153,24 +156,24 @@ ParserImpl::run(Context * ctx, const class Properties ** pDst, ...@@ -153,24 +156,24 @@ ParserImpl::run(Context * ctx, const class Properties ** pDst,
ctx->m_currentToken = input.gets(ctx->m_tokenBuffer, sz); ctx->m_currentToken = input.gets(ctx->m_tokenBuffer, sz);
if(Eof(ctx->m_currentToken)){ if(Eof(ctx->m_currentToken)){
ctx->m_status = Parser<Dummy>::Eof; ctx->m_status = Parser<Dummy>::Eof;
return false; DBUG_RETURN(false);
} }
if(ctx->m_currentToken[0] == 0){ if(ctx->m_currentToken[0] == 0){
ctx->m_status = Parser<Dummy>::NoLine; ctx->m_status = Parser<Dummy>::NoLine;
return false; DBUG_RETURN(false);
} }
if(Empty(ctx->m_currentToken)){ if(Empty(ctx->m_currentToken)){
ctx->m_status = Parser<Dummy>::EmptyLine; ctx->m_status = Parser<Dummy>::EmptyLine;
return false; DBUG_RETURN(false);
} }
trim(ctx->m_currentToken); trim(ctx->m_currentToken);
ctx->m_currentCmd = matchCommand(ctx, ctx->m_currentToken, m_rows); ctx->m_currentCmd = matchCommand(ctx, ctx->m_currentToken, m_rows);
if(ctx->m_currentCmd == 0){ if(ctx->m_currentCmd == 0){
ctx->m_status = Parser<Dummy>::UnknownCommand; ctx->m_status = Parser<Dummy>::UnknownCommand;
return false; DBUG_RETURN(false);
} }
Properties * p = new Properties(); Properties * p = new Properties();
...@@ -200,19 +203,19 @@ ParserImpl::run(Context * ctx, const class Properties ** pDst, ...@@ -200,19 +203,19 @@ ParserImpl::run(Context * ctx, const class Properties ** pDst,
tmp = input.gets(buf, sz); tmp = input.gets(buf, sz);
} while((! * stop) && !Eof(tmp) && !Empty(tmp)); } while((! * stop) && !Eof(tmp) && !Empty(tmp));
} }
return false; DBUG_RETURN(false);
} }
if(* stop){ if(* stop){
delete p; delete p;
ctx->m_status = Parser<Dummy>::ExternalStop; ctx->m_status = Parser<Dummy>::ExternalStop;
return false; DBUG_RETURN(false);
} }
if(!checkMandatory(ctx, p)){ if(!checkMandatory(ctx, p)){
ctx->m_status = Parser<Dummy>::MissingMandatoryArgument; ctx->m_status = Parser<Dummy>::MissingMandatoryArgument;
delete p; delete p;
return false; DBUG_RETURN(false);
} }
/** /**
...@@ -229,7 +232,7 @@ ParserImpl::run(Context * ctx, const class Properties ** pDst, ...@@ -229,7 +232,7 @@ ParserImpl::run(Context * ctx, const class Properties ** pDst,
ctx->m_status = Parser<Dummy>::Ok; ctx->m_status = Parser<Dummy>::Ok;
* pDst = p; * pDst = p;
return true; DBUG_RETURN(true);
} }
const ParserImpl::DummyRow* const ParserImpl::DummyRow*
......
...@@ -57,6 +57,8 @@ SocketClient::init() ...@@ -57,6 +57,8 @@ SocketClient::init()
return false; return false;
} }
DBUG_PRINT("info",("NDB_SOCKET: %d", m_sockfd));
return true; return true;
} }
......
...@@ -64,6 +64,8 @@ SocketServer::tryBind(unsigned short port, const char * intface) { ...@@ -64,6 +64,8 @@ SocketServer::tryBind(unsigned short port, const char * intface) {
return false; return false;
} }
DBUG_PRINT("info",("NDB_SOCKET: %d", sock));
const int on = 1; const int on = 1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
(const char*)&on, sizeof(on)) == -1) { (const char*)&on, sizeof(on)) == -1) {
...@@ -104,6 +106,8 @@ SocketServer::setup(SocketServer::Service * service, ...@@ -104,6 +106,8 @@ SocketServer::setup(SocketServer::Service * service,
DBUG_RETURN(false); DBUG_RETURN(false);
} }
DBUG_PRINT("info",("NDB_SOCKET: %d", sock));
const int on = 1; const int on = 1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
(const char*)&on, sizeof(on)) == -1) { (const char*)&on, sizeof(on)) == -1) {
......
...@@ -38,22 +38,24 @@ Uint32 makeVersion(Uint32 major, Uint32 minor, Uint32 build) { ...@@ -38,22 +38,24 @@ Uint32 makeVersion(Uint32 major, Uint32 minor, Uint32 build) {
} }
const char * getVersionString(Uint32 version, const char * status) { char ndb_version_string_buf[NDB_VERSION_STRING_BUF_SZ];
char buff[100]; const char * getVersionString(Uint32 version, const char * status,
char *buf, unsigned sz)
{
if (status && status[0] != 0) if (status && status[0] != 0)
basestring_snprintf(buff, sizeof(buff), basestring_snprintf(buf, sz,
"Version %d.%d.%d (%s)", "Version %d.%d.%d (%s)",
getMajor(version), getMajor(version),
getMinor(version), getMinor(version),
getBuild(version), getBuild(version),
status); status);
else else
basestring_snprintf(buff, sizeof(buff), basestring_snprintf(buf, sz,
"Version %d.%d.%d", "Version %d.%d.%d",
getMajor(version), getMajor(version),
getMinor(version), getMinor(version),
getBuild(version)); getBuild(version));
return strdup(buff); return buf;
} }
typedef enum { typedef enum {
......
...@@ -257,8 +257,8 @@ private: ...@@ -257,8 +257,8 @@ private:
void hbReceivedLab(Signal* signal); void hbReceivedLab(Signal* signal);
void sendCmRegrefLab(Signal* signal, BlockReference ref, void sendCmRegrefLab(Signal* signal, BlockReference ref,
CmRegRef::ErrorCode); CmRegRef::ErrorCode);
void systemErrorBecauseOtherNodeFailed(Signal* signal, NodeId); void systemErrorBecauseOtherNodeFailed(Signal* signal, Uint32 line, NodeId);
void systemErrorLab(Signal* signal, void systemErrorLab(Signal* signal, Uint32 line,
const char* message = NULL); const char* message = NULL);
void prepFailReqLab(Signal* signal); void prepFailReqLab(Signal* signal);
void prepFailConfLab(Signal* signal); void prepFailConfLab(Signal* signal);
......
...@@ -76,7 +76,7 @@ void Qmgr::execCM_HEARTBEAT(Signal* signal) ...@@ -76,7 +76,7 @@ void Qmgr::execCM_HEARTBEAT(Signal* signal)
void Qmgr::execCM_NODEINFOREF(Signal* signal) void Qmgr::execCM_NODEINFOREF(Signal* signal)
{ {
jamEntry(); jamEntry();
systemErrorLab(signal); systemErrorLab(signal, __LINE__);
return; return;
}//Qmgr::execCM_NODEINFOREF() }//Qmgr::execCM_NODEINFOREF()
...@@ -121,7 +121,7 @@ void Qmgr::execCONTINUEB(Signal* signal) ...@@ -121,7 +121,7 @@ void Qmgr::execCONTINUEB(Signal* signal)
default: default:
jam(); jam();
// ZCOULD_NOT_OCCUR_ERROR; // ZCOULD_NOT_OCCUR_ERROR;
systemErrorLab(signal); systemErrorLab(signal, __LINE__);
return; return;
break; break;
}//switch }//switch
...@@ -593,7 +593,7 @@ void Qmgr::execCM_REGCONF(Signal* signal) ...@@ -593,7 +593,7 @@ void Qmgr::execCM_REGCONF(Signal* signal)
jam(); jam();
char buf[128]; char buf[128];
BaseString::snprintf(buf,sizeof(buf),"incompatible version own=0x%x other=0x%x, shutting down", NDB_VERSION, cmRegConf->presidentVersion); BaseString::snprintf(buf,sizeof(buf),"incompatible version own=0x%x other=0x%x, shutting down", NDB_VERSION, cmRegConf->presidentVersion);
systemErrorLab(signal, buf); systemErrorLab(signal, __LINE__, buf);
return; return;
} }
...@@ -688,7 +688,7 @@ void Qmgr::execCM_REGREF(Signal* signal) ...@@ -688,7 +688,7 @@ void Qmgr::execCM_REGREF(Signal* signal)
switch (TrefuseReason) { switch (TrefuseReason) {
case CmRegRef::ZINCOMPATIBLE_VERSION: case CmRegRef::ZINCOMPATIBLE_VERSION:
jam(); jam();
systemErrorLab(signal, "incompatible version, connection refused by running ndb node"); systemErrorLab(signal, __LINE__, "incompatible version, connection refused by running ndb node");
break; break;
case CmRegRef::ZBUSY: case CmRegRef::ZBUSY:
case CmRegRef::ZBUSY_TO_PRES: case CmRegRef::ZBUSY_TO_PRES:
...@@ -1751,7 +1751,7 @@ void Qmgr::execAPI_FAILCONF(Signal* signal) ...@@ -1751,7 +1751,7 @@ void Qmgr::execAPI_FAILCONF(Signal* signal)
if (failedNodePtr.p->rcv[0] == failedNodePtr.p->rcv[1]) { if (failedNodePtr.p->rcv[0] == failedNodePtr.p->rcv[1]) {
jam(); jam();
systemErrorLab(signal); systemErrorLab(signal, __LINE__);
} else { } else {
jam(); jam();
failedNodePtr.p->rcv[0] = 0; failedNodePtr.p->rcv[0] = 0;
...@@ -1763,7 +1763,7 @@ void Qmgr::execAPI_FAILCONF(Signal* signal) ...@@ -1763,7 +1763,7 @@ void Qmgr::execAPI_FAILCONF(Signal* signal)
ndbout << "failedNodePtr.p->failState = " ndbout << "failedNodePtr.p->failState = "
<< (Uint32)(failedNodePtr.p->failState) << endl; << (Uint32)(failedNodePtr.p->failState) << endl;
#endif #endif
systemErrorLab(signal); systemErrorLab(signal, __LINE__);
}//if }//if
return; return;
}//Qmgr::execAPI_FAILCONF() }//Qmgr::execAPI_FAILCONF()
...@@ -1780,7 +1780,7 @@ void Qmgr::execNDB_FAILCONF(Signal* signal) ...@@ -1780,7 +1780,7 @@ void Qmgr::execNDB_FAILCONF(Signal* signal)
failedNodePtr.p->failState = NORMAL; failedNodePtr.p->failState = NORMAL;
} else { } else {
jam(); jam();
systemErrorLab(signal); systemErrorLab(signal, __LINE__);
}//if }//if
if (cpresident == getOwnNodeId()) { if (cpresident == getOwnNodeId()) {
jam(); jam();
...@@ -1931,20 +1931,13 @@ void Qmgr::execAPI_REGREQ(Signal* signal) ...@@ -1931,20 +1931,13 @@ void Qmgr::execAPI_REGREQ(Signal* signal)
#endif #endif
bool compatability_check; bool compatability_check;
switch(getNodeInfo(apiNodePtr.i).getType()){ NodeInfo::NodeType type= getNodeInfo(apiNodePtr.i).getType();
switch(type){
case NodeInfo::API: case NodeInfo::API:
compatability_check = ndbCompatible_ndb_api(NDB_VERSION, version); compatability_check = ndbCompatible_ndb_api(NDB_VERSION, version);
if (!compatability_check)
infoEvent("Connection attempt from api or mysqld id=%d with %s "
"incompatible with %s", apiNodePtr.i,
getVersionString(version,""), NDB_VERSION_STRING);
break; break;
case NodeInfo::MGM: case NodeInfo::MGM:
compatability_check = ndbCompatible_ndb_mgmt(NDB_VERSION, version); compatability_check = ndbCompatible_ndb_mgmt(NDB_VERSION, version);
if (!compatability_check)
infoEvent("Connection attempt from management server id=%d with %s "
"incompatible with %s", apiNodePtr.i,
getVersionString(version,""), NDB_VERSION_STRING);
break; break;
case NodeInfo::REP: case NodeInfo::REP:
// compatability_check = ndbCompatible_ndb_api(NDB_VERSION, version); // compatability_check = ndbCompatible_ndb_api(NDB_VERSION, version);
...@@ -1953,13 +1946,19 @@ void Qmgr::execAPI_REGREQ(Signal* signal) ...@@ -1953,13 +1946,19 @@ void Qmgr::execAPI_REGREQ(Signal* signal)
case NodeInfo::INVALID: case NodeInfo::INVALID:
default: default:
sendApiRegRef(signal, ref, ApiRegRef::WrongType); sendApiRegRef(signal, ref, ApiRegRef::WrongType);
infoEvent("Invalid connection attempt with type %d", infoEvent("Invalid connection attempt with type %d", type);
getNodeInfo(apiNodePtr.i).getType());
return; return;
} }
if (!compatability_check) { if (!compatability_check) {
jam(); jam();
char buf[NDB_VERSION_STRING_BUF_SZ];
infoEvent("Connection attempt from %s id=%d with %s "
"incompatible with %s",
type == NodeInfo::API ? "api or mysqld" : "management server",
apiNodePtr.i,
getVersionString(version,"",buf,sizeof(buf)),
NDB_VERSION_STRING);
apiNodePtr.p->phase = ZAPI_INACTIVE; apiNodePtr.p->phase = ZAPI_INACTIVE;
sendApiRegRef(signal, ref, ApiRegRef::UnsupportedVersion); sendApiRegRef(signal, ref, ApiRegRef::UnsupportedVersion);
return; return;
...@@ -2085,7 +2084,7 @@ void Qmgr::failReportLab(Signal* signal, Uint16 aFailedNode, ...@@ -2085,7 +2084,7 @@ void Qmgr::failReportLab(Signal* signal, Uint16 aFailedNode,
ptrCheckGuard(failedNodePtr, MAX_NODES, nodeRec); ptrCheckGuard(failedNodePtr, MAX_NODES, nodeRec);
if (failedNodePtr.i == getOwnNodeId()) { if (failedNodePtr.i == getOwnNodeId()) {
jam(); jam();
systemErrorLab(signal); systemErrorLab(signal, __LINE__);
return; return;
}//if }//if
...@@ -2093,7 +2092,7 @@ void Qmgr::failReportLab(Signal* signal, Uint16 aFailedNode, ...@@ -2093,7 +2092,7 @@ void Qmgr::failReportLab(Signal* signal, Uint16 aFailedNode,
ptrCheckGuard(myNodePtr, MAX_NDB_NODES, nodeRec); ptrCheckGuard(myNodePtr, MAX_NDB_NODES, nodeRec);
if (myNodePtr.p->phase != ZRUNNING) { if (myNodePtr.p->phase != ZRUNNING) {
jam(); jam();
systemErrorLab(signal); systemErrorLab(signal, __LINE__);
return; return;
}//if }//if
TnoFailedNodes = cnoFailedNodes; TnoFailedNodes = cnoFailedNodes;
...@@ -2172,7 +2171,7 @@ void Qmgr::execPREP_FAILREQ(Signal* signal) ...@@ -2172,7 +2171,7 @@ void Qmgr::execPREP_FAILREQ(Signal* signal)
ptrCheckGuard(myNodePtr, MAX_NDB_NODES, nodeRec); ptrCheckGuard(myNodePtr, MAX_NDB_NODES, nodeRec);
if (myNodePtr.p->phase != ZRUNNING) { if (myNodePtr.p->phase != ZRUNNING) {
jam(); jam();
systemErrorLab(signal); systemErrorLab(signal, __LINE__);
return; return;
}//if }//if
...@@ -2675,7 +2674,7 @@ void Qmgr::execREAD_NODESREQ(Signal* signal) ...@@ -2675,7 +2674,7 @@ void Qmgr::execREAD_NODESREQ(Signal* signal)
ReadNodesConf::SignalLength, JBB); ReadNodesConf::SignalLength, JBB);
}//Qmgr::execREAD_NODESREQ() }//Qmgr::execREAD_NODESREQ()
void Qmgr::systemErrorBecauseOtherNodeFailed(Signal* signal, void Qmgr::systemErrorBecauseOtherNodeFailed(Signal* signal, Uint32 line,
NodeId failedNodeId) { NodeId failedNodeId) {
jam(); jam();
...@@ -2687,11 +2686,11 @@ void Qmgr::systemErrorBecauseOtherNodeFailed(Signal* signal, ...@@ -2687,11 +2686,11 @@ void Qmgr::systemErrorBecauseOtherNodeFailed(Signal* signal,
"Node was shutdown during startup because node %d failed", "Node was shutdown during startup because node %d failed",
failedNodeId); failedNodeId);
progError(__LINE__, ERR_SR_OTHERNODEFAILED, buf); progError(line, ERR_SR_OTHERNODEFAILED, buf);
} }
void Qmgr::systemErrorLab(Signal* signal, const char * message) void Qmgr::systemErrorLab(Signal* signal, Uint32 line, const char * message)
{ {
jam(); jam();
// Broadcast that this node is failing to other nodes // Broadcast that this node is failing to other nodes
...@@ -2699,7 +2698,7 @@ void Qmgr::systemErrorLab(Signal* signal, const char * message) ...@@ -2699,7 +2698,7 @@ void Qmgr::systemErrorLab(Signal* signal, const char * message)
// If it's known why shutdown occured // If it's known why shutdown occured
// an error message has been passed to this function // an error message has been passed to this function
progError(__LINE__, 0, message); progError(line, 0, message);
return; return;
}//Qmgr::systemErrorLab() }//Qmgr::systemErrorLab()
...@@ -2867,7 +2866,7 @@ Uint16 Qmgr::translateDynamicIdToNodeId(Signal* signal, UintR TdynamicId) ...@@ -2867,7 +2866,7 @@ Uint16 Qmgr::translateDynamicIdToNodeId(Signal* signal, UintR TdynamicId)
}//for }//for
if (TtdiNodeId == ZNIL) { if (TtdiNodeId == ZNIL) {
jam(); jam();
systemErrorLab(signal); systemErrorLab(signal, __LINE__);
}//if }//if
return TtdiNodeId; return TtdiNodeId;
}//Qmgr::translateDynamicIdToNodeId() }//Qmgr::translateDynamicIdToNodeId()
......
...@@ -143,6 +143,7 @@ extern "C" ...@@ -143,6 +143,7 @@ extern "C"
NdbMgmHandle NdbMgmHandle
ndb_mgm_create_handle() ndb_mgm_create_handle()
{ {
DBUG_ENTER("ndb_mgm_create_handle");
NdbMgmHandle h = NdbMgmHandle h =
(NdbMgmHandle)my_malloc(sizeof(ndb_mgm_handle),MYF(MY_WME)); (NdbMgmHandle)my_malloc(sizeof(ndb_mgm_handle),MYF(MY_WME));
h->connected = 0; h->connected = 0;
...@@ -162,17 +163,20 @@ ndb_mgm_create_handle() ...@@ -162,17 +163,20 @@ ndb_mgm_create_handle()
h->logfile = 0; h->logfile = 0;
#endif #endif
return h; DBUG_PRINT("exit",("ret: %lx", h));
DBUG_RETURN(h);
} }
extern "C" extern "C"
int int
ndb_mgm_set_connectstring(NdbMgmHandle handle, const char * mgmsrv) ndb_mgm_set_connectstring(NdbMgmHandle handle, const char * mgmsrv)
{ {
handle->cfg.~LocalConfig();
new (&(handle->cfg)) LocalConfig; new (&(handle->cfg)) LocalConfig;
if (!handle->cfg.init(mgmsrv, 0) || if (!handle->cfg.init(mgmsrv, 0) ||
handle->cfg.ids.size() == 0) handle->cfg.ids.size() == 0)
{ {
handle->cfg.~LocalConfig();
new (&(handle->cfg)) LocalConfig; new (&(handle->cfg)) LocalConfig;
handle->cfg.init(0, 0); /* reset the LocalCongig */ handle->cfg.init(0, 0); /* reset the LocalCongig */
SET_ERROR(handle, NDB_MGM_ILLEGAL_CONNECT_STRING, ""); SET_ERROR(handle, NDB_MGM_ILLEGAL_CONNECT_STRING, "");
...@@ -189,8 +193,11 @@ extern "C" ...@@ -189,8 +193,11 @@ extern "C"
void void
ndb_mgm_destroy_handle(NdbMgmHandle * handle) ndb_mgm_destroy_handle(NdbMgmHandle * handle)
{ {
DBUG_ENTER("ndb_mgm_destroy_handle");
if(!handle) if(!handle)
return; return;
DBUG_PRINT("enter",("*handle: %lx", *handle));
if((* handle)->connected){ if((* handle)->connected){
ndb_mgm_disconnect(* handle); ndb_mgm_disconnect(* handle);
} }
...@@ -203,6 +210,7 @@ ndb_mgm_destroy_handle(NdbMgmHandle * handle) ...@@ -203,6 +210,7 @@ ndb_mgm_destroy_handle(NdbMgmHandle * handle)
(*handle)->cfg.~LocalConfig(); (*handle)->cfg.~LocalConfig();
my_free((char*)* handle,MYF(MY_ALLOW_ZERO_PTR)); my_free((char*)* handle,MYF(MY_ALLOW_ZERO_PTR));
* handle = 0; * handle = 0;
DBUG_VOID_RETURN;
} }
/***************************************************************************** /*****************************************************************************
...@@ -251,6 +259,9 @@ static const Properties * ...@@ -251,6 +259,9 @@ static const Properties *
ndb_mgm_call(NdbMgmHandle handle, const ParserRow<ParserDummy> *command_reply, ndb_mgm_call(NdbMgmHandle handle, const ParserRow<ParserDummy> *command_reply,
const char *cmd, const Properties *cmd_args) const char *cmd, const Properties *cmd_args)
{ {
DBUG_ENTER("ndb_mgm_call");
DBUG_PRINT("enter",("handle->socket: %d, cmd: %s",
handle->socket, cmd));
SocketOutputStream out(handle->socket); SocketOutputStream out(handle->socket);
SocketInputStream in(handle->socket, handle->read_timeout); SocketInputStream in(handle->socket, handle->read_timeout);
...@@ -310,6 +321,8 @@ ndb_mgm_call(NdbMgmHandle handle, const ParserRow<ParserDummy> *command_reply, ...@@ -310,6 +321,8 @@ ndb_mgm_call(NdbMgmHandle handle, const ParserRow<ParserDummy> *command_reply,
/** /**
* Print some info about why the parser returns NULL * Print some info about why the parser returns NULL
*/ */
DBUG_PRINT("info",("ctx.status: %d, ctx.m_currentToken: %s",
ctx.m_status, ctx.m_currentToken));
//ndbout << " status=" << ctx.m_status << ", curr=" //ndbout << " status=" << ctx.m_status << ", curr="
//<< ctx.m_currentToken << endl; //<< ctx.m_currentToken << endl;
} }
...@@ -321,9 +334,9 @@ ndb_mgm_call(NdbMgmHandle handle, const ParserRow<ParserDummy> *command_reply, ...@@ -321,9 +334,9 @@ ndb_mgm_call(NdbMgmHandle handle, const ParserRow<ParserDummy> *command_reply,
p->print(handle->logfile, "IN: "); p->print(handle->logfile, "IN: ");
} }
#endif #endif
return p; DBUG_RETURN(p);
#else #else
return parser.parse(ctx, session); DBUG_RETURN(parser.parse(ctx, session));
#endif #endif
} }
......
...@@ -455,11 +455,13 @@ static int do_event_thread; ...@@ -455,11 +455,13 @@ static int do_event_thread;
static void* static void*
event_thread_run(void* m) event_thread_run(void* m)
{ {
DBUG_ENTER("event_thread_run");
NdbMgmHandle handle= *(NdbMgmHandle*)m; NdbMgmHandle handle= *(NdbMgmHandle*)m;
int filter[] = { 15, NDB_MGM_EVENT_CATEGORY_BACKUP, 0 }; int filter[] = { 15, NDB_MGM_EVENT_CATEGORY_BACKUP, 0 };
int fd = ndb_mgm_listen_event(handle, filter); int fd = ndb_mgm_listen_event(handle, filter);
if (fd > 0) if (fd != NDB_INVALID_SOCKET)
{ {
do_event_thread= 1; do_event_thread= 1;
char *tmp= 0; char *tmp= 0;
...@@ -468,20 +470,26 @@ event_thread_run(void* m) ...@@ -468,20 +470,26 @@ event_thread_run(void* m)
do { do {
if (tmp == 0) NdbSleep_MilliSleep(10); if (tmp == 0) NdbSleep_MilliSleep(10);
if((tmp = in.gets(buf, 1024))) if((tmp = in.gets(buf, 1024)))
ndbout << tmp; {
const char ping_token[]= "<PING>";
if (memcmp(ping_token,tmp,sizeof(ping_token)-1))
ndbout << tmp;
}
} while(do_event_thread); } while(do_event_thread);
NDB_CLOSE_SOCKET(fd);
} }
else else
{ {
do_event_thread= -1; do_event_thread= -1;
} }
return NULL; DBUG_RETURN(NULL);
} }
bool bool
CommandInterpreter::connect() CommandInterpreter::connect()
{ {
DBUG_ENTER("CommandInterpreter::connect");
if(!m_connected) if(!m_connected)
{ {
if(!ndb_mgm_connect(m_mgmsrv, try_reconnect-1, 5, 1)) if(!ndb_mgm_connect(m_mgmsrv, try_reconnect-1, 5, 1))
...@@ -512,8 +520,19 @@ CommandInterpreter::connect() ...@@ -512,8 +520,19 @@ CommandInterpreter::connect()
do_event_thread == 0 || do_event_thread == 0 ||
do_event_thread == -1) do_event_thread == -1)
{ {
printf("Warning, event thread startup failed, degraded printouts as result\n"); DBUG_PRINT("info",("Warning, event thread startup failed, "
"degraded printouts as result, errno=%d",
errno));
printf("Warning, event thread startup failed, "
"degraded printouts as result, errno=%d\n", errno);
do_event_thread= 0; do_event_thread= 0;
if (m_event_thread)
{
void *res;
NdbThread_WaitFor(m_event_thread, &res);
NdbThread_Destroy(&m_event_thread);
}
ndb_mgm_disconnect(m_mgmsrv2);
} }
} }
else else
...@@ -521,6 +540,8 @@ CommandInterpreter::connect() ...@@ -521,6 +540,8 @@ CommandInterpreter::connect()
printf("Warning, event connect failed, degraded printouts as result\n"); printf("Warning, event connect failed, degraded printouts as result\n");
} }
m_connected= true; m_connected= true;
DBUG_PRINT("info",("Connected to Management Server at: %s:%d",
host,port));
if (m_verbose) if (m_verbose)
{ {
printf("Connected to Management Server at: %s:%d\n", printf("Connected to Management Server at: %s:%d\n",
...@@ -528,12 +549,13 @@ CommandInterpreter::connect() ...@@ -528,12 +549,13 @@ CommandInterpreter::connect()
} }
} }
} }
return m_connected; DBUG_RETURN(m_connected);
} }
bool bool
CommandInterpreter::disconnect() CommandInterpreter::disconnect()
{ {
DBUG_ENTER("CommandInterpreter::disconnect");
if (m_event_thread) { if (m_event_thread) {
void *res; void *res;
do_event_thread= 0; do_event_thread= 0;
...@@ -550,7 +572,7 @@ CommandInterpreter::disconnect() ...@@ -550,7 +572,7 @@ CommandInterpreter::disconnect()
} }
m_connected= false; m_connected= false;
} }
return true; DBUG_RETURN(true);
} }
//***************************************************************************** //*****************************************************************************
......
...@@ -44,7 +44,9 @@ static Ndb_mgmclient* com; ...@@ -44,7 +44,9 @@ static Ndb_mgmclient* com;
extern "C" extern "C"
void void
handler(int sig){ handler(int sig)
{
DBUG_ENTER("handler");
switch(sig){ switch(sig){
case SIGPIPE: case SIGPIPE:
/** /**
...@@ -54,6 +56,7 @@ handler(int sig){ ...@@ -54,6 +56,7 @@ handler(int sig){
com->disconnect(); com->disconnect();
break; break;
} }
DBUG_VOID_RETURN;
} }
NDB_STD_OPTS_VARS; NDB_STD_OPTS_VARS;
...@@ -166,7 +169,8 @@ int main(int argc, char** argv){ ...@@ -166,7 +169,8 @@ int main(int argc, char** argv){
com->execute(opt_execute_str,_try_reconnect, &ret); com->execute(opt_execute_str,_try_reconnect, &ret);
} }
delete com; delete com;
ndb_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
return ret; return ret;
} }
...@@ -571,10 +571,11 @@ MgmtSrvr::check_start() ...@@ -571,10 +571,11 @@ MgmtSrvr::check_start()
bool bool
MgmtSrvr::start(BaseString &error_string) MgmtSrvr::start(BaseString &error_string)
{ {
DBUG_ENTER("MgmtSrvr::start");
if (_props == NULL) { if (_props == NULL) {
if (!check_start()) { if (!check_start()) {
error_string.append("MgmtSrvr.cpp: check_start() failed."); error_string.append("MgmtSrvr.cpp: check_start() failed.");
return false; DBUG_RETURN(false);
} }
} }
theFacade= TransporterFacade::theFacadeInstance= new TransporterFacade(); theFacade= TransporterFacade::theFacadeInstance= new TransporterFacade();
...@@ -582,12 +583,12 @@ MgmtSrvr::start(BaseString &error_string) ...@@ -582,12 +583,12 @@ MgmtSrvr::start(BaseString &error_string)
if(theFacade == 0) { if(theFacade == 0) {
DEBUG("MgmtSrvr.cpp: theFacade is NULL."); DEBUG("MgmtSrvr.cpp: theFacade is NULL.");
error_string.append("MgmtSrvr.cpp: theFacade is NULL."); error_string.append("MgmtSrvr.cpp: theFacade is NULL.");
return false; DBUG_RETURN(false);
} }
if ( theFacade->start_instance if ( theFacade->start_instance
(_ownNodeId, (ndb_mgm_configuration*)_config->m_configValues) < 0) { (_ownNodeId, (ndb_mgm_configuration*)_config->m_configValues) < 0) {
DEBUG("MgmtSrvr.cpp: TransporterFacade::start_instance < 0."); DEBUG("MgmtSrvr.cpp: TransporterFacade::start_instance < 0.");
return false; DBUG_RETURN(false);
} }
MGM_REQUIRE(_blockNumber == 1); MGM_REQUIRE(_blockNumber == 1);
...@@ -603,7 +604,7 @@ MgmtSrvr::start(BaseString &error_string) ...@@ -603,7 +604,7 @@ MgmtSrvr::start(BaseString &error_string)
error_string.append("MgmtSrvr.cpp: _blockNumber is -1."); error_string.append("MgmtSrvr.cpp: _blockNumber is -1.");
theFacade->stop_instance(); theFacade->stop_instance();
theFacade = 0; theFacade = 0;
return false; DBUG_RETURN(false);
} }
_ownReference = numberToRef(_blockNumber, _ownNodeId); _ownReference = numberToRef(_blockNumber, _ownNodeId);
...@@ -625,7 +626,7 @@ MgmtSrvr::start(BaseString &error_string) ...@@ -625,7 +626,7 @@ MgmtSrvr::start(BaseString &error_string)
"MgmtSrvr_Service", "MgmtSrvr_Service",
NDB_THREAD_PRIO_LOW); NDB_THREAD_PRIO_LOW);
return true; DBUG_RETURN(true);
} }
...@@ -639,6 +640,7 @@ MgmtSrvr::~MgmtSrvr() ...@@ -639,6 +640,7 @@ MgmtSrvr::~MgmtSrvr()
if(theFacade != 0){ if(theFacade != 0){
theFacade->stop_instance(); theFacade->stop_instance();
delete theFacade;
theFacade = 0; theFacade = 0;
} }
...@@ -2124,6 +2126,24 @@ MgmtSrvr::getNodeType(NodeId nodeId) const ...@@ -2124,6 +2126,24 @@ MgmtSrvr::getNodeType(NodeId nodeId) const
return nodeTypes[nodeId]; return nodeTypes[nodeId];
} }
const char *MgmtSrvr::get_connect_address(Uint32 node_id)
{
if (m_connect_address[node_id].s_addr == 0 &&
theFacade && theFacade->theTransporterRegistry &&
theFacade->theClusterMgr &&
getNodeType(node_id) == NDB_MGM_NODE_TYPE_NDB)
{
const ClusterMgr::Node &node=
theFacade->theClusterMgr->getNodeInfo(node_id);
if (node.connected)
{
m_connect_address[node_id]=
theFacade->theTransporterRegistry->get_connect_address(node_id);
}
}
return inet_ntoa(m_connect_address[node_id]);
}
void void
MgmtSrvr::get_connected_nodes(NodeBitmask &connected_nodes) const MgmtSrvr::get_connected_nodes(NodeBitmask &connected_nodes) const
{ {
...@@ -2583,19 +2603,6 @@ MgmtSrvr::repCommand(Uint32* repReqId, Uint32 request, bool waitCompleted) ...@@ -2583,19 +2603,6 @@ MgmtSrvr::repCommand(Uint32* repReqId, Uint32 request, bool waitCompleted)
} }
/*****************************************************************************
* Area 51 ???
*****************************************************************************/
MgmtSrvr::Area51
MgmtSrvr::getStuff()
{
Area51 ret;
ret.theFacade = theFacade;
ret.theRegistry = theFacade->theTransporterRegistry;
return ret;
}
NodeId NodeId
MgmtSrvr::getPrimaryNode() const { MgmtSrvr::getPrimaryNode() const {
#if 0 #if 0
......
...@@ -60,6 +60,7 @@ public: ...@@ -60,6 +60,7 @@ public:
} }
void add_listener(const Event_listener&); void add_listener(const Event_listener&);
void check_listeners();
void update_max_log_level(const LogLevel&); void update_max_log_level(const LogLevel&);
void update_log_level(const LogLevel&); void update_log_level(const LogLevel&);
...@@ -508,7 +509,7 @@ public: ...@@ -508,7 +509,7 @@ public:
int setDbParameter(int node, int parameter, const char * value, BaseString&); int setDbParameter(int node, int parameter, const char * value, BaseString&);
const char *get_connect_address(Uint32 node_id) { return inet_ntoa(m_connect_address[node_id]); } const char *get_connect_address(Uint32 node_id);
void get_connected_nodes(NodeBitmask &connected_nodes) const; void get_connected_nodes(NodeBitmask &connected_nodes) const;
SocketServer *get_socket_server() { return m_socket_server; } SocketServer *get_socket_server() { return m_socket_server; }
...@@ -764,16 +765,6 @@ private: ...@@ -764,16 +765,6 @@ private:
int send(class NdbApiSignal* signal, Uint32 node, Uint32 node_type); int send(class NdbApiSignal* signal, Uint32 node, Uint32 node_type);
ConfigRetriever *m_config_retriever; ConfigRetriever *m_config_retriever;
public:
/**
* This method does not exist
*/
struct Area51 {
class TransporterFacade * theFacade;
class TransporterRegistry * theRegistry;
};
Area51 getStuff();
}; };
inline inline
......
...@@ -253,15 +253,19 @@ ParserRow<MgmApiSession> commands[] = { ...@@ -253,15 +253,19 @@ ParserRow<MgmApiSession> commands[] = {
}; };
MgmApiSession::MgmApiSession(class MgmtSrvr & mgm, NDB_SOCKET_TYPE sock) MgmApiSession::MgmApiSession(class MgmtSrvr & mgm, NDB_SOCKET_TYPE sock)
: SocketServer::Session(sock), m_mgmsrv(mgm) { : SocketServer::Session(sock), m_mgmsrv(mgm)
{
DBUG_ENTER("MgmApiSession::MgmApiSession");
m_input = new SocketInputStream(sock); m_input = new SocketInputStream(sock);
m_output = new SocketOutputStream(sock); m_output = new SocketOutputStream(sock);
m_parser = new Parser_t(commands, *m_input, true, true, true); m_parser = new Parser_t(commands, *m_input, true, true, true);
m_allocated_resources= new MgmtSrvr::Allocated_resources(m_mgmsrv); m_allocated_resources= new MgmtSrvr::Allocated_resources(m_mgmsrv);
DBUG_VOID_RETURN;
} }
MgmApiSession::~MgmApiSession() MgmApiSession::~MgmApiSession()
{ {
DBUG_ENTER("MgmApiSession::~MgmApiSession");
if (m_input) if (m_input)
delete m_input; delete m_input;
if (m_output) if (m_output)
...@@ -270,10 +274,19 @@ MgmApiSession::~MgmApiSession() ...@@ -270,10 +274,19 @@ MgmApiSession::~MgmApiSession()
delete m_parser; delete m_parser;
if (m_allocated_resources) if (m_allocated_resources)
delete m_allocated_resources; delete m_allocated_resources;
if(m_socket != NDB_INVALID_SOCKET)
{
NDB_CLOSE_SOCKET(m_socket);
m_socket= NDB_INVALID_SOCKET;
}
DBUG_VOID_RETURN;
} }
void void
MgmApiSession::runSession() { MgmApiSession::runSession()
{
DBUG_ENTER("MgmApiSession::runSession");
Parser_t::Context ctx; Parser_t::Context ctx;
while(!m_stop) { while(!m_stop) {
m_parser->run(ctx, *this); m_parser->run(ctx, *this);
...@@ -301,8 +314,13 @@ MgmApiSession::runSession() { ...@@ -301,8 +314,13 @@ MgmApiSession::runSession() {
break; break;
} }
} }
if(m_socket >= 0) if(m_socket != NDB_INVALID_SOCKET)
{
NDB_CLOSE_SOCKET(m_socket); NDB_CLOSE_SOCKET(m_socket);
m_socket= NDB_INVALID_SOCKET;
}
DBUG_VOID_RETURN;
} }
#ifdef MGM_GET_CONFIG_BACKWARDS_COMPAT #ifdef MGM_GET_CONFIG_BACKWARDS_COMPAT
...@@ -1236,7 +1254,7 @@ Ndb_mgmd_event_service::log(int eventType, const Uint32* theData, NodeId nodeId) ...@@ -1236,7 +1254,7 @@ Ndb_mgmd_event_service::log(int eventType, const Uint32* theData, NodeId nodeId)
Uint32 threshold; Uint32 threshold;
LogLevel::EventCategory cat; LogLevel::EventCategory cat;
Logger::LoggerLevel severity; Logger::LoggerLevel severity;
int i; int i, n;
DBUG_ENTER("Ndb_mgmd_event_service::log"); DBUG_ENTER("Ndb_mgmd_event_service::log");
DBUG_PRINT("enter",("eventType=%d, nodeid=%d", eventType, nodeId)); DBUG_PRINT("enter",("eventType=%d, nodeid=%d", eventType, nodeId));
...@@ -1248,28 +1266,30 @@ Ndb_mgmd_event_service::log(int eventType, const Uint32* theData, NodeId nodeId) ...@@ -1248,28 +1266,30 @@ Ndb_mgmd_event_service::log(int eventType, const Uint32* theData, NodeId nodeId)
Vector<NDB_SOCKET_TYPE> copy; Vector<NDB_SOCKET_TYPE> copy;
m_clients.lock(); m_clients.lock();
for(i = m_clients.size() - 1; i >= 0; i--){ for(i = m_clients.size() - 1; i >= 0; i--)
if(threshold <= m_clients[i].m_logLevel.getLogLevel(cat)){ {
if(m_clients[i].m_socket != NDB_INVALID_SOCKET && if(threshold <= m_clients[i].m_logLevel.getLogLevel(cat))
println_socket(m_clients[i].m_socket, {
MAX_WRITE_TIMEOUT, m_text) == -1){ int fd= m_clients[i].m_socket;
copy.push_back(m_clients[i].m_socket); if(fd != NDB_INVALID_SOCKET &&
println_socket(fd, MAX_WRITE_TIMEOUT, m_text) == -1)
{
copy.push_back(fd);
m_clients.erase(i, false); m_clients.erase(i, false);
} }
} }
} }
m_clients.unlock(); m_clients.unlock();
for(i = 0; (unsigned)i < copy.size(); i++){ if ((n= (int)copy.size()))
NDB_CLOSE_SOCKET(copy[i]); {
} for(i= 0; i < n; i++)
NDB_CLOSE_SOCKET(copy[i]);
if(copy.size()){
LogLevel tmp; tmp.clear(); LogLevel tmp; tmp.clear();
m_clients.lock(); m_clients.lock();
for(i = 0; (unsigned)i < m_clients.size(); i++){ for(i= m_clients.size() - 1; i >= 0; i--)
tmp.set_max(m_clients[i].m_logLevel); tmp.set_max(m_clients[i].m_logLevel);
}
m_clients.unlock(); m_clients.unlock();
update_log_level(tmp); update_log_level(tmp);
} }
...@@ -1297,9 +1317,48 @@ Ndb_mgmd_event_service::update_log_level(const LogLevel &tmp) ...@@ -1297,9 +1317,48 @@ Ndb_mgmd_event_service::update_log_level(const LogLevel &tmp)
} }
void void
Ndb_mgmd_event_service::add_listener(const Event_listener& client){ Ndb_mgmd_event_service::check_listeners()
{
int i, n= 0;
DBUG_ENTER("Ndb_mgmd_event_service::check_listeners");
m_clients.lock();
for(i= m_clients.size() - 1; i >= 0; i--)
{
int fd= m_clients[i].m_socket;
DBUG_PRINT("info",("%d %d",i,fd));
char buf[1];
buf[0]=0;
if (fd != NDB_INVALID_SOCKET &&
println_socket(fd,MAX_WRITE_TIMEOUT,"<PING>") == -1)
{
NDB_CLOSE_SOCKET(fd);
m_clients.erase(i, false);
n=1;
}
}
if (n)
{
LogLevel tmp; tmp.clear();
for(i= m_clients.size() - 1; i >= 0; i--)
tmp.set_max(m_clients[i].m_logLevel);
update_log_level(tmp);
}
m_clients.unlock();
DBUG_VOID_RETURN;
}
void
Ndb_mgmd_event_service::add_listener(const Event_listener& client)
{
DBUG_ENTER("Ndb_mgmd_event_service::add_listener");
DBUG_PRINT("enter",("client.m_socket: %d", client.m_socket));
check_listeners();
m_clients.push_back(client); m_clients.push_back(client);
update_max_log_level(client.m_logLevel); update_max_log_level(client.m_logLevel);
DBUG_VOID_RETURN;
} }
void void
......
...@@ -53,16 +53,16 @@ const char progname[] = "mgmtsrvr"; ...@@ -53,16 +53,16 @@ const char progname[] = "mgmtsrvr";
* @struct MgmGlobals * @struct MgmGlobals
* @brief Global Variables used in the management server * @brief Global Variables used in the management server
******************************************************************************/ ******************************************************************************/
/** Command line arguments */
static int opt_daemon; // NOT bool, bool need not be int
static int opt_non_interactive;
static int opt_interactive;
static const char * opt_config_filename= 0;
struct MgmGlobals { struct MgmGlobals {
MgmGlobals(); MgmGlobals();
~MgmGlobals(); ~MgmGlobals();
/** Command line arguments */
int daemon; // NOT bool, bool need not be int
int non_interactive;
int interactive;
const char * config_filename;
/** Stuff found in environment or in local config */ /** Stuff found in environment or in local config */
NodeId localNodeId; NodeId localNodeId;
bool use_specific_ip; bool use_specific_ip;
...@@ -77,7 +77,7 @@ struct MgmGlobals { ...@@ -77,7 +77,7 @@ struct MgmGlobals {
}; };
int g_no_nodeid_checks= 0; int g_no_nodeid_checks= 0;
static MgmGlobals glob; static MgmGlobals *glob= 0;
/****************************************************************************** /******************************************************************************
* Function prototypes * Function prototypes
...@@ -108,14 +108,14 @@ static struct my_option my_long_options[] = ...@@ -108,14 +108,14 @@ static struct my_option my_long_options[] =
{ {
NDB_STD_OPTS("ndb_mgmd"), NDB_STD_OPTS("ndb_mgmd"),
{ "config-file", 'f', "Specify cluster configuration file", { "config-file", 'f', "Specify cluster configuration file",
(gptr*) &glob.config_filename, (gptr*) &glob.config_filename, 0, (gptr*) &opt_config_filename, (gptr*) &opt_config_filename, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
{ "daemon", 'd', "Run ndb_mgmd in daemon mode (default)", { "daemon", 'd', "Run ndb_mgmd in daemon mode (default)",
(gptr*) &glob.daemon, (gptr*) &glob.daemon, 0, (gptr*) &opt_daemon, (gptr*) &opt_daemon, 0,
GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0 }, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0 },
{ "interactive", OPT_INTERACTIVE, { "interactive", OPT_INTERACTIVE,
"Run interactive. Not supported but provided for testing purposes", "Run interactive. Not supported but provided for testing purposes",
(gptr*) &glob.interactive, (gptr*) &glob.interactive, 0, (gptr*) &opt_interactive, (gptr*) &opt_interactive, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
{ "no-nodeid-checks", OPT_NO_NODEID_CHECKS, { "no-nodeid-checks", OPT_NO_NODEID_CHECKS,
"Do not provide any node id checks", "Do not provide any node id checks",
...@@ -123,13 +123,13 @@ static struct my_option my_long_options[] = ...@@ -123,13 +123,13 @@ static struct my_option my_long_options[] =
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
{ "nodaemon", OPT_NO_DAEMON, { "nodaemon", OPT_NO_DAEMON,
"Don't run as daemon, but don't read from stdin", "Don't run as daemon, but don't read from stdin",
(gptr*) &glob.non_interactive, (gptr*) &glob.non_interactive, 0, (gptr*) &opt_non_interactive, (gptr*) &opt_non_interactive, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
#if NDB_VERSION_MAJOR <= 4 #if NDB_VERSION_MAJOR <= 4
{ "config-file", 'c', { "config-file", 'c',
"-c provided for backwards compatability, will be removed in 5.0." "-c provided for backwards compatability, will be removed in 5.0."
" Use -f instead", " Use -f instead",
(gptr*) &glob.config_filename, (gptr*) &glob.config_filename, 0, (gptr*) &opt_config_filename, (gptr*) &opt_config_filename, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
#endif #endif
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
...@@ -167,6 +167,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), ...@@ -167,6 +167,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
NDB_INIT(argv[0]); NDB_INIT(argv[0]);
glob= new MgmGlobals;
/** /**
* OSE specific. Enable shared ownership of file system resources. * OSE specific. Enable shared ownership of file system resources.
...@@ -186,40 +187,40 @@ int main(int argc, char** argv) ...@@ -186,40 +187,40 @@ int main(int argc, char** argv)
if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option))) if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
exit(ho_error); exit(ho_error);
if (glob.interactive || if (opt_interactive ||
glob.non_interactive) { opt_non_interactive) {
glob.daemon= 0; opt_daemon= 0;
} }
glob.socketServer = new SocketServer(); glob->socketServer = new SocketServer();
MgmApiService * mapi = new MgmApiService(); MgmApiService * mapi = new MgmApiService();
glob.mgmObject = new MgmtSrvr(glob.socketServer, glob->mgmObject = new MgmtSrvr(glob->socketServer,
glob.config_filename, opt_config_filename,
opt_connect_str); opt_connect_str);
if (glob.mgmObject->init()) if (glob->mgmObject->init())
goto error_end; goto error_end;
my_setwd(NdbConfig_get_path(0), MYF(0)); my_setwd(NdbConfig_get_path(0), MYF(0));
glob.localNodeId= glob.mgmObject->getOwnNodeId(); glob->localNodeId= glob->mgmObject->getOwnNodeId();
if (glob.localNodeId == 0) { if (glob->localNodeId == 0) {
goto error_end; goto error_end;
} }
glob.port= glob.mgmObject->getPort(); glob->port= glob->mgmObject->getPort();
if (glob.port == 0) if (glob->port == 0)
goto error_end; goto error_end;
glob.interface_name = 0; glob->interface_name = 0;
glob.use_specific_ip = false; glob->use_specific_ip = false;
if(!glob.use_specific_ip){ if(!glob->use_specific_ip){
int count= 5; // no of retries for tryBind int count= 5; // no of retries for tryBind
while(!glob.socketServer->tryBind(glob.port, glob.interface_name)){ while(!glob->socketServer->tryBind(glob->port, glob->interface_name)){
if (--count > 0) { if (--count > 0) {
NdbSleep_MilliSleep(1000); NdbSleep_MilliSleep(1000);
continue; continue;
...@@ -228,33 +229,33 @@ int main(int argc, char** argv) ...@@ -228,33 +229,33 @@ int main(int argc, char** argv)
"Please check if the port is already used,\n" "Please check if the port is already used,\n"
"(perhaps a ndb_mgmd is already running),\n" "(perhaps a ndb_mgmd is already running),\n"
"and if you are executing on the correct computer", "and if you are executing on the correct computer",
(glob.interface_name ? glob.interface_name : "*"), glob.port); (glob->interface_name ? glob->interface_name : "*"), glob->port);
goto error_end; goto error_end;
} }
free(glob.interface_name); free(glob->interface_name);
glob.interface_name = 0; glob->interface_name = 0;
} }
if(!glob.socketServer->setup(mapi, glob.port, glob.interface_name)){ if(!glob->socketServer->setup(mapi, glob->port, glob->interface_name)){
ndbout_c("Unable to setup management port: %d!\n" ndbout_c("Unable to setup management port: %d!\n"
"Please check if the port is already used,\n" "Please check if the port is already used,\n"
"(perhaps a ndb_mgmd is already running),\n" "(perhaps a ndb_mgmd is already running),\n"
"and if you are executing on the correct computer", "and if you are executing on the correct computer",
glob.port); glob->port);
delete mapi; delete mapi;
goto error_end; goto error_end;
} }
if(!glob.mgmObject->check_start()){ if(!glob->mgmObject->check_start()){
ndbout_c("Unable to check start management server."); ndbout_c("Unable to check start management server.");
ndbout_c("Probably caused by illegal initial configuration file."); ndbout_c("Probably caused by illegal initial configuration file.");
goto error_end; goto error_end;
} }
if (glob.daemon) { if (opt_daemon) {
// Become a daemon // Become a daemon
char *lockfile= NdbConfig_PidFileName(glob.localNodeId); char *lockfile= NdbConfig_PidFileName(glob->localNodeId);
char *logfile= NdbConfig_StdoutFileName(glob.localNodeId); char *logfile= NdbConfig_StdoutFileName(glob->localNodeId);
NdbAutoPtr<char> tmp_aptr1(lockfile), tmp_aptr2(logfile); NdbAutoPtr<char> tmp_aptr1(lockfile), tmp_aptr2(logfile);
if (NdbDaemon_Make(lockfile, logfile, 0) == -1) { if (NdbDaemon_Make(lockfile, logfile, 0) == -1) {
...@@ -268,7 +269,7 @@ int main(int argc, char** argv) ...@@ -268,7 +269,7 @@ int main(int argc, char** argv)
#endif #endif
{ {
BaseString error_string; BaseString error_string;
if(!glob.mgmObject->start(error_string)){ if(!glob->mgmObject->start(error_string)){
ndbout_c("Unable to start management server."); ndbout_c("Unable to start management server.");
ndbout_c("Probably caused by illegal initial configuration file."); ndbout_c("Probably caused by illegal initial configuration file.");
ndbout_c(error_string.c_str()); ndbout_c(error_string.c_str());
...@@ -276,8 +277,8 @@ int main(int argc, char** argv) ...@@ -276,8 +277,8 @@ int main(int argc, char** argv)
} }
} }
//glob.mgmObject->saveConfig(); //glob->mgmObject->saveConfig();
mapi->setMgm(glob.mgmObject); mapi->setMgm(glob->mgmObject);
char msg[256]; char msg[256];
BaseString::snprintf(msg, sizeof(msg), BaseString::snprintf(msg, sizeof(msg),
...@@ -286,16 +287,16 @@ int main(int argc, char** argv) ...@@ -286,16 +287,16 @@ int main(int argc, char** argv)
g_eventLogger.info(msg); g_eventLogger.info(msg);
BaseString::snprintf(msg, 256, "Id: %d, Command port: %d", BaseString::snprintf(msg, 256, "Id: %d, Command port: %d",
glob.localNodeId, glob.port); glob->localNodeId, glob->port);
ndbout_c(msg); ndbout_c(msg);
g_eventLogger.info(msg); g_eventLogger.info(msg);
g_StopServer = false; g_StopServer = false;
glob.socketServer->startServer(); glob->socketServer->startServer();
#if ! defined NDB_OSE && ! defined NDB_SOFTOSE #if ! defined NDB_OSE && ! defined NDB_SOFTOSE
if(glob.interactive) { if(opt_interactive) {
CommandInterpreter com(* glob.mgmObject); CommandInterpreter com(* glob->mgmObject);
while(com.readAndExecute()); while(com.readAndExecute());
} else } else
#endif #endif
...@@ -305,22 +306,22 @@ int main(int argc, char** argv) ...@@ -305,22 +306,22 @@ int main(int argc, char** argv)
} }
g_eventLogger.info("Shutting down server..."); g_eventLogger.info("Shutting down server...");
glob.socketServer->stopServer(); glob->socketServer->stopServer();
glob.socketServer->stopSessions(); glob->socketServer->stopSessions(true);
g_eventLogger.info("Shutdown complete"); g_eventLogger.info("Shutdown complete");
delete glob;
ndb_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
return 0; return 0;
error_end: error_end:
delete glob;
ndb_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
return 1; return 1;
} }
MgmGlobals::MgmGlobals(){ MgmGlobals::MgmGlobals(){
// Default values // Default values
port = 0; port = 0;
config_filename = NULL;
interface_name = 0; interface_name = 0;
daemon = 1;
non_interactive = 0;
interactive = 0;
socketServer = 0; socketServer = 0;
mgmObject = 0; mgmObject = 0;
} }
......
...@@ -64,16 +64,21 @@ ClusterMgr::ClusterMgr(TransporterFacade & _facade): ...@@ -64,16 +64,21 @@ ClusterMgr::ClusterMgr(TransporterFacade & _facade):
theStop(0), theStop(0),
theFacade(_facade) theFacade(_facade)
{ {
DBUG_ENTER("ClusterMgr::ClusterMgr");
ndbSetOwnVersion(); ndbSetOwnVersion();
clusterMgrThreadMutex = NdbMutex_Create(); clusterMgrThreadMutex = NdbMutex_Create();
noOfAliveNodes= 0; noOfAliveNodes= 0;
noOfConnectedNodes= 0; noOfConnectedNodes= 0;
theClusterMgrThread= 0; theClusterMgrThread= 0;
DBUG_VOID_RETURN;
} }
ClusterMgr::~ClusterMgr(){ ClusterMgr::~ClusterMgr()
{
DBUG_ENTER("ClusterMgr::~ClusterMgr");
doStop(); doStop();
NdbMutex_Destroy(clusterMgrThreadMutex); NdbMutex_Destroy(clusterMgrThreadMutex);
DBUG_VOID_RETURN;
} }
void void
...@@ -152,7 +157,6 @@ ClusterMgr::doStop( ){ ...@@ -152,7 +157,6 @@ ClusterMgr::doStop( ){
if (theClusterMgrThread) { if (theClusterMgrThread) {
NdbThread_WaitFor(theClusterMgrThread, &status); NdbThread_WaitFor(theClusterMgrThread, &status);
NdbThread_Destroy(&theClusterMgrThread); NdbThread_Destroy(&theClusterMgrThread);
theClusterMgrThread= 0;
} }
NdbMutex_Unlock(clusterMgrThreadMutex); NdbMutex_Unlock(clusterMgrThreadMutex);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
...@@ -468,6 +472,8 @@ ClusterMgr::reportNodeFailed(NodeId nodeId){ ...@@ -468,6 +472,8 @@ ClusterMgr::reportNodeFailed(NodeId nodeId){
ArbitMgr::ArbitMgr(TransporterFacade & _fac) ArbitMgr::ArbitMgr(TransporterFacade & _fac)
: theFacade(_fac) : theFacade(_fac)
{ {
DBUG_ENTER("ArbitMgr::ArbitMgr");
theThreadMutex = NdbMutex_Create(); theThreadMutex = NdbMutex_Create();
theInputCond = NdbCondition_Create(); theInputCond = NdbCondition_Create();
theInputMutex = NdbMutex_Create(); theInputMutex = NdbMutex_Create();
...@@ -485,13 +491,17 @@ ArbitMgr::ArbitMgr(TransporterFacade & _fac) ...@@ -485,13 +491,17 @@ ArbitMgr::ArbitMgr(TransporterFacade & _fac)
memset(&theChooseReq1, 0, sizeof(theChooseReq1)); memset(&theChooseReq1, 0, sizeof(theChooseReq1));
memset(&theChooseReq2, 0, sizeof(theChooseReq2)); memset(&theChooseReq2, 0, sizeof(theChooseReq2));
memset(&theStopOrd, 0, sizeof(theStopOrd)); memset(&theStopOrd, 0, sizeof(theStopOrd));
DBUG_VOID_RETURN;
} }
ArbitMgr::~ArbitMgr() ArbitMgr::~ArbitMgr()
{ {
DBUG_ENTER("ArbitMgr::~ArbitMgr");
NdbMutex_Destroy(theThreadMutex); NdbMutex_Destroy(theThreadMutex);
NdbCondition_Destroy(theInputCond); NdbCondition_Destroy(theInputCond);
NdbMutex_Destroy(theInputMutex); NdbMutex_Destroy(theInputMutex);
DBUG_VOID_RETURN;
} }
// Start arbitrator thread. This is kernel request. // Start arbitrator thread. This is kernel request.
...@@ -508,7 +518,7 @@ ArbitMgr::doStart(const Uint32* theData) ...@@ -508,7 +518,7 @@ ArbitMgr::doStart(const Uint32* theData)
sendSignalToThread(aSignal); sendSignalToThread(aSignal);
void* value; void* value;
NdbThread_WaitFor(theThread, &value); NdbThread_WaitFor(theThread, &value);
theThread = NULL; NdbThread_Destroy(&theThread);
theState = StateInit; theState = StateInit;
theInputFull = false; theInputFull = false;
} }
...@@ -547,7 +557,7 @@ ArbitMgr::doStop(const Uint32* theData) ...@@ -547,7 +557,7 @@ ArbitMgr::doStop(const Uint32* theData)
sendSignalToThread(aSignal); sendSignalToThread(aSignal);
void* value; void* value;
NdbThread_WaitFor(theThread, &value); NdbThread_WaitFor(theThread, &value);
theThread = NULL; NdbThread_Destroy(&theThread);
theState = StateInit; theState = StateInit;
} }
NdbMutex_Unlock(theThreadMutex); NdbMutex_Unlock(theThreadMutex);
......
...@@ -395,12 +395,10 @@ TransporterFacade::doStop(){ ...@@ -395,12 +395,10 @@ TransporterFacade::doStop(){
if (theReceiveThread) { if (theReceiveThread) {
NdbThread_WaitFor(theReceiveThread, &status); NdbThread_WaitFor(theReceiveThread, &status);
NdbThread_Destroy(&theReceiveThread); NdbThread_Destroy(&theReceiveThread);
theReceiveThread= 0;
} }
if (theSendThread) { if (theSendThread) {
NdbThread_WaitFor(theSendThread, &status); NdbThread_WaitFor(theSendThread, &status);
NdbThread_Destroy(&theSendThread); NdbThread_Destroy(&theSendThread);
theSendThread= 0;
} }
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -435,7 +433,7 @@ void TransporterFacade::threadMainSend(void) ...@@ -435,7 +433,7 @@ void TransporterFacade::threadMainSend(void)
theTransporterRegistry->stopSending(); theTransporterRegistry->stopSending();
m_socket_server.stopServer(); m_socket_server.stopServer();
m_socket_server.stopSessions(); m_socket_server.stopSessions(true);
theTransporterRegistry->stop_clients(); theTransporterRegistry->stop_clients();
} }
...@@ -477,6 +475,8 @@ TransporterFacade::TransporterFacade() : ...@@ -477,6 +475,8 @@ TransporterFacade::TransporterFacade() :
theReceiveThread(NULL), theReceiveThread(NULL),
m_fragmented_signal_id(0) m_fragmented_signal_id(0)
{ {
DBUG_ENTER("TransporterFacade::TransporterFacade");
theOwnId = 0; theOwnId = 0;
theMutexPtr = NdbMutex_Create(); theMutexPtr = NdbMutex_Create();
...@@ -493,11 +493,15 @@ TransporterFacade::TransporterFacade() : ...@@ -493,11 +493,15 @@ TransporterFacade::TransporterFacade() :
m_max_trans_id = 0; m_max_trans_id = 0;
theClusterMgr = new ClusterMgr(* this); theClusterMgr = new ClusterMgr(* this);
DBUG_VOID_RETURN;
} }
bool bool
TransporterFacade::init(Uint32 nodeId, const ndb_mgm_configuration* props) TransporterFacade::init(Uint32 nodeId, const ndb_mgm_configuration* props)
{ {
DBUG_ENTER("TransporterFacade::init");
theOwnId = nodeId; theOwnId = nodeId;
theTransporterRegistry = new TransporterRegistry(this); theTransporterRegistry = new TransporterRegistry(this);
...@@ -506,7 +510,7 @@ TransporterFacade::init(Uint32 nodeId, const ndb_mgm_configuration* props) ...@@ -506,7 +510,7 @@ TransporterFacade::init(Uint32 nodeId, const ndb_mgm_configuration* props)
* theTransporterRegistry); * theTransporterRegistry);
if(res <= 0){ if(res <= 0){
TRP_DEBUG( "configureTransporters returned 0 or less" ); TRP_DEBUG( "configureTransporters returned 0 or less" );
return false; DBUG_RETURN(false);
} }
ndb_mgm_configuration_iterator iter(* props, CFG_SECTION_NODE); ndb_mgm_configuration_iterator iter(* props, CFG_SECTION_NODE);
...@@ -524,7 +528,7 @@ TransporterFacade::init(Uint32 nodeId, const ndb_mgm_configuration* props) ...@@ -524,7 +528,7 @@ TransporterFacade::init(Uint32 nodeId, const ndb_mgm_configuration* props)
iter.first(); iter.first();
if(iter.find(CFG_NODE_ID, nodeId)){ if(iter.find(CFG_NODE_ID, nodeId)){
TRP_DEBUG( "Node info missing from config." ); TRP_DEBUG( "Node info missing from config." );
return false; DBUG_RETURN(false);
} }
Uint32 rank = 0; Uint32 rank = 0;
...@@ -553,7 +557,7 @@ TransporterFacade::init(Uint32 nodeId, const ndb_mgm_configuration* props) ...@@ -553,7 +557,7 @@ TransporterFacade::init(Uint32 nodeId, const ndb_mgm_configuration* props)
if (!theTransporterRegistry->start_service(m_socket_server)){ if (!theTransporterRegistry->start_service(m_socket_server)){
ndbout_c("Unable to start theTransporterRegistry->start_service"); ndbout_c("Unable to start theTransporterRegistry->start_service");
return false; DBUG_RETURN(false);
} }
theReceiveThread = NdbThread_Create(runReceiveResponse_C, theReceiveThread = NdbThread_Create(runReceiveResponse_C,
...@@ -573,7 +577,7 @@ TransporterFacade::init(Uint32 nodeId, const ndb_mgm_configuration* props) ...@@ -573,7 +577,7 @@ TransporterFacade::init(Uint32 nodeId, const ndb_mgm_configuration* props)
signalLogger.logOn(true, 0, SignalLoggerManager::LogInOut); signalLogger.logOn(true, 0, SignalLoggerManager::LogInOut);
#endif #endif
return true; DBUG_RETURN(true);
} }
...@@ -694,8 +698,10 @@ TransporterFacade::open(void* objRef, ...@@ -694,8 +698,10 @@ TransporterFacade::open(void* objRef,
DBUG_RETURN(r); DBUG_RETURN(r);
} }
TransporterFacade::~TransporterFacade(){ TransporterFacade::~TransporterFacade()
{
DBUG_ENTER("TransporterFacade::~TransporterFacade");
NdbMutex_Lock(theMutexPtr); NdbMutex_Lock(theMutexPtr);
delete theClusterMgr; delete theClusterMgr;
delete theArbitMgr; delete theArbitMgr;
...@@ -705,6 +711,7 @@ TransporterFacade::~TransporterFacade(){ ...@@ -705,6 +711,7 @@ TransporterFacade::~TransporterFacade(){
#ifdef API_TRACE #ifdef API_TRACE
signalLogger.setOutputStream(0); signalLogger.setOutputStream(0);
#endif #endif
DBUG_VOID_RETURN;
} }
void void
......
...@@ -251,8 +251,9 @@ main(int argc, char** argv) ...@@ -251,8 +251,9 @@ main(int argc, char** argv)
const BackupFormat::FileHeader & tmp = metaData.getFileHeader(); const BackupFormat::FileHeader & tmp = metaData.getFileHeader();
const Uint32 version = tmp.NdbVersion; const Uint32 version = tmp.NdbVersion;
char buf[NDB_VERSION_STRING_BUF_SZ];
ndbout << "Ndb version in backup files: " ndbout << "Ndb version in backup files: "
<< getVersionString(version, 0) << endl; << getVersionString(version, 0, buf, sizeof(buf)) << endl;
/** /**
* check wheater we can restore the backup (right version). * check wheater we can restore the backup (right version).
......
...@@ -306,24 +306,28 @@ static void set_param_int64(Item_param *param, uchar **pos, ulong len) ...@@ -306,24 +306,28 @@ static void set_param_int64(Item_param *param, uchar **pos, ulong len)
static void set_param_float(Item_param *param, uchar **pos, ulong len) static void set_param_float(Item_param *param, uchar **pos, ulong len)
{ {
float data;
#ifndef EMBEDDED_LIBRARY #ifndef EMBEDDED_LIBRARY
if (len < 4) if (len < 4)
return; return;
#endif
float data;
float4get(data,*pos); float4get(data,*pos);
#else
data= *(float*) *pos;
#endif
param->set_double((double) data); param->set_double((double) data);
*pos+= 4; *pos+= 4;
} }
static void set_param_double(Item_param *param, uchar **pos, ulong len) static void set_param_double(Item_param *param, uchar **pos, ulong len)
{ {
double data;
#ifndef EMBEDDED_LIBRARY #ifndef EMBEDDED_LIBRARY
if (len < 8) if (len < 8)
return; return;
#endif
double data;
float8get(data,*pos); float8get(data,*pos);
#else
data= *(double*) *pos;
#endif
param->set_double((double) data); param->set_double((double) data);
*pos+= 8; *pos+= 8;
} }
......
...@@ -437,19 +437,20 @@ then ...@@ -437,19 +437,20 @@ then
/sbin/chkconfig --add mysql /sbin/chkconfig --add mysql
fi fi
# Create a MySQL user. Do not report any problems if it already # Create a MySQL user and group. Do not report any problems if it already
# exists. This is redhat specific and should be handled more portable # exists.
useradd -M -r -d $mysql_datadir -s /bin/bash -c "MySQL server" %{mysqld_user} 2> /dev/null || true groupadd -r -c "MySQL server" %{mysqld_user} 2> /dev/null || true
useradd -M -r -d $mysql_datadir -s /bin/bash -c "MySQL server" -g %{mysqld_user} %{mysqld_user} 2> /dev/null || true
# Change permissions so that the user that will run the MySQL daemon # Change permissions so that the user that will run the MySQL daemon
# owns all database files. # owns all database files.
chown -R %{mysqld_user} $mysql_datadir chown -R %{mysqld_user}:%{mysqld_user} $mysql_datadir
# Initiate databases # Initiate databases
%{_bindir}/mysql_install_db --rpm --user=%{mysqld_user} %{_bindir}/mysql_install_db --rpm --user=%{mysqld_user}
# Change permissions again to fix any new files. # Change permissions again to fix any new files.
chown -R %{mysqld_user} $mysql_datadir chown -R %{mysqld_user}:%{mysqld_user} $mysql_datadir
# Fix permissions for the permission database so that only the user # Fix permissions for the permission database so that only the user
# can read them. # can read them.
...@@ -667,6 +668,11 @@ fi ...@@ -667,6 +668,11 @@ fi
# itself - note that they must be ordered by date (important when # itself - note that they must be ordered by date (important when
# merging BK trees) # merging BK trees)
%changelog %changelog
* Fri Jul 15 2005 Lenz Grimmer <lenz@mysql.com>
- create a "mysql" user group and assign the mysql user account to that group
in the server postinstall section. (BUG 10984)
* Tue Jun 14 2005 Lenz Grimmer <lenz@mysql.com> * Tue Jun 14 2005 Lenz Grimmer <lenz@mysql.com>
- Do not build statically on i386 by default, only when adding either "--with - Do not build statically on i386 by default, only when adding either "--with
......
...@@ -166,6 +166,14 @@ DIE_UNLESS(stmt == 0);\ ...@@ -166,6 +166,14 @@ DIE_UNLESS(stmt == 0);\
#define mytest_r(x) if (x) {myerror(NULL);DIE_UNLESS(FALSE);} #define mytest_r(x) if (x) {myerror(NULL);DIE_UNLESS(FALSE);}
/* A workaround for Sun Forte 5.6 on Solaris x86 */
static int cmp_double(double *a, double *b)
{
return *a == *b;
}
/* Print the error message */ /* Print the error message */
static void print_error(const char *msg) static void print_error(const char *msg)
...@@ -1396,7 +1404,7 @@ static void test_prepare() ...@@ -1396,7 +1404,7 @@ static void test_prepare()
DIE_UNLESS(real_data == o_real_data); DIE_UNLESS(real_data == o_real_data);
DIE_UNLESS(length[5] == 4); DIE_UNLESS(length[5] == 4);
DIE_UNLESS(double_data == o_double_data); DIE_UNLESS(cmp_double(&double_data, &o_double_data));
DIE_UNLESS(length[6] == 8); DIE_UNLESS(length[6] == 8);
DIE_UNLESS(strcmp(data, str_data) == 0); DIE_UNLESS(strcmp(data, str_data) == 0);
...@@ -9583,7 +9591,7 @@ static void test_bug3035() ...@@ -9583,7 +9591,7 @@ static void test_bug3035()
uint32 uint32_val; uint32 uint32_val;
longlong int64_val; longlong int64_val;
ulonglong uint64_val; ulonglong uint64_val;
double double_val, udouble_val; double double_val, udouble_val, double_tmp;
char longlong_as_string[22], ulonglong_as_string[22]; char longlong_as_string[22], ulonglong_as_string[22];
/* mins and maxes */ /* mins and maxes */
...@@ -9727,7 +9735,8 @@ static void test_bug3035() ...@@ -9727,7 +9735,8 @@ static void test_bug3035()
DIE_UNLESS(int64_val == int64_min); DIE_UNLESS(int64_val == int64_min);
DIE_UNLESS(uint64_val == uint64_min); DIE_UNLESS(uint64_val == uint64_min);
DIE_UNLESS(double_val == (longlong) uint64_min); DIE_UNLESS(double_val == (longlong) uint64_min);
DIE_UNLESS(udouble_val == ulonglong2double(uint64_val)); double_tmp= ulonglong2double(uint64_val);
DIE_UNLESS(cmp_double(&udouble_val, &double_tmp));
DIE_UNLESS(!strcmp(longlong_as_string, "0")); DIE_UNLESS(!strcmp(longlong_as_string, "0"));
DIE_UNLESS(!strcmp(ulonglong_as_string, "0")); DIE_UNLESS(!strcmp(ulonglong_as_string, "0"));
...@@ -9743,7 +9752,8 @@ static void test_bug3035() ...@@ -9743,7 +9752,8 @@ static void test_bug3035()
DIE_UNLESS(int64_val == int64_max); DIE_UNLESS(int64_val == int64_max);
DIE_UNLESS(uint64_val == uint64_max); DIE_UNLESS(uint64_val == uint64_max);
DIE_UNLESS(double_val == (longlong) uint64_val); DIE_UNLESS(double_val == (longlong) uint64_val);
DIE_UNLESS(udouble_val == ulonglong2double(uint64_val)); double_tmp= ulonglong2double(uint64_val);
DIE_UNLESS(cmp_double(&udouble_val, &double_tmp));
DIE_UNLESS(!strcmp(longlong_as_string, "-1")); DIE_UNLESS(!strcmp(longlong_as_string, "-1"));
DIE_UNLESS(!strcmp(ulonglong_as_string, "18446744073709551615")); DIE_UNLESS(!strcmp(ulonglong_as_string, "18446744073709551615"));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment