Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WFCORE-7143] Consolidate HostControllerBootstrap and EmbeddedHostCon… #6325

Merged
merged 1 commit into from
Jan 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading