package edu.brown.designer.partitioners;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.voltdb.catalog.CatalogType;
import org.voltdb.catalog.Column;
import org.voltdb.catalog.Procedure;
import org.voltdb.catalog.Table;
import edu.brown.benchmark.tm1.TM1Constants;
import edu.brown.costmodel.SingleSitedCostModel;
import edu.brown.costmodel.TimeIntervalCostModel;
import edu.brown.designer.AccessGraph;
import edu.brown.designer.Designer;
import edu.brown.designer.generators.AccessGraphGenerator;
import edu.brown.designer.partitioners.BranchAndBoundPartitioner.StateVertex;
import edu.brown.designer.partitioners.BranchAndBoundPartitioner.TraverseThread;
import edu.brown.designer.partitioners.plan.PartitionPlan;
import edu.brown.utils.CollectionUtil;
import edu.brown.utils.ProjectType;
public class TestBranchAndBoundPartitioner extends BasePartitionerTestCase {
private BranchAndBoundPartitioner partitioner;
private AccessGraph agraph;
@Override
protected void setUp() throws Exception {
super.setUp(ProjectType.TM1, true);
// BasePartitionerTestCase will setup most of what we need
this.info.setCostModel(new TimeIntervalCostModel<SingleSitedCostModel>(catalogContext, SingleSitedCostModel.class, info.getNumIntervals()));
this.info.setPartitionerClass(BranchAndBoundPartitioner.class);
assertNotNull(info.getStats());
this.designer = new Designer(this.info, this.hints, this.info.getArgs());
this.partitioner = (BranchAndBoundPartitioner) this.designer.getPartitioner();
assertNotNull(this.partitioner);
this.agraph = AccessGraphGenerator.convertToSingleColumnEdges(catalog_db, this.partitioner.generateAccessGraph());
assertNotNull(this.agraph);
}
/**
* testHaltReason
*/
public void testHaltReason() throws Exception {
List<Table> table_visit_order = PartitionerUtil.generateTableOrder(info, agraph, hints);
assertFalse(table_visit_order.isEmpty());
List<Procedure> proc_visit_order = (List<Procedure>)CollectionUtil.addAll(new ArrayList<Procedure>(), catalog_db.getProcedures());
assertFalse(proc_visit_order.isEmpty());
this.partitioner.setParameters(agraph, table_visit_order, proc_visit_order);
// this.partitioner.init(this.hints);
}
/**
* testMemoryExceeded
*/
public void testMemoryExceeded() throws Exception {
List<Procedure> proc_visit_order = new ArrayList<Procedure>();
List<Table> table_visit_order = (List<Table>)CollectionUtil.addAll(new ArrayList<Table>(), catalog_db.getTables());
// Set the tables to all be partitioned on the last column
for (Table catalog_tbl : catalog_db.getTables()) {
Column catalog_col = this.getColumn(catalog_tbl, -1);
catalog_tbl.setPartitioncolumn(catalog_col);
} // FOR
// Set this to be the upperbounds
PartitionPlan ub_pplan = PartitionPlan.createFromCatalog(catalog_db);
assertNotNull(ub_pplan);
this.partitioner.setUpperBounds(hints, ub_pplan, Double.MAX_VALUE, 1000l);
hints.max_memory_per_partition = 1;
hints.enable_procparameter_search = false;
this.partitioner.setParameters(agraph, table_visit_order, proc_visit_order);
this.partitioner.init(this.hints);
StateVertex start_vertex = StateVertex.getStartVertex(Double.MAX_VALUE, Long.MAX_VALUE);
TraverseThread thread = this.partitioner.new TraverseThread(info, hints, start_vertex, agraph, table_visit_order, proc_visit_order);
assertNotNull(thread);
thread.traverse(start_vertex, 0);
this.partitioner.getHaltReason();
// Make sure that the solution we pick has a memory and a cost
StateVertex best_vertex = this.partitioner.getBestVertex();
assertNotNull(best_vertex);
assert(best_vertex.getCatalogKeyMap().isEmpty());
// Map<CatalogType, CatalogType> m = best_vertex.getCatalogMap(catalog_db);
// for (Table catalog_tbl : orig_partitioning.keySet()) {
// assert(m.containsKey(catalog_tbl)) : "Missing " + catalog_tbl;
// assertEquals(orig_partitioning.get(catalog_tbl).fullName(), m.get(catalog_tbl).fullName());
// } // FOR
}
/**
* testTraverse
*/
public void testTraverse() throws Exception {
List<Procedure> proc_visit_order = new ArrayList<Procedure>();
List<Table> table_visit_order = new ArrayList<Table>();
// We have to massage our attributes list so that our testing is deterministic. Set the only table
// that we're going to visit is ACCESS_INFO and change its partitioning column to something that we know
// we can beat if we partition on S_ID
Map<Table, Column> expected = new HashMap<Table, Column>();
Table catalog_tbl = this.getTable(TM1Constants.TABLENAME_SPECIAL_FACILITY);
Column catalog_col = this.getColumn(catalog_tbl, -1);
catalog_tbl.setPartitioncolumn(catalog_col);
table_visit_order.add(catalog_tbl);
expected.put(catalog_tbl, this.getColumn(catalog_tbl, "S_ID"));
catalog_tbl = this.getTable(TM1Constants.TABLENAME_CALL_FORWARDING);
catalog_col = this.getColumn(catalog_tbl, -1);
catalog_tbl.setPartitioncolumn(catalog_col);
table_visit_order.add(catalog_tbl);
expected.put(catalog_tbl, this.getColumn(catalog_tbl, "S_ID"));
// Set this to be the upperbounds
PartitionPlan ub_pplan = PartitionPlan.createFromCatalog(catalog_db);
assertNotNull(ub_pplan);
this.partitioner.setUpperBounds(hints, ub_pplan, Double.MAX_VALUE, 1000l);
hints.enable_multi_partitioning = false;
hints.enable_replication_readmostly = false;
hints.enable_replication_readonly = false;
hints.enable_procparameter_search = false;
hints.max_memory_per_partition = Long.MAX_VALUE;
this.partitioner.setParameters(agraph, table_visit_order, proc_visit_order);
this.partitioner.init(this.hints);
StateVertex start_vertex = StateVertex.getStartVertex(Double.MAX_VALUE, Long.MAX_VALUE);
TraverseThread thread = this.partitioner.new TraverseThread(info, hints, start_vertex, agraph, table_visit_order, proc_visit_order);
assertNotNull(thread);
thread.traverse(start_vertex, 0);
// Make sure that the solution we pick has a memory and a cost
StateVertex best_vertex = this.partitioner.getBestVertex();
assertNotNull(best_vertex);
Map<CatalogType, CatalogType> m = best_vertex.getCatalogMap(catalog_db);
for (Table t : expected.keySet()) {
assert(m.containsKey(t)) : "Missing " + t;
assertEquals(expected.get(t), m.get(t));
} // FOR
assert(best_vertex.getCost() > 0) : best_vertex.getCost();
assert(best_vertex.getMemory() > 0) : best_vertex.getMemory();
}
}