/** * */ package fr.inria.soctrace.framesoc.ui.piechart.loaders; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.core.runtime.IProgressMonitor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import fr.inria.soctrace.framesoc.ui.loaders.LoaderUtils; import fr.inria.soctrace.framesoc.ui.model.TimeInterval; import fr.inria.soctrace.framesoc.ui.piechart.model.PieChartLoaderMap; import fr.inria.soctrace.lib.model.Trace; import fr.inria.soctrace.lib.model.utils.SoCTraceException; import fr.inria.soctrace.lib.query.ValueListString; import fr.inria.soctrace.lib.storage.DBObject; import fr.inria.soctrace.lib.storage.DBObject.DBMode; import fr.inria.soctrace.lib.storage.TraceDBObject; import fr.inria.soctrace.lib.utils.DeltaManager; import fr.inria.soctrace.lib.utils.IdManager; /** * Base abstract class for event Pie Chart loaders. It performs aggregation and the load method * skips empty regions to avoid useless queries. * * Concrete classes have to override the {@link #doRequest()} method. * * @author "Generoso Pagano <generoso.pagano@inria.fr>" */ public abstract class EventPieChartLoader extends PieChartLoader { /** * Logger */ private final static Logger logger = LoggerFactory.getLogger(EventPieChartLoader.class); /** * Average number of event to load in each query */ protected final int EVENTS_PER_QUERY = 100000; /** * Event producers to use (all if null) */ protected List<Integer> producers = null; /** * Event type to use (all if null) */ protected List<Integer> types = null; @Override public void setEventProducerFilter(List<Integer> producers) { this.producers = producers; } @Override public void setEventTypeFilter(List<Integer> types) { this.types = types; } @Override public void load(Trace trace, TimeInterval requestedInterval, PieChartLoaderMap map, IProgressMonitor monitor) { if (trace == null || requestedInterval == null || map == null || monitor == null) throw new NullPointerException(); TraceDBObject traceDB = null; try { DeltaManager dm = new DeltaManager(); dm.start(); traceDB = new TraceDBObject(trace.getDbName(), DBMode.DB_OPEN); // compute interval duration long intervalDuration = LoaderUtils.getIntervalDuration(trace, EVENTS_PER_QUERY); Map<String, Double> values = new HashMap<>(); long t0 = requestedInterval.startTimestamp; TimeInterval loadedInterval = new TimeInterval(t0, 0); boolean first = true; while (t0 < requestedInterval.endTimestamp) { if (checkCancel(map, monitor)) { return; } // load interval long t1 = Math.min(requestedInterval.endTimestamp, t0 + intervalDuration); boolean last = (t1 >= requestedInterval.endTimestamp); int results = doRequest(t0, t1, first, last, values, traceDB, monitor); first = false; logger.debug("Loaded: " + results); if (checkCancel(map, monitor)) { return; } // check for empty regions if (results == 0 && !last) { long oldt0 = t0; t0 = getNextTimestampStartingFrom(traceDB, t1); logger.debug("saved " + ((t0 - oldt0) / intervalDuration) + " queries."); continue; } loadedInterval.endTimestamp = t1; map.setSnapshot(values, loadedInterval); t0 = t1; } map.setComplete(); logger.debug(dm.endMessage("Prepared Pie Chart dataset")); } catch (SoCTraceException e) { e.printStackTrace(); map.setStop(); } finally { if (!map.isStop() && !map.isComplete()) { // something went wrong, respect the map contract anyway map.setStop(); } DBObject.finalClose(traceDB); } } /** * Perform the request to load the statistic for the given time interval. * * @param t0 * start timestamp * @param t1 * end timestamp * @param first * flag indicating if we are requesting the first interval * @param last * flag indicating if we are requesting the last interval * @param values * map to update with new results * @param traceDB * trace DB object * @param monitor * progress monitor * @return the number of results of the query * @throws SoCTraceException */ protected abstract int doRequest(long t0, long t1, boolean first, boolean last, Map<String, Double> values, TraceDBObject traceDB, IProgressMonitor monitor) throws SoCTraceException; protected long getNextTimestampStartingFrom(TraceDBObject traceDB, long end) { long next = end + 1; try { Statement stm = traceDB.getConnection().createStatement(); DeltaManager dm = new DeltaManager(); dm.start(); ResultSet rs = stm.executeQuery("SELECT MIN(TIMESTAMP) FROM EVENT WHERE TIMESTAMP >= " + end); logger.debug(dm.endMessage("exec query")); while (rs.next()) { next = rs.getLong(1); } rs.close(); stm.close(); } catch (SQLException e) { e.printStackTrace(); } catch (SoCTraceException e) { e.printStackTrace(); } return Math.max(next, end + 1); } protected boolean checkCancel(PieChartLoaderMap map, IProgressMonitor monitor) { if (monitor.isCanceled()) { map.setStop(); return true; } return false; } protected boolean hasEventProducerFilter() { return producers != null; } protected boolean hasEventTypeFilter() { return types != null; } protected void addFiltersToQuery(StringBuilder sb) { if (hasEventProducerFilter()) { if (producers.size() == 0) { sb.append(" AND EVENT_PRODUCER_ID IN ( " + IdManager.RESERVED_NO_ID + " ) "); } else { sb.append(" AND EVENT_PRODUCER_ID IN "); ValueListString vls = new ValueListString(); for (Integer p : producers) { vls.addValue(p.toString()); } sb.append(vls.getValueString()); } } if (hasEventTypeFilter()) { if (types.size() == 0) { sb.append(" AND EVENT_TYPE_ID IN ( " + IdManager.RESERVED_NO_ID + " ) "); } else { sb.append(" AND EVENT_TYPE_ID IN "); ValueListString vls = new ValueListString(); for (Integer t : types) { vls.addValue(t.toString()); } sb.append(vls.getValueString()); } } } }