2941 Magnus Svensson 2009-03-13 [merge]
Merge
modified:
storage/ndb/include/portlib/my_daemon.h
storage/ndb/src/common/portlib/my_daemon.cc
storage/ndb/src/mgmsrv/MgmtSrvr.hpp
storage/ndb/src/mgmsrv/main.cpp
2940 Jonas Oreland 2009-03-13 [merge]
merge 63 to 64
modified:
storage/ndb/test/ndbapi/test_event.cpp
storage/ndb/test/src/NdbRestarts.cpp
=== modified file 'storage/ndb/include/portlib/my_daemon.h'
--- a/storage/ndb/include/portlib/my_daemon.h 2009-02-24 11:28:08 +0000
+++ b/storage/ndb/include/portlib/my_daemon.h 2009-03-13 09:48:24 +0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 2008 Sun Microsystems
+/* Copyright (C) 2008-2009 Sun Microsystems, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -16,120 +16,52 @@
#ifndef MY_DAEMON_H
#define MY_DAEMON_H
-#ifndef DAEMONEXPORT
-#define DAEMONEXPORT extern
-#endif
-
C_MODE_START
+
+typedef int (*my_daemon_run_t)(int, char**);
+typedef void (*my_daemon_stop_t)(void);
+
/*
- all functions return 0 for success so the retval can be returned from main()
+ Used from "mini" main to run an application as a
+ service on windows, where the "run" function will be run
+ as a service if first arg is --service=<service_name>.
- 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()
+ Defaults to "normal" behaviour which is to call "run" directly
+ with argc/argv
- 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
*/
+int my_daemon_init(int argc, char** argv,
+ my_daemon_run_t run, my_daemon_stop_t stop,
+ const char* name, const char* display_name);
-typedef int (*daemon_start_t)(void *);
-typedef int (*daemon_onstop_t)();
-struct MY_DAEMON {
- daemon_start_t start;
- daemon_onstop_t stop;
-};
+/*
+ To be called at the point where an application needs to daemonize
+ itself.
-int my_daemon_run(char *name, struct MY_DAEMON*d);
-int my_daemon_files_run(char *name, struct MY_DAEMON*d, char *node_id);
+ The daemonizing will on most platforms do a fork itself as a daemon.
+ I.e fork, setsid, create pidfile, and redirect all output to logfile.
-/*
- if any of the functions in my_daemon return non-zero (failure)
- then my_daemon_error contains the error message
+ On windows, only create pidfile and redirect.
*/
-extern char my_daemon_error[];
+int my_daemonize(const char* pidfile_name, const char *logfile_name);
-/*
- 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);
+ To be called when application should exit.
-int maybe_install_or_remove_service(int argc_,char**argv_,char*opts_remove,char*opts_install,char*default_name);
+ Performs an ordered shutdown of service if running as a serevice.
+ */
+void my_daemon_exit(int status);
-/*
- 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()
+ if any of the functions in my_daemon return non-zero (failure)
+ then my_daemon_error contains the error message
*/
-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);
+extern char my_daemon_error[];
C_MODE_END
+
#endif //MY_DAEMON_H
=== modified file 'storage/ndb/src/common/portlib/my_daemon.cc'
--- a/storage/ndb/src/common/portlib/my_daemon.cc 2009-02-26 10:38:16 +0000
+++ b/storage/ndb/src/common/portlib/my_daemon.cc 2009-03-13 09:48:24 +0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 2008 Sun Microsystems
+/* Copyright (C) 2008-2009 Sun Microsystems, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -20,303 +20,354 @@
#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
+#include <BaseString.hpp>
+
+static FILE *dlog_file;
-static char *daemon_name;
-static long daemonpid;
+static int ERR1(const char* fmt, ...)
+ ATTRIBUTE_FORMAT(printf, 1, 2);
-#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);
+char my_daemon_error[1024];
+static int ERR1(const char* fmt, ...)
+{
+ va_list argptr;
+ va_start(argptr, fmt);
+ my_vsnprintf(my_daemon_error,sizeof(my_daemon_error),fmt,argptr);
va_end(argptr);
return 1;
}
-struct MY_DAEMON g_daemon;
#ifdef _WIN32
-static int init();
-static int stopper(void*)
+
+#include <nt_servc.h>
+static NTService g_ntsvc;
+
+static int g_argc;
+static char** g_argv;
+
+static HANDLE g_shutdown_event;
+static my_daemon_stop_t g_stop_func;
+static my_daemon_run_t g_run_func;
+
+
+static void stopper_thread(void*)
{
- WaitForSingleObject(g_shutdown_evt,INFINITE);
- return g_daemon.stop();
+ // Wait forever until the shutdown event is signaled
+ WaitForSingleObject(g_shutdown_event, INFINITE);
+
+ // Call the installed stop callback function
+ g_stop_func();
}
-#endif
-int my_daemon_run(char *name,struct MY_DAEMON*d)
+
+/*
+ This function is called like:
+ <service dipatcher thread>
+ - NTService::ServiceMain
+ - NTService::StartService
+ <new service thread>
+ -service_main
+ and runs the "application" through
+ the installed callback function "g_run_func"
+*/
+
+static int service_main(NTService* service)
{
- 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;
+ /* Inform SCM that service is running and can be stopped */
+ service->SetRunning();
+
+ /* Run the application with with argc/argv */
+ return g_run_func(g_argc, g_argv);
}
-#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;
+/*
+ Check if "arg" contains "option", return the
+ options argument in opt_arg(i.e everything after =)
+*/
+
+static bool
+is_option(const char* arg, const char* option, const char** opt_arg)
+{
+ size_t option_len = strlen(option);
+ if (strncmp(arg, option, option_len))
+ return false; // No hit
+
+ // Step forward to the end of --<option>
+ arg+= option_len;
+ if (*arg == '=')
+ {
+ /* Assign opt_arg pointer to first char after = */
+ *opt_arg= arg + 1;
+ }
+ return true;
}
-char *my_daemon_make_svc_cmd(int n, char **v, char *name)
+
+static int
+install_or_remove_service(int argc, char** argv,
+ const char* name, const char* display_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 (argc < 2)
+ return 0; // Nothing to do
+
+ /* --remove as first argument on command line */
+ const char* remove_name = NULL;
+ if (is_option(argv[1], "--remove", &remove_name))
+ {
+ if (remove_name)
+ {
+ /* Use the part after = as service name _and_ display name */
+ name = display_name = remove_name;
+ }
+ printf("Removing service '%s'\n", display_name);
+ /* Remove service. Ignore return value, error is printed to stdout */
+ (void)g_ntsvc.Remove(name);
+ return 1;
}
- 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;
+
+ const char* install_name = NULL;
+ if (is_option(argv[1], "--install", &install_name))
+ {
+ if (install_name)
+ {
+ /* Use the part after = as service name _and_ display name */
+ name = display_name = install_name;
}
- printf("Installing service \"%s\"\n",svc);
- printf("as \"%s\"\n",svc_cmd);
- return my_daemon_install(svc, svc_cmd);
+
+ BaseString cmd;
+
+ /* Full path to this binary */
+ char exe[MAX_PATH];
+ GetModuleFileName(NULL, exe, sizeof(exe));
+ cmd.assfmt("\"%s\"", exe);
+
+ /* The option that tells which service is starting */
+ cmd.appfmt(" \"--service=%s\"", name);
+
+ /* All the args after --install(which must be first) */
+ for (int i = 2; i < argc; i++)
+ cmd.appfmt(" \"%s\"", argv[i]);
+
+ printf("Installing service '%s' as '%s'\n", display_name, cmd.c_str());
+
+ /* Install service. Ignore return value, error is printed to stdout */
+ (void)g_ntsvc.Install(1, name, display_name, cmd.c_str());
+ return 1;
}
- return -1;
+ return 0;
}
+#endif
+
-int my_daemon_install(const char *name, const char *cmd)
+int my_daemon_init(int argc, char** argv,
+ my_daemon_run_t run, my_daemon_stop_t stop,
+ const char* name, const char* display_name)
{
- SC_HANDLE svc= 0, scm= 0;
+#ifdef _WIN32
+ // Check for --install or --remove options
+ if (install_or_remove_service(argc, argv, name, display_name))
+ return 1;
+
+ // Check if first arg is --service -> run as service
+ const char* service_name = NULL;
+ if (argc > 1 &&
+ is_option(argv[1], "--service", &service_name) &&
+ service_name)
+ {
+ // Create the shutdown event that will be signaled
+ // by g_ntsvc if the service is to be stopped
+ g_shutdown_event = CreateEvent(0, 0, 0, 0);
+
+ // Install the shutdown event in g_ntsvc
+ g_ntsvc.SetShutdownEvent(g_shutdown_event);
+
+ // Save the stop function so it can be called
+ // by 'stopper_thread'
+ g_stop_func = stop;
+
+ // Create a thread whose only purpose is to wait for
+ // the shutdown event to be signaled and then call the 'stop'
+ // function
+ uintptr_t stop_thread = _beginthread(stopper_thread,0,0);
+ if(!stop_thread)
+ return ERR1("couldn't start stopper thread");
+
+ // Save the run function so it can be called
+ // by 'service_main'
+ g_run_func = run;
+
+ // Build argv without --service
+ BaseString cmd;
+ for (int i = 2; i < argc; i++)
+ cmd.appfmt(" %s", argv[i]);
+ g_argv = BaseString::argify(argv[0], cmd.c_str());
+ g_argc = argc - 1;
+
+ // Start the service thread and let it run 'service_main'
+ // This call will not return until the service thread returns
+ return g_ntsvc.Init(service_name, service_main);
+ }
+#endif
+
+ // Default behaviour, run the "run" function which
+ // should be the "applications" real main
+ return run(argc, argv);
- 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()
+
+
+#ifdef _WIN32
+
+#define F_TLOCK _LK_NBLCK
+#define F_ULOCK _LK_UNLCK
+#define F_LOCK _LK_LOCK
+
+static inline int lockf(int fd, int cmd, off_t len)
{
- close(pidfd);
- fclose(my_dlog);
- return 0;
+ return _locking(fd, cmd, len);
}
-static const char *pidfile, *logfile;
-int my_daemon_prefiles(const char *pidfil, const char *logfil)
+static inline int ftruncate(int fd, off_t length)
{
- int n;
- char buf[64];
+ return _chsize(fd, length);
+}
+#endif
+
- my_dlog= 0;
- pidfile= pidfil;
- logfile= logfil;
- pidfd= logfd= -1;
- /* open log file before becoming daemon */
- if (logfile != NULL)
+static int
+check_files(const char *pidfile_name,
+ const char *logfile_name,
+ int *pidfd_ret, int *logfd_ret)
+{
+ /* Open log file if any */
+ if (logfile_name)
{
- logfd= open(logfile, O_CREAT | O_WRONLY | O_APPEND, 0644);
+ int logfd = open(logfile_name, O_CREAT | O_WRONLY | O_APPEND, 0644);
if(logfd == -1)
- return ERR1("%s: open for write failed\n", logfile);
- my_dlog= fdopen(logfd, "a");
+ return ERR1("Failed to open logfile '%s' for write, errno: %d",
+ logfile_name, errno);
+ dlog_file = fdopen(logfd, "a");
+ *logfd_ret = logfd;
}
+
/* 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);
+ if (!pidfile_name)
+ return ERR1("Missing pid file name");
+ int pidfd= open(pidfile_name, O_CREAT | O_RDWR, 0644);
+ if (pidfd == -1)
+ return ERR1("Failed to open pidfile '%s' for write, errno: %d",
+ pidfile_name, errno);
+
/* 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);
+ char buf[32];
+ int bytes_read = read(pidfd, buf, sizeof(buf));
+ if(bytes_read < 0)
+ return ERR1("Failed to read from pidfile '%s', errno: %d",
+ pidfile_name, errno);
+ buf[bytes_read]= 0;
+ long currpid= 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 */
+ return ERR1("Failed to lseek pidfile '%s', errno: %d",
+ pidfile_name, errno);
+
+ /* Check that file can be locked */
if(lockf(pidfd, F_TLOCK, 0) == -1)
+ {
if(errno == EACCES || errno == EAGAIN)
- return ERR1("pidfile: already locked by pid=%ld\n", daemonpid);
+ return ERR1("Failed to lock pidfile '%s', already locked by "
+ "pid=%ld, errno: %d", pidfile_name, currpid, errno);
+ }
if(lockf(pidfd, F_ULOCK, 0) == -1)
- return ERR1("%s: fail to unlock\n", pidfile);
-#endif
+ return ERR1("Failed to unlock pidfile '%s', errno: %d",
+ pidfile_name, errno);
+
+ *pidfd_ret = pidfd;
return 0;
}
-int my_daemon_files()
+
+static int
+do_files(const char *pidfile_name, int pidfd, int logfd)
{
- 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
+ /* Lock the lock file */
+ if (lockf(pidfd, F_LOCK, 0) == -1)
+ return ERR1("Failed to lock pidfile '%s', errno: %d",
+ pidfile_name, errno);
+
/* 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);
+ if (ftruncate(pidfd, 0) == -1)
+ return ERR1("Failed to truncate file '%s', errno: %d",
+ pidfile_name, errno);
+
+ char buf[32];
+ int length = my_snprintf(buf, sizeof(buf), "%ld", (long)getpid());
+ if (write(pidfd, buf, length) != length)
+ return ERR1("Failed to write pid to pidfile '%s', errno: %d",
+ pidfile_name, errno);
+
/* 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);
+ const char* fname = IF_WIN("nul:", "/dev/null");
+ if (open(fname, O_RDONLY) == -1)
+ return ERR1("Failed to open '%s', errno: %d", fname, errno);
+
#ifdef _WIN32 //no stdout/stderr on windows service
- *stdout= *stderr= *my_dlog;
+ *stdout= *stderr= *dlog_file;
#else
- if (logfd != 0)
+ if (logfd != -1)
{
dup2(logfd, 1);
dup2(logfd, 2);
close(logfd);
- my_dlog= stdout;
+ dlog_file= stdout;
}
#endif
+
return 0;
}
-#ifdef _WIN32
-HANDLE hExitEvent;
-static int evtlog(char *s)
+int my_daemonize(const char* pidfile_name, const char *logfile_name)
{
- 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;
-}
+ int pidfd = -1, logfd = -1;
+ if (check_files(pidfile_name, logfile_name, &pidfd, &logfd))
+ return 1;
+
+#ifndef _WIN32
+ pid_t child = fork();
+ if (child == -1)
+ return ERR1("fork failed, errno: %d, error: %s", errno, strerror(errno));
+
+ /* Exit if we are the parent */
+ if (child != 0)
+ exit(0);
+
+ /* Become process group leader */
+ if(setsid() == -1)
+ return ERR1("Failed to setsid, errno: %d", errno);
+
+#endif
+
+ if (do_files(pidfile_name, pidfd, logfd))
+ return 1;
-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)
+void my_daemon_exit(int status)
{
- return !g_ntsvc.Remove((LPCSTR)name);
-}
+#ifdef _WIN32
+ /*
+ Stop by calling NtService::Stop if running
+ as a service(i.e g_shutdown_event created)
+ */
+ if (g_shutdown_event)
+ g_ntsvc.Stop();
#endif
+ exit(status);
+}
=== modified file 'storage/ndb/src/mgmsrv/MgmtSrvr.hpp'
--- a/storage/ndb/src/mgmsrv/MgmtSrvr.hpp 2009-02-26 14:52:41 +0000
+++ b/storage/ndb/src/mgmsrv/MgmtSrvr.hpp 2009-03-13 09:48:24 +0000
@@ -132,7 +132,6 @@ 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-02-24 11:28:08 +0000
+++ b/storage/ndb/src/mgmsrv/main.cpp 2009-03-13 09:48:24 +0000
@@ -86,7 +86,6 @@ 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 },
@@ -153,9 +152,6 @@ static char **defaults_argv;
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();
@@ -165,30 +161,13 @@ static void 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
+ my_daemon_exit(result);
}
-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)
+static int mgmd_main(int argc, char** argv)
{
NDB_INIT(argv[0]);
- argc_= argc;
- argv_= argv;
g_eventLogger->setCategory("MgmSrvr");
@@ -202,36 +181,27 @@ int main(int argc, char** argv)
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)))
mgmd_exit(ho_error);
if (opts.interactive ||
opts.non_interactive ||
- opts.print_full_config ||
- IF_WIN(1,0)) {
+ opts.print_full_config) {
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
+ if (opts.daemon)
+ {
+ /* Write eventlog output to file for easier debugging */
+ g_eventLogger->createFileHandler("c:\\ndb_mgmd_debug.log");
+ g_eventLogger->info("StdoutFileName: %s", NdbConfig_StdoutFileName(0));
+ g_eventLogger->info("get_path: %s", NdbConfig_get_path(0));
+ g_eventLogger->info("GetCommandLine: %s", GetCommandLine());
+ }
#endif
#endif
/* Output to console initially */
@@ -253,103 +223,92 @@ int main(int argc, char** argv)
#if !defined NDB_WIN32
signal(SIGPIPE, SIG_IGN);
#endif
- return start();
-}
-int daemon_stop()
-{
- g_StopServer= true;
- return 0;
-}
+ while (!g_StopServer)
+ {
+ g_eventLogger->info("NDB Cluster Management Server. %s",
+ NDB_VERSION_STRING);
-int start()
-{
- g_eventLogger->info("NDB Cluster Management Server. %s", NDB_VERSION_STRING);
+ mgm= new MgmtSrvr(opts, opt_connect_str);
+ if (mgm == NULL) {
+ g_eventLogger->critical("Out of memory, couldn't create MgmtSrvr");
+ mgmd_exit(1);
+ }
- 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);
- }
+ /* Init mgm, load or fetch config */
+ if (!mgm->init()) {
+ delete mgm;
+ mgmd_exit(1);
+ }
- /* Init mgm, load or fetch config */
- if (!mgm->init()) {
- delete mgm;
- mgmd_exit(1);
- }
+ my_setwd(NdbConfig_get_path(0), MYF(0));
- my_setwd(NdbConfig_get_path(0), MYF(0));
-#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");
+ if (opts.daemon)
+ {
+ NodeId localNodeId= mgm->getOwnNodeId();
+ if (localNodeId == 0) {
+ g_eventLogger->error("Couldn't get own node id");
+ delete mgm;
+ mgmd_exit(1);
+ }
+
+ char *lockfile= NdbConfig_PidFileName(localNodeId);
+ char *logfile= NdbConfig_StdoutFileName(localNodeId);
+ if (my_daemonize(lockfile, logfile))
+ {
+ g_eventLogger->error("Couldn't start as daemon, error: '%s'",
+ my_daemon_error);
+ mgmd_exit(1);
+ }
+ }
+
+ /* Start mgm services */
+ if (!mgm->start()) {
delete mgm;
mgmd_exit(1);
}
- struct MY_DAEMON thedaemon= {event_loop,daemon_stop};
- char *lockfile= NdbConfig_PidFileName(localNodeId);
- char *logfile= NdbConfig_StdoutFileName(localNodeId);
- 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 (opts.interactive) {
+ int port= mgm->getPort();
+ BaseString con_str;
+ if(opts.bind_address)
+ con_str.appfmt("host=%s:%d", opts.bind_address, port);
+ else
+ con_str.appfmt("localhost:%d", port);
+ Ndb_mgmclient com(con_str.c_str(), 1);
+ while(!g_StopServer){
+ if (!read_and_execute(&com, "ndb_mgm> ", 1))
+ g_StopServer = true;
+ }
}
- if(my_daemon_files()) {
- g_eventLogger->error("daemon_files %s", my_daemon_error);
- mgmd_exit(1);
+ else {
+ while (!g_StopServer)
+ NdbSleep_MilliSleep(500);
}
- 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);
-}
-int event_loop(void*)
-{
- if (!mgm->start()) { /* Start mgm services */
+ g_eventLogger->info("Shutting down server...");
delete mgm;
- mgmd_exit(1);
- }
+ g_eventLogger->info("Shutdown complete");
- if(opts.interactive) {
- int port= mgm->getPort();
- BaseString con_str;
- if(opts.bind_address)
- con_str.appfmt("host=%s:%d", opts.bind_address, port);
- else
- con_str.appfmt("localhost:%d", port);
- Ndb_mgmclient com(con_str.c_str(), 1);
- while(g_StopServer != true && read_and_execute(&com, "ndb_mgm> ", 1));
- }
- else {
- while(g_StopServer != true) {
- NdbSleep_MilliSleep(500);
+ if(g_RestartServer){
+ g_eventLogger->info("Restarting server...");
+ g_RestartServer= g_StopServer= false;
}
}
- g_eventLogger->info("Shutting down server...");
- delete mgm;
- g_eventLogger->info("Shutdown complete");
-
- if(g_RestartServer){
- g_eventLogger->info("Restarting server...");
- g_RestartServer= g_StopServer= false;
- int ex= start();
- if(ex)
- mgmd_exit(ex);
- }
-
mgmd_exit(0);
return 0;
}
+
+static void mgmd_stop(void)
+{
+ g_StopServer= true;
+}
+
+
+int main(int argc, char** argv)
+{
+ return my_daemon_init(argc, argv, mgmd_main, mgmd_stop,
+ "ndb_mgmd", "MySQL Cluster Management Server");
+}
| Thread |
|---|
| • bzr push into mysql-5.1-telco-7.0 branch (msvensson:2940 to 2941) | Magnus Svensson | 13 Mar |