package edu.washington.escience.myria.parallel;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nonnull;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import edu.washington.escience.myria.MyriaConstants.FTMode;
import edu.washington.escience.myria.MyriaConstants.ProfilingMode;
import edu.washington.escience.myria.RelationKey;
import edu.washington.escience.myria.operator.DbReader;
import edu.washington.escience.myria.operator.DbWriter;
import edu.washington.escience.myria.operator.Operator;
import edu.washington.escience.myria.operator.RootOperator;
import edu.washington.escience.myria.util.MyriaUtils;
/**
* Class that contains a list of RootOperators with parameters associated with the query, for example, FT mode. We may
* have more parameters once Myria is launched as a service, in that case a query would have parameters such as resource
* limits.
*/
public class SubQueryPlan implements Serializable, DbReader, DbWriter {
/** Serialization. */
private static final long serialVersionUID = 1L;
/** The list of RootOperators. */
private final List<RootOperator> rootOps;
/** FT mode, default: NONE. */
private FTMode ftMode = FTMode.NONE;
/** The relations that are written, along with their schemas. */
private final Map<RelationKey, RelationWriteMetadata> writeSet;
/** The relations that are read. */
private final Set<RelationKey> readSet;
/** profilingMode. */
private Set<ProfilingMode> profilingMode;
/** Constructor. */
public SubQueryPlan() {
rootOps = new ArrayList<RootOperator>();
writeSet = Maps.newHashMap();
readSet = Sets.newHashSet();
}
/**
* Constructor.
*
* @param op a root operator.
*/
public SubQueryPlan(final RootOperator op) {
this();
addRootOp(op);
}
/**
* Constructor.
*
* @param ops a list of root operators.
*/
public SubQueryPlan(final RootOperator[] ops) {
this();
addRootOp(ops);
}
/**
* Return RootOperators.
*
* @return the rootOps.
*/
public List<RootOperator> getRootOps() {
return rootOps;
}
/**
* Add a RootOperator.
*
* @param op the operator.
*/
public void addRootOp(final RootOperator op) {
rootOps.add(op);
updateReadWriteSets(op, Sets.newIdentityHashSet());
}
/**
* A helper to walk various operators and compute what relations they read and write. This is for understanding query
* contention.
*
* @param op a single operator, which will be recursively traversed
* @param visited which objects have been visited already
*/
private void updateReadWriteSets(final Operator op, final Set<Object> visited) {
if (!visited.add(op)) {
return;
}
if (op instanceof DbWriter) {
MyriaUtils.putNewVerifyOld(((DbWriter) op).writeSet(), writeSet);
} else if (op instanceof DbReader) {
readSet.addAll(((DbReader) op).readSet());
}
for (Operator child : op.getChildren()) {
updateReadWriteSets(child, visited);
}
}
/**
* Add a list of RootOperator.
*
* @param ops operators.
*/
public void addRootOp(final RootOperator[] ops) {
for (RootOperator op : ops) {
addRootOp(op);
}
}
/**
* Set FT mode.
*
* @param ftMode the mode.
*/
public void setFTMode(final FTMode ftMode) {
this.ftMode = ftMode;
}
/**
* Return FT mode.
*
* @return the ft mode.
*/
public FTMode getFTMode() {
return ftMode;
}
/**
* @return the profiling mode.
*/
@Nonnull
public Set<ProfilingMode> getProfilingMode() {
return profilingMode;
}
/**
* Set profiling mode.
*
* @param profilingMode the profiling mode.
*/
public void setProfilingMode(@Nonnull final Set<ProfilingMode> profilingMode) {
this.profilingMode = profilingMode;
}
@Override
public Map<RelationKey, RelationWriteMetadata> writeSet() {
return ImmutableMap.copyOf(writeSet);
}
@Override
public Set<RelationKey> readSet() {
return ImmutableSet.copyOf(readSet);
}
}