in artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java [1260:1563]
private void stop(boolean failoverOnServerShutdown,
final boolean criticalIOError,
boolean shutdownExternalComponents,
boolean restarting,
boolean isShutdown) {
logger.debug("Stopping server {}", this);
synchronized (this) {
if (state == SERVER_STATE.STOPPED || state == SERVER_STATE.STOPPING) {
return;
}
state = SERVER_STATE.STOPPING;
ServerStatus.stopping(this);
callPreDeActiveCallbacks();
if (criticalIOError) {
final ManagementService managementService = this.managementService;
if (managementService != null) {
// notifications trigger disk IO so we don't want to send any on a critical IO error
managementService.enableNotifications(false);
}
}
final FileStoreMonitor fileStoreMonitor = this.fileStoreMonitor;
if (fileStoreMonitor != null) {
fileStoreMonitor.stop();
this.fileStoreMonitor = null;
}
if (failoverOnServerShutdown) {
final Activation activation = this.activation;
if (activation != null) {
activation.sendPrimaryIsStopping();
}
}
stopComponent(connectionRouterManager);
stopComponent(connectorsService);
// we stop the groupingHandler before we stop the cluster manager so binding mappings
// aren't removed in case of failover
if (groupingHandler != null) {
managementService.removeNotificationListener(groupingHandler);
stopComponent(groupingHandler);
}
stopComponent(federationManager);
stopComponent(clusterManager);
for (ActiveMQComponent component : this.protocolServices) {
stopComponent(component);
}
protocolServices.clear();
final RemotingService remotingService = this.remotingService;
if (remotingService != null) {
remotingService.pauseAcceptors();
}
// allows for graceful shutdown
if (remotingService != null && configuration.isGracefulShutdownEnabled()) {
long timeout = configuration.getGracefulShutdownTimeout();
try {
if (timeout == -1) {
remotingService.getConnectionCountLatch().await();
} else {
remotingService.getConnectionCountLatch().await(timeout);
}
} catch (InterruptedException e) {
ActiveMQServerLogger.LOGGER.interruptWhilstStoppingComponent(remotingService.getClass().getName());
}
}
freezeConnections();
}
final Activation activation = this.activation;
if (activation != null) {
activation.postConnectionFreeze();
}
closeAllServerSessions(criticalIOError);
// *************************************************************************************************************
// There's no need to sync this part of the method, since the state stopped | stopping is checked within the sync
//
// we can't synchronized the whole method here as that would cause a deadlock
// so stop is checking for stopped || stopping inside the lock
// which will be already enough to guarantee that no other thread will be accessing this method here.
//
// *************************************************************************************************************
final StorageManager storageManager = this.storageManager;
if (storageManager != null)
storageManager.clearContext();
//before we stop any components deactivate any callbacks
callDeActiveCallbacks();
stopComponent(backupManager);
if (activation != null) {
try {
activation.preStorageClose();
} catch (Throwable t) {
ActiveMQServerLogger.LOGGER.errorStoppingComponent(activation.getClass().getName(), t);
}
}
final RemotingService remotingService = this.remotingService;
if (remotingService != null) {
// The notification must be sent with the StorageManager still up
// this is because NotificationService will use storageManager.generateID
remotingService.notifyStop();
}
// We start the preparation for the broker shutdown by first stopping acceptors, and removing connections
// this is to avoid Exceptions while the broker is stopping as much as possible
// by first stopping any pending connections before stopping the storage.
// if we stopped the journal first before remoting we could have more exceptions being sent for the client.
try {
if (remotingService != null) {
// it will close all connections except to the one used by replication
remotingService.prepareStop(criticalIOError, storageManager != null ? storageManager.getUsedConnections() : Collections.emptySet());
}
} catch (Throwable t) {
ActiveMQServerLogger.LOGGER.errorStoppingComponent(remotingService.getClass().getName(), t);
}
stopComponent(pagingManager);
if (!criticalIOError && pagingManager != null) {
pagingManager.counterSnapshot();
}
final ManagementService managementService = this.managementService;
// we have to disable management service before stopping the storage
// otherwise management would send notifications eventually
if (managementService != null) {
try {
managementService.enableNotifications(false);
} catch (Throwable t) {
ActiveMQServerLogger.LOGGER.errorStoppingComponent(managementService.getClass().getName(), t);
}
}
if (storageManager != null) {
try {
storageManager.stop(criticalIOError, failoverOnServerShutdown);
} catch (Throwable t) {
ActiveMQServerLogger.LOGGER.errorStoppingComponent(storageManager.getClass().getName(), t);
}
}
// We stop remotingService before otherwise we may lock the system in case of a critical IO
// error shutdown
if (remotingService != null) {
try {
remotingService.stop(criticalIOError);
} catch (Throwable t) {
ActiveMQServerLogger.LOGGER.errorStoppingComponent(remotingService.getClass().getName(), t);
}
}
// Stop the management service after the remoting service to ensure all acceptors are deregistered with JMX
if (managementService != null) {
try {
managementService.unregisterServer();
} catch (Throwable t) {
ActiveMQServerLogger.LOGGER.errorStoppingComponent(managementService.getClass().getName(), t);
}
}
stopComponent(managementService);
stopComponent(resourceManager);
stopComponent(postOffice);
if (scheduledPool != null && !scheduledPoolSupplied) {
// we just interrupt all running tasks, these are supposed to be pings and the like.
scheduledPool.shutdownNow();
}
stopComponent(memoryManager);
for (SecuritySettingPlugin securitySettingPlugin : configuration.getSecuritySettingPlugins()) {
securitySettingPlugin.stop();
}
if (ioExecutorPool != null) {
shutdownPool(ioExecutorPool);
}
if (pageExecutorPool != null) {
shutdownPool(pageExecutorPool);
}
if (!scheduledPoolSupplied)
scheduledPool = null;
if (securityStore != null) {
try {
securityStore.stop();
} catch (Throwable t) {
ActiveMQServerLogger.LOGGER.errorStoppingComponent(securityStore.getClass().getName(), t);
}
}
installMirrorController(null);
pagingManager = null;
securityStore = null;
resourceManager = null;
postOffice = null;
queueFactory = null;
resourceManager = null;
messagingServerControl = null;
memoryManager = null;
backupManager = null;
extraRecordsLoader = null;
this.storageManager = null;
sessions.clear();
state = SERVER_STATE.STOPPED;
activationLatch.setCount(1);
// to display in the log message
SimpleString tempNodeID = getNodeID();
if (activation != null) {
try {
activation.close(failoverOnServerShutdown, restarting);
} catch (Throwable t) {
ActiveMQServerLogger.LOGGER.errorStoppingComponent(activation.getClass().getName(), t);
}
}
// JDBC journal can use this thread pool to configure the network timeout on a pooled connection:
// better to stop it after closing activation (and JDBC node manager on it)
final ExecutorService threadPool = this.threadPool;
if (threadPool != null && !threadPoolSupplied) {
shutdownPool(threadPool);
}
if (!threadPoolSupplied) {
this.threadPool = null;
}
// given that threadPool can be garbage collected, need to clear anything that would make it leaks
clearJdbcNetworkTimeout();
if (activationThread != null) {
try {
activationThread.join(30000);
} catch (InterruptedException e) {
ActiveMQServerLogger.LOGGER.interruptWhilstStoppingComponent(activationThread.getClass().getName());
}
if (activationThread.isAlive()) {
ActiveMQServerLogger.LOGGER.activationDidntFinish(this);
activationThread.interrupt();
}
}
stopComponent(nodeManager);
nodeManager = null;
addressSettingsRepository.clearListeners();
addressSettingsRepository.clearCache();
scaledDownNodeIDs.clear();
connectedClientIds.clear();
stopExternalComponents(shutdownExternalComponents);
try {
this.analyzer.clear();
this.analyzer.stop();
} catch (Exception e) {
logger.warn(e.getMessage(), e);
} finally {
this.analyzer = null;
}
for (ActivateCallback callback: activateCallbacks) {
if (isShutdown) {
callback.shutdown(this);
} else {
callback.stop(this);
}
}
if (identity != null) {
ActiveMQServerLogger.LOGGER.serverStopped("identity=" + identity + ",version=" + getVersion().getFullVersion(), tempNodeID, getUptime());
} else {
ActiveMQServerLogger.LOGGER.serverStopped(getVersion().getFullVersion(), tempNodeID, getUptime());
}
}