diff --git a/core-feature-pack/common/src/main/resources/modules/system/layers/base/org/wildfly/extension/core-management/main/module.xml b/core-feature-pack/common/src/main/resources/modules/system/layers/base/org/wildfly/extension/core-management/main/module.xml
index 8c993cf72ce..e98404f4a0b 100644
--- a/core-feature-pack/common/src/main/resources/modules/system/layers/base/org/wildfly/extension/core-management/main/module.xml
+++ b/core-feature-pack/common/src/main/resources/modules/system/layers/base/org/wildfly/extension/core-management/main/module.xml
@@ -26,6 +26,7 @@
+
diff --git a/core-feature-pack/galleon-feature-pack/pom.xml b/core-feature-pack/galleon-feature-pack/pom.xml
index d638df070d4..e565ad95d19 100644
--- a/core-feature-pack/galleon-feature-pack/pom.xml
+++ b/core-feature-pack/galleon-feature-pack/pom.xml
@@ -66,8 +66,8 @@
wildfly-core-model-test-framework
- org.wildfly.core
- wildfly-model-test
+ *
+ *
provided
diff --git a/core-management/core-management-subsystem/src/main/java/org/wildfly/extension/core/management/ProcessStateListenerService.java b/core-management/core-management-subsystem/src/main/java/org/wildfly/extension/core/management/ProcessStateListenerService.java
index 68e507368f9..86d3de63881 100644
--- a/core-management/core-management-subsystem/src/main/java/org/wildfly/extension/core/management/ProcessStateListenerService.java
+++ b/core-management/core-management-subsystem/src/main/java/org/wildfly/extension/core/management/ProcessStateListenerService.java
@@ -27,13 +27,14 @@
import org.jboss.as.controller.ProcessType;
import org.jboss.as.controller.RunningMode;
import org.jboss.as.controller.management.Capabilities;
-import org.jboss.as.server.suspend.OperationListener;
-import org.jboss.as.server.suspend.SuspendController;
+import org.jboss.as.server.suspend.ServerSuspendController;
+import org.jboss.as.server.suspend.ServerSuspendListener;
import org.jboss.msc.Service;
import org.jboss.msc.service.ServiceName;
import org.jboss.msc.service.StartContext;
import org.jboss.msc.service.StartException;
import org.jboss.msc.service.StopContext;
+import org.wildfly.common.function.Functions;
import org.wildfly.extension.core.management.client.Process;
import org.wildfly.extension.core.management.client.Process.RunningState;
import org.wildfly.extension.core.management.client.RuntimeConfigurationStateChangeEvent;
@@ -57,10 +58,10 @@ public class ProcessStateListenerService implements Service {
static final ServiceName SERVICE_NAME = ServiceName.JBOSS.append("core", "management", "process-state-listener");
private final Supplier processStateNotifierSupplier;
- private final Supplier suspendControllerSupplier;
+ private final Supplier suspendControllerSupplier;
private final Supplier executorSupplier;
private final PropertyChangeListener propertyChangeListener;
- private final OperationListener operationListener;
+ private final ServerSuspendListener suspendListener;
private final ProcessStateListener listener;
private final ProcessStateListenerInitParameters parameters;
private final String name;
@@ -72,7 +73,7 @@ public class ProcessStateListenerService implements Service {
private ProcessStateListenerService(ProcessType processType, RunningMode runningMode, String name, ProcessStateListener listener, Map properties, int timeout,
final Supplier processStateNotifierSupplier,
- final Supplier suspendControllerSupplier,
+ final Supplier suspendControllerSupplier,
final Supplier executorSupplier
) {
CoreManagementLogger.ROOT_LOGGER.debugf("Initalizing ProcessStateListenerService with a running mode of %s", runningMode);
@@ -96,20 +97,20 @@ private ProcessStateListenerService(ProcessType processType, RunningMode running
this.suspendControllerSupplier = suspendControllerSupplier;
this.executorSupplier = executorSupplier;
if (!processType.isHostController()) {
- this.operationListener = new OperationListener() {
+ this.suspendListener = new ServerSuspendListener() {
@Override
public void suspendStarted() {
suspendTransition(runningState, Process.RunningState.SUSPENDING);
}
@Override
- public void complete() {
+ public void suspendCompleted() {
suspendTransition(runningState, Process.RunningState.SUSPENDED);
}
@Override
- public void cancelled() {
- if(runningState == null || runningState == Process.RunningState.STARTING) {//gracefull startup
+ public void suspendCancelled() {
+ if (runningState == null || runningState == Process.RunningState.STARTING) {//gracefull startup
suspendTransition(Process.RunningState.STARTING, Process.RunningState.SUSPENDED);
}
switch (runningMode) {
@@ -123,11 +124,11 @@ public void cancelled() {
}
@Override
- public void timeout() {
+ public void suspendTimeout() {
}
};
} else {
- operationListener = null;
+ suspendListener = null;
}
}
@@ -241,8 +242,8 @@ static void install(CapabilityServiceTarget serviceTarget, ProcessType processTy
final CapabilityServiceBuilder> builder = serviceTarget.addCapability(PROCESS_STATE_LISTENER_CAPABILITY.fromBaseCapability(listenerName));
final Supplier psnSupplier = builder.requires(ProcessStateNotifier.SERVICE_DESCRIPTOR);
final Supplier esSupplier = builder.requires(Capabilities.MANAGEMENT_EXECUTOR);
- final Supplier scSupplier = !processType.isHostController() ? builder.requiresCapability("org.wildfly.server.suspend-controller", SuspendController.class) : null;
- builder.setInstance(new ProcessStateListenerService(processType, runningMode, listenerName, listener, properties, timeout, psnSupplier, scSupplier, esSupplier));
+ final Supplier suspendController = !processType.isHostController() ? builder.requires(ServerSuspendController.SERVICE_DESCRIPTOR) : Functions.constantSupplier(null);
+ builder.setInstance(new ProcessStateListenerService(processType, runningMode, listenerName, listener, properties, timeout, psnSupplier, suspendController, esSupplier));
builder.install();
}
@@ -258,10 +259,9 @@ public void start(StartContext context) {
WildFlySecurityManager.setCurrentContextClassLoaderPrivileged(currentTccl);
}
processStateNotifierSupplier.get().addPropertyChangeListener(propertyChangeListener);
- final Supplier suspendControllerSupplier = ProcessStateListenerService.this.suspendControllerSupplier;
- SuspendController controller = suspendControllerSupplier != null ? suspendControllerSupplier.get() : null;
+ ServerSuspendController controller = ProcessStateListenerService.this.suspendControllerSupplier.get();
if (controller != null) {
- controller.addListener(operationListener);
+ controller.addSuspendListener(suspendListener);
CoreManagementLogger.ROOT_LOGGER.debugf("Starting ProcessStateListenerService with a SuspendControllerState %s", controller.getState());
switch (controller.getState()) {
case PRE_SUSPEND:
@@ -321,9 +321,9 @@ public void stop(StopContext context) {
Runnable asyncStop = () -> {
synchronized (stopLock) {
processStateNotifierSupplier.get().removePropertyChangeListener(propertyChangeListener);
- SuspendController controller = suspendControllerSupplier != null ? suspendControllerSupplier.get() : null;
+ ServerSuspendController controller = ProcessStateListenerService.this.suspendControllerSupplier.get();
if (controller != null) {
- controller.removeListener(operationListener);
+ controller.removeSuspendListener(suspendListener);
}
runningState = null;
ClassLoader currentTccl = WildFlySecurityManager.getCurrentContextClassLoaderPrivileged();
diff --git a/core-model-test/framework/pom.xml b/core-model-test/framework/pom.xml
index 27334639cb6..27ba10bcab7 100644
--- a/core-model-test/framework/pom.xml
+++ b/core-model-test/framework/pom.xml
@@ -32,13 +32,17 @@
junit
junit
- provided
+ compile
+
+
+ org.mockito
+ mockito-core
+ compile
+
+
+ org.wildfly.legacy.test
+ wildfly-legacy-spi
+ compile
-
- org.wildfly.legacy.test
- wildfly-legacy-spi
- provided
-
-
diff --git a/core-model-test/framework/src/main/java/org/jboss/as/core/model/test/TestModelControllerService.java b/core-model-test/framework/src/main/java/org/jboss/as/core/model/test/TestModelControllerService.java
index ffab08e347b..a39af0eb3d3 100644
--- a/core-model-test/framework/src/main/java/org/jboss/as/core/model/test/TestModelControllerService.java
+++ b/core-model-test/framework/src/main/java/org/jboss/as/core/model/test/TestModelControllerService.java
@@ -6,6 +6,8 @@
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.NAMESPACES;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SCHEMA_LOCATIONS;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
import java.io.File;
import java.io.IOException;
@@ -78,6 +80,7 @@
import org.jboss.as.server.ServerPathManagerService;
import org.jboss.as.server.controller.resources.ServerRootResourceDefinition;
import org.jboss.as.server.controller.resources.VersionModelInitializer;
+import org.jboss.as.server.suspend.ServerSuspendController;
import org.jboss.as.version.ProductConfig;
import org.jboss.as.version.Version;
import org.jboss.dmr.ModelNode;
@@ -102,6 +105,7 @@ class TestModelControllerService extends ModelTestModelControllerService {
private final ExtensionRegistry extensionRegistry;
private final CapabilityRegistry capabilityRegistry;
private volatile Initializer initializer;
+ private final ServerSuspendController suspendController = mock(ServerSuspendController.class);
TestModelControllerService(ProcessType processType, RunningModeControl runningModeControl, StringConfigurationPersister persister, ModelTestOperationValidatorFilter validateOpsFilter,
TestModelType type, ModelInitializer modelInitializer, TestDelegatingResourceDefinition rootResourceDefinition, ControlledProcessState processState, ExtensionRegistry extensionRegistry,
@@ -124,6 +128,7 @@ class TestModelControllerService extends ModelTestModelControllerService {
} else if (type == TestModelType.DOMAIN) {
initializer = new DomainInitializer();
}
+ doReturn(ServerSuspendController.State.RUNNING).when(this.suspendController).getState();
}
static TestModelControllerService create(ProcessType processType, RunningModeControl runningModeControl, StringConfigurationPersister persister, ModelTestOperationValidatorFilter validateOpsFilter,
@@ -407,7 +412,7 @@ public void setRootResourceDefinitionDelegate() {
securityIdentitySupplier,
AuditLogger.NO_OP_LOGGER,
getMutableRootResourceRegistrationProvider(),
- getBootErrorCollector(), capabilityRegistry));
+ getBootErrorCollector(), capabilityRegistry, suspendController));
}
@Override
diff --git a/host-controller/src/main/java/org/jboss/as/host/controller/model/host/HostResourceDefinition.java b/host-controller/src/main/java/org/jboss/as/host/controller/model/host/HostResourceDefinition.java
index b10cfc30d3d..54bfcfe86a1 100644
--- a/host-controller/src/main/java/org/jboss/as/host/controller/model/host/HostResourceDefinition.java
+++ b/host-controller/src/main/java/org/jboss/as/host/controller/model/host/HostResourceDefinition.java
@@ -323,7 +323,7 @@ public void execute(OperationContext context, ModelNode operation) throws Operat
hostRegistration.registerReadOnlyAttribute(HostResourceDefinition.RUNTIME_CONFIGURATION_STATE, new ProcessStateAttributeHandler(processState));
hostRegistration.registerReadOnlyAttribute(HostResourceDefinition.HOST_STATE, new ProcessStateAttributeHandler(processState));
hostRegistration.registerReadOnlyAttribute(ServerRootResourceDefinition.RUNNING_MODE, new RunningModeReadHandler(runningModeControl));
- hostRegistration.registerReadOnlyAttribute(ServerRootResourceDefinition.SUSPEND_STATE, SuspendStateReadHandler.INSTANCE);
+ hostRegistration.registerReadOnlyAttribute(ServerRootResourceDefinition.SUSPEND_STATE, new SuspendStateReadHandler(null));
}
diff --git a/request-controller/pom.xml b/request-controller/pom.xml
index 2421cc37ad6..4806d1c13e5 100644
--- a/request-controller/pom.xml
+++ b/request-controller/pom.xml
@@ -79,6 +79,11 @@
junit
test
+
+ org.mockito
+ mockito-core
+ test
+
org.wildfly.core
wildfly-subsystem-test
diff --git a/request-controller/src/main/java/org/wildfly/extension/requestcontroller/RequestController.java b/request-controller/src/main/java/org/wildfly/extension/requestcontroller/RequestController.java
index 08827b4583e..36c2f2c884a 100644
--- a/request-controller/src/main/java/org/wildfly/extension/requestcontroller/RequestController.java
+++ b/request-controller/src/main/java/org/wildfly/extension/requestcontroller/RequestController.java
@@ -21,7 +21,7 @@
import org.jboss.as.server.suspend.CountingRequestCountCallback;
import org.jboss.as.server.suspend.ServerActivity;
import org.jboss.as.server.suspend.ServerActivityCallback;
-import org.jboss.as.server.suspend.SuspendController;
+import org.jboss.as.server.suspend.ServerSuspendController;
import org.jboss.msc.service.Service;
import org.jboss.msc.service.ServiceName;
import org.jboss.msc.service.StartContext;
@@ -59,9 +59,9 @@ public class RequestController implements Service, ServerActi
private volatile ServerActivityCallback listener = null;
private final boolean trackIndividualControlPoints;
- private final Supplier suspendController;
+ private final Supplier suspendController;
- public RequestController(boolean trackIndividualControlPoints, Supplier suspendControllerSupplier) {
+ public RequestController(boolean trackIndividualControlPoints, Supplier suspendControllerSupplier) {
this.trackIndividualControlPoints = trackIndividualControlPoints;
this.suspendController = suspendControllerSupplier;
}
@@ -302,13 +302,13 @@ public boolean isPaused() {
@Override
public void start(StartContext startContext) throws StartException {
- suspendController.get().registerActivity(this);
+ suspendController.get().addServerActivity(this);
timer = new Timer();
}
@Override
public void stop(StopContext stopContext) {
- suspendController.get().unRegisterActivity(this);
+ suspendController.get().removeServerActivity(this);
timer.cancel();
timer = null;
while (!taskQueue.isEmpty()) {
diff --git a/request-controller/src/main/java/org/wildfly/extension/requestcontroller/RequestControllerSubsystemAdd.java b/request-controller/src/main/java/org/wildfly/extension/requestcontroller/RequestControllerSubsystemAdd.java
index 8ec91cd32ae..264f4b7483b 100644
--- a/request-controller/src/main/java/org/wildfly/extension/requestcontroller/RequestControllerSubsystemAdd.java
+++ b/request-controller/src/main/java/org/wildfly/extension/requestcontroller/RequestControllerSubsystemAdd.java
@@ -15,7 +15,7 @@
import org.jboss.as.server.AbstractDeploymentChainStep;
import org.jboss.as.server.DeploymentProcessorTarget;
import org.jboss.as.server.deployment.Phase;
-import org.jboss.as.server.suspend.SuspendController;
+import org.jboss.as.server.suspend.ServerSuspendController;
import org.jboss.dmr.ModelNode;
import java.util.function.Supplier;
@@ -49,7 +49,7 @@ protected void execute(DeploymentProcessorTarget processorTarget) {
CapabilityServiceBuilder> svcBuilder = context.getCapabilityServiceTarget().addCapability(REQUEST_CONTROLLER_CAPABILITY);
- Supplier supplier = svcBuilder.requiresCapability("org.wildfly.server.suspend-controller", SuspendController.class);
+ Supplier supplier = svcBuilder.requires(ServerSuspendController.SERVICE_DESCRIPTOR);
RequestController requestController = new RequestController(trackIndividual, supplier);
requestController.setMaxRequestCount(maxRequests);
svcBuilder.setInstance(requestController)
diff --git a/request-controller/src/test/java/org/wildfly/extension/requestcontroller/RequestControllerSubsystemTestCase.java b/request-controller/src/test/java/org/wildfly/extension/requestcontroller/RequestControllerSubsystemTestCase.java
index 23776eeb946..fa1c35ed82f 100644
--- a/request-controller/src/test/java/org/wildfly/extension/requestcontroller/RequestControllerSubsystemTestCase.java
+++ b/request-controller/src/test/java/org/wildfly/extension/requestcontroller/RequestControllerSubsystemTestCase.java
@@ -5,20 +5,20 @@
package org.wildfly.extension.requestcontroller;
-import static org.jboss.as.server.Services.JBOSS_SUSPEND_CONTROLLER;
+import static org.mockito.Mockito.mock;
import java.io.IOException;
+import java.util.function.Consumer;
-import org.jboss.as.controller.PathAddress;
import org.jboss.as.controller.RunningMode;
-import org.jboss.as.controller.notification.NotificationFilter;
-import org.jboss.as.controller.notification.NotificationHandler;
-import org.jboss.as.controller.notification.NotificationHandlerRegistry;
-import org.jboss.as.server.suspend.SuspendController;
+import org.jboss.as.controller.ServiceNameFactory;
+import org.jboss.as.server.suspend.ServerSuspendController;
import org.jboss.as.subsystem.test.AbstractSubsystemBaseTest;
import org.jboss.as.subsystem.test.AdditionalInitialization;
import org.jboss.as.subsystem.test.KernelServices;
import org.jboss.as.subsystem.test.KernelServicesBuilder;
+import org.jboss.msc.Service;
+import org.jboss.msc.service.ServiceBuilder;
import org.jboss.msc.service.ServiceController;
import org.jboss.msc.service.ServiceTarget;
import org.junit.Assert;
@@ -60,21 +60,9 @@ protected AdditionalInitialization createAdditionalInitialization() {
@Override
protected void addExtraServices(ServiceTarget target) {
- SuspendController suspendController = new SuspendController();
- final NotificationHandlerRegistry nhr = new NotificationHandlerRegistry() {
- @Override
- public void registerNotificationHandler(PathAddress source, NotificationHandler handler, NotificationFilter filter) {
-
- }
-
- @Override
- public void unregisterNotificationHandler(PathAddress source, NotificationHandler handler, NotificationFilter filter) {
-
- }
- };
- suspendController.getNotificationHandlerRegistry().setValue(() -> nhr);
- target.addService(JBOSS_SUSPEND_CONTROLLER, suspendController)
- .install();
+ ServiceBuilder> builder = target.addService();
+ Consumer injector = builder.provides(ServiceNameFactory.resolveServiceName(ServerSuspendController.SERVICE_DESCRIPTOR));
+ builder.setInstance(Service.newInstance(injector, mock(ServerSuspendController.class))).install();
}
@Override
diff --git a/server/src/main/java/org/jboss/as/server/ApplicationServerService.java b/server/src/main/java/org/jboss/as/server/ApplicationServerService.java
index 70749133031..924d2a054b7 100644
--- a/server/src/main/java/org/jboss/as/server/ApplicationServerService.java
+++ b/server/src/main/java/org/jboss/as/server/ApplicationServerService.java
@@ -29,7 +29,7 @@
import org.jboss.as.server.mgmt.domain.RemoteFileRepositoryService;
import org.jboss.as.server.moduleservice.ExternalModuleService;
import org.jboss.as.server.moduleservice.ServiceModuleLoader;
-import org.jboss.as.server.suspend.SuspendController;
+import org.jboss.as.server.suspend.ServerSuspendController;
import org.jboss.as.version.ProductConfig;
import org.jboss.msc.service.Service;
import org.jboss.msc.service.ServiceActivator;
@@ -55,7 +55,7 @@ final class ApplicationServerService implements Service extraServices, final Bootstrap.Configuration configuration,
- final ControlledProcessState processState, final SuspendController suspendController,
+ final ControlledProcessState processState, final ServerSuspendController suspendController,
final ElapsedTime elapsedTime) {
this.extraServices = extraServices;
this.configuration = configuration;
diff --git a/server/src/main/java/org/jboss/as/server/BootstrapImpl.java b/server/src/main/java/org/jboss/as/server/BootstrapImpl.java
index 333c6f27c5e..9fcb58bfccb 100644
--- a/server/src/main/java/org/jboss/as/server/BootstrapImpl.java
+++ b/server/src/main/java/org/jboss/as/server/BootstrapImpl.java
@@ -5,9 +5,9 @@
package org.jboss.as.server;
-import static org.jboss.as.server.Services.JBOSS_SUSPEND_CONTROLLER;
-
import java.lang.management.ManagementFactory;
+import java.time.Duration;
+import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -19,8 +19,9 @@
import org.jboss.as.controller.ControlledProcessStateService;
import org.jboss.as.server.jmx.RunningStateJmx;
import org.jboss.as.server.logging.ServerLogger;
-import org.jboss.as.server.suspend.OperationListener;
import org.jboss.as.server.suspend.SuspendController;
+import org.jboss.as.server.suspend.ServerSuspendController;
+import org.jboss.as.server.suspend.ServerSuspendListener;
import org.jboss.modules.Module;
import org.jboss.modules.ModuleIdentifier;
import org.jboss.modules.ModuleLoadException;
@@ -99,7 +100,8 @@ private AsyncFuture internalBootstrap(final Configuration conf
final ControlledProcessState processState = new ControlledProcessState(true);
shutdownHook.setControlledProcessState(processState);
ProcessStateNotifier processStateNotifier = ControlledProcessStateService.addService(tracker, processState);
- final SuspendController suspendController = new SuspendController();
+ ServerSuspendController suspendController = new SuspendController();
+ this.shutdownHook.setSuspendController(suspendController);
//Instantiating the suspendcontroller here to be able to get a reference to it in RunningStateJmx
//Note that the SuspendController service will be started in the ServerService during the boot of the server.
RunningStateJmx.registerMBean(
@@ -211,6 +213,7 @@ private static class ShutdownHook extends Thread {
private boolean down;
private ControlledProcessState processState;
private ServiceContainer container;
+ private volatile ServerSuspendController suspendController;
private ServiceContainer register() {
@@ -229,6 +232,10 @@ private synchronized void setControlledProcessState(final ControlledProcessState
this.processState = ps;
}
+ void setSuspendController(ServerSuspendController suspendController) {
+ this.suspendController = suspendController;
+ }
+
@Override
public void run() {
shutdown(false);
@@ -277,45 +284,47 @@ public void handleTermination(Info info) {
}
}
- private static void suspend(ServiceContainer sc) {
+ private void suspend(ServiceContainer sc) {
try {
- final SuspendController suspendController = getSuspendController(sc);
- if (suspendController != null) {
- long timeout = getSuspendTimeout();
+ final ServerSuspendController suspendController = this.suspendController;
+ if ((suspendController != null) && !sc.isShutdownComplete()) {
+ Duration timeout = getSuspendTimeout();
final CountDownLatch suspendLatch = new CountDownLatch(1);
- OperationListener listener = new OperationListener() {
+ ServerSuspendListener listener = new ServerSuspendListener() {
@Override
public void suspendStarted() {
}
@Override
- public void complete() {
- suspendController.removeListener(this);
+ public void suspendCompleted() {
+ suspendController.removeSuspendListener(this);
suspendLatch.countDown();
}
@Override
- public void cancelled() {
- suspendController.removeListener(this);
+ public void suspendCancelled() {
+ suspendController.removeSuspendListener(this);
suspendLatch.countDown();
}
@Override
- public void timeout() {
- suspendController.removeListener(this);
+ public void suspendTimeout() {
+ suspendController.removeSuspendListener(this);
suspendLatch.countDown();
}
};
- suspendController.addListener(listener);
+ suspendController.addSuspendListener(listener);
suspendController.suspend(timeout);
- if (timeout > 0) {
- // The latch should trip within 'timeout' but if necessary we'll wait
- // 500 ms longer for it in the off chance a gc or something delays things
- suspendLatch.await(timeout + 500, TimeUnit.MILLISECONDS);
- } else if (timeout < 0) {
+ if (timeout != null) {
+ if (!timeout.isZero()) {
+ // The latch should trip within 'timeout' but if necessary we'll wait
+ // 500 ms longer for it in the off chance a gc or something delays things
+ suspendLatch.await(timeout.plus(500, ChronoUnit.MILLIS).toMillis(), TimeUnit.MILLISECONDS);
+ } // else 0 means we don't wait for tasks to finish
+ } else {
suspendLatch.await();
- } // else 0 means we don't wait for tasks to finish
+ }
}
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
@@ -325,33 +334,17 @@ public void timeout() {
}
}
- private static SuspendController getSuspendController(ServiceContainer sc) {
- SuspendController result = null;
- if (sc != null && !sc.isShutdownComplete()) {
- final ServiceController serviceController = sc.getService(JBOSS_SUSPEND_CONTROLLER);
- if (serviceController != null && serviceController.getState() == ServiceController.State.UP) {
- result = (SuspendController) serviceController.getValue();
- }
- }
- return result;
- }
-
- private static long getSuspendTimeout() {
- long result = 0;
+ private static Duration getSuspendTimeout() {
String timeoutString = System.getProperty(SIGTERM_SUSPEND_TIMEOUT_PROP);
if (timeoutString != null && timeoutString.length() > 0) {
try {
- int max = Integer.decode(timeoutString);
- result = max > 0 ? max * 1000 : max;
+ int seconds = Integer.decode(timeoutString);
+ return (seconds >= 0) ? Duration.ofSeconds(seconds) : null;
} catch(NumberFormatException ex) {
- try {
- ServerLogger.ROOT_LOGGER.failedToParseCommandLineInteger(SIGTERM_SUSPEND_TIMEOUT_PROP, timeoutString);
- } catch (Throwable ignored) {
- // ignore
- }
+ ServerLogger.ROOT_LOGGER.failedToParseCommandLineInteger(SIGTERM_SUSPEND_TIMEOUT_PROP, timeoutString);
}
}
- return result;
+ return Duration.ZERO;
}
}
}
diff --git a/server/src/main/java/org/jboss/as/server/GracefulShutdownService.java b/server/src/main/java/org/jboss/as/server/GracefulShutdownService.java
index 8cef855c17a..0485f16b167 100644
--- a/server/src/main/java/org/jboss/as/server/GracefulShutdownService.java
+++ b/server/src/main/java/org/jboss/as/server/GracefulShutdownService.java
@@ -6,14 +6,13 @@
package org.jboss.as.server;
import org.jboss.as.server.logging.ServerLogger;
-import org.jboss.as.server.suspend.OperationListener;
-import org.jboss.as.server.suspend.SuspendController;
+import org.jboss.as.server.suspend.ServerSuspendController;
+import org.jboss.as.server.suspend.ServerSuspendListener;
import org.jboss.msc.service.Service;
import org.jboss.msc.service.ServiceName;
import org.jboss.msc.service.StartContext;
import org.jboss.msc.service.StartException;
import org.jboss.msc.service.StopContext;
-import org.jboss.msc.value.InjectedValue;
/**
@@ -28,13 +27,17 @@ public class GracefulShutdownService implements Service
public static final ServiceName SERVICE_NAME = ServiceName.JBOSS.append("server", "graceful-shutdown-service");
- private final InjectedValue suspendControllerInjectedValue = new InjectedValue<>();
+ private final ServerSuspendController suspendController;
private boolean suspend = false;
private boolean shuttingDown = false;
private final Object lock = new Object();
- private final OperationListener listener = new OperationListener() {
+ GracefulShutdownService(ServerSuspendController suspendController) {
+ this.suspendController = suspendController;
+ }
+
+ private final ServerSuspendListener listener = new ServerSuspendListener() {
@Override
public void suspendStarted() {
synchronized (lock) {
@@ -43,7 +46,7 @@ public void suspendStarted() {
}
@Override
- public void complete() {
+ public void suspendCompleted() {
synchronized (lock) {
suspend = false;
lock.notifyAll();
@@ -51,7 +54,7 @@ public void complete() {
}
@Override
- public void cancelled() {
+ public void suspendCancelled() {
synchronized (lock) {
suspend = false;
@@ -60,7 +63,7 @@ public void cancelled() {
}
@Override
- public void timeout() {
+ public void suspendTimeout() {
synchronized (lock) {
suspend = false;
lock.notifyAll();
@@ -70,12 +73,12 @@ public void timeout() {
@Override
public void start(StartContext context) throws StartException {
- suspendControllerInjectedValue.getValue().addListener(listener);
+ this.suspendController.addSuspendListener(listener);
}
@Override
public void stop(StopContext context) {
- suspendControllerInjectedValue.getValue().removeListener(listener);
+ this.suspendController.removeSuspendListener(listener);
}
public void startGracefulShutdown() {
@@ -96,10 +99,6 @@ public void awaitSuspend() {
}
}
- public InjectedValue getSuspendControllerInjectedValue() {
- return suspendControllerInjectedValue;
- }
-
@Override
public GracefulShutdownService getValue() throws IllegalStateException, IllegalArgumentException {
return this;
diff --git a/server/src/main/java/org/jboss/as/server/ServerService.java b/server/src/main/java/org/jboss/as/server/ServerService.java
index 7e7915dd112..30fda5655d4 100644
--- a/server/src/main/java/org/jboss/as/server/ServerService.java
+++ b/server/src/main/java/org/jboss/as/server/ServerService.java
@@ -53,7 +53,6 @@
import org.jboss.as.controller.capability.registry.RuntimeCapabilityRegistry;
import org.jboss.as.controller.descriptions.ModelDescriptionConstants;
import org.jboss.as.controller.notification.Notification;
-import org.jboss.as.controller.notification.NotificationHandlerRegistry;
import org.jboss.as.controller.persistence.ConfigurationPersistenceException;
import org.jboss.as.controller.persistence.ExtensibleConfigurationPersister;
import org.jboss.as.controller.registry.ManagementResourceRegistration;
@@ -113,6 +112,7 @@
import org.jboss.as.server.moduleservice.ExtensionIndexService;
import org.jboss.as.server.moduleservice.ExternalModule;
import org.jboss.as.server.moduleservice.ServiceModuleLoader;
+import org.jboss.as.server.suspend.ServerSuspendController;
import org.jboss.as.server.suspend.SuspendController;
import org.jboss.as.version.Stability;
import org.jboss.dmr.ModelNode;
@@ -128,6 +128,7 @@
import org.jboss.threads.EnhancedQueueExecutor;
import org.jboss.threads.JBossThreadFactory;
import org.wildfly.security.manager.WildFlySecurityManager;
+import org.wildfly.service.ServiceInstaller;
/**
* Service for the {@link org.jboss.as.controller.ModelController} for an AS server instance.
@@ -158,15 +159,13 @@ public final class ServerService extends AbstractControllerService {
private final RunningModeControl runningModeControl;
private volatile ExtensibleConfigurationPersister extensibleConfigurationPersister;
private final ServerDelegatingResourceDefinition rootResourceDefinition;
- private final SuspendController suspendController;
+ private final ServerSuspendController suspendController;
public static final String SERVER_NAME = "server";
- static final String SUSPEND_CONTROLLER_CAPABILITY_NAME = "org.wildfly.server.suspend-controller";
static final String EXTERNAL_MODULE_CAPABILITY_NAME = "org.wildfly.management.external-module";
- static final RuntimeCapability SUSPEND_CONTROLLER_CAPABILITY =
- RuntimeCapability.Builder.of(SUSPEND_CONTROLLER_CAPABILITY_NAME, SuspendController.class)
- .build();
+ // TODO Remove type narrowing as soon as references to the implementation class are dropped from WildFly
+ static final RuntimeCapability SUSPEND_CONTROLLER_CAPABILITY = RuntimeCapability.Builder.of(ServerSuspendController.SERVICE_DESCRIPTOR.asType(SuspendController.class)).build();
static final RuntimeCapability EXTERNAL_MODULE_CAPABILITY =
RuntimeCapability.Builder.of(EXTERNAL_MODULE_CAPABILITY_NAME, ExternalModule.class)
@@ -185,7 +184,7 @@ private ServerService(final Supplier executorService,
final OperationStepHandler prepareStep, final BootstrapListener bootstrapListener, final ServerDelegatingResourceDefinition rootResourceDefinition,
final RunningModeControl runningModeControl, final ManagedAuditLogger auditLogger,
final DelegatingConfigurableAuthorizer authorizer, final ManagementSecurityIdentitySupplier securityIdentitySupplier,
- final CapabilityRegistry capabilityRegistry, final SuspendController suspendController, final RuntimeExpressionResolver expressionResolver) {
+ final CapabilityRegistry capabilityRegistry, final ServerSuspendController suspendController, final RuntimeExpressionResolver expressionResolver) {
super(executorService, instabilityListener, getProcessType(configuration.getServerEnvironment()), getStability(configuration.getServerEnvironment()), runningModeControl, null, processState,
rootResourceDefinition, prepareStep, expressionResolver, auditLogger, authorizer, securityIdentitySupplier, capabilityRegistry,
configuration.getServerEnvironment().getConfigurationExtension());
@@ -216,7 +215,7 @@ public static void addService(final ServiceTarget serviceTarget, final Bootstrap
final ControlledProcessState processState, final BootstrapListener bootstrapListener,
final RunningModeControl runningModeControl, final ManagedAuditLogger auditLogger,
final DelegatingConfigurableAuthorizer authorizer, final ManagementSecurityIdentitySupplier securityIdentitySupplier,
- final SuspendController suspendController) {
+ final ServerSuspendController suspendController) {
// Install Executor services
final String namePattern = "ServerService Thread Pool -- %t";
@@ -287,10 +286,12 @@ public void updateOperationID(final int operationID) {
super.getAuditLogger(),
getMutableRootResourceRegistrationProvider(),
super.getBootErrorCollector(),
- configuration.getCapabilityRegistry()));
+ configuration.getCapabilityRegistry(),
+ this.suspendController));
super.start(context);
}
+ @Override
protected void boot(final BootContext context) throws ConfigurationPersistenceException {
boolean ok;
Throwable cause = null;
@@ -302,24 +303,23 @@ protected void boot(final BootContext context) throws ConfigurationPersistenceEx
newExtDirs[extDirs.length] = new File(serverEnvironment.getServerBaseDir(), "lib/ext");
serviceTarget.addService(org.jboss.as.server.deployment.Services.JBOSS_DEPLOYMENT_EXTENSION_INDEX,
new ExtensionIndexService(newExtDirs)).setInitialMode(ServiceController.Mode.ON_DEMAND).install();
- final boolean suspend = runningModeControl.getSuspend()!= null ? runningModeControl.getSuspend() : serverEnvironment.isStartSuspended();
+ final boolean suspend = runningModeControl.getSuspend() != null ? runningModeControl.getSuspend() : serverEnvironment.isStartSuspended();
final boolean gracefulStartup = serverEnvironment.isStartGracefully();
- suspendController.setStartSuspended(suspend);
+ this.suspendController.reset();
runningModeControl.setSuspend(false);
- if (!gracefulStartup) {
- if (suspend) {
+ if (suspend) {
+ if (!gracefulStartup) {
ServerLogger.ROOT_LOGGER.disregardingNonGraceful();
- } else {
- suspendController.nonGracefulStart();
}
+ ServerLogger.AS_ROOT_LOGGER.startingServerSuspended();
+ } else if (!gracefulStartup) {
+ ServerLogger.ROOT_LOGGER.startingNonGraceful();
+ this.suspendController.resume();
}
- context.getServiceTarget().addService(SUSPEND_CONTROLLER_CAPABILITY.getCapabilityServiceName(), suspendController)
- .install();
+ ServiceInstaller.builder(this.suspendController).provides(SUSPEND_CONTROLLER_CAPABILITY.getCapabilityServiceName()).build().install(context.getServiceTarget());
- GracefulShutdownService gracefulShutdownService = new GracefulShutdownService();
- context.getServiceTarget().addService(GracefulShutdownService.SERVICE_NAME, gracefulShutdownService)
- .addDependency(SUSPEND_CONTROLLER_CAPABILITY.getCapabilityServiceName(), SuspendController.class, gracefulShutdownService.getSuspendControllerInjectedValue())
- .install();
+ GracefulShutdownService gracefulShutdownService = new GracefulShutdownService(this.suspendController);
+ context.getServiceTarget().addService(GracefulShutdownService.SERVICE_NAME, gracefulShutdownService).install();
// Activate module loader
DeployerChainAddHandler.addDeploymentProcessor(SERVER_NAME, Phase.STRUCTURE, Phase.STRUCTURE_SERVICE_MODULE_LOADER, new DeploymentUnitProcessor() {
@@ -441,9 +441,11 @@ public void logExit() {
}
}
+ @Override
protected void finishBoot(boolean suspend) throws ConfigurationPersistenceException {
super.finishBoot();
if (!suspend) {
+ ServerLogger.ROOT_LOGGER.resumingServer();
suspendController.resume();
}
}
diff --git a/server/src/main/java/org/jboss/as/server/controller/resources/ServerRootResourceDefinition.java b/server/src/main/java/org/jboss/as/server/controller/resources/ServerRootResourceDefinition.java
index 0115c7da797..259f37002da 100644
--- a/server/src/main/java/org/jboss/as/server/controller/resources/ServerRootResourceDefinition.java
+++ b/server/src/main/java/org/jboss/as/server/controller/resources/ServerRootResourceDefinition.java
@@ -117,7 +117,7 @@
import org.jboss.as.server.services.net.SpecifiedInterfaceAddHandler;
import org.jboss.as.server.services.net.SpecifiedInterfaceRemoveHandler;
import org.jboss.as.server.services.net.SpecifiedInterfaceResolveHandler;
-import org.jboss.as.server.suspend.SuspendController;
+import org.jboss.as.server.suspend.ServerSuspendController;
import org.jboss.dmr.ModelNode;
import org.jboss.dmr.ModelType;
@@ -209,7 +209,7 @@ public class ServerRootResourceDefinition extends SimpleResourceDefinition {
.build();
public static final AttributeDefinition SUSPEND_STATE = SimpleAttributeDefinitionBuilder.create(ModelDescriptionConstants.SUSPEND_STATE, ModelType.STRING)
- .setValidator(EnumValidator.create(SuspendController.State.class))
+ .setValidator(EnumValidator.create(ServerSuspendController.State.class))
.setStorageRuntime()
.setRuntimeServiceNotRequired()
.build();
@@ -266,6 +266,7 @@ public class ServerRootResourceDefinition extends SimpleResourceDefinition {
private final CapabilityRegistry capabilityRegistry;
private final MutableRootResourceRegistrationProvider rootResourceRegistrationProvider;
private final BootErrorCollector bootErrorCollector;
+ private final ServerSuspendController suspendController;
public ServerRootResourceDefinition(
final ContentRepository contentRepository,
@@ -282,7 +283,8 @@ public ServerRootResourceDefinition(
final ManagedAuditLogger auditLogger,
final MutableRootResourceRegistrationProvider rootResourceRegistrationProvider,
final BootErrorCollector bootErrorCollector,
- final CapabilityRegistry capabilityRegistry) {
+ final CapabilityRegistry capabilityRegistry,
+ final ServerSuspendController suspendController) {
super(new Parameters(ResourceRegistration.root(), ServerDescriptions.getResourceDescriptionResolver(SERVER, false))
.addCapabilities(PATH_CAPABILITY.fromBaseCapability(ServerEnvironment.HOME_DIR),
PATH_CAPABILITY.fromBaseCapability(ServerEnvironment.SERVER_BASE_DIR),
@@ -309,6 +311,7 @@ public ServerRootResourceDefinition(
this.securityIdentitySupplier = securityIdentitySupplier;
this.rootResourceRegistrationProvider = rootResourceRegistrationProvider;
this.bootErrorCollector = bootErrorCollector;
+ this.suspendController = suspendController;
}
@Override
@@ -405,12 +408,12 @@ public void registerOperations(ManagementResourceRegistration resourceRegistrati
final ServerDomainProcessReloadHandler reloadHandler = new ServerDomainProcessReloadHandler(Services.JBOSS_AS, runningModeControl, processState, operationIDUpdater, serverEnvironment);
resourceRegistration.registerOperationHandler(getDomainServerLifecycleDefinition(RELOAD, ModelType.STRING, null, BLOCKING, START_MODE), reloadHandler);
- resourceRegistration.registerOperationHandler(getDomainServerLifecycleDefinition(SUSPEND, null, null, TIMEOUT, SUSPEND_TIMEOUT), ServerSuspendHandler.INSTANCE);
+ resourceRegistration.registerOperationHandler(getDomainServerLifecycleDefinition(SUSPEND, null, null, TIMEOUT, SUSPEND_TIMEOUT), new ServerSuspendHandler(this.suspendController));
- resourceRegistration.registerOperationHandler(getDomainServerLifecycleDefinition(RESUME, null, null), ServerResumeHandler.INSTANCE);
+ resourceRegistration.registerOperationHandler(getDomainServerLifecycleDefinition(RESUME, null, null), new ServerResumeHandler(this.suspendController));
// This one is completely private, only for use by the HC
- resourceRegistration.registerOperationHandler(ServerDomainProcessShutdownHandler.DOMAIN_DEFINITION, new ServerDomainProcessShutdownHandler());
+ resourceRegistration.registerOperationHandler(ServerDomainProcessShutdownHandler.DOMAIN_DEFINITION, new ServerDomainProcessShutdownHandler(this.suspendController));
} else {
@@ -418,13 +421,13 @@ public void registerOperations(ManagementResourceRegistration resourceRegistrati
ServerProcessReloadHandler.registerStandardReloadOperation(resourceRegistration, runningModeControl, processState, serverEnvironment, extensibleConfigurationPersister);
ServerProcessReloadHandler.registerEnhancedReloadOperation(resourceRegistration, runningModeControl, processState, serverEnvironment, extensibleConfigurationPersister);
- resourceRegistration.registerOperationHandler(ServerSuspendHandler.DEFINITION, ServerSuspendHandler.INSTANCE);
- resourceRegistration.registerOperationHandler(ServerResumeHandler.DEFINITION, ServerResumeHandler.INSTANCE);
+ resourceRegistration.registerOperationHandler(ServerSuspendHandler.DEFINITION, new ServerSuspendHandler(this.suspendController));
+ resourceRegistration.registerOperationHandler(ServerResumeHandler.DEFINITION, new ServerResumeHandler(this.suspendController));
}
// The System.exit() based shutdown command is only valid for a server process directly launched from the command line
if (serverEnvironment.getLaunchType() == ServerEnvironment.LaunchType.STANDALONE) {
- ServerShutdownHandler serverShutdownHandler = new ServerShutdownHandler(processState, serverEnvironment);
+ ServerShutdownHandler serverShutdownHandler = new ServerShutdownHandler(processState, serverEnvironment, this.suspendController);
resourceRegistration.registerOperationHandler(ServerShutdownHandler.DEFINITION, serverShutdownHandler);
}
@@ -447,7 +450,7 @@ public void registerAttributes(ManagementResourceRegistration resourceRegistrati
resourceRegistration.registerReadOnlyAttribute(SERVER_STATE, new ProcessStateAttributeHandler(processState));
resourceRegistration.registerReadOnlyAttribute(PROCESS_TYPE, ProcessTypeHandler.INSTANCE);
resourceRegistration.registerReadOnlyAttribute(RUNNING_MODE, new RunningModeReadHandler(runningModeControl));
- resourceRegistration.registerReadOnlyAttribute(SUSPEND_STATE, SuspendStateReadHandler.INSTANCE);
+ resourceRegistration.registerReadOnlyAttribute(SUSPEND_STATE, new SuspendStateReadHandler(this.suspendController));
resourceRegistration.registerReadOnlyAttribute(UUID, new InstanceUuidReadHandler(serverEnvironment));
diff --git a/server/src/main/java/org/jboss/as/server/jmx/RunningStateJmx.java b/server/src/main/java/org/jboss/as/server/jmx/RunningStateJmx.java
index bbfe6c0dcb9..a6d8d4fd9eb 100644
--- a/server/src/main/java/org/jboss/as/server/jmx/RunningStateJmx.java
+++ b/server/src/main/java/org/jboss/as/server/jmx/RunningStateJmx.java
@@ -25,8 +25,8 @@
import org.jboss.as.controller.ProcessStateNotifier;
import org.jboss.as.controller.RunningModeControl;
import org.jboss.as.server.logging.ServerLogger;
-import org.jboss.as.server.suspend.OperationListener;
-import org.jboss.as.server.suspend.SuspendController;
+import org.jboss.as.server.suspend.ServerSuspendController;
+import org.jboss.as.server.suspend.ServerSuspendListener;
import org.wildfly.extension.core.management.client.Process.RunningMode;
import org.wildfly.extension.core.management.client.Process.RunningState;
import org.wildfly.extension.core.management.client.Process.RuntimeConfigurationState;
@@ -145,7 +145,7 @@ public synchronized void setRunningState(RunningState oldState, RunningState new
sendNotification(notification);
}
- public static void registerMBean(ProcessStateNotifier processStateNotifier, SuspendController suspendController, RunningModeControl runningModeControl, boolean isServer) {
+ public static void registerMBean(ProcessStateNotifier processStateNotifier, ServerSuspendController suspendController, RunningModeControl runningModeControl, boolean isServer) {
try {
final ObjectName name = new ObjectName(OBJECT_NAME);
final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
@@ -156,31 +156,31 @@ public static void registerMBean(ProcessStateNotifier processStateNotifier, Susp
server.registerMBean(mbean, name);
registerStateListener(mbean, processStateNotifier);
if (suspendController != null) {
- suspendController.addListener(new OperationListener() {
+ suspendController.addSuspendListener(new ServerSuspendListener() {
@Override
public void suspendStarted() {
mbean.setRunningState(mbean.getRunningState(), RunningState.SUSPENDING);
}
@Override
- public void complete() {
+ public void suspendCompleted() {
mbean.setRunningState(mbean.getRunningState(), RunningState.SUSPENDED);
}
@Override
- public void cancelled() {
- if(mbean.getRunningState() == RunningState.STARTING) {
+ public void suspendCancelled() {
+ if (mbean.getRunningState() == RunningState.STARTING) {
mbean.setRunningState(RunningState.STARTING, RunningState.SUSPENDED);
}
if (mbean.getRunningMode() == RunningMode.NORMAL) {
mbean.setRunningState(mbean.getRunningState(), RunningState.NORMAL);
} else {
- mbean.setRunningState(mbean.getRunningState(),RunningState.ADMIN_ONLY);
+ mbean.setRunningState(mbean.getRunningState(), RunningState.ADMIN_ONLY);
}
}
@Override
- public void timeout() {
+ public void suspendTimeout() {
}
});
} else {
diff --git a/server/src/main/java/org/jboss/as/server/operations/ServerDomainProcessShutdownHandler.java b/server/src/main/java/org/jboss/as/server/operations/ServerDomainProcessShutdownHandler.java
index d1e9652f2c7..c5f3e12a07d 100644
--- a/server/src/main/java/org/jboss/as/server/operations/ServerDomainProcessShutdownHandler.java
+++ b/server/src/main/java/org/jboss/as/server/operations/ServerDomainProcessShutdownHandler.java
@@ -5,12 +5,11 @@
package org.jboss.as.server.operations;
-
-import static org.jboss.as.server.Services.JBOSS_SUSPEND_CONTROLLER;
import static org.jboss.as.server.controller.resources.ServerRootResourceDefinition.SUSPEND_TIMEOUT;
import static org.jboss.as.server.controller.resources.ServerRootResourceDefinition.TIMEOUT;
import static org.jboss.as.server.controller.resources.ServerRootResourceDefinition.renameTimeoutToSuspendTimeout;
+import java.time.Duration;
import java.util.EnumSet;
import org.jboss.as.controller.OperationContext;
@@ -23,7 +22,7 @@
import org.jboss.as.controller.registry.OperationEntry;
import org.jboss.as.server.GracefulShutdownService;
import org.jboss.as.server.controller.descriptions.ServerDescriptions;
-import org.jboss.as.server.suspend.SuspendController;
+import org.jboss.as.server.suspend.ServerSuspendController;
import org.jboss.dmr.ModelNode;
import org.jboss.msc.service.ServiceController;
import org.jboss.msc.service.ServiceRegistry;
@@ -38,18 +37,25 @@
*/
public class ServerDomainProcessShutdownHandler implements OperationStepHandler {
-
public static final SimpleOperationDefinition DOMAIN_DEFINITION = new SimpleOperationDefinitionBuilder(ModelDescriptionConstants.SHUTDOWN, ServerDescriptions.getResourceDescriptionResolver())
.setParameters(TIMEOUT, SUSPEND_TIMEOUT)
.setPrivateEntry()
.withFlags(OperationEntry.Flag.HOST_CONTROLLER_ONLY, OperationEntry.Flag.RUNTIME_ONLY)
.build();
+ private final ServerSuspendController suspendController;
+
+ public ServerDomainProcessShutdownHandler(ServerSuspendController suspendController) {
+ this.suspendController = suspendController;
+ }
+
@Override
public void execute(final OperationContext context, final ModelNode operation) throws OperationFailedException {
context.acquireControllerLock();
renameTimeoutToSuspendTimeout(operation);
- final int timeout = SUSPEND_TIMEOUT.resolveModelAttribute(context, operation).asInt(); //in milliseconds, as this is what is passed in from the HC
+ final int seconds = SUSPEND_TIMEOUT.resolveModelAttribute(context, operation).asInt(); //in milliseconds, as this is what is passed in from the HC
+ Duration timeout = (seconds >= 0) ? Duration.ofSeconds(seconds) : null;
+
// Acquire the controller lock to prevent new write ops and wait until current ones are done
context.acquireControllerLock();
context.addStep(new OperationStepHandler() {
@@ -77,11 +83,8 @@ public void handleResult(OperationContext.ResultAction resultAction, OperationCo
// is already shutting down due to receiving a SIGINT
final ServiceController gracefulController = (ServiceController) registry.getService(GracefulShutdownService.SERVICE_NAME);
if (gracefulController != null) {
- final ServiceController suspendControllerServiceController = (ServiceController) registry.getService(JBOSS_SUSPEND_CONTROLLER);
- if (suspendControllerServiceController != null) {
- gracefulController.getValue().startGracefulShutdown();
- suspendControllerServiceController.getValue().suspend(timeout > 0 ? timeout * 1000 : timeout);
- }
+ gracefulController.getValue().startGracefulShutdown();
+ ServerDomainProcessShutdownHandler.this.suspendController.suspend(timeout);
}
}
}
diff --git a/server/src/main/java/org/jboss/as/server/operations/ServerResumeHandler.java b/server/src/main/java/org/jboss/as/server/operations/ServerResumeHandler.java
index 05ca0c6e0bf..89ad4675d11 100644
--- a/server/src/main/java/org/jboss/as/server/operations/ServerResumeHandler.java
+++ b/server/src/main/java/org/jboss/as/server/operations/ServerResumeHandler.java
@@ -8,7 +8,6 @@
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RESUME;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RUNNING_SERVER;
-import static org.jboss.as.server.Services.JBOSS_SUSPEND_CONTROLLER;
import org.jboss.as.controller.OperationContext;
import org.jboss.as.controller.OperationFailedException;
@@ -16,10 +15,9 @@
import org.jboss.as.controller.SimpleOperationDefinition;
import org.jboss.as.controller.SimpleOperationDefinitionBuilder;
import org.jboss.as.server.controller.descriptions.ServerDescriptions;
-import org.jboss.as.server.suspend.SuspendController;
+import org.jboss.as.server.logging.ServerLogger;
+import org.jboss.as.server.suspend.ServerSuspendController;
import org.jboss.dmr.ModelNode;
-import org.jboss.msc.service.ServiceController;
-import org.jboss.msc.service.ServiceRegistry;
/**
* Handler that suspends server operations
@@ -28,12 +26,16 @@
*/
public class ServerResumeHandler implements OperationStepHandler {
- public static final ServerResumeHandler INSTANCE = new ServerResumeHandler();
+ private final ServerSuspendController suspendController;
public static final SimpleOperationDefinition DEFINITION = new SimpleOperationDefinitionBuilder(RESUME, ServerDescriptions.getResourceDescriptionResolver(RUNNING_SERVER))
.setRuntimeOnly()
.build();
+ public ServerResumeHandler(ServerSuspendController suspendController) {
+ this.suspendController = suspendController;
+ }
+
/**
* {@inheritDoc}
*/
@@ -44,17 +46,12 @@ public void execute(OperationContext context, ModelNode operation) throws Operat
context.addStep(new OperationStepHandler() {
@Override
public void execute(OperationContext context, ModelNode operation) throws OperationFailedException {
- // Even though we don't read from the service registry, we have a reference to a
- // service-fronted 'processState' so tell the controller we are modifying a service
- final ServiceRegistry registry = context.getServiceRegistry(true);
context.completeStep(new OperationContext.ResultHandler() {
@Override
public void handleResult(OperationContext.ResultAction resultAction, OperationContext context, ModelNode operation) {
- if(resultAction == OperationContext.ResultAction.KEEP) {
- //even if the timeout is zero we still pause the server
- //to stop new requests being accepted as it is shutting down
- ServiceController shutdownController = (ServiceController) registry.getRequiredService(JBOSS_SUSPEND_CONTROLLER);
- shutdownController.getValue().resume();
+ if (resultAction == OperationContext.ResultAction.KEEP) {
+ ServerLogger.ROOT_LOGGER.resumingServer();
+ ServerResumeHandler.this.suspendController.resume();
}
}
});
diff --git a/server/src/main/java/org/jboss/as/server/operations/ServerShutdownHandler.java b/server/src/main/java/org/jboss/as/server/operations/ServerShutdownHandler.java
index c011c4e73ae..7b9fbbce226 100644
--- a/server/src/main/java/org/jboss/as/server/operations/ServerShutdownHandler.java
+++ b/server/src/main/java/org/jboss/as/server/operations/ServerShutdownHandler.java
@@ -10,7 +10,6 @@
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.SHUTDOWN;
-import static org.jboss.as.server.Services.JBOSS_SUSPEND_CONTROLLER;
import static org.jboss.as.server.controller.resources.ServerRootResourceDefinition.SUSPEND_TIMEOUT;
import static org.jboss.as.server.controller.resources.ServerRootResourceDefinition.TIMEOUT;
import static org.jboss.as.server.controller.resources.ServerRootResourceDefinition.renameTimeoutToSuspendTimeout;
@@ -19,6 +18,7 @@
import java.io.FileInputStream;
import java.io.FileReader;
import java.nio.file.Path;
+import java.time.Duration;
import java.util.EnumSet;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -41,13 +41,11 @@
import org.jboss.as.server.SystemExiter;
import org.jboss.as.server.controller.descriptions.ServerDescriptions;
import org.jboss.as.server.logging.ServerLogger;
-import org.jboss.as.server.suspend.OperationListener;
-import org.jboss.as.server.suspend.SuspendController;
-import org.jboss.as.server.suspend.SuspendController.State;
+import org.jboss.as.server.suspend.ServerSuspendController;
+import org.jboss.as.server.suspend.ServerSuspendController.State;
+import org.jboss.as.server.suspend.ServerSuspendListener;
import org.jboss.dmr.ModelNode;
import org.jboss.dmr.ModelType;
-import org.jboss.msc.service.ServiceController;
-import org.jboss.msc.service.ServiceRegistry;
/**
* Handler that shuts down the standalone server.
@@ -77,10 +75,12 @@ public class ServerShutdownHandler implements OperationStepHandler {
private final ControlledProcessState processState;
private final ServerEnvironment environment;
+ private final ServerSuspendController suspendController;
- public ServerShutdownHandler(ControlledProcessState processState, ServerEnvironment serverEnvironment) {
+ public ServerShutdownHandler(ControlledProcessState processState, ServerEnvironment serverEnvironment, ServerSuspendController suspendController) {
this.processState = processState;
this.environment = serverEnvironment;
+ this.suspendController = suspendController;
}
/**
@@ -90,7 +90,8 @@ public ServerShutdownHandler(ControlledProcessState processState, ServerEnvironm
public void execute(OperationContext context, ModelNode operation) throws OperationFailedException {
renameTimeoutToSuspendTimeout(operation);
final boolean restart = RESTART.resolveModelAttribute(context, operation).asBoolean();
- final int timeout = SUSPEND_TIMEOUT.resolveModelAttribute(context, operation).asInt(); //in seconds, need to convert to ms
+ final int seconds = SUSPEND_TIMEOUT.resolveModelAttribute(context, operation).asInt();
+ Duration timeout = (seconds >= 0) ? Duration.ofSeconds(seconds) : null;
final boolean performInstallation = PERFORM_INSTALLATION.resolveModelAttribute(context, operation).asBoolean();
// Verify the candidate server is prepared
@@ -148,39 +149,37 @@ public void handleResult(OperationContext.ResultAction resultAction, OperationCo
//even if the timeout is zero we still pause the server
//to stop new requests being accepted as it is shutting down
final ShutdownAction shutdown = new ShutdownAction(getOperationName(operation), restart, performInstallation);
- final ServiceRegistry registry = context.getServiceRegistry(false);
- final ServiceController suspendControllerServiceController = (ServiceController) registry.getRequiredService(JBOSS_SUSPEND_CONTROLLER);
- final SuspendController suspendController = suspendControllerServiceController.getValue();
+ final ServerSuspendController suspendController = ServerShutdownHandler.this.suspendController;
if (suspendController.getState() == State.SUSPENDED) {
// WFCORE-4935 if server is already in suspend, don't register any listener, just shut it down
shutdown.shutdown();
} else {
- OperationListener listener = new OperationListener() {
+ ServerSuspendListener listener = new ServerSuspendListener() {
@Override
public void suspendStarted() {
}
@Override
- public void complete() {
- suspendController.removeListener(this);
+ public void suspendCompleted() {
+ suspendController.removeSuspendListener(this);
shutdown.shutdown();
}
@Override
- public void cancelled() {
- suspendController.removeListener(this);
+ public void suspendCancelled() {
+ suspendController.removeSuspendListener(this);
shutdown.cancel();
}
@Override
- public void timeout() {
- suspendController.removeListener(this);
+ public void suspendTimeout() {
+ suspendController.removeSuspendListener(this);
shutdown.shutdown();
}
};
- suspendController.addListener(listener);
- suspendController.suspend(timeout > 0 ? timeout * 1000 : timeout);
+ suspendController.addSuspendListener(listener);
+ suspendController.suspend(timeout);
}
}
}
diff --git a/server/src/main/java/org/jboss/as/server/operations/ServerSuspendHandler.java b/server/src/main/java/org/jboss/as/server/operations/ServerSuspendHandler.java
index 63405f14c20..b6aff4671de 100644
--- a/server/src/main/java/org/jboss/as/server/operations/ServerSuspendHandler.java
+++ b/server/src/main/java/org/jboss/as/server/operations/ServerSuspendHandler.java
@@ -7,11 +7,11 @@
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RUNNING_SERVER;
-import static org.jboss.as.server.Services.JBOSS_SUSPEND_CONTROLLER;
import static org.jboss.as.server.controller.resources.ServerRootResourceDefinition.SUSPEND_TIMEOUT;
import static org.jboss.as.server.controller.resources.ServerRootResourceDefinition.TIMEOUT;
import static org.jboss.as.server.controller.resources.ServerRootResourceDefinition.renameTimeoutToSuspendTimeout;
+import java.time.Duration;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -22,11 +22,10 @@
import org.jboss.as.controller.SimpleOperationDefinitionBuilder;
import org.jboss.as.controller.descriptions.ModelDescriptionConstants;
import org.jboss.as.server.controller.descriptions.ServerDescriptions;
-import org.jboss.as.server.suspend.OperationListener;
-import org.jboss.as.server.suspend.SuspendController;
+import org.jboss.as.server.logging.ServerLogger;
+import org.jboss.as.server.suspend.ServerSuspendController;
+import org.jboss.as.server.suspend.ServerSuspendListener;
import org.jboss.dmr.ModelNode;
-import org.jboss.msc.service.ServiceController;
-import org.jboss.msc.service.ServiceRegistry;
/**
* Handler that suspends server operations
@@ -35,14 +34,18 @@
*/
public class ServerSuspendHandler implements OperationStepHandler {
- public static final ServerSuspendHandler INSTANCE = new ServerSuspendHandler();
-
public static final SimpleOperationDefinition DEFINITION = new SimpleOperationDefinitionBuilder(ModelDescriptionConstants.SUSPEND,
ServerDescriptions.getResourceDescriptionResolver(RUNNING_SERVER))
.setParameters(TIMEOUT, SUSPEND_TIMEOUT)
.setRuntimeOnly()
.build();
+ private final ServerSuspendController suspendController;
+
+ public ServerSuspendHandler(ServerSuspendController suspendController) {
+ this.suspendController = suspendController;
+ }
+
/**
* {@inheritDoc}
*/
@@ -51,53 +54,53 @@ public void execute(final OperationContext context, ModelNode operation) throws
// Acquire the controller lock to prevent new write ops and wait until current ones are done
context.acquireControllerLock();
renameTimeoutToSuspendTimeout(operation);
- final int timeout = SUSPEND_TIMEOUT.resolveModelAttribute(context, operation).asInt();
+ int seconds = SUSPEND_TIMEOUT.resolveModelAttribute(context, operation).asInt();
+ Duration timeout = (seconds >= 0) ? Duration.ofSeconds(seconds) : null;
context.addStep(new OperationStepHandler() {
@Override
public void execute(final OperationContext context, ModelNode operation) throws OperationFailedException {
- final ServiceRegistry registry = context.getServiceRegistry(false);
- ServiceController suspendControllerServiceController = (ServiceController) registry.getRequiredService(JBOSS_SUSPEND_CONTROLLER);
- final SuspendController suspendController = suspendControllerServiceController.getValue();
+ final ServerSuspendController suspendController = ServerSuspendHandler.this.suspendController;
final CountDownLatch latch = new CountDownLatch(1);
final AtomicBoolean cancelled = new AtomicBoolean();
- OperationListener operationListener = new OperationListener() {
+ ServerSuspendListener listener = new ServerSuspendListener() {
@Override
public void suspendStarted() {
}
@Override
- public void complete() {
- suspendController.removeListener(this);
+ public void suspendCompleted() {
+ suspendController.removeSuspendListener(this);
latch.countDown();
}
@Override
- public void cancelled() {
- suspendController.removeListener(this);
+ public void suspendCancelled() {
+ suspendController.removeSuspendListener(this);
cancelled.set(true);
latch.countDown();
}
@Override
- public void timeout() {
- suspendController.removeListener(this);
+ public void suspendTimeout() {
+ suspendController.removeSuspendListener(this);
latch.countDown();
}
};
- suspendController.addListener(operationListener);
- suspendController.suspend(timeout > 0 ? timeout * 1000 : timeout);
- if(timeout != 0 && suspendController.getState() != SuspendController.State.SUSPENDED) {
+ suspendController.addSuspendListener(listener);
+ suspendController.suspend(timeout);
+ boolean waitForSuspend = (timeout == null) || !timeout.isZero();
+ if (waitForSuspend && suspendController.getState() != ServerSuspendController.State.SUSPENDED) {
try {
latch.await();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
- if(cancelled.get()) {
+ if (cancelled.get()) {
context.setRollbackOnly();
}
context.completeStep(new RollbackHandler(suspendController));
@@ -108,15 +111,16 @@ public void timeout() {
private static final class RollbackHandler implements OperationContext.ResultHandler {
- private final SuspendController controller;
+ private final ServerSuspendController controller;
- private RollbackHandler(SuspendController controller) {
+ private RollbackHandler(ServerSuspendController controller) {
this.controller = controller;
}
@Override
public void handleResult(OperationContext.ResultAction resultAction, OperationContext context, ModelNode operation) {
- if(resultAction == OperationContext.ResultAction.ROLLBACK) {
+ if (resultAction == OperationContext.ResultAction.ROLLBACK) {
+ ServerLogger.ROOT_LOGGER.resumingServer();
controller.resume();
}
}
diff --git a/server/src/main/java/org/jboss/as/server/operations/SuspendStateReadHandler.java b/server/src/main/java/org/jboss/as/server/operations/SuspendStateReadHandler.java
index a5cccbccdf0..757f74b4887 100644
--- a/server/src/main/java/org/jboss/as/server/operations/SuspendStateReadHandler.java
+++ b/server/src/main/java/org/jboss/as/server/operations/SuspendStateReadHandler.java
@@ -5,42 +5,28 @@
package org.jboss.as.server.operations;
-import static org.jboss.as.server.Services.JBOSS_SUSPEND_CONTROLLER;
-
import org.jboss.as.controller.OperationContext;
import org.jboss.as.controller.OperationFailedException;
import org.jboss.as.controller.OperationStepHandler;
-import org.jboss.as.server.suspend.SuspendController;
+import org.jboss.as.server.suspend.ServerSuspendController;
import org.jboss.dmr.ModelNode;
-import org.jboss.msc.service.ServiceController;
/**
- * Reports the current server {@link org.jboss.as.server.suspend.SuspendController.State}
+ * Reports the current server {@link org.jboss.as.server.suspend.ServerSuspendController.State}
*
* @author Stuart Douglas
*/
public class SuspendStateReadHandler implements OperationStepHandler {
- public static final SuspendStateReadHandler INSTANCE = new SuspendStateReadHandler();
+ private final ServerSuspendController suspendController;
- private SuspendStateReadHandler(){}
+ public SuspendStateReadHandler(ServerSuspendController suspendController) {
+ this.suspendController = suspendController;
+ }
@Override
public void execute(OperationContext context, ModelNode operation) throws OperationFailedException {
- @SuppressWarnings("unchecked")
- ServiceController sc = (ServiceController) context.getServiceRegistry(false).getService(JBOSS_SUSPEND_CONTROLLER);
- SuspendController.State state;
- if(sc != null) {
- state = sc.getValue().getState();
- } else {
- // Either we haven't installed the SC yet or we're stopping and it's been removed
- // If we haven't installed, when we do its initial state is SUSPENDED
- // If it's been removed, it's last state was SUSPENDED.
- // So, report that.
- state = SuspendController.State.SUSPENDED;
- }
+ ServerSuspendController.State state = (this.suspendController != null) ? this.suspendController.getState() : ServerSuspendController.State.SUSPENDED;
context.getResult().set(state.name());
}
-
-
}
diff --git a/server/src/main/java/org/jboss/as/server/suspend/CountingRequestCountCallback.java b/server/src/main/java/org/jboss/as/server/suspend/CountingRequestCountCallback.java
index ec7adc21911..9a8083a989d 100644
--- a/server/src/main/java/org/jboss/as/server/suspend/CountingRequestCountCallback.java
+++ b/server/src/main/java/org/jboss/as/server/suspend/CountingRequestCountCallback.java
@@ -7,8 +7,7 @@
import java.util.concurrent.atomic.AtomicInteger;
/**
- * RequestCountListener that till n notification have been received before notifying
- * its delegate.
+ * RequestCountListener that waits until a specified number of calls to {@link #done()} have been received before invoking {@link #done()} on its delegate.
*
* @author Stuart Douglas
*/
@@ -26,10 +25,9 @@ public CountingRequestCountCallback(int count, ServerActivityCallback delegate)
@Override
public void done() {
if (count.decrementAndGet() == 0) {
- if(delegate != null) {
+ if (delegate != null) {
delegate.done();
}
}
}
-
}
diff --git a/server/src/main/java/org/jboss/as/server/suspend/OperationListener.java b/server/src/main/java/org/jboss/as/server/suspend/OperationListener.java
index 51368ab6b0d..1eec38d1d64 100644
--- a/server/src/main/java/org/jboss/as/server/suspend/OperationListener.java
+++ b/server/src/main/java/org/jboss/as/server/suspend/OperationListener.java
@@ -11,7 +11,9 @@
* suspend operation.
*
* @author Stuart Douglas
+ * @deprecated Use {@link ServerSuspendListener} instead.
*/
+@Deprecated(forRemoval = true)
public interface OperationListener {
/**
diff --git a/server/src/main/java/org/jboss/as/server/suspend/ServerActivity.java b/server/src/main/java/org/jboss/as/server/suspend/ServerActivity.java
index ca3dbbe5fe9..4679d98f3ca 100644
--- a/server/src/main/java/org/jboss/as/server/suspend/ServerActivity.java
+++ b/server/src/main/java/org/jboss/as/server/suspend/ServerActivity.java
@@ -30,7 +30,7 @@ public interface ServerActivity {
/**
* Returns a value that indicates to which set of {@code ServerActivity} instances
- * {@link SuspendController#registerActivity(ServerActivity) registered} with the {@link SuspendController}
+ * {@link ServerActivityRegistry#addServerActivity(ServerActivity) registered} with the {@link ServerActivityRegistry}
* this activity should belong. All {@code ServerActivity} instances with the same execution group value have their
* {@link #preSuspend(ServerActivityCallback) preSuspend}, {@link #suspended(ServerActivityCallback) suspended}
* and {@link #resume() resume} methods invoked separately from activities with different execution group values.
diff --git a/server/src/main/java/org/jboss/as/server/suspend/ServerActivityRegistry.java b/server/src/main/java/org/jboss/as/server/suspend/ServerActivityRegistry.java
new file mode 100644
index 00000000000..2f0e714cf85
--- /dev/null
+++ b/server/src/main/java/org/jboss/as/server/suspend/ServerActivityRegistry.java
@@ -0,0 +1,31 @@
+/*
+`` * Copyright The WildFly Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package org.jboss.as.server.suspend;
+
+import org.wildfly.service.descriptor.NullaryServiceDescriptor;
+
+/**
+ * A registrar of server activity.
+ */
+public interface ServerActivityRegistry {
+ NullaryServiceDescriptor SERVICE_DESCRIPTOR = NullaryServiceDescriptor.of("org.wildfly.server.suspend-controller", ServerActivityRegistry.class);
+
+ /**
+ * Adds the specified {@link ServerActivity} to this registry.
+ * @param activity server activity that should complete prior to suspending the server
+ * @throws NullPointerException if {@code activity} is null
+ * @throws IllegalArgumentException if {@link ServerActivity#getExecutionGroup() getExecutionGroup()} is invalid.
+ */
+ void addServerActivity(ServerActivity activity);
+
+ /**
+ * Removes the specified {@link ServerActivity} from this registry.
+ * @param activity server activity that should complete prior to suspending the server
+ * @throws NullPointerException if {@code activity} is null
+ * @throws IllegalArgumentException if {@link ServerActivity#getExecutionGroup() getExecutionGroup()} is invalid.
+ */
+ void removeServerActivity(ServerActivity activity);
+}
diff --git a/server/src/main/java/org/jboss/as/server/suspend/ServerSuspendController.java b/server/src/main/java/org/jboss/as/server/suspend/ServerSuspendController.java
new file mode 100644
index 00000000000..0b99cc4d466
--- /dev/null
+++ b/server/src/main/java/org/jboss/as/server/suspend/ServerSuspendController.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright The WildFly Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package org.jboss.as.server.suspend;
+
+import java.time.Duration;
+
+import org.wildfly.service.descriptor.NullaryServiceDescriptor;
+
+public interface ServerSuspendController extends ServerActivityRegistry {
+ NullaryServiceDescriptor SERVICE_DESCRIPTOR = ServerActivityRegistry.SERVICE_DESCRIPTOR.asType(ServerSuspendController.class);
+
+ enum State {
+ RUNNING,
+ PRE_SUSPEND,
+ SUSPENDING,
+ SUSPENDED
+ }
+
+ /**
+ * Suspend the server after waiting for {@link ServerActivity#preSuspend(ServerActivityCallback)} and {@link ServerActivity#suspended(ServerActivityCallback)} completion for all registered server activity.
+ */
+ default void suspend() {
+ this.suspend(null);
+ }
+
+ /**
+ * Suspend the server, waiting for {@link ServerActivity#preSuspend(ServerActivityCallback)} and {@link ServerActivity#suspended(ServerActivityCallback)} completion for all registered server activity,
+ * or after the specified timeout (if not null) has elapsed.
+ * @param timeout the duration of time to wait for pre-suspend activity to complete before suspending the server, or null to wait indefinitely.
+ * @throws IllegalArgumentException if timeout is negative
+ */
+ void suspend(Duration timeout);
+
+ /**
+ * Resumes the server, invoking {@link ServerActivity#resume()} for all registered activity.
+ */
+ void resume();
+
+ /**
+ * Resets the state of the suspend controller.
+ */
+ void reset();
+
+ /**
+ * Returns the state of this controller.
+ * @return the suspend controller state.
+ */
+ State getState();
+
+ /**
+ * Adds the specified server suspension event listener to this controller.
+ * @param listener a server suspension event listener
+ */
+ void addSuspendListener(ServerSuspendListener listener);
+
+ /**
+ * Removes the specified server suspension event listener from this controller.
+ * @param listener a server suspension event listener
+ */
+ void removeSuspendListener(ServerSuspendListener listener);
+}
diff --git a/server/src/main/java/org/jboss/as/server/suspend/ServerSuspendListener.java b/server/src/main/java/org/jboss/as/server/suspend/ServerSuspendListener.java
new file mode 100644
index 00000000000..ebd827560d3
--- /dev/null
+++ b/server/src/main/java/org/jboss/as/server/suspend/ServerSuspendListener.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright The WildFly Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package org.jboss.as.server.suspend;
+
+/**
+ * Server suspend event listener.
+ */
+public interface ServerSuspendListener {
+
+ /**
+ * Invoked when a suspend operation starts.
+ */
+ void suspendStarted();
+
+ /**
+ * Invoked when a suspend operation completes successfully.
+ */
+ void suspendCompleted();
+
+ /**
+ * Invoked upon canceling server suspension, i.e. resuming the server.
+ */
+ void suspendCancelled();
+
+ /**
+ * Invoked when a suspend operation completes due to timeout, i.e. before registered server activity preparation completes.
+ */
+ void suspendTimeout();
+}
diff --git a/server/src/main/java/org/jboss/as/server/suspend/SuspendController.java b/server/src/main/java/org/jboss/as/server/suspend/SuspendController.java
index 287d9062631..2a47badcbd5 100644
--- a/server/src/main/java/org/jboss/as/server/suspend/SuspendController.java
+++ b/server/src/main/java/org/jboss/as/server/suspend/SuspendController.java
@@ -5,8 +5,10 @@
package org.jboss.as.server.suspend;
+import java.time.Duration;
import java.util.ArrayList;
import java.util.Iterator;
+import java.util.LinkedList;
import java.util.List;
import java.util.NavigableMap;
import java.util.Timer;
@@ -15,11 +17,6 @@
import java.util.function.BiConsumer;
import org.jboss.as.server.logging.ServerLogger;
-import org.jboss.msc.service.Service;
-import org.jboss.msc.service.StartContext;
-import org.jboss.msc.service.StartException;
-import org.jboss.msc.service.StopContext;
-import org.jboss.msc.value.InjectedValue;
import org.wildfly.common.Assert;
/**
@@ -33,49 +30,66 @@
*
* @author Stuart Douglas
*/
-public class SuspendController implements Service {
+public class SuspendController implements ServerSuspendController {
+ private static final ServerActivityCallback NO_OP = new ServerActivityCallback() {
+ @Override
+ public void done() {
+ // Do nothing
+ }
+ };
/**
* Timer that handles the timeout. We create it on pause, rather than leaving it hanging round.
*/
private Timer timer;
- private State state = State.SUSPENDED;
+ private volatile State state = State.SUSPENDED;
private final NavigableMap> activitiesByGroup = new TreeMap<>();
- private final List operationListeners = new ArrayList<>();
+ private final List listeners = new LinkedList<>();
private int groupsCount;
- private boolean startSuspended;
-
private final ServerActivityCallback listener = this::activityPaused;
- public SuspendController() {
- this.startSuspended = false;
+ @Override
+ public void reset() {
+ this.state = State.SUSPENDED;
}
- public void setStartSuspended(boolean startSuspended) {
- //TODO: it is not very clear what this boolean stands for now.
- this.startSuspended = startSuspended;
- state = State.SUSPENDED;
+ /**
+ * @deprecated Use {@link #suspend()} or {@link #suspend(Duration)} instead.
+ */
+ @Deprecated(forRemoval = true)
+ public void suspend(long timeoutMillis) {
+ if (timeoutMillis >= 0) {
+ this.suspend(Duration.ofMillis(timeoutMillis));
+ } else {
+ this.suspend();
+ }
}
- public synchronized void suspend(long timeoutMillis) {
- if(state == State.SUSPENDED) {
+ @Override
+ public synchronized void suspend(Duration timeout) {
+ if (state == State.SUSPENDED) {
return;
}
- if (timeoutMillis > 0) {
- ServerLogger.ROOT_LOGGER.suspendingServer(timeoutMillis);
- } else if (timeoutMillis < 0) {
- ServerLogger.ROOT_LOGGER.suspendingServerWithNoTimeout();
+ if (timeout != null) {
+ if (timeout.isNegative()) {
+ throw new IllegalArgumentException(timeout.toString());
+ }
+ if (timeout.isZero()) {
+ ServerLogger.ROOT_LOGGER.suspendingServer();
+ } else {
+ ServerLogger.ROOT_LOGGER.suspendingServer(timeout.toMillis());
+ }
} else {
- ServerLogger.ROOT_LOGGER.suspendingServer();
+ ServerLogger.ROOT_LOGGER.suspendingServerWithNoTimeout();
}
state = State.PRE_SUSPEND;
- //we iterate a copy, in case a listener tries to register a new listener
- for(OperationListener listener: new ArrayList<>(operationListeners)) {
+ // Iterate over a copy, in case a listener tries to register a new listener
+ for (ServerSuspendListener listener: List.copyOf(this.listeners)) {
listener.suspendStarted();
}
groupsCount = activitiesByGroup.size();
@@ -104,44 +118,43 @@ public synchronized void suspend(long timeoutMillis) {
}
}, preSuspendGroupCallBack);
- if (timeoutMillis > 0) {
- timer = new Timer();
- timer.schedule(new TimerTask() {
- @Override
- public void run() {
- timeout();
- }
- }, timeoutMillis);
- } else if (timeoutMillis == 0) {
- timeout();
+ if (timeout != null) {
+ if (timeout.isZero()) {
+ this.timeout();
+ } else {
+ timer = new Timer();
+ timer.schedule(new TimerTask() {
+ @Override
+ public void run() {
+ SuspendController.this.timeout();
+ }
+ }, timeout.toMillis());
+ }
}
}
}
+ /**
+ * @deprecated Use {@link #resume()} instead.
+ */
+ @Deprecated(forRemoval = true)
public void nonGracefulStart() {
- resume(false);
+ this.resume();
}
- public void resume() {
- resume(true);
- }
-
- private synchronized void resume(boolean gracefulStart) {
+ @Override
+ public synchronized void resume() {
if (state == State.RUNNING) {
return;
}
- if (!gracefulStart) {
- ServerLogger.ROOT_LOGGER.startingNonGraceful();
- } else {
- ServerLogger.ROOT_LOGGER.resumingServer();
- }
if (timer != null) {
timer.cancel();
timer = null;
}
- for (OperationListener listener : new ArrayList<>(operationListeners)) {
- listener.cancelled();
+ // Iterate over a copy, in case a listener tries to register a new listener
+ for (ServerSuspendListener listener: List.copyOf(this.listeners)) {
+ listener.suspendCancelled();
}
for (List executionGroup : activitiesByGroup.descendingMap().values()) {
for (ServerActivity activity : executionGroup) {
@@ -161,24 +174,38 @@ private synchronized void resume(boolean gracefulStart) {
* @throws IllegalArgumentException if {@code activity} is {@code null} of if its
* {@link ServerActivity#getExecutionGroup() getExecutionGroup()} method
* returns a value outside of that method's documented legal range.
+ * @deprecated Use {@link #addServerActivity(ServerActivity)} instead.
*/
- public synchronized void registerActivity(final ServerActivity activity) {
+ @Deprecated(forRemoval = true)
+ public void registerActivity(final ServerActivity activity) {
+ this.addServerActivity(activity);
+ }
+
+ /**
+ * @deprecated Use {@link #removeServerActivity(ServerActivity)} instead.
+ */
+ @Deprecated(forRemoval = true)
+ public void unRegisterActivity(final ServerActivity activity) {
+ this.removeServerActivity(activity);
+ }
+
+ @Override
+ public synchronized void addServerActivity(ServerActivity activity) {
Assert.checkNotNullParam("activity", activity);
Assert.checkMinimumParameter("activity.getExecutionGroup()", ServerActivity.LOWEST_EXECUTION_GROUP, activity.getExecutionGroup());
Assert.checkMaximumParameter("activity.getExecutionGroup()", ServerActivity.HIGHEST_EXECUTION_GROUP, activity.getExecutionGroup());
List executionGroup = this.activitiesByGroup.computeIfAbsent(activity.getExecutionGroup(), ArrayList::new);
executionGroup.add(activity);
- if(state != State.RUNNING) {
+ if (state != State.RUNNING) {
//if the activity is added when we are not running we just immediately suspend it
//this should only happen at boot, so there should be no outstanding requests anyway
// note that this means there is no execution group grouping of these calls.
- activity.suspended(() -> {
-
- });
+ activity.suspended(NO_OP);
}
}
- public synchronized void unRegisterActivity(final ServerActivity activity) {
+ @Override
+ public synchronized void removeServerActivity(ServerActivity activity) {
List executionGroup = activitiesByGroup.get(activity.getExecutionGroup());
if (executionGroup != null) {
executionGroup.remove(activity);
@@ -189,16 +216,6 @@ public synchronized void unRegisterActivity(final ServerActivity activity) {
}
@Override
- public synchronized void start(StartContext startContext) throws StartException {
- if(startSuspended) {
- ServerLogger.AS_ROOT_LOGGER.startingServerSuspended();
- }
- }
-
- @Override
- public synchronized void stop(StopContext stopContext) {
- }
-
public State getState() {
return state;
}
@@ -215,9 +232,9 @@ private void handlePause() {
timer.cancel();
timer = null;
}
-
- for(OperationListener listener: new ArrayList<>(operationListeners)) {
- listener.complete();
+ // Iterate over a copy, in case a listener tries to register a new listener
+ for (ServerSuspendListener listener: List.copyOf(this.listeners)) {
+ listener.suspendCompleted();
}
}
}
@@ -227,23 +244,36 @@ private synchronized void timeout() {
timer.cancel();
timer = null;
}
- for(OperationListener listener: new ArrayList<>(operationListeners)) {
- listener.timeout();
+ // Iterate over a copy, in case a listener tries to register a new listener
+ for (ServerSuspendListener listener: List.copyOf(this.listeners)) {
+ listener.suspendTimeout();
}
}
+ @Override
+ public synchronized void addSuspendListener(ServerSuspendListener listener) {
+ this.listeners.add(listener);
+ }
- public synchronized void addListener(final OperationListener listener) {
- operationListeners.add(listener);
+ @Override
+ public synchronized void removeSuspendListener(ServerSuspendListener listener) {
+ this.listeners.remove(listener);
}
- public synchronized void removeListener(final OperationListener listener) {
- operationListeners.remove(listener);
+ /**
+ * @deprecated Use {@link #addSuspendListener(ServerSuspendListener)} instead.
+ */
+ @Deprecated(forRemoval = true)
+ public void addListener(final OperationListener listener) {
+ this.addSuspendListener(new LegacyServerSuspendListener(listener));
}
- @Override
- public SuspendController getValue() throws IllegalStateException, IllegalArgumentException {
- return this;
+ /**
+ * @deprecated Use {@link #removeSuspendListener(ServerSuspendListener)} instead.
+ */
+ @Deprecated(forRemoval = true)
+ public void removeListener(final OperationListener listener) {
+ this.removeSuspendListener(new LegacyServerSuspendListener(listener));
}
private void processGroups(Iterator> iterator,
@@ -262,10 +292,50 @@ private void processGroups(Iterator> iterator,
}
}
- public enum State {
- RUNNING,
- PRE_SUSPEND,
- SUSPENDING,
- SUSPENDED
+ @Deprecated
+ private static class LegacyServerSuspendListener implements ServerSuspendListener {
+ private final OperationListener listener;
+
+ LegacyServerSuspendListener(OperationListener listener) {
+ this.listener = listener;
+ }
+
+ @Override
+ public void suspendStarted() {
+ this.listener.suspendStarted();
+ }
+
+ @Override
+ public void suspendCompleted() {
+ this.listener.complete();
+ }
+
+ @Override
+ public void suspendCancelled() {
+ this.listener.cancelled();
+ }
+
+ @Override
+ public void suspendTimeout() {
+ this.listener.timeout();
+ }
+
+ @Override
+ public int hashCode() {
+ return this.listener.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ if (this == object) return true;
+ if (!(object instanceof LegacyServerSuspendListener)) return false;
+ LegacyServerSuspendListener listener = (LegacyServerSuspendListener) object;
+ return this.listener.equals(listener.listener);
+ }
+
+ @Override
+ public String toString() {
+ return this.listener.toString();
+ }
}
}
diff --git a/server/src/test/java/org/jboss/as/server/suspend/SuspendControllerTestCase.java b/server/src/test/java/org/jboss/as/server/suspend/SuspendControllerTestCase.java
index 51ad5c24cfc..f0ec3b0858b 100644
--- a/server/src/test/java/org/jboss/as/server/suspend/SuspendControllerTestCase.java
+++ b/server/src/test/java/org/jboss/as/server/suspend/SuspendControllerTestCase.java
@@ -16,7 +16,7 @@
import org.junit.Test;
/**
- * Unit tests of {@link SuspendController}.
+ * Unit tests of {@link ServerSuspendController}.
*/
public class SuspendControllerTestCase {
@@ -33,16 +33,16 @@ public void testServerActivityCallbackOrder() {
}
private void serverActivityCallbackOrderTest(CounterActivity... activities) {
- SuspendController testee = new SuspendController();
+ ServerSuspendController testee = new SuspendController();
testee.resume();
NavigableSet activitySet = new TreeSet<>();
for (CounterActivity activity : activities) {
- testee.registerActivity(activity);
+ testee.addServerActivity(activity);
activitySet.add(activity);
}
- testee.suspend(-1);
+ testee.suspend();
testee.resume();
orderCheck(activitySet);
@@ -50,12 +50,12 @@ private void serverActivityCallbackOrderTest(CounterActivity... activities) {
// Randomly unregister some activities
for (CounterActivity activity : activities) {
if (Math.random() < 0.5) {
- testee.unRegisterActivity(activity);
+ testee.removeServerActivity(activity);
assertTrue(activitySet.remove(activity));
}
}
- testee.suspend(-1);
+ testee.suspend();
testee.resume();
orderCheck(activitySet);
diff --git a/server/src/test/java/org/jboss/as/server/test/InterfaceManagementUnitTestCase.java b/server/src/test/java/org/jboss/as/server/test/InterfaceManagementUnitTestCase.java
index 938448cfb00..2acfbfd3637 100644
--- a/server/src/test/java/org/jboss/as/server/test/InterfaceManagementUnitTestCase.java
+++ b/server/src/test/java/org/jboss/as/server/test/InterfaceManagementUnitTestCase.java
@@ -7,6 +7,7 @@
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ANY_ADDRESS;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OUTCOME;
+import static org.mockito.Mockito.mock;
import java.io.ByteArrayOutputStream;
import java.io.File;
@@ -61,6 +62,7 @@
import org.jboss.as.server.controller.resources.ServerRootResourceDefinition;
import org.jboss.as.server.parsing.StandaloneXml;
import org.jboss.as.server.services.net.NetworkInterfaceService;
+import org.jboss.as.server.suspend.ServerSuspendController;
import org.jboss.as.version.ProductConfig;
import org.jboss.dmr.ModelNode;
import org.jboss.dmr.ModelType;
@@ -310,7 +312,7 @@ protected void initModel(ManagementModel managementModel, Resource modelControll
public void start(StartContext context) throws StartException {
rootResourceDefinition.setDelegate(new ServerRootResourceDefinition(MockRepository.INSTANCE,
persister, environment, processState, null, extensionRegistry, false, MOCK_PATH_MANAGER, null,
- authorizer, securityIdentitySupplier, AuditLogger.NO_OP_LOGGER, getMutableRootResourceRegistrationProvider(), getBootErrorCollector(), capabilityRegistry));
+ authorizer, securityIdentitySupplier, AuditLogger.NO_OP_LOGGER, getMutableRootResourceRegistrationProvider(), getBootErrorCollector(), capabilityRegistry, mock(ServerSuspendController.class)));
super.start(context);
}