// just return if no routes to shutdown
if (routes.isEmpty()) {
return true;
}
StopWatch watch = new StopWatch();
// at first sort according to route startup order
List<RouteStartupOrder> routesOrdered = new ArrayList<RouteStartupOrder>(routes);
Collections.sort(routesOrdered, new Comparator<RouteStartupOrder>() {
public int compare(RouteStartupOrder o1, RouteStartupOrder o2) {
return o1.getStartupOrder() - o2.getStartupOrder();
}
});
if (shutdownRoutesInReverseOrder) {
Collections.reverse(routesOrdered);
}
LOG.info("Starting to graceful shutdown " + routesOrdered.size() + " routes (timeout " + timeout + " " + timeUnit.toString().toLowerCase(Locale.ENGLISH) + ")");
// use another thread to perform the shutdowns so we can support timeout
timeoutOccurred.set(false);
currentShutdownTaskFuture = getExecutorService().submit(new ShutdownTask(context, routesOrdered, timeout, timeUnit, suspendOnly, abortAfterTimeout, timeoutOccurred));
try {
currentShutdownTaskFuture.get(timeout, timeUnit);
} catch (ExecutionException e) {
// unwrap execution exception
throw ObjectHelper.wrapRuntimeCamelException(e.getCause());
} catch (Exception e) {
// either timeout or interrupted exception was thrown so this is okay
// as interrupted would mean cancel was called on the currentShutdownTaskFuture to signal a forced timeout
// we hit a timeout, so set the flag
timeoutOccurred.set(true);
// timeout then cancel the task
currentShutdownTaskFuture.cancel(true);
// signal we are forcing shutdown now, since timeout occurred
this.forceShutdown = forceShutdown;
// if set, stop processing and return false to indicate that the shutdown is aborting
if (!forceShutdown && abortAfterTimeout) {
LOG.warn("Timeout occurred during graceful shutdown. Aborting the shutdown now."
+ " Notice: some resources may still be running as graceful shutdown did not complete successfully.");
return false;
} else {
if (forceShutdown || shutdownNowOnTimeout) {
LOG.warn("Timeout occurred during graceful shutdown. Forcing the routes to be shutdown now."
+ " Notice: some resources may still be running as graceful shutdown did not complete successfully.");
// force the routes to shutdown now
shutdownRoutesNow(routesOrdered);
// now the route consumers has been shutdown, then prepare route services for shutdown now (forced)
for (RouteStartupOrder order : routes) {
for (Service service : order.getServices()) {
prepareShutdown(service, true, true, isSuppressLoggingOnTimeout());
}
}
} else {
LOG.warn("Timeout occurred during graceful shutdown. Will ignore shutting down the remainder routes."
+ " Notice: some resources may still be running as graceful shutdown did not complete successfully.");
}
}
} finally {
currentShutdownTaskFuture = null;
}
// convert to seconds as its easier to read than a big milli seconds number
long seconds = TimeUnit.SECONDS.convert(watch.stop(), TimeUnit.MILLISECONDS);
LOG.info("Graceful shutdown of " + routesOrdered.size() + " routes completed in " + seconds + " seconds");
return true;
}