package edu.brown.hstore.stats; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import org.apache.log4j.Logger; import org.voltdb.CatalogContext; import org.voltdb.StatsSource; import org.voltdb.SysProcSelector; import org.voltdb.VoltTable; import org.voltdb.VoltTable.ColumnInfo; import org.voltdb.VoltType; import org.voltdb.catalog.Procedure; import edu.brown.hstore.BatchPlanner; import edu.brown.hstore.HStoreSite; import edu.brown.hstore.PartitionExecutor; import edu.brown.logging.LoggerUtil; import edu.brown.logging.LoggerUtil.LoggerBoolean; import edu.brown.profilers.BatchPlannerProfiler; import edu.brown.profilers.ProfileMeasurement; public class BatchPlannerProfilerStats extends StatsSource { private static final Logger LOG = Logger.getLogger(BatchPlannerProfilerStats.class); private static final LoggerBoolean debug = new LoggerBoolean(); private static final LoggerBoolean trace = new LoggerBoolean(); static { LoggerUtil.attachObserver(LOG, debug, trace); } private final HStoreSite hstore_site; private final CatalogContext catalogContext; public BatchPlannerProfilerStats(HStoreSite hstore_site, CatalogContext catalogContext) { super(SysProcSelector.PLANNERPROFILER.name(), false); this.hstore_site = hstore_site; this.catalogContext = catalogContext; } @Override protected Iterator<Object> getStatsRowKeyIterator(boolean interval) { final Iterator<Procedure> it = this.catalogContext.getRegularProcedures().iterator(); return new Iterator<Object>() { @Override public boolean hasNext() { return it.hasNext(); } @Override public Object next() { return it.next(); } @Override public void remove() { it.remove(); } }; } @Override protected void populateColumnSchema(ArrayList<ColumnInfo> columns) { super.populateColumnSchema(columns); columns.add(new VoltTable.ColumnInfo("PROCEDURE", VoltType.STRING)); columns.add(new VoltTable.ColumnInfo("NUM_PLANNERS", VoltType.BIGINT)); columns.add(new VoltTable.ColumnInfo("TRANSACTIONS", VoltType.BIGINT)); columns.add(new VoltTable.ColumnInfo("CACHED", VoltType.BIGINT)); BatchPlannerProfiler profiler = new BatchPlannerProfiler(); for (ProfileMeasurement pm : profiler.getProfileMeasurements()) { String name = pm.getName().toUpperCase(); columns.add(new VoltTable.ColumnInfo(name, VoltType.BIGINT)); columns.add(new VoltTable.ColumnInfo(name+"_CNT", VoltType.BIGINT)); } // FOR } @Override protected synchronized void updateStatsRow(Object rowKey, Object[] rowValues) { Procedure proc = (Procedure)rowKey; if (debug.val) LOG.debug("Collecting BatchPlanner stats for " + proc.getName()); // We're going to create a new profiler that we can use // to add up all of the values from the individual BatchPlannerProfilers BatchPlannerProfiler total = new BatchPlannerProfiler(); ProfileMeasurement totalPMs[] = total.getProfileMeasurements(); // Find all of the BatchPlanners for each partition for our target procedure Collection<BatchPlanner> planners = this.getBatchPlanners(proc); for (BatchPlanner planner : planners) { BatchPlannerProfiler profiler = planner.getDebugContext().getProfiler(); if (profiler == null) continue; ProfileMeasurement profilerPMs[] = profiler.getProfileMeasurements(); assert(totalPMs.length == profilerPMs.length); for (int i = 0; i < totalPMs.length; i++) { totalPMs[i].appendTime(profilerPMs[i]); } // FOR total.transactions.addAndGet(profiler.transactions.get()); total.cached.addAndGet(profiler.cached.get()); if (debug.val) LOG.debug(String.format("%s/%s -> Txns:%d Cached:%d", planner.getClass().getSimpleName(), planner.getProcedure().getName(), profiler.transactions.get(), profiler.cached.get())); } // FOR if (debug.val) LOG.debug(String.format("TOTAL -> Txns:%d Cached:%d", total.transactions.get(), total.cached.get())); int offset = this.columnNameToIndex.get("PROCEDURE"); rowValues[offset++] = proc.getName(); rowValues[offset++] = planners.size(); rowValues[offset++] = total.transactions.get(); rowValues[offset++] = total.cached.get(); for (ProfileMeasurement pm : totalPMs) { rowValues[offset++] = pm.getTotalThinkTime(); rowValues[offset++] = pm.getInvocations(); } // FOR super.updateStatsRow(rowKey, rowValues); } private Collection<BatchPlanner> getBatchPlanners(Procedure proc) { Set<BatchPlanner> planners = new HashSet<BatchPlanner>(); for (int partition : hstore_site.getLocalPartitionIds().values()) { PartitionExecutor executor = hstore_site.getPartitionExecutor(partition); PartitionExecutor.Debug executorDebug = executor.getDebugContext(); for (BatchPlanner planner : executorDebug.getBatchPlanners()) { if (planner.getProcedure().equals(proc)) { planners.add(planner); } } // FOR } // FOR return (planners); } }