/** * */ package edu.brown.designer.generators; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.log4j.Logger; 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.PartitionTree; import edu.brown.graphs.AbstractDirectedGraph; import edu.uci.ics.jung.graph.util.EdgeType; /** * @author pavlo */ public class ReplicationTreeGenerator extends AbstractGenerator<AbstractDirectedGraph<DesignerVertex, DesignerEdge>> { private static final Logger LOG = Logger.getLogger(ReplicationTreeGenerator.class); private final PartitionTree ptree; private final AccessGraph agraph; private Set<Table> replication_candidates = new HashSet<Table>(); private Set<DesignerEdge> conflict_edges = new HashSet<DesignerEdge>(); private Set<DesignerVertex> conflict_vertices = new HashSet<DesignerVertex>(); public ReplicationTreeGenerator(DesignerInfo info, AccessGraph agraph, PartitionTree ptree) { super(info); this.agraph = agraph; this.ptree = ptree; } /** * Return the list of replication candidates generated * * @return */ public Set<Table> getReplicationCandidates() { return (this.replication_candidates); } /** * Return the list of edges that were added to the partition tree * * @return */ public Set<DesignerEdge> getConflictEdges() { return (this.conflict_edges); } /** * Return the list of vertices that cause conflict edges to be added to the * tree * * @return */ public Set<DesignerVertex> getConflictVertices() { return (this.conflict_vertices); } @Override public void generate(AbstractDirectedGraph<DesignerVertex, DesignerEdge> graph) throws Exception { // // First clone the original partition tree // graph.clone(this.ptree); for (DesignerVertex vertex : graph.getVertices()) { vertex.copyAttributes(this.ptree, graph); } // FOR // // Then for each root we want to traverse their section of the // PartitionTree // and check to see that for each pair of adjacent vertices in the // AccessGraph // that there is a path from one vertex to another // List<DesignerVertex> ptree_vertices = new ArrayList<DesignerVertex>(); ptree_vertices.addAll(this.ptree.getVertices()); Set<DesignerVertex> modified = new HashSet<DesignerVertex>(); for (int ctr0 = 0, cnt = ptree_vertices.size(); ctr0 < cnt; ctr0++) { DesignerVertex v0 = ptree_vertices.get(ctr0); if (this.ptree.isReplicated(v0)) continue; LOG.debug("v0: " + v0 + "\n"); for (int ctr1 = ctr0 + 1; ctr1 < cnt; ctr1++) { DesignerVertex v1 = ptree_vertices.get(ctr1); LOG.debug(" |- v1: " + v1 + "\n"); DesignerEdge ag_edge = this.agraph.findEdge(v0, v1); if (((v0.getCatalogItem().getName().equals("WAREHOUSE") && v1.getCatalogItem().getName().equals("STOCK")) || (v1.getCatalogItem().getName().equals("WAREHOUSE") && v0.getCatalogItem() .getName().equals("STOCK"))) && ag_edge == null) { LOG.debug("???????????\n"); } // // If this other vertex is already replicated, then we don't // care // if (this.ptree.isReplicated(v1)) continue; // // If there is an edge between these two vertices, then check // whether // there is a path from the "upper" vertex to the "lower" vertex // if (ag_edge != null && this.ptree.getPath(v0, v1).isEmpty() && this.ptree.getPath(v1, v0).isEmpty() && graph.getPath(v0, v1).isEmpty() && graph.getPath(v1, v0).isEmpty()) { // // There was no edge in the PartitionTree, so that means we // want to add // an edge in our replication tree. Note that although edges // in the AccessGraph // are undirected, we need to make sure that our edge goes // in the right direction. // Well, that's easy then there is a foreign key but what // about when it's just // some random join? // boolean found = false; for (int ctr = 0; ctr < 2; ctr++) { if (ctr == 1) { DesignerVertex temp = v0; v0 = v1; v1 = temp; } // Edge dg_edge = this.info.dgraph.findEdge(v0, v1); // Edge dg_edge = this.agraph.findEdge(v0, v1); if (this.info.dependencies.getDescendants((Table) v0.getCatalogItem()).contains(v1.getCatalogItem())) { LOG.debug("CREATED EDGE: " + v0 + " -> " + v1 + "\n"); DesignerEdge new_edge = new DesignerEdge(graph, ag_edge); graph.addEdge(new_edge, v0, v1, EdgeType.DIRECTED); this.conflict_edges.add(new_edge); this.conflict_vertices.add(v1); found = true; modified.add(v0); modified.add(v1); break; } } // FOR if (!found) { // LOG.warn("Not creating missing edge " + ag_edge + // " because there is no edge in the DependencyGraph"); } } } // FOR } // FOR // // Now for each vertex that was modified, we mark their roots as // candidates // Map<DesignerVertex, Set<DesignerVertex>> descendants = new HashMap<DesignerVertex, Set<DesignerVertex>>(); for (DesignerVertex root : graph.getRoots()) { descendants.put(root, graph.getDescendants(root)); LOG.debug(root + ": " + descendants.get(root) + "\n"); } // FOR for (DesignerVertex vertex : modified) { LOG.debug("Checking: " + vertex + "\n"); for (DesignerVertex root : descendants.keySet()) { if (descendants.get(root).contains(vertex)) { LOG.debug("Found in " + descendants.get(root) + "\n"); this.replication_candidates.add((Table) root.getCatalogItem()); // break; } } // FOR } // FOR LOG.info("Replication Candidates: " + this.replication_candidates); return; } }