List:Commits« Previous MessageNext Message »
From:Magnus Svensson Date:March 4 2009 9:20am
Subject:bzr push into mysql-5.1-telco-6.4 branch (msvensson:2902 to 2903)
View as plain text  
 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 Svensson4 Mar