package org.gcube.accounting.aggregator; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import org.gcube.accounting.datamodel.validations.validators.MatcherReplace; import org.gcube.accounting.persistence.AccountingPersistenceConfiguration; import org.gcube.com.fasterxml.jackson.databind.JavaType; import org.gcube.com.fasterxml.jackson.databind.ObjectMapper; import org.gcube.documentstore.persistence.ExecutorUtils; import org.gcube.documentstore.records.DSMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class RegexRulesAggregator implements Runnable { private static final Logger logger = LoggerFactory.getLogger(RegexRulesAggregator.class); public static final ScheduledExecutorService REGEX_REDISCOVERY_POOL; protected static final String DELAY = "delay"; protected static final String TIME_UNIT = "timeUnit"; protected static final String MATCHER_REPLACE_RULES = "MatcherReplaceRules"; static { REGEX_REDISCOVERY_POOL = Executors.newScheduledThreadPool(50, new ThreadFactory() { private int counter = 0; private static final String prefix = "AggregationRegexRediscoveryThread"; public Thread newThread(Runnable r) { return new Thread(r, prefix + "-" + counter++); } }); } protected TimeUnit timeUnit = TimeUnit.MINUTES; protected long delay = TimeUnit.MINUTES.toMinutes(15); protected ScheduledFuture rulesReloader; protected List matcherReplaceList; protected AccountingPersistenceConfiguration accountingPersistenceConfiguration; protected static RegexRulesAggregator instance; protected boolean changeRate; protected ScheduledFuture reloadAggregatorRules; public synchronized static RegexRulesAggregator getInstance() { if(instance==null) { instance = new RegexRulesAggregator(); } return instance; } protected RegexRulesAggregator() { matcherReplaceList = new ArrayList<>(); changeRate = false; readConfiguration(); } public List getMatcherReplaceList() { synchronized(matcherReplaceList) { return matcherReplaceList; } } public MatcherReplace addMatcherReplace(MatcherReplace matcherReplace) { synchronized(matcherReplaceList) { matcherReplaceList.add(matcherReplace); } return matcherReplace; } public void vacumRules() { synchronized(matcherReplaceList) { matcherReplaceList = new ArrayList<>(); } } public void readConfiguration() { try { accountingPersistenceConfiguration = new AccountingPersistenceConfiguration(this.getClass()); try { long oldDelay = delay; String delayString = accountingPersistenceConfiguration.getProperty(DELAY); delay = Long.parseLong(delayString); if(oldDelay!=delay) { changeRate = true; } TimeUnit oldTimeUnit = timeUnit; String timeUnitString = accountingPersistenceConfiguration.getProperty(TIME_UNIT); timeUnit = TimeUnit.valueOf(timeUnitString.toUpperCase()); if(oldTimeUnit.ordinal() != timeUnit.ordinal()) { changeRate = true; } }catch (Exception e) { logger.warn("Unable to retrieve regex reload delay. Goign to use last known delay {} {}", delay, timeUnit.name().toLowerCase()); } String rulesString = accountingPersistenceConfiguration.getProperty(MATCHER_REPLACE_RULES); ObjectMapper mapper = DSMapper.getObjectMapper(); JavaType type = mapper.getTypeFactory().constructCollectionType(List.class, MatcherReplace.class); List rules = mapper.readValue(rulesString, type); synchronized(matcherReplaceList) { matcherReplaceList = rules; } } catch(Exception e) { logger.error("Unable to properly load RegexRules", e); } } @Override public void run() { readConfiguration(); if(changeRate) { stop(); } if(reloadAggregatorRules == null) { reloadAggregatorRules = REGEX_REDISCOVERY_POOL.scheduleAtFixedRate(this, delay, delay, timeUnit); } } /** * Stop rule reloader. Use only if you really know what you do. */ public void stop() { if(reloadAggregatorRules != null) { try { reloadAggregatorRules.cancel(true); reloadAggregatorRules = null; }catch (Throwable t) { logger.error("Unable to properly stop {} reloader", this.getClass().getSimpleName(), t); } } } @Deprecated public void start() { } public static void shutdown() { RegexRulesAggregator.getInstance().stop(); ExecutorUtils.shutDownPool(RegexRulesAggregator.REGEX_REDISCOVERY_POOL); } }