diff --git a/symmetric-wrapper/src/main/java/org/jumpmind/symmetric/wrapper/WindowsService.java b/symmetric-wrapper/src/main/java/org/jumpmind/symmetric/wrapper/WindowsService.java index 8dbd6f9562..ef14fd4a9b 100644 --- a/symmetric-wrapper/src/main/java/org/jumpmind/symmetric/wrapper/WindowsService.java +++ b/symmetric-wrapper/src/main/java/org/jumpmind/symmetric/wrapper/WindowsService.java @@ -20,6 +20,8 @@ import com.sun.jna.platform.win32.WinNT.HANDLE; import com.sun.jna.platform.win32.Winsvc; import com.sun.jna.platform.win32.Winsvc.SC_HANDLE; +import com.sun.jna.platform.win32.Winsvc.SC_STATUS_TYPE; +import com.sun.jna.ptr.IntByReference; @IgnoreJRERequirement public class WindowsService extends WrapperService { @@ -54,18 +56,24 @@ public void start() { Advapi32Ex advapi = Advapi32Ex.INSTANCE; SC_HANDLE manager = openServiceManager(); SC_HANDLE service = advapi.OpenService(manager, config.getName(), Winsvc.SERVICE_ALL_ACCESS); - - if (service != null) { - System.out.println("Waiting for server to start"); - if (!advapi.StartService(service, 0, null)) { - throwException("StartService"); + try { + if (service != null) { + System.out.println("Waiting for server to start"); + if (!advapi.StartService(service, 0, null)) { + throwException("StartService"); + } + Winsvc.SERVICE_STATUS_PROCESS status = waitForService(manager, service); + if (status.dwCurrentState == Winsvc.SERVICE_STOPPED) { + throw new WrapperException(Constants.RC_SERVER_EXITED, status.dwWin32ExitCode, "Unexpected exit from service"); + } + System.out.println("Started"); + } else { + throwException("OpenService"); } - advapi.CloseServiceHandle(service); - System.out.println("Started"); - } else { - throwException("OpenService"); + } finally { + closeServiceHandle(service); + closeServiceHandle(manager); } - advapi.CloseServiceHandle(manager); } } @@ -79,18 +87,24 @@ public void stop() { Advapi32Ex advapi = Advapi32Ex.INSTANCE; SC_HANDLE manager = openServiceManager(); SC_HANDLE service = advapi.OpenService(manager, config.getName(), Winsvc.SERVICE_ALL_ACCESS); - - if (service != null) { - System.out.println("Waiting for server to stop"); - if (!advapi.ControlService(service, Winsvc.SERVICE_CONTROL_STOP, new Winsvc.SERVICE_STATUS())) { - throwException("ControlService"); + try { + if (service != null) { + System.out.println("Waiting for server to stop"); + if (!advapi.ControlService(service, Winsvc.SERVICE_CONTROL_STOP, new Winsvc.SERVICE_STATUS())) { + throwException("ControlService"); + } + Winsvc.SERVICE_STATUS_PROCESS status = waitForService(manager, service); + if (status.dwCurrentState != Winsvc.SERVICE_STOPPED) { + throw new WrapperException(Constants.RC_FAIL_STOP_SERVER, status.dwWin32ExitCode, "Service did not stop"); + } + System.out.println("Stopped"); + } else { + throwException("OpenService"); } - advapi.CloseServiceHandle(service); - System.out.println("Stopped"); - } else { - throwException("OpenService"); + } finally { + closeServiceHandle(service); + closeServiceHandle(manager); } - advapi.CloseServiceHandle(manager); } } @@ -100,12 +114,11 @@ protected boolean isPidRunning(int pid) { if (pid != 0) { Kernel32 kernel = Kernel32.INSTANCE; HANDLE process = kernel.OpenProcess(Kernel32.SYNCHRONIZE, false, pid); - if (process == null) { - throwException("OpenProcess"); + if (process != null) { + int rc = kernel.WaitForSingleObject(process, 0); + kernel.CloseHandle(process); + isRunning = (rc == Kernel32.WAIT_TIMEOUT); } - int rc = kernel.WaitForSingleObject(process, 0); - kernel.CloseHandle(process); - isRunning = (rc == Kernel32.WAIT_TIMEOUT); } return isRunning; } @@ -162,27 +175,29 @@ public void install() { Advapi32Ex advapi = Advapi32Ex.INSTANCE; SC_HANDLE manager = openServiceManager(); SC_HANDLE service = advapi.OpenService(manager, config.getName(), Winsvc.SERVICE_ALL_ACCESS); - - if (service != null) { - throw new WrapperException(Constants.RC_ALREADY_INSTALLED, 0, "Service " + config.getName() + " is already installed"); - } else { - System.out.println("Installing " + config.getName() + " ..."); - - service = advapi.CreateService(manager, config.getName(), config.getDisplayName(), Winsvc.SERVICE_ALL_ACCESS, - WinsvcEx.SERVICE_WIN32_OWN_PROCESS, config.isAutoStart() ? WinsvcEx.SERVICE_AUTO_START - : WinsvcEx.SERVICE_DEMAND_START, WinsvcEx.SERVICE_ERROR_NORMAL, - commandToString(getWrapperCommand("init")), null, null, null, null, null); - + try { if (service != null) { - Advapi32Ex.SERVICE_DESCRIPTION desc = new Advapi32Ex.SERVICE_DESCRIPTION(config.getDescription()); - advapi.ChangeServiceConfig2(service, WinsvcEx.SERVICE_CONFIG_DESCRIPTION, desc); - advapi.CloseServiceHandle(service); + throw new WrapperException(Constants.RC_ALREADY_INSTALLED, 0, "Service " + config.getName() + " is already installed"); } else { - throwException("CreateService"); + System.out.println("Installing " + config.getName() + " ..."); + + service = advapi.CreateService(manager, config.getName(), config.getDisplayName(), Winsvc.SERVICE_ALL_ACCESS, + WinsvcEx.SERVICE_WIN32_OWN_PROCESS, config.isAutoStart() ? WinsvcEx.SERVICE_AUTO_START + : WinsvcEx.SERVICE_DEMAND_START, WinsvcEx.SERVICE_ERROR_NORMAL, + commandToString(getWrapperCommand("init")), null, null, null, null, null); + + if (service != null) { + Advapi32Ex.SERVICE_DESCRIPTION desc = new Advapi32Ex.SERVICE_DESCRIPTION(config.getDescription()); + advapi.ChangeServiceConfig2(service, WinsvcEx.SERVICE_CONFIG_DESCRIPTION, desc); + } else { + throwException("CreateService"); + } + + System.out.println("Done"); } - - advapi.CloseServiceHandle(manager); - System.out.println("Done"); + } finally { + closeServiceHandle(service); + closeServiceHandle(manager); } } @@ -195,17 +210,20 @@ public void uninstall() { Advapi32Ex advapi = Advapi32Ex.INSTANCE; SC_HANDLE manager = openServiceManager(); SC_HANDLE service = advapi.OpenService(manager, config.getName(), Winsvc.SERVICE_ALL_ACCESS); - if (service != null) { - System.out.println("Uninstalling " + config.getName() + " ..."); - if (!advapi.DeleteService(service)) { - throwException("DeleteService"); + try { + if (service != null) { + System.out.println("Uninstalling " + config.getName() + " ..."); + if (!advapi.DeleteService(service)) { + throwException("DeleteService"); + } + System.out.println("Done"); + } else { + throw new WrapperException(Constants.RC_NOT_INSTALLED, 0, "Service " + config.getName() + " is not installed"); } - advapi.CloseServiceHandle(service); - System.out.println("Done"); - } else { - throw new WrapperException(Constants.RC_NOT_INSTALLED, 0, "Service " + config.getName() + " is not installed"); + } finally { + closeServiceHandle(service); + closeServiceHandle(manager); } - advapi.CloseServiceHandle(manager); } protected SC_HANDLE openServiceManager() { @@ -246,6 +264,39 @@ protected void updateStatus(int status, int controlsAccepted) { } } + protected Winsvc.SERVICE_STATUS_PROCESS waitForService(SC_HANDLE manager, SC_HANDLE service) { + int seconds = 0; + Advapi32Ex advapi = Advapi32Ex.INSTANCE; + IntByReference bytesNeeded = new IntByReference(); + advapi.QueryServiceStatusEx(service, SC_STATUS_TYPE.SC_STATUS_PROCESS_INFO, null, 0, bytesNeeded); + Winsvc.SERVICE_STATUS_PROCESS status = new Winsvc.SERVICE_STATUS_PROCESS(bytesNeeded.getValue()); + + while (seconds <= 5) { + System.out.print("."); + if (!advapi.QueryServiceStatusEx(service, SC_STATUS_TYPE.SC_STATUS_PROCESS_INFO, + status, status.size(), bytesNeeded)) { + throwException("QueryServiceStatusEx"); + } + if (status.dwCurrentState == Winsvc.SERVICE_STOPPED) { + break; + } + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + } + seconds++; + } + System.out.println(""); + return status; + } + + protected void closeServiceHandle(SC_HANDLE handle) { + if (handle != null) { + Advapi32Ex advapi = Advapi32Ex.INSTANCE; + advapi.CloseServiceHandle(handle); + } + } + protected void throwException(String name) { int rc = Native.getLastError(); throw new WrapperException(Constants.RC_NATIVE_ERROR, rc, name + " returned error " + rc + ": " diff --git a/symmetric-wrapper/src/main/java/org/jumpmind/symmetric/wrapper/Wrapper.java b/symmetric-wrapper/src/main/java/org/jumpmind/symmetric/wrapper/Wrapper.java index 1f955ec71f..a54d0e3c20 100644 --- a/symmetric-wrapper/src/main/java/org/jumpmind/symmetric/wrapper/Wrapper.java +++ b/symmetric-wrapper/src/main/java/org/jumpmind/symmetric/wrapper/Wrapper.java @@ -1,21 +1,35 @@ package org.jumpmind.symmetric.wrapper; +import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; public class Wrapper { public static void main(String[] args) throws Exception { - if (args.length < 2) { + if (args.length < 1) { printUsage(); System.exit(Constants.RC_BAD_USAGE); } + String configFile = null; + if (args.length > 1) { + configFile = args[1]; + } else { + String dir = System.getenv("SYM_HOME"); + if (dir == null || dir.equals("")) { + System.out.println("Missing config file. Either specify config file or define SYM_HOME environment variable."); + System.exit(Constants.RC_MISSING_CONFIG_FILE); + } else { + configFile = dir + File.separator + "conf" + File.separator + "sym_service.conf"; + } + } + WrapperService service = WrapperService.getInstance(); try { - service.loadConfig(args[1]); + service.loadConfig(configFile); } catch (FileNotFoundException e) { - System.out.println("Cannot find config file " + args[1]); + System.out.println("Missing config file " + args[1]); System.out.println(e.getMessage()); System.exit(Constants.RC_MISSING_CONFIG_FILE); } catch (IOException e) { @@ -61,7 +75,7 @@ public static void main(String[] args) throws Exception { } private static void printUsage() { - System.out.println("Usage: [start|stop|restart|install|remove|console] "); + System.out.println("Usage: [CONFIG-FILE]"); System.out.println(" start - Start service"); System.out.println(" stop - Stop service"); System.out.println(" restart - Restart service"); diff --git a/symmetric-wrapper/src/main/java/org/jumpmind/symmetric/wrapper/WrapperService.java b/symmetric-wrapper/src/main/java/org/jumpmind/symmetric/wrapper/WrapperService.java index b42827d6b3..f0cc07deac 100644 --- a/symmetric-wrapper/src/main/java/org/jumpmind/symmetric/wrapper/WrapperService.java +++ b/symmetric-wrapper/src/main/java/org/jumpmind/symmetric/wrapper/WrapperService.java @@ -49,7 +49,7 @@ public void start() { throw new WrapperException(Constants.RC_SERVER_ALREADY_RUNNING, 0, "Server is already running"); } - System.out.print("Waiting for server to start"); + System.out.println("Waiting for server to start"); boolean success = false; int rc = 0; try { @@ -60,7 +60,6 @@ public void start() { } } catch (IOException e) { rc = -1; - System.out.println(""); System.out.println(e.getMessage()); } @@ -174,7 +173,7 @@ public void stop() { if (!isPidRunning(symPid) && !isPidRunning(wrapperPid)) { throw new WrapperException(Constants.RC_SERVER_NOT_RUNNING, 0, "Server is not running"); } - System.out.print("Waiting for server to stop"); + System.out.println("Waiting for server to stop"); if (!(stopProcess(wrapperPid, "wrapper") && stopProcess(symPid, "symmetricds"))) { throw new WrapperException(Constants.RC_FAIL_STOP_SERVER, 0, "Server did not stop"); } @@ -225,6 +224,14 @@ public boolean isRunning() { return isPidRunning(readPidFromFile(config.getSymPidFile())); } + public int getWrapperPid() { + return readPidFromFile(config.getWrapperPidFile()); + } + + public int getSymmetricPid() { + return readPidFromFile(config.getSymPidFile()); + } + protected String commandToString(ArrayList cmd) { StringBuilder sb = new StringBuilder(); for (String c : cmd) {