2903 Magnus Svensson 2009-03-04 [merge]
Merge
added:
storage/ndb/include/portlib/my_daemon.h
storage/ndb/src/common/portlib/my_daemon.cc
modified:
CMakeLists.txt
client/mysqltest.cc
mysql-test/include/ndb_setup_slave.inc
mysql-test/suite/ndb/r/ndb_config.result
mysql-test/suite/ndb/r/ndb_config2.result
mysql-test/suite/ndb/t/ndb_config.test
mysql-test/suite/ndb/t/ndb_config2.test
mysql-test/suite/rpl_ndb/r/rpl_ndb_idempotent.result
mysql-test/suite/rpl_ndb/r/rpl_ndb_multi.result
mysql-test/suite/rpl_ndb/r/rpl_ndb_sync.result
mysql-test/suite/rpl_ndb/t/rpl_ndb_idempotent.test
mysql-test/suite/rpl_ndb/t/rpl_ndb_multi.test
storage/ndb/include/logger/ConsoleLogHandler.hpp
storage/ndb/include/logger/FileLogHandler.hpp
storage/ndb/include/logger/Logger.hpp
storage/ndb/include/util/NdbOut.hpp
storage/ndb/src/common/logger/ConsoleLogHandler.cpp
storage/ndb/src/common/logger/FileLogHandler.cpp
storage/ndb/src/common/logger/Logger.cpp
storage/ndb/src/common/portlib/CMakeLists.txt
storage/ndb/src/common/portlib/Makefile.am
storage/ndb/src/common/util/NdbOut.cpp
storage/ndb/src/common/util/OutputStream.cpp
storage/ndb/src/kernel/main.cpp
storage/ndb/src/kernel/vm/Configuration.hpp
storage/ndb/src/mgmsrv/InitConfigFileParser.cpp
storage/ndb/src/mgmsrv/InitConfigFileParser.hpp
storage/ndb/src/mgmsrv/MgmtSrvr.hpp
storage/ndb/src/mgmsrv/main.cpp
storage/ndb/src/mgmsrv/testConfig.cpp
storage/ndb/test/CMakeLists.txt
storage/ndb/tools/ndb_config.cpp
win/configure.js
2902 Frazer Clement 2009-03-02 [merge]
Merge 6.3->6.4 and extend testBlobs to test HashMapPartitioning
modified:
storage/ndb/include/ndbapi/NdbBlob.hpp
storage/ndb/src/ndbapi/NdbBlob.cpp
storage/ndb/test/ndbapi/testBlobs.cpp
=== modified file 'CMakeLists.txt'
--- a/CMakeLists.txt 2009-02-11 10:27:14 +0000
+++ b/CMakeLists.txt 2009-02-26 14:52:41 +0000
@@ -17,6 +17,9 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.4.7 FAT
PROJECT(MySql)
INCLUDE(config.cmake)
+if(COMMAND cmake_policy)
+ cmake_policy(SET CMP0003 NEW)
+endif(COMMAND cmake_policy)
# This reads user configuration, generated by configure.js.
INCLUDE(win/configure.data OPTIONAL)
=== modified file 'client/mysqltest.cc'
--- a/client/mysqltest.cc 2009-02-11 11:12:08 +0000
+++ b/client/mysqltest.cc 2009-03-03 14:30:41 +0000
@@ -2619,6 +2619,9 @@ static int replace(DYNAMIC_STRING *ds_st
}
+/* where to put this declaration in the file? */
+int regex_replace(DYNAMIC_STRING *ds, char *expr);
+
/*
Execute given command.
@@ -2670,12 +2673,18 @@ void do_exec(struct st_command *command)
#ifdef __WIN__
#ifndef USE_CYGWIN
- /* Replace /dev/null with NUL */
- while(replace(&ds_cmd, "/dev/null", 9, "NUL", 3) == 0)
- ;
- /* Replace "closed stdout" with non existing output fd */
- while(replace(&ds_cmd, ">&-", 3, ">&4", 3) == 0)
- ;
+ {
+ char *replaces[]= {
+ /* Replace /dev/null with NUL */
+ "/\\/dev\\/null/NUL/",
+ /* Replace "closed stdout" with non existing output fd */
+ "/>&-/>&4/",
+ 0
+ };
+ int i= 0;
+ for(;replaces[i];i++)
+ regex_replace(&ds_cmd, replaces[i]);
+ }
#endif
#endif
@@ -8566,15 +8575,31 @@ void do_get_replace_regex(struct st_comm
command->last_argument= command->end;
}
+/* where to put these functions in the file? */
+void free_regex(struct st_replace_regex* r)
+{
+ delete_dynamic(&r->regex_arr);
+ my_free(r->even_buf,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(r->odd_buf,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(r,MYF(0));
+}
+
+/* where to put these functions in the file? */
+int regex_replace(DYNAMIC_STRING *ds, char *expr)
+{
+ struct st_replace_regex* r= init_replace_regex(expr);
+ int rv= multi_reg_replace(r, ds->str);
+ dynstr_set(ds, r->buf);
+ free_regex(r);
+ return rv;
+}
+
void free_replace_regex()
{
if (glob_replace_regex)
{
- delete_dynamic(&glob_replace_regex->regex_arr);
- my_free(glob_replace_regex->even_buf,MYF(MY_ALLOW_ZERO_PTR));
- my_free(glob_replace_regex->odd_buf,MYF(MY_ALLOW_ZERO_PTR));
- my_free(glob_replace_regex,MYF(0));
- glob_replace_regex=0;
+ free_regex(glob_replace_regex);
+ glob_replace_regex= 0;
}
}
=== modified file 'mysql-test/include/ndb_setup_slave.inc'
--- a/mysql-test/include/ndb_setup_slave.inc 2007-06-13 20:28:44 +0000
+++ b/mysql-test/include/ndb_setup_slave.inc 2009-02-09 11:40:31 +0000
@@ -15,8 +15,11 @@ SELECT @the_epoch:=MAX(epoch) FROM mysql
--connection master
--replace_result $the_epoch <the_epoch>
--replace_column 1 <the_pos>
-eval SELECT @the_pos:=Position,@the_file:=SUBSTRING_INDEX(FILE, '/', -1)
+--disable_query_log
+eval SELECT @the_pos:=Position,
+ @the_file:=SUBSTRING_INDEX(REPLACE(FILE,'\\\\','/'), '/', -1)
FROM mysql.ndb_binlog_index WHERE epoch > $the_epoch ORDER BY epoch ASC LIMIT 1;
+--enable_query_log
--let $the_pos= `SELECT @the_pos`
--let $the_file= `SELECT @the_file`
=== modified file 'mysql-test/suite/ndb/r/ndb_config.result'
--- a/mysql-test/suite/ndb/r/ndb_config.result 2009-02-16 14:55:43 +0000
+++ b/mysql-test/suite/ndb/r/ndb_config.result 2009-02-26 14:52:41 +0000
@@ -18,7 +18,7 @@ ndb_mgmd,6,localhost mysqld,1, mysqld,7,
== 9 ==
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
== 10 ==
-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
+tcp,3,4,55,3 tcp,3,5,55,3 tcp,3,6,55,3 tcp,4,5,55,4 tcp,4,6,55,4 tcp,5,6,55,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
== 11 ==
3 1 2
== 12 ==
=== modified file 'mysql-test/suite/ndb/r/ndb_config2.result'
--- a/mysql-test/suite/ndb/r/ndb_config2.result 2008-10-21 12:41:59 +0000
+++ b/mysql-test/suite/ndb/r/ndb_config2.result 2008-11-27 01:19:14 +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 tcp,1,2,55,2
+tcp,3,4,55,3 tcp,3,5,55,3 tcp,3,6,55,3 tcp,4,5,55,4 tcp,4,6,55,4 tcp,5,6,55,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 'mysql-test/suite/ndb/t/ndb_config.test'
--- a/mysql-test/suite/ndb/t/ndb_config.test 2009-02-11 10:27:14 +0000
+++ b/mysql-test/suite/ndb/t/ndb_config.test 2009-02-26 14:52:41 +0000
@@ -8,7 +8,7 @@ echo == 2 ==;
--exec $NDB_CONFIG --no-defaults --query=nodeid,host,DataMemory,IndexMemory --type=ndbd 2> /dev/null
echo == 3 ==;
---exec $NDB_CONFIG --no-defaults -r \\\n -f " " --query=nodeid,host,DataMemory,IndexMemory --type=ndbd 2> /dev/null
+--exec $NDB_CONFIG --no-defaults -r \\n -f " " --query=nodeid,host,DataMemory,IndexMemory --type=ndbd 2> /dev/null
echo == 4 ==;
--exec $NDB_CONFIG --no-defaults --query=nodeid --type=ndbd --host=localhost 2> /dev/null
@@ -28,9 +28,8 @@ echo == 8 ==;
echo == 9 ==;
--exec $NDB_CONFIG --defaults-group-suffix=.cluster2 --defaults-file=$MYSQL_TEST_DIR/std_data/ndb_config_mycnf2.cnf --query=type,nodeid,host --mycnf 2> /dev/null
-
echo == 10 ==;
---exec $NDB_CONFIG --defaults-group-suffix=.cluster2 --defaults-file=$MYSQL_TEST_DIR/std_data/ndb_config_mycnf2.cnf --ndb-shm --connections --query=type,nodeid1,nodeid2,group,nodeidserver --mycnf 2> /dev/null
+--exec $NDB_CONFIG --defaults-group-suffix=.cluster2 --defaults-file=$MYSQL_TEST_DIR/std_data/ndb_config_mycnf2.cnf --connections --query=type,nodeid1,nodeid2,group,nodeidserver --mycnf 2> /dev/null
echo == 11 ==;
--exec $NDB_CONFIG --no-defaults --query=nodeid --host=localhost --config-file=$MYSQL_TEST_DIR/std_data/ndb_config_config.ini 2> /dev/null
=== modified file 'mysql-test/suite/ndb/t/ndb_config2.test'
--- a/mysql-test/suite/ndb/t/ndb_config2.test 2008-10-13 17:45:03 +0000
+++ b/mysql-test/suite/ndb/t/ndb_config2.test 2008-11-27 01:19:14 +0000
@@ -3,4 +3,4 @@
# Following doesn't work in all configurations (if shm is not defined)
---exec $NDB_CONFIG --defaults-group-suffix=.cluster2 --defaults-file=$MYSQL_TEST_DIR/std_data/ndb_config_mycnf2.cnf --ndb-shm --connections --query=type,nodeid1,nodeid2,group,nodeidserver --mycnf 2> /dev/null
+--exec $NDB_CONFIG --defaults-group-suffix=.cluster2 --defaults-file=$MYSQL_TEST_DIR/std_data/ndb_config_mycnf2.cnf --connections --query=type,nodeid1,nodeid2,group,nodeidserver --mycnf 2> /dev/null
=== modified file 'mysql-test/suite/rpl_ndb/r/rpl_ndb_idempotent.result'
--- a/mysql-test/suite/rpl_ndb/r/rpl_ndb_idempotent.result 2009-01-08 17:44:55 +0000
+++ b/mysql-test/suite/rpl_ndb/r/rpl_ndb_idempotent.result 2009-02-09 11:40:31 +0000
@@ -15,10 +15,6 @@ SELECT @the_epoch:=MAX(epoch) FROM mysql
SELECT * FROM t1 ORDER BY c3;
c1 c2 c3
row1 will go away 1
-SELECT @the_pos:=Position,@the_file:=SUBSTRING_INDEX(FILE, '/', -1)
-FROM mysql.ndb_binlog_index WHERE epoch = <the_epoch> ;
-@the_pos:=Position @the_file:=SUBSTRING_INDEX(FILE, '/', -1)
-<the_pos> master-bin.000001
INSERT INTO t1 VALUES ("row2","will go away",2),("row3","will change",3),("row4","D",4);
DELETE FROM t1 WHERE c3 = 1;
UPDATE t1 SET c2="should go away" WHERE c3 = 2;
=== modified file 'mysql-test/suite/rpl_ndb/r/rpl_ndb_multi.result'
--- a/mysql-test/suite/rpl_ndb/r/rpl_ndb_multi.result 2009-02-03 13:35:56 +0000
+++ b/mysql-test/suite/rpl_ndb/r/rpl_ndb_multi.result 2009-02-26 14:52:41 +0000
@@ -23,9 +23,7 @@ SELECT * FROM t1 ORDER BY c3;
c1 c2 c3
row1 will go away 1
stop slave;
-SELECT @the_pos:=Position,@the_file:=SUBSTRING_INDEX(FILE, '/', -1)
-FROM mysql.ndb_binlog_index WHERE epoch = <the_epoch> ;
-@the_pos:=Position @the_file:=SUBSTRING_INDEX(FILE, '/', -1)
+@the_pos:=Position @the_file:=SUBSTRING_INDEX(REPLACE(FILE,'\\','/'), '/', -1)
107 master-bin.000001
CHANGE MASTER TO
master_port=<MASTER_PORT1>,
=== modified file 'mysql-test/suite/rpl_ndb/r/rpl_ndb_sync.result'
--- a/mysql-test/suite/rpl_ndb/r/rpl_ndb_sync.result 2009-02-11 10:27:14 +0000
+++ b/mysql-test/suite/rpl_ndb/r/rpl_ndb_sync.result 2009-02-26 14:52:41 +0000
@@ -59,9 +59,7 @@ hex(c2) hex(c3) c1
SELECT @the_epoch:=MAX(epoch) FROM mysql.ndb_apply_status;
@the_epoch:=MAX(epoch)
<the_epoch>
-SELECT @the_pos:=Position,@the_file:=SUBSTRING_INDEX(FILE, '/', -1)
-FROM mysql.ndb_binlog_index WHERE epoch > <the_epoch> ORDER BY epoch ASC LIMIT 1;
-@the_pos:=Position @the_file:=SUBSTRING_INDEX(FILE, '/', -1)
+@the_pos:=Position @the_file:=SUBSTRING_INDEX(REPLACE(FILE,'\\','/'), '/', -1)
<the_pos> master-bin.000001
CHANGE MASTER TO
master_log_file = 'master-bin.000001',
=== modified file 'mysql-test/suite/rpl_ndb/t/rpl_ndb_idempotent.test'
--- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_idempotent.test 2007-07-25 13:40:43 +0000
+++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_idempotent.test 2009-02-09 11:40:31 +0000
@@ -21,12 +21,16 @@ SELECT * FROM t1 ORDER BY c3;
# get the master binlog pos from the epoch
connection master;
---replace_result $the_epoch <the_epoch>
---replace_column 1 <the_pos>
-eval SELECT @the_pos:=Position,@the_file:=SUBSTRING_INDEX(FILE, '/', -1)
+--disable_query_log
+--disable_result_log
+eval SELECT @the_pos:=Position,
+ @the_file:=SUBSTRING_INDEX(REPLACE(FILE,'\\\\','/'), '/', -1)
FROM mysql.ndb_binlog_index WHERE epoch = $the_epoch ;
let $the_pos= `SELECT @the_pos` ;
let $the_file= `SELECT @the_file` ;
+let $the_epoch=`SELECT MAX(epoch) FROM mysql.ndb_apply_status`;
+--enable_result_log
+--enable_query_log
# insert some more values
INSERT INTO t1 VALUES ("row2","will go away",2),("row3","will change",3),("row4","D",4);
=== modified file 'mysql-test/suite/rpl_ndb/t/rpl_ndb_multi.test'
--- a/mysql-test/suite/rpl_ndb/t/rpl_ndb_multi.test 2008-11-13 19:19:00 +0000
+++ b/mysql-test/suite/rpl_ndb/t/rpl_ndb_multi.test 2009-02-26 14:52:41 +0000
@@ -32,8 +32,11 @@ stop slave;
# get the master binlog pos from the epoch, from the _other_ "master", server2
connection server2;
--replace_result $the_epoch <the_epoch>
-eval SELECT @the_pos:=Position,@the_file:=SUBSTRING_INDEX(FILE, '/', -1)
+--disable_query_log
+eval SELECT @the_pos:=Position,
+ @the_file:=SUBSTRING_INDEX(REPLACE(FILE,'\\\\','/'), '/', -1)
FROM mysql.ndb_binlog_index WHERE epoch = $the_epoch ;
+--enable_query_log
let $the_pos= `SELECT @the_pos` ;
let $the_file= `SELECT @the_file` ;
=== modified file 'storage/ndb/include/logger/ConsoleLogHandler.hpp'
--- a/storage/ndb/include/logger/ConsoleLogHandler.hpp 2008-12-10 17:55:10 +0000
+++ b/storage/ndb/include/logger/ConsoleLogHandler.hpp 2009-01-29 17:16:09 +0000
@@ -17,6 +17,7 @@
#define CONSOLELOGHANDLER_H
#include "LogHandler.hpp"
+#include <NdbOut.hpp>
/**
* Logs messages to the console/stdout.
@@ -30,7 +31,7 @@ public:
/**
* Default constructor.
*/
- ConsoleLogHandler();
+ ConsoleLogHandler(const NdbOut &out= ndbout);
/**
* Destructor.
*/
@@ -47,7 +48,8 @@ protected:
virtual void writeHeader(const char* pCategory, Logger::LoggerLevel level);
virtual void writeMessage(const char* pMsg);
virtual void writeFooter();
-
+ const NdbOut& _out;
+
private:
/** Prohibit*/
ConsoleLogHandler(const ConsoleLogHandler&);
=== modified file 'storage/ndb/include/logger/FileLogHandler.hpp'
--- a/storage/ndb/include/logger/FileLogHandler.hpp 2008-12-10 17:55:10 +0000
+++ b/storage/ndb/include/logger/FileLogHandler.hpp 2009-01-29 17:16:09 +0000
@@ -45,11 +45,6 @@ public:
virtual const char* handler_type() {return "FILE"; };
/**
- * Default constructor.
- */
- FileLogHandler();
-
- /**
* Creates a new file handler with the specified filename,
* max number of archived log files and max log size for each log.
*
@@ -58,7 +53,7 @@ public:
* @param maxFileSize the maximum log file size before archiving.
* @param maxLogEntries the maximum number of log entries before checking time to archive.
*/
- FileLogHandler(const char* aFileName,
+ FileLogHandler(const char* aFileName = "logger.log",
int maxNoFiles = MAX_NO_FILES,
long maxFileSize = MAX_FILE_SIZE,
unsigned int maxLogEntries = MAX_LOG_ENTRIES);
=== modified file 'storage/ndb/include/logger/Logger.hpp'
--- a/storage/ndb/include/logger/Logger.hpp 2008-11-06 16:52:59 +0000
+++ b/storage/ndb/include/logger/Logger.hpp 2009-01-23 12:50:40 +0000
@@ -18,6 +18,7 @@
#include <ndb_global.h>
#include <BaseString.hpp>
+#include <NdbOut.hpp>
#define MAX_LOG_MESSAGE_SIZE 1024
@@ -132,7 +133,7 @@ public:
*
* @return true if successful.
*/
- bool createConsoleHandler();
+ bool createConsoleHandler(const NdbOut &out= ndbout);
/**
* Remove the default console handler.
@@ -144,7 +145,7 @@ public:
*
* @return true if successful.
*/
- bool createFileHandler();
+ bool createFileHandler(char* filename= 0);
/**
* Remove the default file handler.
=== added file 'storage/ndb/include/portlib/my_daemon.h'
--- a/storage/ndb/include/portlib/my_daemon.h 1970-01-01 00:00:00 +0000
+++ b/storage/ndb/include/portlib/my_daemon.h 2009-02-24 11:28:08 +0000
@@ -0,0 +1,135 @@
+/* Copyright (C) 2008 Sun Microsystems
+
+ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+#ifndef MY_DAEMON_H
+#define MY_DAEMON_H
+
+#ifndef DAEMONEXPORT
+#define DAEMONEXPORT extern
+#endif
+
+C_MODE_START
+
+/*
+ all functions return 0 for success so the retval can be returned from main()
+
+ to run the daemon, you must provide a struct MY_DAEMON * to my_daemon_run().
+ the two functions in that struct are start() and stop()
+
+ int start(void*)
+ . this function should do the main work of the daemon
+ . on windows, it is run in a new thread.
+ -- the parameter to start will always be 0.
+ -- the return value of start is ignored
+
+ int stop()
+ . when called, this function must terminate the start() function
+ . usually, start() runs an event loop and setting a global variable
+ to 0 breaks the loop. stop() should set this variable to 0.
+ -- the return value is ignored
+*/
+
+typedef int (*daemon_start_t)(void *);
+typedef int (*daemon_onstop_t)();
+struct MY_DAEMON {
+ daemon_start_t start;
+ daemon_onstop_t stop;
+};
+
+int my_daemon_run(char *name, struct MY_DAEMON*d);
+int my_daemon_files_run(char *name, struct MY_DAEMON*d, char *node_id);
+
+/*
+ if any of the functions in my_daemon return non-zero (failure)
+ then my_daemon_error contains the error message
+*/
+extern char my_daemon_error[];
+
+/*
+ my_daemon_install() adds a service called [name] which will
+ be called using the command line [cmd]
+ to start a service after installing it, you can use the command line
+ > net start [name]
+*/
+int my_daemon_install(const char *name, const char *cmd);
+
+/*
+ my_daemon_remove() deletes any service called [name]
+*/
+int my_daemon_remove(const char *name);
+
+int maybe_install_or_remove_service(int argc_,char**argv_,char*opts_remove,char*opts_install,char*default_name);
+
+/*
+ these macros are provided for convenience. including these macros
+ in your main source file give you standard options for services
+*/
+#define NONE
+#ifdef _WIN32
+#define MY_DAEMON_VARS_PASTE(prefix) \
+ uchar *prefix##remove,*prefix##install,*prefix##service
+#define MY_DAEMON_VARS(prefix) uchar *prefix remove,* install,*prefix service
+#define MY_DAEMON_VARS0 MY_DAEMON_VARS(NONE)
+#define MY_DAEMON_LONG_OPTS(prefix) \
+ {"install", 'i', "Install this program as a service. (must be first argument)", \
+ &prefix install, &prefix install, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, \
+ {"remove", 'r', "Remove this program as a service. (must be first argument)", \
+ &prefix remove, &prefix remove, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, \
+ {"service", 's', "Internal use only (for windows service)", \
+ &prefix service, &prefix service, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+
+#else
+#define MY_DAEMON_VARS_PASTE(prefix)
+#define MY_DAEMON_VARS(prefix)
+#define MY_DAEMON_VARS0
+#define MY_DAEMON_LONG_OPTS(prefix)
+#define MY_DAEMON_LONG_OPTS_PASTE(prefix)
+#endif
+/*
+ my_dlog is the log file created in daemon_files()
+*/
+DAEMONEXPORT FILE *my_dlog;
+/*
+ convenience macros -- mainly for debugging a service
+*/
+#define DLOG(x) do{fprintf(my_dlog,"%s",x);fflush(my_dlog);}while(0)
+#define DLOG1(x,y) do{fprintf(my_dlog,x,y);fflush(my_dlog);}while(0)
+
+/*
+ my_daemon_prefiles() checks that pidname and logname can be created
+ and that pidname can be locked.
+ a non-zero return usually means that the process abort -- can't create
+ necessary files.
+*/
+int my_daemon_prefiles(const char *pidname, const char *logname);
+/*
+ my_daemon_files() opens the files passed in prefiles() and redirects
+ stdout/stderr to the logfile.
+ my_dlog points is the logfile after daemon_files()
+*/
+int my_daemon_files();
+/*
+ my_daemon_closefiles() closes files opened by my_daemon_files()
+*/
+int my_daemon_closefiles();
+
+/*
+ a helper function to turn a --install command line to a
+ --service command line for internal use with MY_DAEMON_LONG_OPTS
+*/
+char *my_daemon_make_svc_cmd(int n, char **v, char *default_name);
+
+C_MODE_END
+#endif //MY_DAEMON_H
=== modified file 'storage/ndb/include/util/NdbOut.hpp'
--- a/storage/ndb/include/util/NdbOut.hpp 2008-12-16 11:50:38 +0000
+++ b/storage/ndb/include/util/NdbOut.hpp 2009-01-29 17:16:09 +0000
@@ -49,7 +49,7 @@ class OutputStream;
class NullOutputStream;
/* Declare a static variable of NdbOut as ndbout */
-extern NdbOut ndbout;
+extern NdbOut ndbout, ndberr;
class NdbOut
{
=== modified file 'storage/ndb/src/common/logger/ConsoleLogHandler.cpp'
--- a/storage/ndb/src/common/logger/ConsoleLogHandler.cpp 2008-12-10 17:55:10 +0000
+++ b/storage/ndb/src/common/logger/ConsoleLogHandler.cpp 2009-01-29 17:16:09 +0000
@@ -15,9 +15,8 @@
#include "ConsoleLogHandler.hpp"
-#include <NdbOut.hpp>
-
-ConsoleLogHandler::ConsoleLogHandler() : LogHandler()
+ConsoleLogHandler::ConsoleLogHandler(const NdbOut& out)
+ : LogHandler(), _out(out)
{
}
=== modified file 'storage/ndb/src/common/logger/FileLogHandler.cpp'
--- a/storage/ndb/src/common/logger/FileLogHandler.cpp 2008-12-10 17:55:10 +0000
+++ b/storage/ndb/src/common/logger/FileLogHandler.cpp 2009-01-29 17:16:09 +0000
@@ -20,17 +20,6 @@
//
// PUBLIC
//
-
-FileLogHandler::FileLogHandler() :
- LogHandler(),
- m_maxNoFiles(MAX_NO_FILES),
- m_maxFileSize(MAX_FILE_SIZE),
- m_maxLogEntries(MAX_LOG_ENTRIES)
-
-{
- m_pLogFile = new File_class("logger.log", "a+");
-}
-
FileLogHandler::FileLogHandler(const char* aFileName,
int maxNoFiles,
long maxFileSize,
=== modified file 'storage/ndb/src/common/logger/Logger.cpp'
--- a/storage/ndb/src/common/logger/Logger.cpp 2008-12-10 17:55:10 +0000
+++ b/storage/ndb/src/common/logger/Logger.cpp 2009-01-29 17:16:09 +0000
@@ -68,14 +68,14 @@ Logger::setCategory(const char* pCategor
}
bool
-Logger::createConsoleHandler()
+Logger::createConsoleHandler(const NdbOut &out)
{
Guard g(m_handler_mutex);
bool rc = true;
if (m_pConsoleHandler == NULL)
{
- m_pConsoleHandler = new ConsoleLogHandler();
+ m_pConsoleHandler = new ConsoleLogHandler(out);
if (!addHandler(m_pConsoleHandler)) // TODO: check error code
{
rc = false;
@@ -98,13 +98,14 @@ Logger::removeConsoleHandler()
}
bool
-Logger::createFileHandler()
+Logger::createFileHandler(char*filename)
{
Guard g(m_handler_mutex);
bool rc = true;
if (m_pFileHandler == NULL)
{
- m_pFileHandler = new FileLogHandler();
+ m_pFileHandler = filename ? new FileLogHandler(filename)
+ : new FileLogHandler();
if (!addHandler(m_pFileHandler)) // TODO: check error code
{
rc = false;
=== modified file 'storage/ndb/src/common/portlib/CMakeLists.txt'
--- a/storage/ndb/src/common/portlib/CMakeLists.txt 2008-08-26 12:29:06 +0000
+++ b/storage/ndb/src/common/portlib/CMakeLists.txt 2009-01-23 12:50:40 +0000
@@ -29,6 +29,7 @@ ADD_LIBRARY(ndbportlib STATIC
NdbCondition.c NdbMutex.c
NdbEnv.c NdbThread.c NdbHost.c NdbTCP.cpp
NdbMem.c NdbConfig.c NdbTick.c
+ my_daemon.cc ${CMAKE_SOURCE_DIR}/sql/nt_servc.cc
${EXTRA_SRC}
)
TARGET_LINK_LIBRARIES(ndbportlib mysys ${EXTRA_LIB})
=== modified file 'storage/ndb/src/common/portlib/Makefile.am'
--- a/storage/ndb/src/common/portlib/Makefile.am 2008-08-27 01:18:40 +0000
+++ b/storage/ndb/src/common/portlib/Makefile.am 2009-01-23 12:50:40 +0000
@@ -20,7 +20,7 @@ noinst_LTLIBRARIES = libportlib.la
libportlib_la_SOURCES = \
NdbCondition.c NdbMutex.c NdbTick.c \
NdbEnv.c NdbThread.c NdbHost.c NdbTCP.cpp \
- NdbDaemon.c NdbMem.c \
+ NdbDaemon.c my_daemon.cc NdbMem.c \
NdbConfig.c
include $(top_srcdir)/storage/ndb/config/common.mk.am
=== added file 'storage/ndb/src/common/portlib/my_daemon.cc'
--- a/storage/ndb/src/common/portlib/my_daemon.cc 1970-01-01 00:00:00 +0000
+++ b/storage/ndb/src/common/portlib/my_daemon.cc 2009-02-26 10:38:16 +0000
@@ -0,0 +1,322 @@
+/* Copyright (C) 2008 Sun Microsystems
+
+ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifdef _WIN32
+#include <process.h>
+#endif
+#include <my_global.h>
+#include <my_sys.h>
+#include <m_string.h>
+#define DAEMONEXPORT
+#include <my_daemon.h>
+#include <NdbConfig.h>
+
+#ifdef _WIN32
+#include <nt_servc.h>
+NTService g_ntsvc;
+HANDLE g_shutdown_evt;
+#endif
+
+static char *daemon_name;
+static long daemonpid;
+
+#define errorlen 1023
+char my_daemon_error[errorlen+1];
+int ERR1(const char*fmt,...) {
+ va_list argptr;
+ va_start(argptr, fmt);
+ my_snprintf(my_daemon_error,errorlen,fmt,argptr);
+ va_end(argptr);
+ return 1;
+}
+
+struct MY_DAEMON g_daemon;
+
+#ifdef _WIN32
+static int init();
+static int stopper(void*)
+{
+ WaitForSingleObject(g_shutdown_evt,INFINITE);
+ return g_daemon.stop();
+}
+#endif
+
+int my_daemon_run(char *name,struct MY_DAEMON*d)
+{
+ daemon_name= name;
+ memcpy(&g_daemon,d,sizeof(g_daemon));
+#ifdef _WIN32
+ g_shutdown_evt=CreateEvent(0, 0, 0, 0);
+ g_ntsvc.SetShutdownEvent(g_shutdown_evt);
+ uintptr_t stop_thread= _beginthread((THREAD_FC)stopper,0,0);
+ if(!stop_thread)
+ return ERR1("couldn't start stopper thread\n");
+ if(init())
+ return ERR1("init failed\n");
+#else /* Fork */
+ pid_t n = fork();
+ if(n==-1)
+ return ERR1("fork failed: %s", strerror(errno));
+ /* Exit if we are the parent */
+ if (n != 0)
+ exit(0);
+ g_daemon.start(0);
+#endif
+ return 0;
+}
+
+#ifdef _WIN32
+char *my_daemon_makecmdv(int c, const char **v)
+{
+ char exe[_MAX_PATH + 3], *retval, *strpos;
+ int i= 0, n= 0;
+
+ GetModuleFileName(NULL, exe, sizeof(exe));
+ n= strlen(exe);
+ for (i= 0; i < c; i++)
+ n += strlen(v[i]) + 8;
+ strpos= retval= (char*)my_malloc(n, MY_FAE);
+ strpos += my_snprintf(strpos, n, "\"%s\"", exe);
+ for (i= 0; i < c; i++)
+ strpos += my_snprintf(strpos, n, " \"%s\"", v[i]);
+ return retval;
+}
+
+static int startswith(char*s,char**set)
+{
+ char**item=set;
+ for(;*item;item++)
+ if(!strncmp(*item,s,strlen(*item)))
+ return 1;
+ return 0;
+}
+
+char *my_daemon_make_svc_cmd(int n, char **v, char *name)
+{
+ char*swi[]= {"--install","-i",0},
+ *swirs[]= {"--remove","-r","--install","-i","--service","-s",0};
+ if(!startswith(v[0],swi))
+ return ERR1("The install option (-i) must be the first argument\n"),0;
+ int i= 0;
+ for(i=1;i<n;i++)
+ if(startswith(v[i],swirs))
+ return ERR1("The install option (-i) must be the only -i or -r"
+ " on command line\n"),0;
+ size_t opt_size= strlen(name)+16;
+ char*svcopt=(char*)my_malloc(opt_size, MY_FAE);
+ my_snprintf(svcopt,opt_size-1,"--service=%s",name);
+
+ size_t size=sizeof(char*)*(n+2);
+ char**v1= (char**)my_malloc(size, MY_FAE);
+ memset(v1,0,size);
+ i=0;
+ v1[i++]= svcopt;
+
+ int j= 1;
+ for(;j<n&&v[j][0]!='-';j++); // skip through to first option
+ for(;j<n;j++)
+ v1[i++]= v[j];
+ return my_daemon_makecmdv(i, (const char**)v1);
+}
+
+//returns -1: no install/remove, 0: success, +ve error
+int maybe_install_or_remove_service(int argc_,char**argv_,char*opts_remove,char*opts_install,char*default_name)
+{
+ if(argc_<2)
+ return -1;
+ char*svc=default_name,
+ *r[]={"-r","--remove",0},
+ *i[]={"-i","--install",0};
+ if(opts_remove||startswith(argv_[1],r)) {
+ if(opts_remove)
+ svc=(char*)opts_remove;
+ printf("Removing service \"%s\"\n",svc);
+ return my_daemon_remove(svc);
+ }
+ if(opts_install||startswith(argv_[1],i)) {
+ char *svc_cmd;
+ if(opts_install)
+ svc=(char*)opts_install;
+ svc_cmd= my_daemon_make_svc_cmd(argc_-1, argv_+1, svc);
+ if(!svc_cmd) {
+ fprintf(stderr, my_daemon_error);
+ return 1;
+ }
+ printf("Installing service \"%s\"\n",svc);
+ printf("as \"%s\"\n",svc_cmd);
+ return my_daemon_install(svc, svc_cmd);
+ }
+ return -1;
+}
+
+int my_daemon_install(const char *name, const char *cmd)
+{
+ SC_HANDLE svc= 0, scm= 0;
+
+ if(!g_ntsvc.SeekStatus(name, 1))
+ return ERR1("SeekStatus on %s failed\n", name);
+ if(!(scm= OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE)))
+ return ERR1("Failed to install the service: "
+ "Could not open Service Control Manager.\n");
+ if(!(svc= CreateService(scm, name, name,
+ SERVICE_ALL_ACCESS,
+ SERVICE_WIN32_OWN_PROCESS,
+ (1 ? SERVICE_AUTO_START :
+ SERVICE_DEMAND_START), SERVICE_ERROR_NORMAL,
+ cmd, 0, 0, 0, 0, 0)))
+ return CloseServiceHandle(scm),
+ ERR1("Failed to install the service: "
+ "Couldn't create service)\n");
+ printf("Service successfully installed.\n");
+ CloseServiceHandle(svc);
+ CloseServiceHandle(scm);
+ return 0;
+}
+#endif
+static int pidfd, logfd;
+int daemon_closefiles()
+{
+ close(pidfd);
+ fclose(my_dlog);
+ return 0;
+}
+
+static const char *pidfile, *logfile;
+int my_daemon_prefiles(const char *pidfil, const char *logfil)
+{
+ int n;
+ char buf[64];
+
+ my_dlog= 0;
+ pidfile= pidfil;
+ logfile= logfil;
+ pidfd= logfd= -1;
+ /* open log file before becoming daemon */
+ if (logfile != NULL)
+ {
+ logfd= open(logfile, O_CREAT | O_WRONLY | O_APPEND, 0644);
+ if(logfd == -1)
+ return ERR1("%s: open for write failed\n", logfile);
+ my_dlog= fdopen(logfd, "a");
+ }
+ /* Check that we have write access to lock file */
+ assert(pidfile != NULL);
+ pidfd= open(pidfile, O_CREAT | O_RDWR, 0644);
+ if(pidfd == -1)
+ return ERR1("%s: open for write failed\n", pidfile);
+ /* Read any old pid from lock file */
+ n= read(pidfd, buf, sizeof(buf));
+ if(n < 0)
+ return ERR1("%s: read failed\n", pidfile);
+ buf[n]= 0;
+ daemonpid= atol(buf);
+ if(lseek(pidfd, 0, SEEK_SET) == -1)
+ return ERR1("%s: lseek failed\n", pidfile);
+#ifdef __WIN__ //TODO: add my_lockf.c with these definitions
+#define lockf _locking
+#define F_TLOCK _LK_NBLCK
+#define F_ULOCK _LK_UNLCK
+#define F_LOCK _LK_LOCK
+#endif
+#ifdef F_TLOCK
+ /* Test for lock before becoming daemon */
+ if(lockf(pidfd, F_TLOCK, 0) == -1)
+ if(errno == EACCES || errno == EAGAIN)
+ return ERR1("pidfile: already locked by pid=%ld\n", daemonpid);
+ if(lockf(pidfd, F_ULOCK, 0) == -1)
+ return ERR1("%s: fail to unlock\n", pidfile);
+#endif
+ return 0;
+}
+
+int my_daemon_files()
+{
+ int n;
+ char buf[64];
+ /* Running in child process */
+ daemonpid= getpid();
+#ifdef F_TLOCK
+ /* Lock the lock file (likely to succeed due to test above) */
+ if(lockf(pidfd, F_LOCK, 0) == -1)
+ return ERR1("%s: lock failed\n", pidfile);
+#endif
+#ifndef _WIN32
+ /* Become process group leader */
+ if(setsid()==-1)
+ return ERR1("setsid failed\n");
+#endif
+ /* Write pid to lock file */
+ if(IF_WIN(_chsize, ftruncate)(pidfd, 0) == -1)
+ return ERR1("%s: ftruncate failed\n", pidfile);
+ n= my_sprintf(buf, (buf, "%ld\n", daemonpid));
+ if(write(pidfd, buf, n) != n)
+ return ERR1("%s: write failed\n", pidfile);
+ /* Do input/output redirections (assume fd 0,1,2 not in use) */
+ close(0);
+ const char* fname=IF_WIN("nul:", "/dev/null");
+ if(open(fname, O_RDONLY)==-1)
+ return ERR1("couldn't open %s\n", fname);
+#ifdef _WIN32 //no stdout/stderr on windows service
+ *stdout= *stderr= *my_dlog;
+#else
+ if (logfd != 0)
+ {
+ dup2(logfd, 1);
+ dup2(logfd, 2);
+ close(logfd);
+ my_dlog= stdout;
+ }
+#endif
+ return 0;
+}
+
+#ifdef _WIN32
+HANDLE hExitEvent;
+
+static int evtlog(char *s)
+{
+ HANDLE eventsrc;
+ int n= strlen(s);
+ char *msg= (char*)my_malloc(n + 1, MY_FAE);
+ char *ss[]= { msg };
+ my_snprintf(msg, n, "\n\n%s", s);
+ if(!(eventsrc= RegisterEventSource(0, daemon_name)))
+ return 1;
+ if(!(ReportEvent(eventsrc, EVENTLOG_ERROR_TYPE, 0, 0, 0, 1, 0, (LPCSTR*)ss, 0)))
+ return 1;
+ if(!(DeregisterEventSource(eventsrc)))
+ return 1;
+ my_free(msg,MY_FAE);
+ return 0;
+}
+
+static DWORD WINAPI main_function(LPVOID x)
+{
+ g_ntsvc.SetRunning();
+ g_daemon.start(0);
+ return 0;
+}
+
+static int init()
+{
+ return !g_ntsvc.Init(daemon_name,main_function);
+}
+
+int my_daemon_remove(const char *name)
+{
+ return !g_ntsvc.Remove((LPCSTR)name);
+}
+#endif
=== modified file 'storage/ndb/src/common/util/NdbOut.cpp'
--- a/storage/ndb/src/common/util/NdbOut.cpp 2008-12-16 11:50:38 +0000
+++ b/storage/ndb/src/common/util/NdbOut.cpp 2009-01-29 17:16:09 +0000
@@ -20,6 +20,8 @@
static FileOutputStream ndbouts_fileoutputstream(stdout);
NdbOut ndbout(ndbouts_fileoutputstream);
+static FileOutputStream ndberrs_fileoutputstream(stderr);
+NdbOut ndberr(ndberrs_fileoutputstream);
static const char * fms[] = {
"%d", "0x%02x", // Int8
=== modified file 'storage/ndb/src/common/util/OutputStream.cpp'
--- a/storage/ndb/src/common/util/OutputStream.cpp 2008-12-16 11:50:38 +0000
+++ b/storage/ndb/src/common/util/OutputStream.cpp 2009-01-29 17:16:09 +0000
@@ -19,6 +19,23 @@
#include <OutputStream.hpp>
#include <socket_io.h>
+size_t my_vfprintf(FILE *f, const char* fmt, va_list ap)
+{
+ size_t size= 1024, len;
+ char *buf= (char*)malloc(size);
+ if(!buf)
+ return 0;
+ len= my_vsnprintf(buf, size, fmt, ap);
+ if(len >= size)
+ {
+ buf= (char*)realloc(buf, ++len);
+ len= my_vsnprintf(buf, len, fmt, ap);
+ }
+ len= fprintf(f, "%s", buf);
+ free(buf);
+ return len;
+}
+
FileOutputStream::FileOutputStream(FILE * file){
f = file;
}
@@ -27,7 +44,7 @@ int
FileOutputStream::print(const char * fmt, ...){
va_list ap;
va_start(ap, fmt);
- const int ret = vfprintf(f, fmt, ap);
+ const int ret = my_vfprintf(f, fmt, ap);
va_end(ap);
return ret;
}
@@ -36,7 +53,7 @@ int
FileOutputStream::println(const char * fmt, ...){
va_list ap;
va_start(ap, fmt);
- const int ret = vfprintf(f, fmt, ap);
+ const int ret = my_vfprintf(f, fmt, ap);
va_end(ap);
return ret + fprintf(f, "\n");
}
=== modified file 'storage/ndb/src/kernel/main.cpp'
--- a/storage/ndb/src/kernel/main.cpp 2009-02-11 14:26:06 +0000
+++ b/storage/ndb/src/kernel/main.cpp 2009-02-26 14:52:41 +0000
@@ -33,6 +33,7 @@
#include <LogLevel.hpp>
#include <EventLogger.hpp>
+#include <Logger.hpp>
#include <NdbEnv.h>
#include <NdbAutoPtr.hpp>
@@ -86,16 +87,86 @@ void childReportError(int error)
void childExit(int code, Uint32 currentStartPhase)
{
+#ifndef NDB_WIN
writeChildInfo("sphase", currentStartPhase);
writeChildInfo("exit", code);
fprintf(child_info_file_w, "\n");
fclose(child_info_file_r);
fclose(child_info_file_w);
exit(code);
+#else
+ {
+ Configuration* theConfig = globalEmulatorData.theConfiguration;
+ theConfig->closeConfiguration(true);
+ switch(code){
+ case NRT_Default:
+ g_eventLogger->info("Angel shutting down");
+ reportShutdown(theConfig, 0, 0, currentStartPhase);
+ exit(0);
+ break;
+ case NRT_NoStart_Restart:
+ theConfig->setInitialStart(false);
+ globalData.theRestartFlag = initial_state;
+ break;
+ case NRT_NoStart_InitialStart:
+ theConfig->setInitialStart(true);
+ globalData.theRestartFlag = initial_state;
+ break;
+ case NRT_DoStart_InitialStart:
+ theConfig->setInitialStart(true);
+ globalData.theRestartFlag = perform_start;
+ break;
+ default:
+ if(theConfig->stopOnError()){
+ /**
+ * Error shutdown && stopOnError()
+ */
+ reportShutdown(theConfig, 1, 0, currentStartPhase);
+ exit(0);
+ }
+ // Fall-through
+ case NRT_DoStart_Restart:
+ theConfig->setInitialStart(false);
+ globalData.theRestartFlag = perform_start;
+ break;
+ }
+ char buf[80];
+ BaseString::snprintf(buf, sizeof(buf), "WIN_NDBD_CFG=%d %d %d",
+ theConfig->getInitialStart(),
+ globalData.theRestartFlag, globalData.ownId);
+ _putenv(buf);
+
+ char exe[MAX_PATH];
+ GetModuleFileName(0,exe,sizeof(exe));
+
+ STARTUPINFO sinfo;
+ ZeroMemory(&sinfo, sizeof(sinfo));
+ sinfo.cb= sizeof(STARTUPINFO);
+ sinfo.dwFlags= STARTF_USESHOWWINDOW;
+ sinfo.wShowWindow= SW_HIDE;
+
+ PROCESS_INFORMATION pinfo;
+ if(reportShutdown(theConfig, 0, 1, currentStartPhase)) {
+ g_eventLogger->error("unable to shutdown");
+ exit(1);
+ }
+ g_eventLogger->info("Ndb has terminated. code=%d", code);
+ if(code==NRT_NoStart_Restart)
+ globalTransporterRegistry.disconnectAll();
+ g_eventLogger->info("Ndb has terminated. Restarting");
+ if(CreateProcess(exe, GetCommandLine(), NULL, NULL, TRUE, 0, NULL, NULL,
+ &sinfo, &pinfo) == 0)
+ {
+ g_eventLogger->error("Angel was unable to create child ndbd process"
+ " error: %d", GetLastError());
+ }
+ }
+#endif
}
void childAbort(int code, Uint32 currentStartPhase)
{
+#ifndef NDB_WIN
writeChildInfo("sphase", currentStartPhase);
writeChildInfo("exit", code);
fprintf(child_info_file_w, "\n");
@@ -105,6 +176,9 @@ void childAbort(int code, Uint32 current
signal(SIGABRT, SIG_DFL);
#endif
abort();
+#else
+ childExit(code,currentStartPhase);
+#endif
}
static int insert(const char * pair, Properties & p)
@@ -144,16 +218,17 @@ static bool get_int_property(Properties
return true;
}
-int reportShutdown(class Configuration *config, int error_exit, int restart)
+int reportShutdown(class Configuration *config, int error_exit, int restart, Uint32 sphase= 256)
{
- Uint32 error= 0, signum= 0, sphase= 256;
+ Uint32 error= 0, signum= 0;
+#ifndef NDB_WIN
Properties info;
readChildInfo(info);
get_int_property(info, "signal", &signum);
get_int_property(info, "error", &error);
get_int_property(info, "sphase", &sphase);
-
+#endif
Uint32 length, theData[25];
EventReport *rep = (EventReport *)theData;
@@ -417,7 +492,6 @@ get_multithreaded_config(EmulatorData& e
return 0;
}
-
int main(int argc, char** argv)
{
NDB_INIT(argv[0]);
@@ -438,7 +512,17 @@ int main(int argc, char** argv)
if(!theConfig->init(argc, argv)){
return NRT_Default;
}
-
+ char*cfg= getenv("WIN_NDBD_CFG");
+ if(cfg) {
+ int x,y,z;
+ if(3!=sscanf(cfg,"%d %d %d",&x,&y,&z)) {
+ g_eventLogger->error("internal error: couldn't find 3 parameters");
+ exit(1);
+ }
+ theConfig->setInitialStart(x);
+ globalData.theRestartFlag= (restartStates)y;
+ globalData.ownId= z;
+ }
{ // Do configuration
#ifndef NDB_WIN32
signal(SIGPIPE, SIG_IGN);
=== modified file 'storage/ndb/src/kernel/vm/Configuration.hpp'
--- a/storage/ndb/src/kernel/vm/Configuration.hpp 2009-02-11 14:26:06 +0000
+++ b/storage/ndb/src/kernel/vm/Configuration.hpp 2009-02-26 14:52:41 +0000
@@ -137,7 +137,7 @@ public:
private:
friend class Cmvmi;
friend class Qmgr;
- friend int reportShutdown(class Configuration *config, int error, int restart);
+ friend int reportShutdown(class Configuration *config, int error, int restart, Uint32 sphase);
Uint32 _stopOnError;
Uint32 m_restartOnErrorInsert;
=== modified file 'storage/ndb/src/mgmsrv/InitConfigFileParser.cpp'
--- a/storage/ndb/src/mgmsrv/InitConfigFileParser.cpp 2008-10-21 12:41:59 +0000
+++ b/storage/ndb/src/mgmsrv/InitConfigFileParser.cpp 2009-01-23 12:50:40 +0000
@@ -19,8 +19,11 @@
#include "Config.hpp"
#include <NdbOut.hpp>
#include "ConfigInfo.hpp"
+#include "EventLogger.hpp"
#include <m_string.h>
+extern EventLogger *g_eventLogger;
+
const int MAX_LINE_LENGTH = 1024; // Max length of line of text in config file
static void trim(char *);
@@ -29,10 +32,9 @@ static void require(bool v) { if(!v) abo
//****************************************************************************
// Ctor / Dtor
//****************************************************************************
-InitConfigFileParser::InitConfigFileParser(FILE * out)
+InitConfigFileParser::InitConfigFileParser()
{
m_info = new ConfigInfo();
- m_errstream = out ? out : stderr;
}
InitConfigFileParser::~InitConfigFileParser() {
@@ -42,12 +44,11 @@ InitConfigFileParser::~InitConfigFilePar
//****************************************************************************
// Read Config File
//****************************************************************************
-InitConfigFileParser::Context::Context(const ConfigInfo * info, FILE * out)
+InitConfigFileParser::Context::Context(const ConfigInfo * info)
: m_userProperties(true), m_configValues(1000, 20) {
m_config = new Properties(true);
m_defaults = new Properties(true);
- m_errstream = out;
}
InitConfigFileParser::Context::~Context(){
@@ -62,7 +63,7 @@ Config *
InitConfigFileParser::parseConfig(const char * filename) {
FILE * file = fopen(filename, "r");
if(file == 0){
- fprintf(m_errstream, "Error opening file: %s\n", filename);
+ g_eventLogger->error("Error opening '%s', error: %d, %s", filename, errno, strerror(errno));
return 0;
}
@@ -76,7 +77,7 @@ InitConfigFileParser::parseConfig(FILE *
char line[MAX_LINE_LENGTH];
- Context ctx(m_info, m_errstream);
+ Context ctx(m_info);
ctx.m_lineno = 0;
ctx.m_currentSection = 0;
@@ -851,7 +852,7 @@ InitConfigFileParser::parse_mycnf()
api = &options[idx+3];
}
- Context ctx(m_info, m_errstream);
+ Context ctx(m_info);
const char *groups[]= { "cluster_config", 0 };
if (load_defaults(options, groups))
goto end;
=== modified file 'storage/ndb/src/mgmsrv/InitConfigFileParser.hpp'
--- a/storage/ndb/src/mgmsrv/InitConfigFileParser.hpp 2008-06-10 09:21:15 +0000
+++ b/storage/ndb/src/mgmsrv/InitConfigFileParser.hpp 2009-01-23 12:50:40 +0000
@@ -33,12 +33,11 @@ class ConfigInfo;
* object if the config file has correct syntax and semantic.
*/
class InitConfigFileParser {
- FILE * m_errstream;
public:
/**
* Constructor
*/
- InitConfigFileParser(FILE * errstream = stdout);
+ InitConfigFileParser();
~InitConfigFileParser();
/**
@@ -61,7 +60,7 @@ public:
* Context = Which section in init config file we are currently parsing
*/
struct Context {
- Context(const ConfigInfo *, FILE * out);
+ Context(const ConfigInfo *);
~Context();
ContextSectionType type; ///< Section type (e.g. default section,section)
=== modified file 'storage/ndb/src/mgmsrv/MgmtSrvr.hpp'
--- a/storage/ndb/src/mgmsrv/MgmtSrvr.hpp 2009-02-18 15:01:04 +0000
+++ b/storage/ndb/src/mgmsrv/MgmtSrvr.hpp 2009-02-26 14:52:41 +0000
@@ -26,6 +26,7 @@
#include <EventLogger.hpp>
#include <SignalSender.hpp>
+#include <my_daemon.h>
#define MGM_ERROR_MAX_INJECT_SESSION_ONLY 10000
@@ -131,6 +132,7 @@ public:
int print_full_config;
const char* configdir;
int verbose;
+ MY_DAEMON_VARS0;
MgmtOpts() : configdir(MYSQLCLUSTERDIR) {};
int reload;
int initial;
=== modified file 'storage/ndb/src/mgmsrv/main.cpp'
--- a/storage/ndb/src/mgmsrv/main.cpp 2009-01-07 09:55:03 +0000
+++ b/storage/ndb/src/mgmsrv/main.cpp 2009-02-24 11:28:08 +0000
@@ -1,3 +1,4 @@
+
/* Copyright (C) 2003-2008 MySQL AB, 2008 Sun Microsystems, Inc.
This program is free software; you can redistribute it and/or modify
@@ -22,7 +23,7 @@
#include <version.h>
#include <kernel_types.h>
-#include <NdbDaemon.h>
+#include <my_daemon.h>
#include <NdbConfig.h>
#include <NdbSleep.h>
#include <ndb_version.h>
@@ -85,6 +86,7 @@ static MgmtSrvr::MgmtOpts opts;
static struct my_option my_long_options[] =
{
NDB_STD_OPTS("ndb_mgmd"),
+ MY_DAEMON_LONG_OPTS(opts.)
{ "config-file", 'f', "Specify cluster configuration file",
(uchar**) &opts.config_filename, (uchar**) &opts.config_filename, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
@@ -145,8 +147,16 @@ static void usage()
static char **defaults_argv;
-static void
-mgmd_exit(int result)
+/*
+ mgmd_exit()
+ do_exit=true:
+ if in a windows service, don't want process to exit()
+ until cleanup of other threads is done
+*/
+#ifdef _WIN32
+extern HANDLE g_shutdown_evt;
+#endif
+static void mgmd_exit(int result)
{
g_eventLogger->close();
@@ -155,13 +165,30 @@ mgmd_exit(int result)
ndb_end(opt_ndb_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
+#ifdef _WIN32
+ if(opts.service)
+ SetEvent(g_shutdown_evt); // release stopper thread
+ else
+ exit(result);
+#else
exit(result);
+#endif
}
+int null_printf(const char*s,...)
+{
+ return 0;
+}
+#define DBG IF_WIN(g_eventLogger->debug,null_printf)
+int event_loop(void*);
+int start();
+int argc_;char**argv_;
int main(int argc, char** argv)
{
NDB_INIT(argv[0]);
+ argc_= argc;
+ argv_= argv;
g_eventLogger->setCategory("MgmSrvr");
@@ -172,18 +199,41 @@ int main(int argc, char** argv)
int ho_error;
#ifndef DBUG_OFF
- opt_debug= "d:t:i:F:o,/tmp/ndb_mgmd.trace";
+ opt_debug= IF_WIN("d:t:i:F:o,c:\\ndb_mgmd.trace",
+ "d:t:i:F:o,/tmp/ndb_mgmd.trace");
#endif
- if ((ho_error=handle_options(&argc, &argv, my_long_options,
- ndb_std_get_one_option)))
+ if ((ho_error=handle_options(&argc, &argv, my_long_options,
+ ndb_std_get_one_option)))
mgmd_exit(ho_error);
if (opts.interactive ||
opts.non_interactive ||
- opts.print_full_config) {
+ opts.print_full_config ||
+ IF_WIN(1,0)) {
opts.daemon= 0;
}
+#ifdef _WIN32
+ int r=maybe_install_or_remove_service(argc_,argv_,
+ (char*)opts.remove,(char*)opts.install,
+ "MySQL Cluster Management Server");
+ if(r!=-1)
+ return r;
+#ifdef _DEBUG
+ /* it is impossible to attach a debugger to a starting service
+ ** so it is necessary to log to a known place to diagnose
+ ** problems. services don't have a stdout/stderr so the only
+ ** way to write debug info is to a file.
+ ** change this path if you don't have a c:\
+ */
+ if(opts.service) {
+ char *fn= "c:\\ndb_mgmd_debug.log";
+ g_eventLogger->createFileHandler(fn);
+ DBG(NdbConfig_StdoutFileName(0));
+ DBG(NdbConfig_get_path(0));
+ } else
+#endif
+#endif
/* Output to console initially */
g_eventLogger->createConsoleHandler();
@@ -203,13 +253,22 @@ int main(int argc, char** argv)
#if !defined NDB_WIN32
signal(SIGPIPE, SIG_IGN);
#endif
+ return start();
+}
-start:
+int daemon_stop()
+{
+ g_StopServer= true;
+ return 0;
+}
+int start()
+{
g_eventLogger->info("NDB Cluster Management Server. %s", NDB_VERSION_STRING);
mgm= new MgmtSrvr(opts, opt_connect_str);
if (mgm == NULL) {
+ DBG("mgm is NULL");
g_eventLogger->critical("Out of memory, couldn't create MgmtSrvr");
mgmd_exit(1);
}
@@ -221,30 +280,43 @@ start:
}
my_setwd(NdbConfig_get_path(0), MYF(0));
-
- if (opts.daemon) {
-
+#ifdef _WIN32
+ DBG("cl %s",GetCommandLine());
+#endif
+ if (IF_WIN(opts.service,opts.daemon)) {
+ DBG("service name %s",IF_WIN(opts.service,""));
NodeId localNodeId= mgm->getOwnNodeId();
if (localNodeId == 0) {
g_eventLogger->error("Couldn't get own node id");
delete mgm;
mgmd_exit(1);
}
-
- // Become a daemon
+ struct MY_DAEMON thedaemon= {event_loop,daemon_stop};
char *lockfile= NdbConfig_PidFileName(localNodeId);
char *logfile= NdbConfig_StdoutFileName(localNodeId);
- NdbAutoPtr<char> tmp_aptr1(lockfile), tmp_aptr2(logfile);
-
- if (NdbDaemon_Make(lockfile, logfile, 0) == -1) {
- g_eventLogger->error("Cannot become daemon: %s", NdbDaemon_ErrorText);
- delete mgm;
+ DBG("to open %s,%s", lockfile, logfile);
+ if (my_daemon_prefiles(lockfile, logfile)) {
+ g_eventLogger->error("daemon_prefiles %s", my_daemon_error);
+ mgmd_exit(1);
+ }
+ if(my_daemon_files()) {
+ g_eventLogger->error("daemon_files %s", my_daemon_error);
mgmd_exit(1);
}
+ return my_daemon_run((char*)IF_WIN(opts.service,0),&thedaemon);
}
+#ifdef _WIN32
+ if(opts.daemon) {
+ g_eventLogger->error("no daemon mode on windows, use -i to set up a service.");
+ mgmd_exit(1);
+ }
+#endif
+ return event_loop(0);
+}
- /* Start mgm services */
- if (!mgm->start()) {
+int event_loop(void*)
+{
+ if (!mgm->start()) { /* Start mgm services */
delete mgm;
mgmd_exit(1);
}
@@ -260,8 +332,9 @@ start:
while(g_StopServer != true && read_and_execute(&com, "ndb_mgm> ", 1));
}
else {
- while(g_StopServer != true)
+ while(g_StopServer != true) {
NdbSleep_MilliSleep(500);
+ }
}
g_eventLogger->info("Shutting down server...");
@@ -271,9 +344,12 @@ start:
if(g_RestartServer){
g_eventLogger->info("Restarting server...");
g_RestartServer= g_StopServer= false;
- goto start;
+ int ex= start();
+ if(ex)
+ mgmd_exit(ex);
}
mgmd_exit(0);
+ return 0;
}
=== modified file 'storage/ndb/src/mgmsrv/testConfig.cpp'
--- a/storage/ndb/src/mgmsrv/testConfig.cpp 2008-09-16 09:37:22 +0000
+++ b/storage/ndb/src/mgmsrv/testConfig.cpp 2009-01-23 12:50:40 +0000
@@ -67,11 +67,10 @@ check_param(const ConfigInfo::ParamInfo
// Run the config file through InitConfigFileParser
// throw away the error messages for now.
- FILE* err_file= tmpfile();
- InitConfigFileParser parser(err_file);
+
+ InitConfigFileParser parser;
Config* conf = parser.parseConfig(config_file);
fclose(config_file);
- fclose(err_file);
if (conf == NULL)
return false;
=== modified file 'storage/ndb/test/CMakeLists.txt'
--- a/storage/ndb/test/CMakeLists.txt 2008-08-20 13:22:09 +0000
+++ b/storage/ndb/test/CMakeLists.txt 2009-01-23 12:50:40 +0000
@@ -14,6 +14,8 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
ADD_SUBDIRECTORY(src)
+IF(WITH_NDB_TEST)
ADD_SUBDIRECTORY(tools)
ADD_SUBDIRECTORY(ndbapi)
ADD_SUBDIRECTORY(run-test)
+ENDIF(WITH_NDB_TEST)
=== modified file 'storage/ndb/tools/ndb_config.cpp'
--- a/storage/ndb/tools/ndb_config.cpp 2008-08-21 06:39:44 +0000
+++ b/storage/ndb/tools/ndb_config.cpp 2009-01-23 12:50:40 +0000
@@ -533,11 +533,16 @@ noconnect:
}
#include <Config.hpp>
+#include <EventLogger.hpp>
+
+extern EventLogger *g_eventLogger;
ndb_mgm_configuration*
load_configuration()
-{
- InitConfigFileParser parser(stderr);
+{
+ g_eventLogger->removeAllHandlers();
+ g_eventLogger->createConsoleHandler(ndberr);
+ InitConfigFileParser parser;
if (g_config_file)
{
if (g_verbose)
=== modified file 'win/configure.js'
--- a/win/configure.js 2009-01-19 14:40:33 +0000
+++ b/win/configure.js 2009-01-29 17:16:09 +0000
@@ -32,6 +32,7 @@ try
var default_comment = "Source distribution";
var default_port = GetValue(configureIn, "MYSQL_TCP_PORT_DEFAULT");
var actual_port = 0;
+ var with_ndb_test = 0;
var configfile = fso.CreateTextFile("win\\configure.data", true);
for (i=0; i < args.Count(); i++)
@@ -66,6 +67,9 @@ try
case "MYSQL_TCP_PORT":
actual_port = parts[1];
break;
+ case "WITH_NDB_TEST":
+ with_ndb_test = 1;
+ break;
}
}
if (actual_port == 0)
@@ -117,6 +121,7 @@ try
GetBaseVersion(version) + "\")");
configfile.WriteLine("SET (MYSQL_VERSION_ID \"" +
GetVersionId(version) + "\")");
+ configfile.WriteLine("SET (WITH_NDB_TEST \"" + with_ndb_test + "\")");
configfile.Close();
| Thread |
|---|
| • bzr push into mysql-5.1-telco-6.4 branch (msvensson:2902 to 2903) | Magnus Svensson | 4 Mar |