/** * */ package edu.brown.designer.generators; import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.voltdb.benchmark.tpcc.procedures.slev; import org.voltdb.catalog.Column; import org.voltdb.catalog.ProcParameter; import org.voltdb.catalog.Procedure; import org.voltdb.catalog.Statement; import org.voltdb.catalog.StmtParameter; import org.voltdb.catalog.Table; import edu.brown.BaseTestCase; import edu.brown.catalog.CatalogUtil; import edu.brown.designer.AccessGraph; import edu.brown.designer.DesignerInfo; import edu.brown.designer.DesignerEdge; import edu.brown.designer.DesignerVertex; import edu.brown.designer.AccessGraph.EdgeAttributes; import edu.brown.statistics.Histogram; import edu.brown.statistics.ObjectHistogram; import edu.brown.utils.CollectionUtil; import edu.brown.utils.PredicatePairs; import edu.brown.utils.ProjectType; import edu.brown.workload.TransactionTrace; import edu.brown.workload.Workload; import edu.brown.workload.filters.ProcedureLimitFilter; import edu.brown.workload.filters.ProcedureNameFilter; /** * @author pavlo * */ public class TestAccessGraphGenerator extends BaseTestCase { private static final long WORKLOAD_XACT_LIMIT = 100; private static final String TARGET_PROCEDURE = slev.class.getSimpleName(); private static final String TARGET_STATEMENT = "GetStockCount"; // Reading the workload takes a long time, so we only want to do it once private static Workload workload; private Procedure catalog_proc; private DesignerInfo info; private AccessGraph agraph; private AccessGraphGenerator generator; @Override protected void setUp() throws Exception { super.setUp(ProjectType.TPCC, true); // Super hack! Walk back the directories and find out workload directory if (workload == null) { this.applyParameterMappings(ProjectType.TPCC); // Load up the workload! File workload_file = this.getWorkloadFile(ProjectType.TPCC); workload = new Workload(catalog); // Workload Filter ProcedureNameFilter filter = new ProcedureNameFilter(false); filter.include(TARGET_PROCEDURE); filter.attach(new ProcedureLimitFilter(WORKLOAD_XACT_LIMIT)); ((Workload)workload).load(workload_file, catalog_db, filter); } assertTrue(workload.getTransactionCount() > 0); // Setup everything else this.catalog_proc = this.getProcedure(TARGET_PROCEDURE); this.info = new DesignerInfo(catalogContext, workload); this.agraph = new AccessGraph(catalog_db); this.generator = new AccessGraphGenerator(this.info, this.catalog_proc); } // private void display(final AccessGraph agraph) throws Exception { // javax.swing.SwingUtilities.invokeAndWait(new Runnable() { // public void run() { // GraphVisualizationPanel.createFrame(agraph).setVisible(true); // } // }); // } /** * testConvertToSingleColumnEdges */ public void testConvertToSingleColumnEdges() throws Exception { System.err.println(CollectionUtil.first(workload.getTransactions()).debug(catalog_db)); new AccessGraphGenerator(this.info, this.catalog_proc).generate(agraph); System.err.println(agraph.debug()); System.err.println("=========================="); agraph = AccessGraphGenerator.convertToSingleColumnEdges(catalog_db, agraph); // Make sure that there is at least one edge between DISTRICT and all other tables Table target = this.getTable("DISTRICT"); DesignerVertex v0 = agraph.getVertex(target); assertNotNull(v0); String expected[] = { "ORDER_LINE", "STOCK" }; for (String tbl_name : expected) { Table catalog_tbl = this.getTable(tbl_name); DesignerVertex v1 = agraph.getVertex(catalog_tbl); assertNotNull(v1); Collection<DesignerEdge> edges = agraph.findEdgeSet(v0, v1); assertNotNull(edges); if (edges.isEmpty()) { System.err.println(agraph.debug()); } assertFalse(v0 + "<->" + v1, edges.isEmpty()); for (DesignerEdge e : edges) { PredicatePairs cset = e.getAttribute(EdgeAttributes.COLUMNSET); assertNotNull(cset); assertEquals(cset.toString(), 1, cset.size()); } } // FOR // agraph.setVerbose(true); // System.err.println("Dumping AccessGraph to " + FileUtil.writeStringToTempFile(GraphvizExport.export(agraph, "tpcc"), "dot")); } /** * testInitialize */ public void testInitialize() throws Exception { this.generator.initialize(agraph); for (Table catalog_tbl : CatalogUtil.getDataTables(catalog_db)) { if (catalog_tbl.getSystable()) continue; assertNotNull("Missing " + catalog_tbl, this.agraph.getVertex(catalog_tbl)); } // FOR } /** * testFindEdgeSetUsingColumn */ public void testFindEdgeSetUsingColumn() throws Exception { AccessGraph agraph = new AccessGraph(catalog_db); new AccessGraphGenerator(this.info, this.catalog_proc).generate(agraph); agraph.setVerbose(true); Table catalog_tbl = this.getTable("STOCK"); Column catalog_col = this.getColumn(catalog_tbl, "S_W_ID"); DesignerVertex v = agraph.getVertex(catalog_tbl); assertNotNull(v); Collection<DesignerEdge> edges = agraph.findEdgeSet(v, catalog_col); assertNotNull(edges); assert(agraph.getEdgeCount() != edges.size()); } /** * testMultiPass */ public void testMultiPass() throws Exception { AccessGraph agraph0 = new AccessGraph(catalog_db); new AccessGraphGenerator(this.info, this.catalog_proc).generate(agraph0); AccessGraph agraph1 = new AccessGraph(catalog_db); new AccessGraphGenerator(this.info, this.catalog_proc).generate(agraph1); // Make sure that all of the weights are the same for (DesignerEdge e0 : agraph0.getEdges()) { List<DesignerVertex> vertices0 = new ArrayList<DesignerVertex>(agraph0.getIncidentVertices(e0)); DesignerVertex v1_0 = agraph1.getVertex(vertices0.get(0).getCatalogKey()); assertNotNull("Missing vertex " + vertices0.get(0), v1_0); DesignerVertex v1_1 = agraph1.getVertex(vertices0.get(1).getCatalogKey()); assertNotNull("Missing vertex " + vertices0.get(1), v1_1); DesignerEdge e1 = agraph1.findEdge(v1_0, v1_1); assertNotNull("Missing edge " + e0, e1); assertEquals(e0.getIntervalCount(), e1.getIntervalCount()); for (int i = 0, cnt = e0.getIntervalCount(); i < cnt; i++) { assertEquals("Mismatched weights for " + e0 + " [" + i + "]", e0.getWeight(i), e1.getWeight(i)); } // FOR } // FOR } /** * testCreateExplicitEdges */ public void testCreateExplicitEdges() throws Exception { this.generator.initialize(agraph); Statement catalog_stmt = this.catalog_proc.getStatements().get(TARGET_STATEMENT); assertNotNull(catalog_stmt); this.generator.createExplicitEdges(agraph, catalog_stmt); assert(this.agraph.getVertexCount() > 0); assert(this.agraph.getEdgeCount() > 0); // Make sure that there is an edge between STOCK and ORDER_LINE Table tbl0 = this.getTable("STOCK"); DesignerVertex v0 = this.agraph.getVertex(tbl0); assertNotNull(v0); Table tbl1 = this.getTable("ORDER_LINE"); DesignerVertex v1 = this.agraph.getVertex(tbl1); assertNotNull(v1); DesignerEdge edge = this.agraph.findEdge(v0, v1); assertNotNull("No edge exists between " + tbl0 + " and " + tbl1, edge); } /** * testCreateSharedParamEdges */ public void testCreateSharedParamEdges() throws Exception { this.generator.initialize(agraph); Statement catalog_stmts[] = this.catalog_proc.getStatements().values(); Statement catalog_stmt0 = catalog_stmts[0]; assertNotNull(catalog_stmt0); this.generator.createExplicitEdges(agraph, catalog_stmt0); Statement catalog_stmt1 = catalog_stmts[1]; assertNotNull(catalog_stmt1); this.generator.createExplicitEdges(agraph, catalog_stmt1); List<ProcParameter> catalog_stmt0_params = new ArrayList<ProcParameter>(); for (StmtParameter param : catalog_stmt0.getParameters()) { if (param.getProcparameter() != null) catalog_stmt0_params.add(param.getProcparameter()); } // FOR assertFalse("No ProcParameters mapped for " + catalog_stmt0, catalog_stmt0_params.isEmpty()); // this.generator.setDebug(true); this.generator.createSharedParamEdges(agraph, catalog_stmt0, catalog_stmt1, catalog_stmt0_params); // We should now have a complete graph between the following tables String tables[] = { "ORDER_LINE", "DISTRICT", "STOCK" }; for (int i = 0; i < tables.length; i++) { Table t0 = this.getTable(tables[i]); DesignerVertex v0 = agraph.getVertex(t0); assertNotNull(v0); for (int ii = i + 1; ii < tables.length; ii++) { Table t1 = this.getTable(tables[ii]); assertNotSame(t0, t1); DesignerVertex v1 = agraph.getVertex(t1); assertNotNull(v1); assertNotNull(agraph.findEdge(v0, v1)); } // FOR } // FOR } /** * testUpdateEdgeWeights */ public void testUpdateEdgeWeights() throws Exception { this.generator.initialize(this.agraph); for (Statement catalog_stmt : this.catalog_proc.getStatements()) { this.generator.createExplicitEdges(this.agraph, catalog_stmt); } // FOR Collection<TransactionTrace> traces = workload.getTransactions(); Histogram<Integer> hist = new ObjectHistogram<Integer>(); // TransactionTrace middle = traces.get(traces.size() / 2); for (TransactionTrace xact : traces) { // int time = (xact.getStartTimestamp() < middle.getStartTimestamp() ? 0 : 1); int time = workload.getTimeInterval(xact, info.getNumIntervals()); hist.put(time); // System.err.println("[" + time + "] " + xact); this.generator.updateEdgeWeights(this.agraph, xact); } // FOR // System.err.println(hist); // for (Edge edge : agraph.getEdges()) { // System.err.println(edge + ": " + edge.getWeights()); // // assertEquals(edge.getWeight(0), edge.getWeight(1)); // } // FOR } }