mgm for win32

ooo bzr diff -r1 -pa/:b/ ndb/src/mgm* |di -m '\S+\.[hc]c?(pp)?(\.in)?'
--- a/ndb/src/mgmapi/LocalConfig.cpp	2007-08-29 07:25:53 +0000
+++ b/ndb/src/mgmapi/LocalConfig.cpp	2007-09-06 13:30:50 +0000
@@ -186,7 +186,7 @@
     if (buf == tempString2)
       break;
     // try to add default port to see if it works
-    snprintf(tempString2, sizeof(tempString2),"%s:%s", buf, NDB_PORT);
+    BaseString::snprintf(tempString2, sizeof(tempString2),"%s:%s", buf, NDB_PORT);
     buf= tempString2;
   } while(1);
   return false;

--- a/ndb/src/mgmapi/mgmapi.cpp	2007-08-29 07:25:53 +0000
+++ b/ndb/src/mgmapi/mgmapi.cpp	2007-09-09 06:52:12 +0000
@@ -761,6 +761,7 @@
 struct ndb_mgm_cluster_state * 
 ndb_mgm_get_status(NdbMgmHandle handle)
 {
+  DBUG_ENTER("ndb_mgm_get_status");
   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_get_status");
   CHECK_HANDLE(handle, NULL);
   CHECK_CONNECTED(handle, NULL);
@@ -775,16 +776,17 @@
   if(!in.gets(buf, sizeof(buf)))
   {
     SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY, "Probably disconnected");
-    return NULL;
+    DBUG_RETURN(NULL);
   }
   if(strcmp("node status\n", buf) != 0) {
     SET_ERROR(handle, NDB_MGM_ILLEGAL_NODE_STATUS, buf);
-    return NULL;
+    DBUG_PRINT("info", ("buffer = '%s'", buf));
+    DBUG_RETURN(NULL);
   }
   if(!in.gets(buf, sizeof(buf)))
   {
     SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY, "Probably disconnected");
-    return NULL;
+    DBUG_RETURN(NULL);
   }
 
   BaseString tmp(buf);
@@ -792,12 +794,12 @@
   tmp.split(split, ":");
   if(split.size() != 2){
     SET_ERROR(handle, NDB_MGM_ILLEGAL_NODE_STATUS, buf);
-    return NULL;
+    DBUG_RETURN(NULL);
   }
 
   if(!(split[0].trim() == "nodes")){
     SET_ERROR(handle, NDB_MGM_ILLEGAL_NODE_STATUS, buf);
-    return NULL;
+    DBUG_RETURN(NULL);
   }
 
   const int noOfNodes = atoi(split[1].c_str());
@@ -810,7 +812,7 @@
   {
     SET_ERROR(handle, NDB_MGM_OUT_OF_MEMORY,
               "Allocating ndb_mgm_cluster_state");
-    return NULL;
+    DBUG_RETURN(NULL);
   }
 
   state->no_of_nodes= noOfNodes;
@@ -827,7 +829,7 @@
       free(state);
       SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY,
                 "Probably disconnected");
-      return NULL;
+      DBUG_RETURN(NULL);
     }
     tmp.assign(buf);
 
@@ -858,12 +860,12 @@
   if(i+1 != noOfNodes){
     free(state);
     SET_ERROR(handle, NDB_MGM_ILLEGAL_NODE_STATUS, "Node count mismatch");
-    return NULL;
+    DBUG_RETURN(NULL);
   }
 
   qsort(state->node_states, state->no_of_nodes, sizeof(state->node_states[0]),
 	cmp_state);
-  return state;
+  DBUG_RETURN(state);
 }
 
 extern "C"
@@ -1539,7 +1541,7 @@
   handle->socket = tmp;
 
   if(reply == NULL) {
-    close(sockfd);
+    NDB_CLOSE_SOCKET(sockfd);
     CHECK_REPLY(reply, -1);
   }
   delete reply;

--- a/ndb/src/mgmapi/ndb_logevent.cpp	2007-08-29 07:25:53 +0000
+++ b/ndb/src/mgmapi/ndb_logevent.cpp	2007-09-06 13:30:50 +0000
@@ -17,6 +17,10 @@
 #include <my_sys.h>
 #include <mgmapi.h>
 
+#ifdef NDB_WIN32
+#include <sys/timeb.h>
+#endif
+
 #include <NdbOut.hpp>
 #include <Properties.hpp>
 #include <socket_io.h>
@@ -80,7 +84,7 @@
     return;
 
   if ( *h )
-    close((*h)->socket);
+    NDB_CLOSE_SOCKET((*h)->socket);
 
   my_free((char*)* h,MYF(MY_ALLOW_ZERO_PTR));
   * h = 0;
@@ -386,8 +390,13 @@
   Properties p;
   char buf[256];
 
+#ifdef NDB_WIN32
+  struct _timeb start_time;
+  _ftime(&start_time);
+#else
   struct timeval start_time;
   gettimeofday(&start_time, 0);
+#endif
 
   /* header */
   while (1) {
@@ -407,10 +416,17 @@
     if ( strcmp("<PING>\n", buf) )
       ndbout_c("skipped: %s", buf);
 
+#ifdef NDB_WIN32
+  struct _timeb now;
+  _ftime(&now);
+  unsigned elapsed_ms= (signed int)(now.time-start_time.time)*1000 +
+      ((signed int)now.millitm-(signed int)start_time.millitm);
+#else
     struct timeval now;
     gettimeofday(&now, 0);
     unsigned elapsed_ms= (now.tv_sec-start_time.tv_sec)*1000 +
       ((signed int)now.tv_usec-(signed int)start_time.tv_usec)/1000;
+#endif
 
     if (elapsed_ms >= timeout_in_milliseconds)
     {

--- a/ndb/src/mgmclient/CommandInterpreter.cpp	2007-08-29 07:25:53 +0000
+++ b/ndb/src/mgmclient/CommandInterpreter.cpp	2007-09-16 12:55:19 +0000
@@ -14,6 +14,7 @@
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
 #include <ndb_global.h>
+#include <NdbTCP.h>
 #include <my_sys.h>
 
 //#define HAVE_GLOBAL_REPLICATION
@@ -23,7 +24,13 @@
 #include "../rep/repapi/repapi.h"
 #endif
 
-#include <mgmapi.h>
+#undef sleep
+#define sleep(X) NdbSleep_SecSleep(X)
+#ifdef NDB_WIN
+#define strncasecmp(S1,S2,L) strnicmp((S1),(S2),(L))
+#endif 
+
+#include <mgmapi.h>   
 #include <util/BaseString.hpp>
 #include <ndbd_exit_codes.h>
 

--- a/ndb/src/mgmclient/main.cpp	2007-08-29 07:25:53 +0000
+++ b/ndb/src/mgmclient/main.cpp	2007-09-06 13:30:50 +0000
@@ -42,6 +42,7 @@
 
 static Ndb_mgmclient* com;
 
+#ifndef NDB_WIN32
 extern "C"
 void 
 handler(int sig)
@@ -58,6 +59,7 @@
   }
   DBUG_VOID_RETURN;
 }
+#endif
 
 NDB_STD_OPTS_VARS;
 
@@ -152,7 +154,9 @@
     prompt= 0;
   }
 
+#ifndef NDB_WIN32
   signal(SIGPIPE, handler);
+#endif
   com = new Ndb_mgmclient(opt_connect_str,1);
   int ret= 0;
   if (!opt_execute_str)

--- a/ndb/src/mgmsrv/MgmtSrvr.cpp	2007-08-29 07:25:53 +0000
+++ b/ndb/src/mgmsrv/MgmtSrvr.cpp	2007-09-06 13:30:50 +0000
@@ -215,15 +215,14 @@
   }
   errStr[0]='\0';
   if(!g_eventLogger.addHandler(logdest, &err, sizeof(errStr), errStr)) {
-    ndbout << "Warning: could not add log destination \""
-           << logdest.c_str() << "\". Reason: ";
+    ndbout_c("Warning: could not add log destination \"%s\". Reason: ",logdest.c_str());
     if(err)
-      ndbout << strerror(err);
+      ndbout_c(strerror(err));
     if(err && errStr[0]!='\0')
-      ndbout << ", ";
+      ndbout_c(", ");
     if(errStr[0]!='\0')
-      ndbout << errStr;
-    ndbout << endl;
+      ndbout_c(errStr);
+    ndbout_c("\n");
   }
 }
 
@@ -460,10 +459,8 @@
     // read config locally
     _config= readConfig();
     if (_config == 0) {
-      if (config_filename != NULL)
-        ndbout << "Invalid configuration file: " << config_filename << endl;
-      else
-        ndbout << "Invalid configuration file" << endl;
+	  ndbout_c("Invalid configuration file: %s\n",
+		  config_filename?config_filename:"<null>");
       exit(-1);
     }
   }
@@ -519,7 +516,7 @@
 
   if ((m_node_id_mutex = NdbMutex_Create()) == 0)
   {
-    ndbout << "mutex creation failed line = " << __LINE__ << endl;
+    ndbout_c("%s%d\n","mutex creation failed line = ",__LINE__ );
     require(false);
   }
 
@@ -2890,7 +2887,7 @@
 {
   int r= 0;
   m_local_mgm_handle= ndb_mgm_create_handle();
-  snprintf(m_local_mgm_connect_string,sizeof(m_local_mgm_connect_string),
+  BaseString::snprintf(m_local_mgm_connect_string,sizeof(m_local_mgm_connect_string),
            "localhost:%u",getPort());
   ndb_mgm_set_connectstring(m_local_mgm_handle, m_local_mgm_connect_string);
 

--- a/ndb/src/mgmsrv/main.cpp	2007-08-29 07:25:53 +0000
+++ b/ndb/src/mgmsrv/main.cpp	2007-09-08 05:58:21 +0000
@@ -13,9 +13,22 @@
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
+#if 0 && !defined(MYSQL_YACC)&& !defined(_WINSOCKAPI_)
+//           ^... sql_yacc.cc includes this file, and defines GROUP which is a typedef in winsock2.h
+#include <winsock2.h>     // http://cboard.cprogramming.com/archive/index.php/t-71596.html
+#endif                    //
+
+
 #include <ndb_global.h>
 #include <ndb_opts.h>
 
+#ifdef NDB_WIN32
+#define NDB_SVC svc
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#endif
+
 #include "MgmtSrvr.hpp"
 #include "EventLogger.hpp"
 #include <Config.hpp>
@@ -45,6 +58,7 @@
 #undef DEBUG
 #define DEBUG(x) ndbout << x << endl;
 
+typedef BaseString bstring;
 const char progname[] = "mgmtsrvr";
 const char *load_default_groups[]= { "mysql_cluster","ndb_mgmd",0 };
 
@@ -103,7 +117,15 @@
 static int opt_interactive;
 static const char * opt_config_filename= 0;
 static int opt_mycnf = 0;
-  
+static const char * opt_install_svc_name, *opt_remove_svc_name;
+static int opt_install_svc, opt_remove_svc;
+static int opt_svc;
+
+#ifdef NDB_WIN32
+#define W32 1
+#else
+#define W32 0
+#endif
 struct MgmGlobals {
   MgmGlobals();
   ~MgmGlobals();
@@ -153,9 +175,12 @@
   { "print-full-config", 'P', "Print full config and exit",
     (gptr*) &g_print_full_config, (gptr*) &g_print_full_config, 0,
     GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
-  { "daemon", 'd', "Run ndb_mgmd in daemon mode (default)",
-    (gptr*) &opt_daemon, (gptr*) &opt_daemon, 0,
-    GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0 },
+  { "daemon", 'd', "Run ndb_mgmd in daemon mode (default)"
+#ifdef NDB_WIN32
+	"\n\t[WINDOWS: option not available]"
+#endif
+    ,(gptr*) &opt_daemon, (gptr*) &opt_daemon, 0,
+    GET_BOOL, NO_ARG, !W32, 0, 0, 0, 0, 0 },
   { "interactive", OPT_INTERACTIVE,
     "Run interactive. Not supported but provided for testing purposes",
     (gptr*) &opt_interactive, (gptr*) &opt_interactive, 0,
@@ -165,13 +190,27 @@
     (gptr*) &g_no_nodeid_checks, (gptr*) &g_no_nodeid_checks, 0,
     GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
   { "nodaemon", OPT_NO_DAEMON,
-    "Don't run as daemon, but don't read from stdin",
-    (gptr*) &opt_non_interactive, (gptr*) &opt_non_interactive, 0,
+    "Don't run as daemon, but don't read from stdin"
+#ifdef NDB_WIN32
+	"\n\t[WINDOWS: will only run as --nodaemon]"
+#endif
+	,(gptr*) &opt_non_interactive, (gptr*) &opt_non_interactive, 0,
     GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
   { "mycnf", 256,
     "Read cluster config from my.cnf",
     (gptr*) &opt_mycnf, (gptr*) &opt_mycnf, 0,
     GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+#ifdef NDB_WIN32
+  { "install", 'i', "install [windows service name]",
+    (gptr*) &opt_install_svc, (gptr*) &opt_install_svc_name, 0,
+    GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0 },
+  { "remove", 'r', "remove [windows service name]",
+    (gptr*) &opt_remove_svc, (gptr*) &opt_remove_svc_name, 0,
+    GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0 },
+  { "service", 's', "internal use. must be passed to the service",
+    (gptr*) &opt_svc, (gptr*) &opt_svc, 0,
+    GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+#endif
   { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
 };
 
@@ -189,12 +228,59 @@
   my_print_variables(my_long_options);
 }
 
+#ifdef NDB_WIN32
+#define NDB_SVC
+#include <nt_servc.h>
+NTService  svc;
+static char*sname="ndb_mgmd";
+#include <ndb_global.h>
+#include <my_sys.h>
+
+int remove(char*argv0,const char*s);
+int install(char*argv0,const char*s,int argc,char**argv)
+{ if(!s)s=sname;
+  if (svc.IsService(s))remove(argv0,s);    
+  char file_path[FN_REFLEN];
+  my_path(file_path, argv0, "");
+  fn_format(file_path,argv0,file_path,"",
+            MY_REPLACE_DIR | MY_UNPACK_FILENAME | MY_RESOLVE_SYMLINKS);
+  bstring sp=" ",q="\"",cmd=bstring().append(q).append(file_path).append(q).append(sp).append("-s").append(sp);
+  argc--;argv++;
+  while(argc--)
+      cmd.append(q).append(*argv++).append(q).append(sp);
+  svc.Install(1,s,s,cmd.c_str(),0);
+  return 0;
+}
+int remove(char*argv0,const char*s)
+{
+    return svc.Remove(s);
+}
+#endif
 /*
  *  MAIN 
  */
+static MgmApiService * mapi; 
+int start(void*);
+#ifdef NDB_WIN32 
+int useeventlog;
+int evtlog(char*s)
+{ if(useeventlog)
+  {	  BaseString msg("\n\n");
+	  msg.append(s);
+	  LPCSTR ss[]={msg.c_str()};
+	  HANDLE eventsrc=RegisterEventSource(0,*svc.my_argv);
+	  assert(eventsrc);
+	  assert(ReportEvent(eventsrc,EVENTLOG_ERROR_TYPE,0,0,0,1,0,ss,0));
+	  assert(DeregisterEventSource(eventsrc));
+  }
+  return !useeventlog;
+}
+#endif
+
 int main(int argc, char** argv)
 {
-
+  int argc_=argc;
+  char**argv_=argv;
   NDB_INIT(argv[0]);
 
   load_defaults("my",load_default_groups,&argc,&argv);
@@ -206,8 +292,36 @@
   if ((ho_error=handle_options(&argc, &argv, my_long_options, 
 			       ndb_std_get_one_option)))
     exit(ho_error);
-
-start:
+  if (opt_interactive ||
+      opt_non_interactive ||
+      g_print_full_config) {
+    opt_daemon= 0;
+  }
+#ifdef NDB_WIN32
+#define CHECKFIRST(IR) if(strcmp(argv_[1],"-"#IR))return ndbout_c("-"#IR" must be first")
+  if(opt_install_svc)
+  {   CHECKFIRST(i);
+      int havename=(opt_install_svc_name!=0);
+      return install(argv_[0],opt_install_svc_name,argc_-1-havename,argv_+1+havename);
+  }
+  if(opt_remove_svc)
+  {   CHECKFIRST(r);
+      return remove(argv_[0],opt_remove_svc_name);   
+  }
+  if(opt_svc)
+  {
+	  ndbout_svc=&evtlog;
+	  useeventlog=1;
+	  return svc.Init(argv_[0],start);
+  }
+#endif
+  return start(0);
+}
+int restofmain(void*);
+int error_end();
+int the_end();
+int start(void*)
+{
   glob= new MgmGlobals;
 
   /**
@@ -221,12 +335,6 @@
 
   global_mgmt_server_check = 1;
 
-  if (opt_interactive ||
-      opt_non_interactive ||
-      g_print_full_config) {
-    opt_daemon= 0;
-  }
-
   if (opt_mycnf && opt_config_filename)
   {
     ndbout_c("Both --mycnf and -f is not supported");
@@ -235,36 +343,42 @@
 
   if (opt_mycnf == 0 && opt_config_filename == 0)
   {
-    struct stat buf;
-    if (stat("config.ini", &buf) != -1)
+      struct stat buf;
+      if (stat("config.ini", &buf) != -1)
       opt_config_filename = "config.ini";
   }
+
+  if (!opt_config_filename && !opt_connect_str)
+  {
+      ndbout_c("config file required");
+      return 0;
+  }
   
   glob->socketServer = new SocketServer();
 
-  MgmApiService * mapi = new MgmApiService();
+  mapi = new MgmApiService();
 
   glob->mgmObject = new MgmtSrvr(glob->socketServer,
 				 opt_config_filename,
 				 opt_connect_str);
 
   if (g_print_full_config)
-    goto the_end;
+    return the_end();
 
   if (glob->mgmObject->init())
-    goto error_end;
+    return error_end();
 
   my_setwd(NdbConfig_get_path(0), MYF(0));
 
   glob->localNodeId= glob->mgmObject->getOwnNodeId();
   if (glob->localNodeId == 0) {
-    goto error_end;
+    return error_end();
   }
 
   glob->port= glob->mgmObject->getPort();
 
   if (glob->port == 0)
-    goto error_end;
+    return error_end();
 
   glob->interface_name = 0;
   glob->use_specific_ip = false;
@@ -281,7 +395,7 @@
 	       "(perhaps a ndb_mgmd is already running),\n"
 	       "and if you are executing on the correct computer", 
 	       (glob->interface_name ? glob->interface_name : "*"), glob->port);
-      goto error_end;
+      return error_end();
     }
     free(glob->interface_name);
     glob->interface_name = 0;
@@ -295,29 +409,37 @@
 	     "and if you are executing on the correct computer", 
 	     glob->port);
     delete mapi;
-    goto error_end;
+    return error_end();
   }
 
   if(!glob->mgmObject->check_start()){
     ndbout_c("Unable to check start management server.");
     ndbout_c("Probably caused by illegal initial configuration file.");
-    goto error_end;
+    return error_end();
   }
 
-  if (opt_daemon) {
+  if (opt_daemon||opt_svc) {
     // Become a daemon
     char *lockfile= NdbConfig_PidFileName(glob->localNodeId);
     char *logfile=  NdbConfig_StdoutFileName(glob->localNodeId);
     NdbAutoPtr<char> tmp_aptr1(lockfile), tmp_aptr2(logfile);
 
-    if (NdbDaemon_Make(lockfile, logfile, 0) == -1) {
-      ndbout << "Cannot become daemon: " << NdbDaemon_ErrorText << endl;
+    if (NdbDaemonService_Make(my_progname,lockfile, logfile, 0, restofmain) == -1) {
+	  BaseString msg("Cannot become daemon: ");
+	  msg.append(NdbDaemon_ErrorText);
+      ndbout_c(msg.c_str());
       return 1;
     }
+    return 0;
   }
-
+  restofmain(0);
+}
+int restofmain(void*)
+{
 #ifndef NDB_WIN32
   signal(SIGPIPE, SIG_IGN);
+#else
+  useeventlog=0;
 #endif
   {
     BaseString error_string;
@@ -325,7 +447,7 @@
       ndbout_c("Unable to start management server.");
       ndbout_c("Probably caused by illegal initial configuration file.");
       ndbout_c(error_string.c_str());
-      goto error_end;
+      return error_end();
     }
   }
 
@@ -371,14 +493,19 @@
   // We disconnect from the ConfigRetreiver mgmd when we delete glob below
   glob->socketServer->stopSessions(true);
   g_eventLogger.info("Shutdown complete");
- the_end:
   delete glob;
+  ndb_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
+  return 1;
+}
+int the_end()
+{ delete glob;
   if(g_RestartServer)
-    goto start;
+    return start(0);
   ndb_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
   return 0;
- error_end:
-  delete glob;
+}
+int error_end()
+{ delete glob;
   ndb_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
   return 1;
 }

