package edu.brown.catalog;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.apache.log4j.Logger;
import org.voltdb.CatalogContext;
import org.voltdb.catalog.Column;
import org.voltdb.catalog.Database;
import org.voltdb.catalog.Host;
import org.voltdb.catalog.Partition;
import org.voltdb.catalog.Procedure;
import org.voltdb.catalog.Site;
import org.voltdb.catalog.Table;
import edu.brown.designer.AccessGraph;
import edu.brown.designer.DesignerEdge;
import edu.brown.designer.DesignerInfo;
import edu.brown.designer.DesignerVertex;
import edu.brown.designer.generators.AccessGraphGenerator;
import edu.brown.hstore.HStoreThreadManager;
import edu.brown.utils.ArgumentsParser;
import edu.brown.utils.MathUtil;
import edu.brown.utils.PredicatePairs;
import edu.brown.utils.StringUtil;
import edu.brown.workload.Workload;
public class CatalogInfo {
private static final Logger LOG = Logger.getLogger(CatalogInfo.class);
private static final String HOST_INNER = "\u251c";
private static final String HOST_LAST = "\u2514";
public static double complexity(ArgumentsParser args, Database catalog_db, Workload workload) throws Exception {
AccessGraph agraph = new AccessGraph(catalog_db);
DesignerInfo info = new DesignerInfo(args);
for (Procedure catalog_proc : catalog_db.getProcedures()) {
// Skip if there are no transactions in the workload for this
// procedure
if (workload.getTraces(catalog_proc).isEmpty() || catalog_proc.getSystemproc())
continue;
new AccessGraphGenerator(info, catalog_proc).generate(agraph);
} // FOR
double ret = 1;
for (Table catalog_tbl : catalog_db.getTables()) {
DesignerVertex v = agraph.getVertex(catalog_tbl);
if (v == null)
continue;
Set<Column> used_cols = new HashSet<Column>();
Collection<DesignerEdge> edges = agraph.getIncidentEdges(v);
if (edges == null)
continue;
for (DesignerEdge e : edges) {
PredicatePairs cset = e.getAttribute(agraph, AccessGraph.EdgeAttributes.COLUMNSET);
assert (cset != null) : e.debug();
Collection<Column> cols = cset.findAllForParent(Column.class, catalog_tbl);
assert (cols != null) : catalog_tbl + "\n" + cset.debug();
used_cols.addAll(cols);
}
int num_cols = used_cols.size();
// Picking columns + repl
ret *= num_cols * num_cols;
// Secondary Indexes
for (int i = 0; i < num_cols - 1; i++) {
ret *= MathUtil.factorial(num_cols - 1).doubleValue() / MathUtil.factorial(i).multiply(MathUtil.factorial(num_cols - 1 - i)).doubleValue();
} // FOR
System.err.println(catalog_tbl + ": " + num_cols + " - " + ret);
}
for (Procedure catalog_proc : catalog_db.getProcedures()) {
if (catalog_proc.getParameters().isEmpty() || catalog_proc.getSystemproc())
continue;
ret *= catalog_proc.getParameters().size() * catalog_proc.getParameters().size();
System.err.println(catalog_proc + ": " + catalog_proc.getParameters().size() + " - " + ret);
}
return (ret);
}
public static String getInfo(CatalogContext catalogContext) {
StringBuilder sb = new StringBuilder();
// Just print out the Host/Partition Information
Map<String, Object> m = new LinkedHashMap<String, Object>();
if (catalogContext.jarPath != null) {
m.put("Catalog File", catalogContext.jarPath.getAbsolutePath());
}
m.put("# of Hosts", catalogContext.numberOfHosts);
m.put("# of Sites", catalogContext.numberOfSites);
m.put("# of Partitions", catalogContext.numberOfPartitions);
sb.append(StringUtil.formatMaps(":", false, false, false, true, true, true, m));
sb.append("\nCluster Information:\n");
Map<Host, Set<Site>> hosts = CatalogUtil.getSitesPerHost(catalogContext.catalog);
Set<String> partition_ids = new TreeSet<String>();
String partition_f = "%0" + Integer.toString(catalogContext.numberOfPartitions).length() + "d";
int num_cols = Math.min(4, hosts.size());
String cols[] = new String[num_cols];
for (int i = 0; i < num_cols; i++)
cols[i] = "";
int i = 0;
for (Host catalog_host : hosts.keySet()) {
int idx = i % num_cols;
cols[idx] += String.format("[%02d] HOST %s\n", i, catalog_host.getIpaddr());
Set<Site> sites = hosts.get(catalog_host);
int j = 0;
for (Site catalog_site : sites) {
partition_ids.clear();
for (Partition catalog_part : catalog_site.getPartitions()) {
partition_ids.add(String.format(partition_f, catalog_part.getId()));
} // FOR
String prefix = (++j == sites.size() ? HOST_LAST : HOST_INNER);
cols[idx] += String.format(" %s SITE %s: %s\n", prefix, HStoreThreadManager.formatSiteName(catalog_site.getId()), partition_ids);
} // FOR
cols[idx] += "\n";
i++;
} // FOR
sb.append(StringUtil.columns(cols));
return sb.toString();
}
/**
* @param args
*/
public static void main(String[] vargs) throws Exception {
ArgumentsParser args = ArgumentsParser.load(vargs);
args.require(ArgumentsParser.PARAM_CATALOG);
// if (args.hasParam(ArgumentsParser.PARAM_WORKLOAD)) {
// m.put("Complexity", complexity(args, args.catalog_db, args.workload));
// }
System.out.println(getInfo(args.catalogContext));
// Check for Sequential Scans
// for (Procedure proc : args.catalogContext.database.getProcedures()) {
// for (Statement stmt : proc.getStatements()) {
// AbstractPlanNode root = PlanNodeUtil.getRootPlanNodeForStatement(stmt, true);
// Collection<SeqScanPlanNode> scans = PlanNodeUtil.getPlanNodes(root, SeqScanPlanNode.class);
// Collection<AggregatePlanNode> aggs = PlanNodeUtil.getPlanNodes(root, AggregatePlanNode.class);
// if (scans.isEmpty() == false && aggs.isEmpty()) {
// LOG.warn("Sequential Scan: " + stmt.fullName());
// }
// } // FOR (stmt)
// } // FOR (proc)
//
// DUMP PREFETCHABLE QUERIES
// for (Procedure proc : args.catalogContext.database.getProcedures()) {
// boolean hasPrefetchable = false;
// for (Statement stmt : proc.getStatements()) {
// if (stmt.getPrefetchable()) {
// System.out.println(stmt.fullName());
// hasPrefetchable = true;
// }
// }
// if (hasPrefetchable) System.out.println();
// }
// DUMP SYSPROCS
// for (Procedure proc : args.catalogContext.getSysProcedures()) {
// System.out.println(proc.getName());
// int ctr = 0;
// for (ProcParameter param : CatalogUtil.getSortedCatalogItems(proc.getParameters(), "index")) {
// System.out.printf(" [%02d] %s%s\n", ctr++,
// VoltType.get(param.getType()),
// (param.getIsarray() ? " <array>" : ""));
// } // FOR
// } // FOR
}
}