package dgm.modules.fsmon;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import dgm.configuration.*;
import dgm.exceptions.ConfigurationException;
import org.nnsoft.guice.sli4j.core.InjectLogger;
import org.slf4j.Logger;
import javax.inject.Named;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
@Singleton
class ConfigurationReloader implements FilesystemMonitor, Provider<Configuration>
{
@InjectLogger
Logger log;
final String scriptFolder;
final List<File> libraries;
final CachedProvider<Configuration> cachedProvider;
final ConfigurationMonitor configurationMonitor;
final ObjectMapper om = new ObjectMapper();
@Inject
public ConfigurationReloader(Set<ConfigurationMonitor> configurationMonitors,
final @Named("scriptFolder") String scriptFolder,
final @Named("libraryFiles") List<File> libraries) throws IOException
{
this.scriptFolder = scriptFolder;
this.libraries = libraries;
configurationMonitor = new CompositeConfigurationMonitor(configurationMonitors);
/**
* When loading the configuration this will throw an exception with an invalid configuration, but only on startup.
* When already running with a configuration this will log an error message trying to load an invalid configuration, but
* will continue to run with the previous valid configuration.
*/
final Provider<Configuration> confLoader = new Provider<Configuration>()
{
private AtomicReference<Configuration> configuration =
new AtomicReference<Configuration>(AbstractConfigurationModule.createConfiguration(om, scriptFolder, libraries));
@Override public Configuration get() {
try
{
final Configuration d = configuration.getAndSet(null);
if (d == null)
return AbstractConfigurationModule.createConfiguration(om, scriptFolder, libraries);
return d;
}
catch (ConfigurationException ce)
{
log.info("Failed to load configuration, {}", ce.getMessage());
return null;
}
catch (Exception e)
{
log.info("Unknown Exception while loading configuration, {}", e);
return null;
}
}
};
this.cachedProvider = new CachedProvider<Configuration> (confLoader);
}
@Override
public void directoryChanged(String directory)
{
log.info("Filesystem change detected for directory (target-index) {}", directory);
// try to reload the configuration
if(!cachedProvider.invalidate())
log.info("Failed to reload configuration");
// print configuration if debugging is enabled
if(log.isDebugEnabled())
{
// get new config
final Configuration cfg = cachedProvider.get();
for(final IndexConfig i : cfg.indices().values())
for(final TypeConfig t : i.types().values())
log.debug("Found target configuration /{}/{} --> /{}/{}",
new Object[]{t.sourceIndex(), t.sourceType(), i.name(), t.name()});
}
// notify all configuration listeners
configurationMonitor.configurationChanged(directory);
}
@Override
public Configuration get()
{
return cachedProvider.get();
}
}