// 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);
}
if (timeout > 0) {
LOG.info("Starting to graceful shutdown " + routesOrdered.size() + " routes (timeout " + timeout + " " + timeUnit.toString().toLowerCase(Locale.ENGLISH) + ")");
} else {
LOG.info("Starting to graceful shutdown " + routesOrdered.size() + " routes (no timeout)");
}
// use another thread to perform the shutdowns so we can support timeout
Future<?> future = getExecutorService().submit(new ShutdownTask(context, routesOrdered, timeout, timeUnit, suspendOnly, abortAfterTimeout));
try {
if (timeout > 0) {
future.get(timeout, timeUnit);
} else {
future.get();
}
} catch (TimeoutException e) {
// timeout then cancel the task
future.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. Aborting the shutdown now.");
return false;
} else {
if (forceShutdown || shutdownNowOnTimeout) {
LOG.warn("Timeout occurred. Now forcing the routes to be shutdown now.");
// 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);
}
}
} else {
LOG.warn("Timeout occurred. Will ignore shutting down the remainder routes.");
}
}
} catch (ExecutionException e) {
// unwrap execution exception
throw ObjectHelper.wrapRuntimeCamelException(e.getCause());
}
// 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;
}