Wed Jul 20 14:59:56 PDT 2005
- Previous message: [Slony1-commit] By dpage: New Directory
- Next message: [Slony1-commit] By dpage: Fix 'make install' for Win32
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Log Message:
-----------
Initial Win32 port, from Magnus Hagander, with minor tweaks by Dave Page. Needs service and eventlog code yet, but works nicely from the command line :-)
Changes:
* Added "override" to LDFLAGS in the Makefile. I am no makefile guru, so
I don't really know why :-) But it was there for CFLAGS, and without it,
the pthreads library simply wasn't added to the build command...
* For win32 only, added mandatory link to "wsock32" winsock functions,
required so we can access TCP/IP functions at all.
* #ifdef out the whole "watchdog process" for win32. Win32 does not have
signals, so we don't need a special process to catch and channel those.
And we expect the service control manager to deal with restarts as
required (when it comes).
* As a consequence of win32 not having signals, change exits to just do
exit() instead of sigterm:ing the own process. This includes modifying
slon_abort() and slon_restart() (_restart seems never to be used?)
* Import pgpipe implementation from postgresql backend, and change all
read/write to piperead/pipewrite - same as in the pg backend. This is
rquired because on win32 you can't "select()" on a pipe. The pgpipe
implementation uses TCP sockets instead.
* Remove the sched_shutdown() code per my previous mail. Not strictly a
part of the win32 work...
* Start and stop winsock as appropriate.
Modified Files:
--------------
slony1-engine/src/slon:
Makefile (r1.33 -> r1.34)
cleanup_thread.c (r1.26 -> r1.27)
local_listen.c (r1.31 -> r1.32)
misc.c (r1.18 -> r1.19)
misc.h (r1.6 -> r1.7)
runtime_config.c (r1.24 -> r1.25)
scheduler.c (r1.20 -> r1.21)
slon.c (r1.52 -> r1.53)
slon.h (r1.48 -> r1.49)
Added Files:
-----------
slony1-engine/src/slon/port:
pipe.c (r1.1)
-------------- next part --------------
Index: misc.h
===================================================================
RCS file: /usr/local/cvsroot/slony1/slony1-engine/src/slon/misc.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -Lsrc/slon/misc.h -Lsrc/slon/misc.h -u -w -r1.6 -r1.7
--- src/slon/misc.h
+++ src/slon/misc.h
@@ -25,6 +25,17 @@
extern int slon_scanint64(char *str, int64 * result);
#endif
+#ifdef WIN32
+/* Remove some defines that are imported from the postgresql headers, but
+ * that refer to backend porting functions. */
+#undef select
+#undef accept
+#undef connect
+#undef socket
+#undef recv
+#undef send
+#endif
+
/*
* Local Variables:
* tab-width: 4
Index: scheduler.c
===================================================================
RCS file: /usr/local/cvsroot/slony1/slony1-engine/src/slon/scheduler.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -Lsrc/slon/scheduler.c -Lsrc/slon/scheduler.c -u -w -r1.20 -r1.21
--- src/slon/scheduler.c
+++ src/slon/scheduler.c
@@ -192,7 +192,7 @@
* Give the scheduler thread a heads up, release the master lock and wait
* for it to tell us that the event we're waiting for happened.
*/
- if (write(sched_wakeuppipe[1], "x", 1) < 0)
+ if (pipewrite(sched_wakeuppipe[1], "x", 1) < 0)
{
perror("sched_wait_conn: write()");
exit(-1);
@@ -326,7 +326,7 @@
*/
if (num_wakeup > 0)
{
- if (write(sched_wakeuppipe[1], "x", 1) < 0)
+ if (pipewrite(sched_wakeuppipe[1], "x", 1) < 0)
{
perror("sched_wait_conn: write()");
slon_abort();
@@ -517,7 +517,7 @@
char buf [1];
rc--;
- if (read(sched_wakeuppipe[0], buf, 1) != 1)
+ if (piperead(sched_wakeuppipe[0], buf, 1) != 1)
{
perror("sched_mainloop: read()");
sched_status = SCHED_STATUS_ERROR;
@@ -638,60 +638,6 @@
/*
- * ---------- sched_sighandler
- *
- * After starting up the sole purpose of the main thread (the original process)
- * is to respond to signals while waiting for the scheduler to finish. The
- * signal handler is here because it is actually sched_start_mainloop() that
- * arranges for the signal handling and sched_wait_mainloop() that enables
- * them. And the only one really interested in the signals is the scheduler
- * thread ... but that's doing select(2) mainly and we have to avoid race
- * conditions with signals. ----------
- */
-static void
-sched_shutdown()
-{
- /*
- * Lock the master mutex and make sure that we are the main thread
- */
- pthread_mutex_lock(&sched_master_lock);
- if (!pthread_equal(pthread_self(), sched_main_thread))
- {
- slon_log(SLON_FATAL, "sched_sighandler: called in non-main thread\n");
- slon_abort();
- }
-
- /*
- * Set the scheduling status to shutdown
- */
- if (sched_status == SCHED_STATUS_OK)
- sched_status = SCHED_STATUS_SHUTDOWN;
-
- /*
- * Try to wakeup the scheduler thread by throwing a bait
- */
- if (sched_wakeuppipe[1] < 0)
- {
- slon_log(SLON_ERROR, "sched_sighandler: sockpair already closed\n");
- pthread_mutex_unlock(&sched_master_lock);
- return;
- }
- if (write(sched_wakeuppipe[1], "x", 1) < 0)
- {
- perror("sched_sighandler: write()");
- pthread_mutex_unlock(&sched_master_lock);
- exit(-1);
- }
-
- /*
- * Unlock the master mutex
- */
- pthread_mutex_unlock(&sched_master_lock);
-}
-
-
-
-/*
* ---------- sched_add_fdset
*
* Add a file descriptor to one of the global scheduler sets and adjust
Index: slon.h
===================================================================
RCS file: /usr/local/cvsroot/slony1/slony1-engine/src/slon/slon.h,v
retrieving revision 1.48
retrieving revision 1.49
diff -Lsrc/slon/slon.h -Lsrc/slon/slon.h -u -w -r1.48 -r1.49
--- src/slon/slon.h
+++ src/slon/slon.h
@@ -324,8 +324,10 @@
* ----------
*/
extern pid_t slon_pid;
+#ifndef WIN32
extern pid_t slon_ppid;
extern pid_t slon_cpid;
+#endif
extern char *rtcfg_cluster_name;
extern char *rtcfg_namespace;
extern char *rtcfg_conninfo;
@@ -344,6 +346,7 @@
* Functions in slon.c
* ----------
*/
+#ifndef WIN32
#define slon_abort() \
do { \
kill((slon_ppid == 0 ? slon_pid : slon_ppid), SIGTERM); \
@@ -353,6 +356,17 @@
do { \
kill((slon_ppid == 0 ? slon_pid : slon_ppid), SIGHUP); \
} while (0)
+#else /* WIN32 */
+/* On win32, we currently just bail out and let the service control manager
+ * deal with possible restarts */
+#define slon_abort() \
+WSACleanup(); \
+exit(1);
+#define slon_restart() \
+WSACleanup(); \
+exit(1);
+#endif
+
extern void slon_exit(int code);
extern int slon_restart_request;
Index: runtime_config.c
===================================================================
RCS file: /usr/local/cvsroot/slony1/slony1-engine/src/slon/runtime_config.c,v
retrieving revision 1.24
retrieving revision 1.25
diff -Lsrc/slon/runtime_config.c -Lsrc/slon/runtime_config.c -u -w -r1.24 -r1.25
--- src/slon/runtime_config.c
+++ src/slon/runtime_config.c
@@ -33,8 +33,10 @@
* ---------- Global data ----------
*/
pid_t slon_pid;
+#ifndef WIN32
pid_t slon_cpid;
pid_t slon_ppid;
+#endif
char *rtcfg_cluster_name = NULL;
char *rtcfg_namespace = NULL;
char *rtcfg_conninfo = NULL;
Index: misc.c
===================================================================
RCS file: /usr/local/cvsroot/slony1/slony1-engine/src/slon/misc.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -Lsrc/slon/misc.c -Lsrc/slon/misc.c -u -w -r1.18 -r1.19
--- src/slon/misc.c
+++ src/slon/misc.c
@@ -24,7 +24,9 @@
#include <sys/time.h>
#include <sys/types.h>
+#ifndef WIN32
#include <syslog.h>
+#endif
#include <stdarg.h>
#include "libpq-fe.h"
Index: local_listen.c
===================================================================
RCS file: /usr/local/cvsroot/slony1/slony1-engine/src/slon/local_listen.c,v
retrieving revision 1.31
retrieving revision 1.32
diff -Lsrc/slon/local_listen.c -Lsrc/slon/local_listen.c -u -w -r1.31 -r1.32
--- src/slon/local_listen.c
+++ src/slon/local_listen.c
@@ -160,7 +160,13 @@
slon_log(SLON_INFO,
"localListenThread: got restart notification - "
"signal scheduler\n");
+#ifndef WIN32
kill(getppid(), SIGHUP);
+#else
+ /* XXX */
+ /* Win32 defer to service manager to restart for now */
+ slon_abort();
+#endif
}
/*
Index: cleanup_thread.c
===================================================================
RCS file: /usr/local/cvsroot/slony1/slony1-engine/src/slon/cleanup_thread.c,v
retrieving revision 1.26
retrieving revision 1.27
diff -Lsrc/slon/cleanup_thread.c -Lsrc/slon/cleanup_thread.c -u -w -r1.26 -r1.27
--- src/slon/cleanup_thread.c
+++ src/slon/cleanup_thread.c
@@ -91,8 +91,12 @@
*/
if ((conn = slon_connectdb(rtcfg_conninfo, "local_cleanup")) == NULL)
{
+#ifndef WIN32
kill(getpid(), SIGTERM);
pthread_exit(NULL);
+#else
+ exit(0);
+#endif
/* slon_abort(); */
}
dbconn = conn->dbconn;
Index: slon.c
===================================================================
RCS file: /usr/local/cvsroot/slony1/slony1-engine/src/slon/slon.c,v
retrieving revision 1.52
retrieving revision 1.53
diff -Lsrc/slon/slon.c -Lsrc/slon/slon.c -u -w -r1.52 -r1.53
--- src/slon/slon.c
+++ src/slon/slon.c
@@ -24,16 +24,23 @@
#include <sys/types.h>
#include <sys/wait.h>
+#ifdef WIN32
+#include <winsock.h>
+#endif
+
#include "libpq-fe.h"
#include "c.h"
#include "slon.h"
#include "confoptions.h"
+
/*
* ---------- Global data ----------
*/
+#ifndef WIN32
int watchdog_pipe[2];
+#endif
int sched_wakeuppipe[2];
pthread_mutex_t slon_wait_listen_lock = PTHREAD_MUTEX_INITIALIZER;
@@ -53,9 +60,11 @@
static pthread_t main_thread;
static char *const *main_argv;
+#ifndef WIN32
static void sighandler(int signo);
static void main_sigalrmhandler(int signo);
static void slon_kill_child(void);
+#endif
int slon_log_level;
char *pid_file;
@@ -83,7 +92,12 @@
extern int optind;
extern char *optarg;
-#ifndef CYGWIN
+#ifdef WIN32
+ WSADATA wsaData;
+ int err;
+#endif
+
+#if !defined(CYGWIN) && !defined(WIN32)
struct sigaction act;
#endif
InitializeConfOptions();
@@ -155,8 +169,10 @@
* identifier
*/
slon_pid = getpid();
+#ifndef WIN32
slon_cpid = 0;
slon_ppid = 0;
+#endif
main_argv = argv;
if ((char *)argv[optind])
@@ -212,6 +228,16 @@
return 1;
}
+#ifdef WIN32
+ /*
+ * Startup the network subsystem, in case our libpq doesn't
+ */
+ err = WSAStartup(MAKEWORD(1, 1), &wsaData);
+ if (err != 0) {
+ slon_log(SLON_FATAL, "main: Cannot start the network subsystem - %d\n", err);
+ slon_exit(-1);
+ }
+#endif
/*
* Connect to the local database to read the initial configuration
@@ -268,17 +294,23 @@
* Pipes to be used as communication devices between the parent (watchdog)
* and child (worker) processes.
*/
- if (pipe(watchdog_pipe) < 0)
+#ifndef WIN32
+ if (pgpipe(watchdog_pipe) < 0)
{
slon_log(SLON_FATAL, "slon: parent pipe create failed -(%d) %s\n", errno,strerror(errno));
slon_exit(-1);
}
- if (pipe(sched_wakeuppipe) < 0)
+#endif
+ if (pgpipe(sched_wakeuppipe) < 0)
{
slon_log(SLON_FATAL, "slon: sched_wakeuppipe create failed -(%d) %s\n", errno,strerror(errno));
slon_exit(-1);
}
+ /* There is no watchdog process on win32. We delegate restarting and
+ * other such tasks to the Service Control Manager. And win32 doesn't
+ * support signals, so we don't need to catch them... */
+#ifndef WIN32
/*
* Fork here to allow parent process to trap signals and child process to
* handle real processing work creating a watchdog and worker process
@@ -290,11 +322,15 @@
slon_exit(-1);
}
else if (slon_cpid == 0) /* child */
+#endif /* WIN32 */
{
slon_pid = getpid();
+#ifndef WIN32
slon_ppid = getppid();
+#endif
slon_log(SLON_DEBUG2, "main: main process started\n");
+#ifndef WIN32
/*
* Wait for the parent process to initialize
*/
@@ -339,6 +375,7 @@
}
slon_log(SLON_DEBUG2, "main: end signal handler setup\n");
+#endif
/*
* Start the event scheduling system
@@ -619,13 +656,17 @@
* Wait for all remote threads to finish
*/
main_thread = pthread_self();
+#ifndef WIN32 /* XXX WIN32 no sigalarm, how fix? XXX */
signal(SIGALRM, main_sigalrmhandler);
alarm(20);
+#endif
slon_log(SLON_DEBUG2, "main: wait for remote threads\n");
rtcfg_joinAllRemoteThreads();
+#ifndef WIN32 /* XXX WIN32 XXX */
alarm(0);
+#endif
/*
* Wait for the local threads to finish
@@ -651,6 +692,7 @@
/*
* Tell parent that worker is done
*/
+#ifndef WIN32
slon_log(SLON_DEBUG2, "main: notify parent that worker is done\n");
if (write(watchdog_pipe[1], "c", 1) != 1)
@@ -658,11 +700,13 @@
slon_log(SLON_FATAL, "main: write to watchdog pipe failed -(%d) %s\n", errno,strerror(errno));
slon_exit(-1);
}
+#endif
slon_log(SLON_DEBUG1, "main: done\n");
exit(0);
}
+#ifndef WIN32 /* Again, no watchdog process on WIN32 */
else /* parent */
{
slon_log(SLON_DEBUG2, "slon: watchdog process started\n");
@@ -733,9 +777,11 @@
*/
slon_exit(0);
}
+#endif /* WIN32 */
}
+#ifndef WIN32
static void
main_sigalrmhandler(int signo)
{
@@ -814,7 +860,7 @@
slon_exit(-1);
}
- if (write(sched_wakeuppipe[1], "p", 1) != 1)
+ if (pipewrite(sched_wakeuppipe[1], "p", 1) != 1)
{
slon_log(SLON_FATAL, "main: write to worker pipe failed -(%d) %s\n", errno,strerror(errno));
kill(slon_cpid,SIGKILL);
@@ -852,11 +898,19 @@
slon_log(SLON_DEBUG2, "slon: worker process shutdown ok\n");
}
+#endif
void
slon_exit(int code)
{
+#ifdef WIN32
+ /* Cleanup winsock */
+ WSACleanup();
+
+ if (pid_file)
+#else
if (slon_ppid == 0 && pid_file)
+#endif
{
slon_log(SLON_DEBUG2, "slon: remove pid file\n");
unlink(pid_file);
Index: Makefile
===================================================================
RCS file: /usr/local/cvsroot/slony1/slony1-engine/src/slon/Makefile,v
retrieving revision 1.33
retrieving revision 1.34
diff -Lsrc/slon/Makefile -Lsrc/slon/Makefile -u -w -r1.33 -r1.34
--- src/slon/Makefile
+++ src/slon/Makefile
@@ -13,8 +13,8 @@
CC = $(PTHREAD_CC)
-override CFLAGS += $(PTHREAD_CFLAGS) -I$(slony_top_builddir) -I$(pgincludedir)
-LDFLAGS += $(rpath) $(PTHREAD_LIBS) -L$(pglibdir) -lpq
+override CFLAGS += $(PTHREAD_CFLAGS) -I$(slony_top_builddir) -I$(slony_top_builddir)/$(slony_subdir) -I$(pgincludedir)
+override LDFLAGS += $(rpath) $(PTHREAD_LIBS) -L$(pglibdir) -lpq
PROG = slon
@@ -45,8 +45,13 @@
LDFLAGS+= ${NETSNMP_AGENTLIBS}
endif
+ifeq ($(PORTNAME), win32)
+OBJS += port/pipe.o
+override LDFLAGS += -lwsock32
+endif
+
-DISTFILES = Makefile README $(wildcard *.c) $(wildcard *.h) $(wildcard *.l) $(wildcard *.y)
+DISTFILES = Makefile README $(wildcard *.c) $(wildcard port/*.c) $(wildcard *.h) $(wildcard *.l) $(wildcard *.y)
ALL = \
$(PROG)
--- /dev/null
+++ src/slon/port/pipe.c
@@ -0,0 +1,95 @@
+/*-------------------------------------------------------------------------
+ *
+ * pipe.c
+ * pipe()
+ *
+ * Copyright (c) 1996-2005, PostgreSQL Global Development Group
+ *
+ * This is a replacement version of pipe for Win32 which allows
+ * returned handles to be used in select(). Note that read/write calls
+ * must be replaced with recv/send.
+ *
+ * $Id: pipe.c,v 1.1 2005/07/20 13:59:47 dpage Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+#include "misc.h"
+
+#ifdef WIN32
+int
+pgpipe(int handles[2])
+{
+ SOCKET s;
+ struct sockaddr_in serv_addr;
+ int len = sizeof(serv_addr);
+
+ handles[0] = handles[1] = INVALID_SOCKET;
+
+ if ((s = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
+ {
+ slon_log(SLON_ERROR, "pgpipe: failed to create socket: %ui", WSAGetLastError());
+ return -1;
+ }
+
+ memset((void *) &serv_addr, 0, sizeof(serv_addr));
+ serv_addr.sin_family = AF_INET;
+ serv_addr.sin_port = htons(0);
+ serv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ if (bind(s, (SOCKADDR *) & serv_addr, len) == SOCKET_ERROR)
+ {
+ slon_log(SLON_ERROR, "pgpipe: failed to bind: %ui", WSAGetLastError());
+ closesocket(s);
+ return -1;
+ }
+ if (listen(s, 1) == SOCKET_ERROR)
+ {
+ slon_log(SLON_ERROR, "pgpipe: failed to listen: %ui", WSAGetLastError());
+ closesocket(s);
+ return -1;
+ }
+ if (getsockname(s, (SOCKADDR *) & serv_addr, &len) == SOCKET_ERROR)
+ {
+ slon_log(SLON_ERROR, "pgpipe: failed to getsockname: %ui", WSAGetLastError());
+ closesocket(s);
+ return -1;
+ }
+ if ((handles[1] = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
+ {
+ slon_log(SLON_ERROR, "pgpipe: failed to create socket 2: %ui", WSAGetLastError());
+ closesocket(s);
+ return -1;
+ }
+
+ if (connect(handles[1], (SOCKADDR *) & serv_addr, len) == SOCKET_ERROR)
+ {
+ slon_log(SLON_ERROR, "pgpipe: filed to connect socket: %ui", WSAGetLastError());
+ closesocket(s);
+ return -1;
+ }
+ if ((handles[0] = accept(s, (SOCKADDR *) & serv_addr, &len)) == INVALID_SOCKET)
+ {
+ slon_log(SLON_ERROR, "pgpipe: failed to accept socket: %ui", WSAGetLastError());
+ closesocket(handles[1]);
+ handles[1] = INVALID_SOCKET;
+ closesocket(s);
+ return -1;
+ }
+ closesocket(s);
+ return 0;
+}
+
+
+int
+piperead(int s, char *buf, int len)
+{
+ int ret = recv(s, buf, len, 0);
+
+ if (ret < 0 && WSAGetLastError() == WSAECONNRESET)
+ /* EOF on the pipe! (win32 socket based implementation) */
+ ret = 0;
+ return ret;
+}
+
+#endif
- Previous message: [Slony1-commit] By dpage: New Directory
- Next message: [Slony1-commit] By dpage: Fix 'make install' for Win32
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
More information about the Slony1-commit mailing list