Skip to content

Commit

Permalink
WFLY-1247 Initial core work on graceful shutdown
Browse files Browse the repository at this point in the history
  • Loading branch information
stuartwdouglas committed Aug 6, 2014
1 parent f0636ec commit 6e95b54
Show file tree
Hide file tree
Showing 47 changed files with 2,858 additions and 96 deletions.
Expand Up @@ -373,6 +373,8 @@ public class ModelDescriptionConstants {
public static final String OPERATION_REQUIRES_RESTART = "operation-requires-restart";
public static final String RELOAD_SERVERS = "reload-servers";
public static final String RESTART_SERVERS = "restart-servers";
public static final String RESUME_SERVERS = "resume-servers";
public static final String RESUME = "resume";
public static final String SERVER_LOGGER = "server-logger";
public static final String SHUTDOWN = "shutdown";
public static final String SOCKET_BINDING = "socket-binding";
Expand All @@ -397,12 +399,15 @@ public class ModelDescriptionConstants {
public static final String SUBDEPLOYMENT = "subdeployment";
public static final String SUBSYSTEM = "subsystem";
public static final String SUCCESS = "success";
public static final String SUSPEND = "suspend";
public static final String SUSPEND_SERVERS = "suspend-servers";
public static final String SYSLOG_FORMAT = "syslog-format";
public static final String SYSLOG_HANDLER = "syslog-handler";
public static final String SYSTEM_PROPERTY = "system-property";
public static final String SYSTEM_PROPERTIES = "system-properties";
public static final String TAIL_COMMENT_ALLOWED = "tail-comment-allowed";
public static final String TCP = "tcp";
public static final String TIMEOUT = "timeout";
public static final String TLS = "tls";
public static final String TO_REPLACE = "to-replace";
public static final String TRUNCATE = "truncate";
Expand Down

Large diffs are not rendered by default.

Expand Up @@ -1009,6 +1009,21 @@ public void killServer(String serverName) {
public void awaitServersState(Collection<String> serverNames, boolean started) {
getServerInventory().awaitServersState(serverNames, started);
}

@Override
public void suspendServer(String serverName) {
getServerInventory().suspendServer(serverName);
}

@Override
public void resumeServer(String serverName) {
getServerInventory().resumeServer(serverName);
}

@Override
public boolean awaitServerSuspend(Set<String> waitForServers, int timeout) {
return getServerInventory().awaitServerSuspend(waitForServers, timeout);
}
}

private static <S> S service(final Class<S> service) {
Expand Down
Expand Up @@ -26,6 +26,7 @@
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RUNNING_SERVER;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.TIMEOUT;
import static org.jboss.as.host.controller.logging.HostControllerLogger.ROOT_LOGGER;

import java.io.IOException;
Expand Down Expand Up @@ -159,7 +160,7 @@ byte[] getAuthKey() {
*
* @return the server name
*/
public String getServerName() {
String getServerName() {
return serverName;
}

Expand All @@ -168,7 +169,7 @@ public String getServerName() {
*
* @return the proxy controller
*/
public TransformingProxyController getProxyController() {
TransformingProxyController getProxyController() {
return proxyController;
}

Expand All @@ -177,7 +178,7 @@ public TransformingProxyController getProxyController() {
*
* @return the server status
*/
public ServerStatus getState() {
ServerStatus getState() {
final InternalState requiredState = this.requiredState;
final InternalState state = internalState;
if(requiredState == InternalState.FAILED) {
Expand All @@ -198,14 +199,14 @@ public ServerStatus getState() {
}
}

protected boolean isRequiresReload() {
boolean isRequiresReload() {
return requiresReload;
}

/**
* Require a reload on the the next reconnect.
*/
protected void requireReload() {
void requireReload() {
requiresReload = true;
}

Expand All @@ -215,7 +216,7 @@ protected void requireReload() {
* @param permit the controller permit
* @return whether the state was changed successfully or not
*/
protected synchronized boolean reload(int permit) {
synchronized boolean reload(int permit) {
return internalSetState(new ReloadTask(permit), InternalState.SERVER_STARTED, InternalState.RELOADING);
}

Expand All @@ -224,7 +225,7 @@ protected synchronized boolean reload(int permit) {
*
* @param factory the boot command factory
*/
protected synchronized void start(final ManagedServerBootCmdFactory factory) {
synchronized void start(final ManagedServerBootCmdFactory factory) {
final InternalState required = this.requiredState;
// Ignore if the server is already started
if(required == InternalState.SERVER_STARTED) {
Expand All @@ -248,17 +249,16 @@ protected synchronized void start(final ManagedServerBootCmdFactory factory) {
/**
* Stop a managed server.
*/
protected synchronized void stop() {
synchronized void stop(int operationID, int timeout) {
final InternalState required = this.requiredState;
if(required != InternalState.STOPPED) {
this.requiredState = InternalState.STOPPED;
ROOT_LOGGER.stoppingServer(serverName);
// Transition, but don't wait for async notifications to complete
transition(false);
internalSetState(new ServerStopTask(operationID, timeout), internalState, InternalState.PROCESS_STOPPING);
}
}

protected synchronized void destroy() {
synchronized void destroy(int permit) {
final InternalState required = this.requiredState;
if(required == InternalState.STOPPED) {
if(internalState != InternalState.STOPPED) {
Expand All @@ -269,11 +269,11 @@ protected synchronized void destroy() {
}
}
} else {
stop();
stop(permit, 0);
}
}

protected synchronized void kill() {
synchronized void kill(int permit) {
final InternalState required = this.requiredState;
if(required == InternalState.STOPPED) {
if(internalState != InternalState.STOPPED) {
Expand All @@ -284,14 +284,14 @@ protected synchronized void kill() {
}
}
} else {
stop();
stop(permit, 0);
}
}

/**
* Try to reconnect to a started server.
*/
protected synchronized void reconnectServerProcess(final ManagedServerBootCmdFactory factory) {
synchronized void reconnectServerProcess(final ManagedServerBootCmdFactory factory) {
if(this.requiredState != InternalState.SERVER_STARTED) {
this.bootConfiguration = factory;
this.requiredState = InternalState.SERVER_STARTED;
Expand All @@ -303,15 +303,15 @@ protected synchronized void reconnectServerProcess(final ManagedServerBootCmdFac
/**
* On host controller reload, remove a not running server registered in the process controller declared as down.
*/
protected synchronized void removeServerProcess() {
synchronized void removeServerProcess() {
this.requiredState = InternalState.STOPPED;
internalSetState(new ProcessRemoveTask(), InternalState.STOPPED, InternalState.PROCESS_REMOVING);
}

/**
* On host controller reload, remove a not running server registered in the process controller declared as stopping.
*/
protected synchronized void setServerProcessStopping() {
synchronized void setServerProcessStopping() {
this.requiredState = InternalState.STOPPED;
internalSetState(null, InternalState.STOPPED, InternalState.PROCESS_STOPPING);
}
Expand All @@ -322,7 +322,7 @@ protected synchronized void setServerProcessStopping() {
* @param expected the expected state
* @return {@code true} if the state was reached, {@code false} otherwise
*/
protected boolean awaitState(final InternalState expected) {
boolean awaitState(final InternalState expected) {
synchronized (this) {
final InternalState initialRequired = this.requiredState;
for(;;) {
Expand Down Expand Up @@ -351,18 +351,18 @@ protected boolean awaitState(final InternalState expected) {
/**
* Notification that the process was added
*/
protected void processAdded() {
void processAdded() {
finishTransition(InternalState.PROCESS_ADDING, InternalState.PROCESS_ADDED);
}

/**
* Notification that the process was started.
*/
protected void processStarted() {
void processStarted() {
finishTransition(InternalState.PROCESS_STARTING, InternalState.PROCESS_STARTED);
}

protected synchronized TransactionalProtocolClient channelRegistered(final ManagementChannelHandler channelAssociation) {
synchronized TransactionalProtocolClient channelRegistered(final ManagementChannelHandler channelAssociation) {
final InternalState current = this.internalState;
// Create the remote controller client
channelAssociation.getAttachments().attach(TransactionalProtocolClient.SEND_SUBJECT, Boolean.TRUE);
Expand Down Expand Up @@ -392,11 +392,11 @@ public boolean execute(final ManagedServer server) throws Exception {
return remoteClient;
}

protected synchronized void serverStarted(final TransitionTask task) {
synchronized void serverStarted(final TransitionTask task) {
internalSetState(task, InternalState.SERVER_STARTING, InternalState.SERVER_STARTED);
}

protected synchronized void serverStartFailed() {
synchronized void serverStartFailed() {
internalSetState(null, InternalState.SERVER_STARTING, InternalState.FAILED);
}

Expand All @@ -407,7 +407,7 @@ protected synchronized void serverStartFailed() {
* @param shuttingDown whether the server inventory is shutting down
* @return whether the registration can be removed from the domain-controller
*/
protected synchronized boolean callbackUnregistered(final TransactionalProtocolClient old, final boolean shuttingDown) {
synchronized boolean callbackUnregistered(final TransactionalProtocolClient old, final boolean shuttingDown) {
// Disconnect the remote connection
protocolClient.disconnected(old);

Expand Down Expand Up @@ -439,7 +439,7 @@ protected synchronized boolean callbackUnregistered(final TransactionalProtocolC
/**
* Notification that the server process finished.
*/
protected synchronized void processFinished() {
synchronized void processFinished() {
final InternalState required = this.requiredState;
final InternalState state = this.internalState;
// If the server was not stopped
Expand All @@ -454,7 +454,7 @@ protected synchronized void processFinished() {
/**
* Notification that the process got removed from the process controller.
*/
protected void processRemoved() {
void processRemoved() {
finishTransition(InternalState.PROCESS_REMOVING, InternalState.STOPPED);
}

Expand Down Expand Up @@ -550,7 +550,7 @@ private TransitionTask getTransitionTask(final InternalState next) {
} case SERVER_STARTED: {
return new ServerStartedTask();
} case PROCESS_STOPPING: {
return new ServerStopTask();
return new ServerStopTask(-1, 0);
} case PROCESS_REMOVING: {
return new ProcessRemoveTask();
} default: {
Expand Down Expand Up @@ -640,6 +640,66 @@ private static InternalState nextState(final InternalState state, final Internal
return null;
}

boolean suspend() {

final ModelNode operation = new ModelNode();
operation.get(OP).set("suspend");
operation.get(OP_ADDR).setEmptyList();

try {
final TransactionalProtocolClient.PreparedOperation<?> prepared = TransactionalProtocolHandlers.executeBlocking(operation, protocolClient);
if (prepared.isFailed()) {
return false;
}
prepared.commit();
prepared.getFinalResult().get();
} catch (Exception ignore) {
return false;
}
return true;
}


boolean resume() {

final ModelNode operation = new ModelNode();
operation.get(OP).set("resume");
operation.get(OP_ADDR).setEmptyList();

try {
final TransactionalProtocolClient.PreparedOperation<?> prepared = TransactionalProtocolHandlers.executeBlocking(operation, protocolClient);
if (prepared.isFailed()) {
return false;
}
prepared.commit();
prepared.getFinalResult().get();
} catch (Exception ignore) {
return false;
}
return true;
}

void awaitSuspended(long timeout) {

//we just re-suspend, but this time give a timeout
final ModelNode operation = new ModelNode();
operation.get(OP).set("suspend");
operation.get(OP_ADDR).setEmptyList();
operation.get(TIMEOUT).set(timeout);

try {
final TransactionalProtocolClient.PreparedOperation<?> prepared = TransactionalProtocolHandlers.executeBlocking(operation, protocolClient);
if (prepared.isFailed()) {
return;
}
prepared.commit();
prepared.getFinalResult().get();
} catch (Exception ignore) {
return;
}
return;
}

static enum InternalState {

STOPPED,
Expand All @@ -654,6 +714,7 @@ static enum InternalState {
PROCESS_STOPPING(true),
PROCESS_STOPPED,
PROCESS_REMOVING(true),
SUSPENDING(true),

FAILED,
;
Expand All @@ -669,7 +730,7 @@ static enum InternalState {
this.async = async;
}

public boolean isAsync() {
boolean isAsync() {
return async;
}
}
Expand Down Expand Up @@ -753,11 +814,46 @@ public boolean execute(ManagedServer server) throws Exception {

private class ServerStopTask implements TransitionTask {

private final int permit;
private final int timeout;

private ServerStopTask(int permit, int timeout) {
this.permit = permit;
this.timeout = timeout;
}

@Override
public boolean execute(ManagedServer server) throws Exception {
assert Thread.holdsLock(ManagedServer.this); // Call under lock
// Stop process
processControllerClient.stopProcess(serverProcessName);

try {
//graceful shutdown
//this just suspends the server, it does not actually shut it down
if (operationID != -1) {

final ModelNode operation = new ModelNode();
operation.get(OP).set("shutdown");
operation.get(OP_ADDR).setEmptyList();
operation.get("operation-id").set(permit);
operation.get("timeout").set(timeout);

final TransactionalProtocolClient.PreparedOperation<?> prepared = TransactionalProtocolHandlers.executeBlocking(operation, protocolClient);
if (prepared.isFailed()) {
return true;
}
//we stop the server via an operation
prepared.commit();
prepared.getFinalResult().get();
}
} catch (Exception ignore) {
} finally {
try {
processControllerClient.stopProcess(serverProcessName);
} catch (IOException ignore) {

}
}
return true;
}
}
Expand Down

0 comments on commit 6e95b54

Please sign in to comment.