package org.atomnuke.util.config.update; import org.atomnuke.util.config.io.ConfigurationManager; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.atomnuke.service.gc.ReclamationHandler; import org.atomnuke.util.config.ConfigurationException; import org.atomnuke.util.remote.CancellationRemote; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * TODO: SRP * * @author zinic */ public class ConfigurationUpdateManagerImpl implements ConfigurationUpdateService { private static final Logger LOG = LoggerFactory.getLogger(ConfigurationUpdateManagerImpl.class); private final Map<String, UpdateContext> updateContexts; private final ReclamationHandler reclamationHandler; public ConfigurationUpdateManagerImpl(ReclamationHandler reclamationHandler) { updateContexts = new HashMap<String, UpdateContext>(); this.reclamationHandler = reclamationHandler; } @Override public void destroy() { updateContexts.clear(); } @Override public void update() { for (UpdateContext contextToDispatch : getDispatchList()) { try { contextToDispatch.dispatch(); } catch (ConfigurationException ce) { LOG.error("Exception during configuration read: " + ce.getMessage(), ce); } } } private synchronized List<UpdateContext> getDispatchList() { final List<UpdateContext> dispatchList = new LinkedList<UpdateContext>(); for (Iterator<Map.Entry<String, UpdateContext>> updateContextItr = updateContexts.entrySet().iterator(); updateContextItr.hasNext();) { final Map.Entry<String, UpdateContext> entry = updateContextItr.next(); final UpdateContext currentCtx = entry.getValue(); // Cancellation may happen at anytime, remotely - check for it on every poll if (currentCtx.cancellationRemote().canceled()) { updateContextItr.remove(); continue; } try { if (currentCtx.updated()) { dispatchList.add(currentCtx); } } catch (ConfigurationException ce) { LOG.error("Exception during configuration update check: " + ce.getMessage(), ce); } } return dispatchList; } @Override public synchronized <T> ConfigurationContext<T> register(String name, ConfigurationManager<T> configurationManager) { final ConfigurationContext context = updateContexts.get(name); if (context != null) { LOG.error("Configuration already under update watch. This registration attempt will be ignored for: " + name); return context; } final CancellationRemote cancellationRemote = reclamationHandler.watch(configurationManager); final UpdateContext<T> newContext = new UpdateContext<T>(configurationManager, cancellationRemote); updateContexts.put(name, newContext); return newContext; } @Override public synchronized UpdateContext get(String name) { return updateContexts.get(name); } }