package mil.nga.giat.geowave.core.store.adapter.statistics; import java.io.Closeable; import java.io.Flushable; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import mil.nga.giat.geowave.core.index.ByteArrayId; import mil.nga.giat.geowave.core.store.base.DataStoreEntryInfo; import mil.nga.giat.geowave.core.store.callback.DeleteCallback; import mil.nga.giat.geowave.core.store.callback.IngestCallback; import mil.nga.giat.geowave.core.store.callback.ScanCallback; /** * * This tool does not react to callbacks if the provided statistics store is * null or the provided data adapter does not implement * {@link DataStatisticsStore}. * * @param <T> * Entry type */ public class StatsCompositionTool<T> implements IngestCallback<T>, ScanCallback<T>, DeleteCallback<T>, AutoCloseable, Closeable, Flushable { private final static Logger LOGGER = LoggerFactory.getLogger(StatsCompositionTool.class); public static final int FLUSH_STATS_THRESHOLD = 16384; int updateCount = 0; DataStatisticsStore statisticsStore; List<DataStatisticsBuilder<T>> statisticsBuilders = null; final Object MUTEX = new Object(); protected boolean skipFlush = false; public StatsCompositionTool() { statisticsStore = null; } public StatsCompositionTool( final StatisticsProvider<T> statisticsProvider ) { this.statisticsStore = null; this.init(statisticsProvider); } public StatsCompositionTool( final StatisticsProvider<T> statisticsProvider, final DataStatisticsStore statisticsStore ) { this.statisticsStore = statisticsStore; this.init(statisticsProvider); } private void init( final StatisticsProvider<T> statisticsProvider ) { final ByteArrayId[] statisticsIds = statisticsProvider.getSupportedStatisticsTypes(); statisticsBuilders = new ArrayList<DataStatisticsBuilder<T>>( statisticsIds.length); for (final ByteArrayId id : statisticsIds) { statisticsBuilders.add(new DataStatisticsBuilder<T>( statisticsProvider, id)); } try { final Object v = System.getProperty("StatsCompositionTool.skipFlush"); skipFlush = ((v != null) && v.toString().equalsIgnoreCase( "true")); } catch (final Exception ex) { LOGGER.error( "Unable to determine property AccumuloIndexWriter.skipFlush", ex); } } @Override public void entryDeleted( final DataStoreEntryInfo entryInfo, final T entry ) { if (statisticsBuilders == null) { return; } synchronized (MUTEX) { for (final DataStatisticsBuilder<T> builder : statisticsBuilders) { builder.entryDeleted( entryInfo, entry); } updateCount++; checkStats(); } } @Override public void entryScanned( final DataStoreEntryInfo entryInfo, final T entry ) { if (statisticsBuilders == null) { return; } synchronized (MUTEX) { for (final DataStatisticsBuilder<T> builder : statisticsBuilders) { builder.entryScanned( entryInfo, entry); } updateCount++; checkStats(); } } /** * Update statistics store */ @Override public void flush() { if (statisticsBuilders == null) { return; } synchronized (MUTEX) { for (final DataStatisticsBuilder<T> builder : statisticsBuilders) { final Collection<DataStatistics<T>> statistics = builder.getStatistics(); for (final DataStatistics<T> s : statistics) { statisticsStore.incorporateStatistics(s); } statistics.clear(); } } } /** * Reset statistics, losing and updates since last flush */ public void reset() { if (statisticsBuilders == null) { return; } synchronized (MUTEX) { for (final DataStatisticsBuilder<T> builder : statisticsBuilders) { final Collection<DataStatistics<T>> statistics = builder.getStatistics(); statistics.clear(); } } } @Override public void entryIngested( final DataStoreEntryInfo entryInfo, final T entry ) { if (statisticsBuilders == null) { return; } synchronized (MUTEX) { for (final DataStatisticsBuilder<T> builder : statisticsBuilders) { builder.entryIngested( entryInfo, entry); } updateCount++; checkStats(); } } @Override public void close() { flush(); } public void setStatisticsStore( DataStatisticsStore statisticsStore ) { this.statisticsStore = statisticsStore; } private void checkStats() { if (!skipFlush && (updateCount > FLUSH_STATS_THRESHOLD)) { updateCount = 0; } } }