package edu.washington.escience.myria.operator.network;
import com.google.common.base.Preconditions;
import edu.washington.escience.myria.DbException;
import edu.washington.escience.myria.operator.BatchTupleSource;
import edu.washington.escience.myria.operator.Operator;
import edu.washington.escience.myria.parallel.ExchangePairID;
import edu.washington.escience.myria.parallel.ipc.StreamOutputChannel;
import edu.washington.escience.myria.storage.TupleBatch;
/**
* The producer part of the Collect Exchange operator. The producer actively pushes the tuples generated by the child
* operator to the paired consumer.
*/
public final class RecoverProducer extends CollectProducer {
/** Required for Java serialization. */
private static final long serialVersionUID = 1L;
/** The logger for this class. */
private static final org.slf4j.Logger LOGGER =
org.slf4j.LoggerFactory.getLogger(RecoverProducer.class);
/** the original producer. */
private final Producer origProducer;
/** the channel index that this operator is recovering for. */
private final int channelIdx;
/**
* @param child the child who provides data for this producer to distribute.
* @param operatorID destination operator the data goes
* @param consumerWorkerID destination worker the data goes.
* @param origProducer the original producer.
* @param channelIdx the channel index that this operator is recovering for. *
*/
public RecoverProducer(
final Operator child,
final ExchangePairID operatorID,
final int consumerWorkerID,
final Producer origProducer,
final int channelIdx) {
super(child, operatorID, consumerWorkerID);
this.origProducer = origProducer;
this.channelIdx = channelIdx;
}
@Override
protected void childEOS() throws DbException {
writePartitionsIntoChannels(null);
Preconditions.checkArgument(getChild() instanceof BatchTupleSource);
if (!origProducer.eos()) {
StreamOutputChannel<TupleBatch> tmp = getChannels()[0];
if (LOGGER.isTraceEnabled()) {
LOGGER.trace(
"recovery task {} detach & attach channel {} old channel {} new channel {}",
getOpName(),
tmp.getID(),
origProducer.getChannels()[channelIdx],
tmp);
}
origProducer.getChannels()[channelIdx] = tmp;
/* have to do this otherwise the channel will be released in resourceManager.cleanup() */
getTaskResourceManager().removeOutputChannel(tmp);
/* have to do this otherwise the channel will be released in Producer.cleanup() */
getChannels()[0] = null;
/* set the channel to be available again */
origProducer.getChannelsAvail()[channelIdx] = true;
/* if the channel was disabled before crash, need to give the task a chance to enable it. */
origProducer.getTaskResourceManager().getFragment().notifyOutputEnabled(tmp.getID());
/* if the task has no new input, but needs to produce potential EOSs & push TBs in its buffers out. */
origProducer.getTaskResourceManager().getFragment().notifyNewInput();
} else {
channelEnds(0);
}
}
}