package eu.stratosphere.sopremo.pact; import eu.stratosphere.nephele.configuration.Configuration; import eu.stratosphere.pact.common.stubs.Collector; import eu.stratosphere.pact.common.stubs.CrossStub; import eu.stratosphere.pact.common.type.PactRecord; import eu.stratosphere.sopremo.EvaluationContext; import eu.stratosphere.sopremo.serialization.Schema; import eu.stratosphere.sopremo.type.IJsonNode; /** * An abstract implementation of the {@link CrossStub}. SopremoCross provides the functionality to convert the * standard input of the CrossStub to a more manageable representation (both inputs are converted to an * {@link IJsonNode}). */ public abstract class SopremoCross extends CrossStub { private EvaluationContext context; private Schema inputSchema1, inputSchema2; private JsonCollector collector; private IJsonNode cachedInput1, cachedInput2; /* * (non-Javadoc) * @see eu.stratosphere.pact.common.stubs.Stub#open(eu.stratosphere.nephele.configuration.Configuration) */ @Override public void open(final Configuration parameters) throws Exception { // We need to pass our class loader since the default class loader is // not able to resolve classes coming from the Sopremo user jar file. this.context = SopremoUtil.deserialize(parameters, SopremoUtil.CONTEXT, EvaluationContext.class, this.getClass().getClassLoader()); this.inputSchema1 = this.context.getInputSchema(0); this.inputSchema2 = this.context.getInputSchema(1); this.collector = new JsonCollector(this.context.getOutputSchema(0)); SopremoUtil.configureStub(this, parameters); } /** * This method must be implemented to provide a user implementation of a cross. * * @param values1 * an {@link IJsonNode} from the first input * @param values2 * an {@link IJsonNode} from the second input * @param out * a collector that collects all output pairs */ protected abstract void cross(IJsonNode value1, IJsonNode value2, JsonCollector out); /* * (non-Javadoc) * @see eu.stratosphere.pact.common.stubs.CrossStub#cross(eu.stratosphere.pact.common.type.PactRecord, * eu.stratosphere.pact.common.type.PactRecord, eu.stratosphere.pact.common.stubs.Collector) */ @Override public void cross(final PactRecord record1, final PactRecord record2, final Collector<PactRecord> out) { this.context.increaseInputCounter(); this.collector.configure(out, this.context); final IJsonNode input1 = this.inputSchema1.recordToJson(record1, this.cachedInput1); final IJsonNode input2 = this.inputSchema2.recordToJson(record2, this.cachedInput2); if (SopremoUtil.LOG.isTraceEnabled()) SopremoUtil.LOG.trace(String.format("%s %s/%s", this.getContext().operatorTrace(), input1, input2)); try { this.cross(input1, input2, this.collector); } catch (final RuntimeException e) { SopremoUtil.LOG.error(String.format("Error occurred @ %s with v1 %s/%s v2: %s", this.getContext() .operatorTrace(), input1, input2, e)); throw e; } } protected final EvaluationContext getContext() { return this.context; } }