-
Notifications
You must be signed in to change notification settings - Fork 467
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #6325 from bstansberry/WFCORE-7143
[WFCORE-7143] Consolidate HostControllerBootstrap and EmbeddedHostCon…
- Loading branch information
Showing
3 changed files
with
195 additions
and
179 deletions.
There are no files selected for viewing
164 changes: 164 additions & 0 deletions
164
...ontroller/src/main/java/org/jboss/as/host/controller/AbstractHostControllerBootstrap.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
/* | ||
* Copyright The WildFly Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package org.jboss.as.host.controller; | ||
|
||
import java.util.concurrent.CountDownLatch; | ||
import java.util.concurrent.Future; | ||
|
||
import org.jboss.as.controller.ControlledProcessState; | ||
import org.jboss.as.controller.ControlledProcessStateService; | ||
import org.jboss.as.controller.ProcessStateNotifier; | ||
import org.jboss.as.server.FutureServiceContainer; | ||
import org.jboss.as.server.jmx.RunningStateJmx; | ||
import org.jboss.msc.service.ServiceActivator; | ||
import org.jboss.msc.service.ServiceContainer; | ||
import org.jboss.msc.service.ServiceTarget; | ||
|
||
/** | ||
* Base class for bootstrapping embedded and non-embedded Host Controllers. | ||
* | ||
* @author Emanuel Muckenhuber | ||
* @author <a href="mailto:[email protected]">Darran Lofthouse</a> | ||
* @author Brian Stansberry (c) 2011 Red Hat Inc. | ||
* @author Ken Wills (c) 2015 Red Hat Inc. | ||
*/ | ||
public abstract class AbstractHostControllerBootstrap { | ||
|
||
private final ShutdownHook shutdownHook; | ||
private final ServiceContainer serviceContainer; | ||
private final HostControllerEnvironment environment; | ||
private final String authCode; | ||
|
||
protected AbstractHostControllerBootstrap(final HostControllerEnvironment environment, final String authCode, | ||
final ShutdownHook shutdownHook) { | ||
this.environment = environment; | ||
this.authCode = authCode; | ||
this.shutdownHook = shutdownHook; | ||
this.serviceContainer = shutdownHook.register(); | ||
} | ||
|
||
/** | ||
* Bootstrap the host controller. | ||
* | ||
* @param embedded {@code true} if the host controller is embedded in another process | ||
* @param extraServices any extra services to launch as part of bootstrap | ||
* @return future that will provide the MSC {@link ServiceContainer} for the host controller | ||
*/ | ||
protected final Future<ServiceContainer> bootstrap(boolean embedded, ServiceActivator... extraServices) { | ||
final HostRunningModeControl runningModeControl = environment.getRunningModeControl(); | ||
final ControlledProcessState processState = new ControlledProcessState(true, embedded); | ||
shutdownHook.setControlledProcessState(processState); | ||
ServiceTarget target = serviceContainer.subTarget(); | ||
|
||
final ProcessStateNotifier processStateNotifier = ControlledProcessStateService.addService(target, processState); | ||
RunningStateJmx.registerMBean(processStateNotifier, null, runningModeControl, false); | ||
|
||
final FutureServiceContainer futureServiceContainer = new FutureServiceContainer(); | ||
final HostControllerService hcs = new HostControllerService(environment, runningModeControl, authCode, | ||
processState, futureServiceContainer, extraServices); | ||
target.addService(HostControllerService.HC_SERVICE_NAME, hcs).install(); | ||
return futureServiceContainer; | ||
} | ||
|
||
/** | ||
* {@link Runtime#addShutdownHook JVM shutdown hook} thread that cleans up the | ||
* Host Controller services. | ||
*/ | ||
public static final class ShutdownHook extends Thread { | ||
|
||
private final Runnable processExitingCallback; | ||
private boolean down; | ||
private ControlledProcessState processState; | ||
private ServiceContainer container; | ||
|
||
/** | ||
* Creates a new {@code ShutdownHook} thread. | ||
*/ | ||
public ShutdownHook() { | ||
this(null); | ||
} | ||
|
||
/** | ||
* Creates a new {@code ShutdownHook} thread. | ||
* | ||
* @param processExitingCallback runnable to invoke after the {@code ControlledProcessState} has been | ||
* {@link ControlledProcessState#setStopping() set as stopping} but before | ||
* the MSC {@link ServiceContainer} has been {@link ServiceContainer#shutdown() shut down}. | ||
* May be {@code null}. | ||
*/ | ||
public ShutdownHook(Runnable processExitingCallback) { | ||
this.processExitingCallback = processExitingCallback; | ||
} | ||
|
||
private ServiceContainer register() { | ||
|
||
Runtime.getRuntime().addShutdownHook(this); | ||
synchronized (this) { | ||
if (!down) { | ||
container = ServiceContainer.Factory.create("host-controller", false); | ||
return container; | ||
} else { | ||
throw new IllegalStateException(); | ||
} | ||
} | ||
} | ||
|
||
private synchronized void setControlledProcessState(final ControlledProcessState ps) { | ||
this.processState = ps; | ||
} | ||
|
||
/** | ||
* Calls {@link #shutdown()}. | ||
*/ | ||
@Override | ||
public void run() { | ||
shutdown(); | ||
} | ||
|
||
/** | ||
* Notifies the {@code ControlledProcessState} for the Host Controller that | ||
* {@link ControlledProcessState#setStopping() it is stopping}, invokes any {@link Runnable} | ||
* provided to our {@link ShutdownHook#ShutdownHook(Runnable) constructor}, and | ||
* {@link ServiceContainer#shutdown() shuts down} the Host Controller's {@link ServiceContainer}. | ||
*/ | ||
public void shutdown() { | ||
final ServiceContainer sc; | ||
final ControlledProcessState ps; | ||
synchronized (this) { | ||
down = true; | ||
sc = container; | ||
ps = processState; | ||
} | ||
try { | ||
if (ps != null) { | ||
ps.setStopping(); | ||
} | ||
} finally { | ||
if (sc != null) { | ||
if (processExitingCallback != null) { | ||
processExitingCallback.run(); | ||
} | ||
final CountDownLatch latch = new CountDownLatch(1); | ||
sc.addTerminateListener(new ServiceContainer.TerminateListener() { | ||
@Override | ||
public void handleTermination(Info info) { | ||
latch.countDown(); | ||
} | ||
}); | ||
sc.shutdown(); | ||
// wait for all services to finish. | ||
for (;;) { | ||
try { | ||
latch.await(); | ||
break; | ||
} catch (InterruptedException e) { | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,110 +5,31 @@ | |
|
||
package org.jboss.as.host.controller; | ||
|
||
import java.util.concurrent.CountDownLatch; | ||
|
||
import org.jboss.as.controller.ControlledProcessState; | ||
import org.jboss.as.controller.ProcessStateNotifier; | ||
import org.jboss.as.controller.ControlledProcessStateService; | ||
import org.jboss.as.host.controller.logging.HostControllerLogger; | ||
import org.jboss.as.server.jmx.RunningStateJmx; | ||
import org.jboss.msc.service.ServiceContainer; | ||
import org.jboss.msc.service.ServiceTarget; | ||
|
||
/** | ||
* Bootstrap of the HostController process. | ||
* Bootstrap of a non-embedded HostController process. | ||
* | ||
* @author Emanuel Muckenhuber | ||
* @author <a href="mailto:[email protected]">Darran Lofthouse</a> | ||
* @author Brian Stansberry (c) 2011 Red Hat Inc. | ||
*/ | ||
public class HostControllerBootstrap { | ||
|
||
private final ShutdownHook shutdownHook; | ||
private final ServiceContainer serviceContainer; | ||
private final HostControllerEnvironment environment; | ||
private final String authCode; | ||
public final class HostControllerBootstrap extends AbstractHostControllerBootstrap { | ||
|
||
public HostControllerBootstrap(final HostControllerEnvironment environment, final String authCode) { | ||
this.environment = environment; | ||
this.authCode = authCode; | ||
this.shutdownHook = new ShutdownHook(); | ||
this.serviceContainer = shutdownHook.register(); | ||
super(environment, authCode, | ||
new ShutdownHook(HostControllerBootstrap::handleProcessExiting)); | ||
} | ||
|
||
/** | ||
* Start the host controller services. | ||
* | ||
* @throws Exception | ||
*/ | ||
public void bootstrap() throws Exception { | ||
final HostRunningModeControl runningModeControl = environment.getRunningModeControl(); | ||
final ControlledProcessState processState = new ControlledProcessState(true, false); | ||
shutdownHook.setControlledProcessState(processState); | ||
ServiceTarget target = serviceContainer.subTarget(); | ||
ProcessStateNotifier processStateNotifier = ControlledProcessStateService.addService(target, processState); | ||
RunningStateJmx.registerMBean(processStateNotifier, null, runningModeControl, false); | ||
final HostControllerService hcs = new HostControllerService(environment, runningModeControl, authCode, processState); | ||
target.addService(HostControllerService.HC_SERVICE_NAME, hcs).install(); | ||
public void bootstrap() { | ||
bootstrap(false); | ||
} | ||
|
||
private static class ShutdownHook extends Thread { | ||
private boolean down; | ||
private ControlledProcessState processState; | ||
private ServiceContainer container; | ||
|
||
private ServiceContainer register() { | ||
|
||
Runtime.getRuntime().addShutdownHook(this); | ||
synchronized (this) { | ||
if (!down) { | ||
container = ServiceContainer.Factory.create("host-controller", false); | ||
return container; | ||
} else { | ||
throw new IllegalStateException(); | ||
} | ||
} | ||
} | ||
|
||
private synchronized void setControlledProcessState(final ControlledProcessState ps) { | ||
this.processState = ps; | ||
} | ||
|
||
@Override | ||
public void run() { | ||
final ServiceContainer sc; | ||
final ControlledProcessState ps; | ||
synchronized (this) { | ||
down = true; | ||
sc = container; | ||
ps = processState; | ||
} | ||
try { | ||
if (ps != null) { | ||
ps.setStopping(); | ||
} | ||
} finally { | ||
if (sc != null) { | ||
SystemExiter.logBeforeExit(HostControllerLogger.ROOT_LOGGER::shutdownHookInvoked); | ||
final CountDownLatch latch = new CountDownLatch(1); | ||
sc.addTerminateListener(new ServiceContainer.TerminateListener() { | ||
@Override | ||
public void handleTermination(Info info) { | ||
latch.countDown(); | ||
} | ||
}); | ||
sc.shutdown(); | ||
// wait for all services to finish. | ||
for (;;) { | ||
try { | ||
latch.await(); | ||
break; | ||
} catch (InterruptedException e) { | ||
} | ||
} | ||
} | ||
} | ||
} | ||
private static void handleProcessExiting() { | ||
SystemExiter.logBeforeExit(HostControllerLogger.ROOT_LOGGER::shutdownHookInvoked); | ||
} | ||
|
||
} |
Oops, something went wrong.