package edu.washington.escience.myria.operator;
import java.util.Objects;
import javax.annotation.Nonnull;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import edu.washington.escience.myria.DbException;
import edu.washington.escience.myria.MyriaConstants;
import edu.washington.escience.myria.Schema;
import edu.washington.escience.myria.parallel.Server;
import edu.washington.escience.myria.storage.TupleBatch;
/**
* A utility class used to update the global variables of a query at the master.
*
*/
public class SetGlobal extends RootOperator {
/** Required for Java serialization. */
private static final long serialVersionUID = 1L;
/** The {@link Server} on which the queries are run. */
private final Server server;
/** The name of the global variable to be updated. */
private final String key;
/** The query that is running. */
private Long queryId;
/** Whether we have written the global yet. */
private boolean hasWritten;
/**
* This operator will update the server's catalog with the tuple counts supplied by the child. The child schema is
* expected to be (userName:string, programName:string, relationName:string, count:long).
*
* @param child the source of tuples.
* @param key the variable whose value will be set.
* @param server the server whose catalog will be updated.
*/
public SetGlobal(final Operator child, @Nonnull final String key, @Nonnull final Server server) {
super(child);
this.server = Objects.requireNonNull(server, "server");
this.key = Objects.requireNonNull(key, "key");
queryId = null;
hasWritten = false;
}
@Override
protected void init(final ImmutableMap<String, Object> execEnvVars) throws Exception {
int nodeId =
(Integer)
Preconditions.checkNotNull(
execEnvVars.get(MyriaConstants.EXEC_ENV_VAR_NODE_ID), "node ID in execEnvVars");
Preconditions.checkArgument(
nodeId == MyriaConstants.MASTER_ID, "%s can only be run on the master", SetGlobal.class);
Schema schema = Preconditions.checkNotNull(getSchema(), "schema cannot be null");
Preconditions.checkArgument(
schema.numColumns() == 1,
"the child of %s must be a singleton and have only 1 column, not %s",
SetGlobal.class,
schema.numColumns());
queryId =
(Long)
Preconditions.checkNotNull(
execEnvVars.get(MyriaConstants.EXEC_ENV_VAR_QUERY_ID), "query ID in execEnvVars");
}
@SuppressWarnings("deprecation")
@Override
protected void consumeTuples(final TupleBatch tuples) throws DbException {
for (int i = 0; i < tuples.numTuples(); ++i) {
Preconditions.checkState(
!hasWritten,
"In query %s: have already written to the global variable %s. Further writes violate the invariant",
queryId,
key);
server.setQueryGlobal(queryId, key, tuples.getObject(0, i));
hasWritten = true;
}
}
@Override
protected void childEOI() throws DbException {
/* Do nothing. */
}
@Override
protected void childEOS() throws DbException {
/* Do nothing. */
}
}