Skip to content

Commit

Permalink
0003431: Recovery options for service wrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
erilong committed Feb 19, 2018
1 parent 06e752c commit b4a143d
Show file tree
Hide file tree
Showing 5 changed files with 168 additions and 4 deletions.
21 changes: 21 additions & 0 deletions symmetric-server/src/main/deploy/conf/sym_service.conf
Expand Up @@ -97,3 +97,24 @@ wrapper.ntservice.starttype=auto

# Service dependencies. Use + prefix for groups.
wrapper.ntservice.dependency.1=

# First failure action (NONE, RESTART)
wrapper.ntservice.failure.action.type.1=RESTART

# Milliseconds to wait before performing the action
wrapper.ntservice.failure.action.delay.1=10000

# Second failure action (NONE, RESTART)
wrapper.ntservice.failure.action.type.2=NONE

# Milliseconds to wait before performing the action
wrapper.ntservice.failure.action.delay.2=0

# Subsequent failure action (NONE, RESTART)
wrapper.ntservice.failure.action.type.3=NONE

# Milliseconds to wait before performing the action
wrapper.ntservice.failure.action.delay.3=0

# Seconds after which to reset the failure count to zero
wrapper.ntservice.failure.reset.period=300
Expand Up @@ -25,11 +25,13 @@
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement;
import org.jumpmind.symmetric.wrapper.Constants.Status;
import org.jumpmind.symmetric.wrapper.WrapperConfig.FailureAction;
import org.jumpmind.symmetric.wrapper.jna.Advapi32Ex;
import org.jumpmind.symmetric.wrapper.jna.Advapi32Ex.HANDLER_FUNCTION;
import org.jumpmind.symmetric.wrapper.jna.Advapi32Ex.SERVICE_STATUS_HANDLE;
Expand Down Expand Up @@ -322,6 +324,27 @@ public void install() {
Advapi32Ex.SERVICE_DESCRIPTION desc = new Advapi32Ex.SERVICE_DESCRIPTION(config.getDescription());
advapi.ChangeServiceConfig2(service, WinsvcEx.SERVICE_CONFIG_DESCRIPTION, desc);

WinsvcEx.SC_ACTION.ByReference actionRef = null;
WinsvcEx.SC_ACTION[] actionArray = null;
List<FailureAction> failureActions = config.getFailureActions();
if (failureActions.size() > 0) {
actionRef = new WinsvcEx.SC_ACTION.ByReference();
actionArray = (WinsvcEx.SC_ACTION[]) actionRef.toArray(failureActions.size());
}
int i = 0;
for (FailureAction failureAction : failureActions) {
actionArray[i].type = failureAction.getType();
actionArray[i].delay = failureAction.getDelay();
i++;
}

WinsvcEx.SERVICE_FAILURE_ACTIONS actions = new WinsvcEx.SERVICE_FAILURE_ACTIONS(config.getFailureResetPeriod(), "",
config.getFailureActionCommand(), failureActions.size(), actionRef);
advapi.ChangeServiceConfig2(service, WinsvcEx.SERVICE_CONFIG_FAILURE_ACTIONS, actions);

WinsvcEx.SERVICE_FAILURE_ACTIONS_FLAG flag = new WinsvcEx.SERVICE_FAILURE_ACTIONS_FLAG(false);
advapi.ChangeServiceConfig2(service, WinsvcEx.SERVICE_CONFIG_FAILURE_ACTIONS_FLAG, flag);

if (config.isDelayStart()) {
WinsvcEx.SERVICE_DELAYED_AUTO_START_INFO delayedInfo = new WinsvcEx.SERVICE_DELAYED_AUTO_START_INFO(true);
advapi.ChangeServiceConfig2(service, WinsvcEx.SERVICE_CONFIG_DELAYED_AUTO_START_INFO, delayedInfo);
Expand Down
Expand Up @@ -30,6 +30,8 @@
import java.util.List;
import java.util.Map;

import org.jumpmind.symmetric.wrapper.jna.WinsvcEx;

public class WrapperConfig {

protected String configFile;
Expand Down Expand Up @@ -110,6 +112,31 @@ public boolean isDelayStart() {
return getProperty(prop, "wrapper.ntservice.starttype", "auto").equalsIgnoreCase("delay");
}

public String getFailureActionCommand() {
return getProperty(prop, "wrapper.ntservice.failure.action.command", "");
}

public int getFailureResetPeriod() {
return Integer.parseInt(getProperty(prop, "wrapper.ntservice.failure.reset.period", "300"));
}

public List<FailureAction> getFailureActions() {
List<String> types = getListProperty(prop, "wrapper.ntservice.failure.action.type");
List<String> delays = getListProperty(prop, "wrapper.ntservice.failure.action.delay");
int count = types.size() >= 3 ? 3 : types.size();
List<FailureAction> actions = new ArrayList<FailureAction>(count);
int i = 0;
for (String type : types) {
String delay = "0";
if (i < delays.size()) {
delay = delays.get(i);
}
actions.add(new FailureAction(type, delay));
i++;
}
return actions;
}

public List<String> getDependencies() {
return prop.get("wrapper.ntservice.dependency");
}
Expand Down Expand Up @@ -252,4 +279,32 @@ private List<String> getListProperty(Map<String, ArrayList<String>> prop, String
}
return value;
}

public class FailureAction {
int type;
int delay;

public FailureAction(String type, String delay) {
if (type != null) {
if (type.equalsIgnoreCase("restart")) {
this.type = WinsvcEx.SC_ACTION_RESTART;
} else if (type.equalsIgnoreCase("reboot")) {
this.type = WinsvcEx.SC_ACTION_REBOOT;
} else if (type.equalsIgnoreCase("run_command")) {
this.type = WinsvcEx.SC_ACTION_RUN_COMMAND;
} else {
this.type = WinsvcEx.SC_ACTION_NONE;
}
}
this.delay = Integer.parseInt(delay);
}

public int getType() {
return type;
}

public int getDelay() {
return delay;
}
}
}
Expand Up @@ -24,7 +24,6 @@
import java.util.List;

import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement;
import org.jumpmind.symmetric.wrapper.jna.WinsvcEx.SERVICE_DELAYED_AUTO_START_INFO;

import com.sun.jna.Native;
import com.sun.jna.Pointer;
Expand All @@ -45,8 +44,6 @@ SC_HANDLE CreateService(SC_HANDLE manager, String serviceName, String displayNam
String loadOrderGroup, String tagId, String dependencies, String user, String password);

boolean ChangeServiceConfig2(SC_HANDLE service, int infoLevel, SERVICE_INFO info);

boolean ChangeServiceConfig2(SC_HANDLE service, int infoLevel, SERVICE_DELAYED_AUTO_START_INFO info);

boolean DeleteService(SC_HANDLE serviceHandle);

Expand Down
Expand Up @@ -24,6 +24,7 @@
import java.util.List;

import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement;
import org.jumpmind.symmetric.wrapper.jna.Advapi32Ex.SERVICE_INFO;

import com.sun.jna.Pointer;
import com.sun.jna.Structure;
Expand All @@ -37,8 +38,15 @@ public interface WinsvcEx extends Winsvc {
int SERVICE_DEMAND_START = 0x00000003;
int SERVICE_ERROR_NORMAL = 0x00000001;
int SERVICE_CONFIG_DESCRIPTION = 1;
int SERVICE_CONFIG_FAILURE_ACTIONS = 2;
int SERVICE_CONFIG_DELAYED_AUTO_START_INFO = 3;
int SERVICE_CONFIG_FAILURE_ACTIONS_FLAG = 4;

int SC_ACTION_NONE = 0;
int SC_ACTION_RESTART = 1;
int SC_ACTION_REBOOT = 2;
int SC_ACTION_RUN_COMMAND = 3;

public interface SERVICE_MAIN_FUNCTION extends StdCallCallback {
void serviceMain(int argc, Pointer argv);
}
Expand All @@ -61,7 +69,7 @@ protected List<String> getFieldOrder() {
}
}

public static class SERVICE_DELAYED_AUTO_START_INFO extends Structure {
public static class SERVICE_DELAYED_AUTO_START_INFO extends SERVICE_INFO {
public int fDelayedAutostart;

public SERVICE_DELAYED_AUTO_START_INFO() {
Expand All @@ -76,4 +84,64 @@ protected List<String> getFieldOrder() {
return Arrays.asList(new String[] { "fDelayedAutostart" });
}
}

public static class SERVICE_FAILURE_ACTIONS_FLAG extends SERVICE_INFO {
public boolean fFailureActionsOnNonCrashFailures;

public SERVICE_FAILURE_ACTIONS_FLAG() {
}

public SERVICE_FAILURE_ACTIONS_FLAG(boolean fFailureActionsOnNonCrashFailures) {
this.fFailureActionsOnNonCrashFailures = fFailureActionsOnNonCrashFailures;
}

@Override
protected List<String> getFieldOrder() {
return Arrays.asList(new String[] { "fFailureActionsOnNonCrashFailures" });
}
}

public static class SERVICE_FAILURE_ACTIONS extends SERVICE_INFO {
public int dwResetPeriod;
public String lpRebootMsg;
public String lpCommand;
public int cActions;
public SC_ACTION.ByReference lpsaActions;

public SERVICE_FAILURE_ACTIONS() {
}

public SERVICE_FAILURE_ACTIONS(int dwResetPeriod, String lpRebootMsg, String lpCommand, int cActions, SC_ACTION.ByReference lpsaActions) {
this.dwResetPeriod = dwResetPeriod;
this.lpRebootMsg = lpRebootMsg;
this.lpCommand = lpCommand;
this.cActions = cActions;
this.lpsaActions = lpsaActions;
}

@Override
protected List<String> getFieldOrder() {
return Arrays.asList(new String[] { "dwResetPeriod", "lpRebootMsg", "lpCommand", "cActions", "lpsaActions" });
}
}

public static class SC_ACTION extends Structure {
public static class ByReference extends SC_ACTION implements Structure.ByReference {}
public int type;
public int delay;

public SC_ACTION() {
}

public SC_ACTION(int type, int delay) {
this.type = type;
this.delay = delay;
}

@Override
protected List<String> getFieldOrder() {
return Arrays.asList(new String[] { "type", "delay" });
}
}

}

0 comments on commit b4a143d

Please sign in to comment.