Skip to content

Commit

Permalink
Merge pull request #6325 from bstansberry/WFCORE-7143
Browse files Browse the repository at this point in the history
[WFCORE-7143] Consolidate HostControllerBootstrap and EmbeddedHostCon…
  • Loading branch information
yersan authored Jan 30, 2025
2 parents 217b4cc + 7386934 commit 247c4c5
Show file tree
Hide file tree
Showing 3 changed files with 195 additions and 179 deletions.
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) {
}
}
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

}
Loading

0 comments on commit 247c4c5

Please sign in to comment.