package edu.brown.hstore.stats; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Map.Entry; 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.util.TransactionCounter; public class TransactionCounterStats extends StatsSource { private static final Set<TransactionCounter> COUNTER_EXCLUDE = new HashSet<TransactionCounter>(); static { COUNTER_EXCLUDE.add(TransactionCounter.SYSPROCS); // COUNTER_EXCLUDE.add(TransactionCounter.BLOCKED_LOCAL); // COUNTER_EXCLUDE.add(TransactionCounter.BLOCKED_REMOTE); } private static class ProcedureRow { final Map<TransactionCounter, Long> data = new LinkedHashMap<TransactionCounter, Long>(); boolean has_values = false; public ProcedureRow(Procedure catalog_proc) { for (TransactionCounter tc : TransactionCounter.values()) { if (COUNTER_EXCLUDE.contains(tc)) continue; Long cnt = tc.get(catalog_proc); if (cnt != null) { this.data.put(tc, cnt); this.has_values = true; } else { this.data.put(tc, 0l); } } // FOR } } private final CatalogContext catalogContext; private final List<Procedure> procedures; public TransactionCounterStats(CatalogContext catalogContext) { super(SysProcSelector.TXNCOUNTER.name(), false); this.catalogContext = catalogContext; // We'll put the sysprocs first this.procedures = new ArrayList<Procedure>(this.catalogContext.getSysProcedures()); for (Procedure proc : catalogContext.procedures) { if (proc.getSystemproc()) continue; this.procedures.add(proc); } // FOR // Additional stuff to exclude // HStoreConf hstore_conf = HStoreConf.singleton(); // if (hstore_conf.site.anticache_enable == false) { // COUNTER_EXCLUDE.add(TransactionCounter.EVICTEDACCESS); // } // if (hstore_conf.site.exec_prefetch_queries == false) { // COUNTER_EXCLUDE.add(TransactionCounter.PREFETCH_LOCAL); // COUNTER_EXCLUDE.add(TransactionCounter.PREFETCH_REMOTE); // } } @Override protected Iterator<Object> getStatsRowKeyIterator(boolean interval) { // HACK: Figure out what procedures actually have results List<Object> hasResults = new ArrayList<Object>(TransactionCounter.getAllProcedures(this.catalogContext)); return hasResults.iterator(); } @Override protected void populateColumnSchema(ArrayList<ColumnInfo> columns) { super.populateColumnSchema(columns); columns.add(new VoltTable.ColumnInfo("PROCEDURE", VoltType.STRING)); for (TransactionCounter tc : TransactionCounter.values()) { if (COUNTER_EXCLUDE.contains(tc)) continue; columns.add(new VoltTable.ColumnInfo(tc.name().toUpperCase(), VoltType.INTEGER)); } // FOR } @Override protected synchronized void updateStatsRow(Object rowKey, Object[] rowValues) { // sum up all of the site statistics Procedure proc = (Procedure)rowKey; ProcedureRow totals = new TransactionCounterStats.ProcedureRow(proc); if (totals.has_values) { rowValues[columnNameToIndex.get("PROCEDURE")] = proc.getName(); for (Entry<TransactionCounter, Long> e : totals.data.entrySet()) { Long v = e.getValue(); if (v == null) v = Long.valueOf(0); rowValues[columnNameToIndex.get(e.getKey().name().toUpperCase())] = v.intValue(); } // FOR super.updateStatsRow(rowKey, rowValues); } } }