/** * Copyright (c) Codice Foundation * <p> * This is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser * General Public License as published by the Free Software Foundation, either version 3 of the * License, or any later version. * <p> * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. A copy of the GNU Lesser General Public License * is distributed along with this program and can be found at * <http://www.gnu.org/licenses/lgpl.html>. */ package ddf.catalog.util.impl; import java.util.Map; import java.util.Optional; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ddf.catalog.CatalogFramework; import ddf.catalog.source.Source; /** * The SourcePoller is the scheduler of the task to poll all configured sources at a fixed interval * to determine their availability. It is created by the CatalogFramework's blueprint. * <p> * An isAvailable() method is included in this class so that the caller, nominally the * CatalogFramework, can retrieve the cached availability of a specific source, or have it polled on * demand if there is no availability status cached. */ public class SourcePoller { private static final Logger LOGGER = LoggerFactory.getLogger(SourcePoller.class); private static final int INITIAL_DELAY = 0; private int interval = 1; private ScheduledExecutorService scheduler; private ScheduledFuture<?> handle; private SourcePollerRunner runner; /** * Constructor to schedule the SourcePollerRunner to execute immediately and at a fixed * interval, currently set at every 1 minute. This constructor is invoked by the * CatalogFramework's blueprint. * * @param incomingRunner the SourcePollerRunner to use for polling */ public SourcePoller(SourcePollerRunner incomingRunner) { this.runner = incomingRunner; scheduler = Executors.newSingleThreadScheduledExecutor(); handle = scheduler.scheduleAtFixedRate(runner, INITIAL_DELAY, interval, TimeUnit.MINUTES); } /** * Retrieves a {@link CachedSource} which contains cached values from the * specified {@link Source}. Returns a {@link Source} with values from the * last polling interval. If the {@link Source} is not known, null is returned. * * @param source the source to get the {@link CachedSource} for * @return a {@link CachedSource} which contains cached values */ public CachedSource getCachedSource(Source source) { return runner.getCachedSource(source); } /** * Cancels the {@link SourcePollerRunner} thread that had been previously scheduled to run at * specific intervals. Invoked by the CatalogFramework's blueprint when the framework is * unregistered/uninstalled. * * @param framework unused, but required by blueprint * @param properties unused, but required by blueprint */ public void cancel(CatalogFramework framework, Map properties) { LOGGER.debug("Cancelling scheduled polling."); runner.shutdown(); handle.cancel(true); scheduler.shutdownNow(); } /** * Start method for this poller, invoked by the CatalogFramework's blueprint when the framework * is registered/installed. No logic is executed except for logging the framework name. * * @param framework the catalog framework being started * @param properties unused, but required by blueprint */ public void start(CatalogFramework framework, Map properties) { LOGGER.debug("Framework started for [{}]", framework); } public int getInterval() { return interval; } public void setInterval(int interval) { if (interval < 1) { throw new IllegalArgumentException("Cannot set to lower than 1 minute"); } this.interval = interval; Optional.ofNullable(handle) .ifPresent((handle) -> handle.cancel(false)); handle = scheduler.scheduleAtFixedRate(runner, INITIAL_DELAY, this.interval, TimeUnit.MINUTES); } }