Search in sources :

Example 6 with InputPortMeta

use of com.datatorrent.stram.plan.logical.LogicalPlan.InputPortMeta in project apex-core by apache.

the class StreamMapping method redoMapping.

/**
   * rebuild the tree, which may cause more changes to execution layer than need be
   * TODO: investigate incremental logic
   */
private void redoMapping() {
    Set<Pair<PTOperator, InputPortMeta>> downstreamOpers = Sets.newHashSet();
    // figure out the downstream consumers
    for (InputPortMeta ipm : streamMeta.getSinks()) {
        // skipped for parallel partitions - those are handled elsewhere
        if (!ipm.getValue(PortContext.PARTITION_PARALLEL) && plan.hasMapping(ipm.getOperatorMeta())) {
            List<PTOperator> partitions = plan.getOperators(ipm.getOperatorMeta());
            for (PTOperator doper : partitions) {
                downstreamOpers.add(new Pair<>(doper, ipm));
            }
        }
    }
    if (!downstreamOpers.isEmpty()) {
        // unifiers are required
        for (PTOperator unifier : this.cascadingUnifiers) {
            detachUnifier(unifier);
        }
        if (this.finalUnifier != null) {
            detachUnifier(finalUnifier);
        }
        List<PTOperator> currentUnifiers = Lists.newArrayList(this.cascadingUnifiers);
        this.cascadingUnifiers.clear();
        plan.undeployOpers.addAll(currentUnifiers);
        addSlidingUnifiers();
        int limit = streamMeta.getSource().getValue(PortContext.UNIFIER_LIMIT);
        boolean separateUnifiers = false;
        Integer lastId = null;
        for (InputPortMeta ipm : streamMeta.getSinks()) {
            Integer id = plan.getStreamCodecIdentifier(ipm.getStreamCodec());
            if (lastId == null) {
                lastId = id;
            } else if (!id.equals(lastId)) {
                separateUnifiers = true;
                break;
            }
        }
        List<PTOutput> unifierSources = this.upstream;
        Map<StreamCodec<?>, List<PTOutput>> cascadeUnifierSourcesMap = Maps.newHashMap();
        if (limit > 1 && this.upstream.size() > limit) {
            // cascading unifier
            if (!separateUnifiers) {
                unifierSources = setupCascadingUnifiers(this.upstream, currentUnifiers, limit, 0);
            } else {
                for (InputPortMeta ipm : streamMeta.getSinks()) {
                    StreamCodec<?> streamCodec = ipm.getStreamCodec();
                    if (!cascadeUnifierSourcesMap.containsKey(streamCodec)) {
                        unifierSources = setupCascadingUnifiers(this.upstream, currentUnifiers, limit, 0);
                        cascadeUnifierSourcesMap.put(streamCodec, unifierSources);
                    }
                }
            }
        }
        // remove remaining unifiers
        for (PTOperator oper : currentUnifiers) {
            plan.removePTOperator(oper);
        }
        // Directly getting attribute from map to know if it is set or not as it can be overriden by the input
        Boolean sourceSingleFinal = streamMeta.getSource().getAttributes().get(PortContext.UNIFIER_SINGLE_FINAL);
        // link the downstream operators with the unifiers
        for (Pair<PTOperator, InputPortMeta> doperEntry : downstreamOpers) {
            Map<LogicalPlan.InputPortMeta, PartitionKeys> partKeys = doperEntry.first.partitionKeys;
            PartitionKeys pks = partKeys != null ? partKeys.get(doperEntry.second) : null;
            Boolean sinkSingleFinal = doperEntry.second.getAttributes().get(PortContext.UNIFIER_SINGLE_FINAL);
            boolean lastSingle = (sinkSingleFinal != null) ? sinkSingleFinal : (sourceSingleFinal != null ? sourceSingleFinal.booleanValue() : PortContext.UNIFIER_SINGLE_FINAL.defaultValue);
            if (upstream.size() > 1) {
                // detach downstream from upstream operator for the case where no unifier existed previously
                for (PTOutput source : upstream) {
                    Iterator<PTInput> sinks = source.sinks.iterator();
                    while (sinks.hasNext()) {
                        PTInput sink = sinks.next();
                        if (sink.target == doperEntry.first) {
                            doperEntry.first.inputs.remove(sink);
                            sinks.remove();
                        }
                    }
                }
                if (!separateUnifiers && lastSingle) {
                    if (finalUnifier == null) {
                        finalUnifier = createUnifier(streamMeta, plan);
                    }
                    setInput(doperEntry.first, doperEntry.second, finalUnifier, (pks == null) || (pks.mask == 0) ? null : pks);
                    if (finalUnifier.inputs.isEmpty()) {
                        // set unifier inputs once, regardless how many downstream operators there are
                        for (PTOutput out : unifierSources) {
                            addInput(this.finalUnifier, out, null);
                        }
                    }
                } else {
                    // MxN partitioning: unifier per downstream partition
                    LOG.debug("MxN unifier for {} {} {}", new Object[] { doperEntry.first, doperEntry.second.getPortName(), pks });
                    PTOperator unifier = doperEntry.first.upstreamMerge.get(doperEntry.second);
                    if (unifier == null) {
                        unifier = createUnifier(streamMeta, plan);
                        doperEntry.first.upstreamMerge.put(doperEntry.second, unifier);
                        setInput(doperEntry.first, doperEntry.second, unifier, null);
                    }
                    // sources may change dynamically, rebuild inputs (as for cascading unifiers)
                    for (PTInput in : unifier.inputs) {
                        in.source.sinks.remove(in);
                    }
                    unifier.inputs.clear();
                    List<PTOutput> doperUnifierSources = unifierSources;
                    if (separateUnifiers) {
                        List<PTOutput> cascadeSources = cascadeUnifierSourcesMap.get(doperEntry.second.getStreamCodec());
                        if (cascadeSources != null) {
                            doperUnifierSources = cascadeSources;
                        }
                    }
                    // add new inputs
                    for (PTOutput out : doperUnifierSources) {
                        addInput(unifier, out, (pks == null) || (pks.mask == 0) ? null : pks);
                    }
                }
            } else {
                // no partitioning
                PTOperator unifier = doperEntry.first.upstreamMerge.remove(doperEntry.second);
                if (unifier != null) {
                    plan.removePTOperator(unifier);
                }
                setInput(doperEntry.first, doperEntry.second, upstream.get(0).source, pks);
            }
        }
        // 2) Downstream operators partitions are scaled up from one to multiple. (replaced by merged unifier)
        if (finalUnifier != null && finalUnifier.inputs.isEmpty()) {
            plan.removePTOperator(finalUnifier);
            finalUnifier = null;
        }
    }
}
Also used : InputPortMeta(com.datatorrent.stram.plan.logical.LogicalPlan.InputPortMeta) PTInput(com.datatorrent.stram.plan.physical.PTOperator.PTInput) StreamCodec(com.datatorrent.api.StreamCodec) PTOutput(com.datatorrent.stram.plan.physical.PTOperator.PTOutput) List(java.util.List) PartitionKeys(com.datatorrent.api.Partitioner.PartitionKeys) Pair(com.datatorrent.common.util.Pair)

Example 7 with InputPortMeta

use of com.datatorrent.stram.plan.logical.LogicalPlan.InputPortMeta in project apex-core by apache.

the class PhysicalPlan method updatePartitionsInfoForPersistOperator.

private void updatePartitionsInfoForPersistOperator(LogicalPlan dag) {
    // StreamCodec for persist operator
    try {
        for (OperatorMeta n : dag.getAllOperators()) {
            for (StreamMeta s : n.getOutputStreams().values()) {
                if (s.getPersistOperator() != null) {
                    InputPortMeta persistInputPort = s.getPersistOperatorInputPort();
                    StreamCodecWrapperForPersistance<?> persistCodec = (StreamCodecWrapperForPersistance<?>) persistInputPort.getStreamCodec();
                    if (persistCodec == null) {
                        continue;
                    }
                    // Logging is enabled for the stream
                    for (InputPortMeta portMeta : s.getSinksToPersist()) {
                        updatePersistOperatorWithSinkPartitions(persistInputPort, s.getPersistOperator(), persistCodec, portMeta);
                    }
                }
                // Check partitioning for persist operators per sink too
                for (Map.Entry<InputPortMeta, InputPortMeta> entry : s.sinkSpecificPersistInputPortMap.entrySet()) {
                    InputPortMeta persistInputPort = entry.getValue();
                    StreamCodec<?> streamCodec = persistInputPort.getStreamCodec();
                    if (streamCodec != null && streamCodec instanceof StreamCodecWrapperForPersistance) {
                        updatePersistOperatorWithSinkPartitions(persistInputPort, s.sinkSpecificPersistOperatorMap.get(entry.getKey()), (StreamCodecWrapperForPersistance<?>) streamCodec, entry.getKey());
                    }
                }
            }
        }
    } catch (Exception e) {
        throw Throwables.propagate(e);
    }
}
Also used : StreamMeta(com.datatorrent.stram.plan.logical.LogicalPlan.StreamMeta) OperatorMeta(com.datatorrent.stram.plan.logical.LogicalPlan.OperatorMeta) InputPortMeta(com.datatorrent.stram.plan.logical.LogicalPlan.InputPortMeta) Map(java.util.Map) HashMap(java.util.HashMap) ConcurrentMap(java.util.concurrent.ConcurrentMap) LinkedHashMap(java.util.LinkedHashMap) IOException(java.io.IOException) StreamCodecWrapperForPersistance(com.datatorrent.stram.plan.logical.StreamCodecWrapperForPersistance)

Example 8 with InputPortMeta

use of com.datatorrent.stram.plan.logical.LogicalPlan.InputPortMeta in project apex-core by apache.

the class PhysicalPlan method setContainer.

private void setContainer(PTOperator pOperator, PTContainer container) {
    LOG.debug("Setting container {} for {}", container, pOperator);
    assert (pOperator.container == null) : "Container already assigned for " + pOperator;
    pOperator.container = container;
    container.operators.add(pOperator);
    int upStreamUnifierMemory = 0;
    if (!pOperator.upstreamMerge.isEmpty()) {
        for (Map.Entry<InputPortMeta, PTOperator> mEntry : pOperator.upstreamMerge.entrySet()) {
            assert (mEntry.getValue().container == null) : "Container already assigned for " + mEntry.getValue();
            mEntry.getValue().container = container;
            container.operators.add(mEntry.getValue());
            upStreamUnifierMemory += mEntry.getValue().getOperatorMeta().getValue(OperatorContext.MEMORY_MB);
        }
    }
    int memoryMB = pOperator.getOperatorMeta().getValue(OperatorContext.MEMORY_MB) + upStreamUnifierMemory;
    container.setRequiredMemoryMB(container.getRequiredMemoryMB() + memoryMB);
}
Also used : InputPortMeta(com.datatorrent.stram.plan.logical.LogicalPlan.InputPortMeta) Map(java.util.Map) HashMap(java.util.HashMap) ConcurrentMap(java.util.concurrent.ConcurrentMap) LinkedHashMap(java.util.LinkedHashMap) Checkpoint(com.datatorrent.stram.api.Checkpoint)

Example 9 with InputPortMeta

use of com.datatorrent.stram.plan.logical.LogicalPlan.InputPortMeta in project apex-core by apache.

the class PlanModifier method removeOperator.

/**
   * Remove named operator and any outgoing streams.
   * @param name
   */
public void removeOperator(String name) {
    OperatorMeta om = logicalPlan.getOperatorMeta(name);
    if (om == null) {
        return;
    }
    if (!om.getInputStreams().isEmpty()) {
        for (Map.Entry<InputPortMeta, StreamMeta> input : om.getInputStreams().entrySet()) {
            if (input.getValue().getSinks().size() == 1) {
                // would result in dangling stream
                String msg = String.format("Operator %s connected to input streams %s", om.getName(), om.getInputStreams());
                throw new ValidationException(msg);
            }
        }
    }
    if (!om.getOutputStreams().isEmpty()) {
        String msg = String.format("Operator %s connected to output streams %s", om.getName(), om.getOutputStreams());
        throw new ValidationException(msg);
    }
    /*
    // remove associated sinks
    Map<InputPortMeta, StreamMeta> inputStreams = om.getInputStreams();
    for (Map.Entry<InputPortMeta, StreamMeta> e : inputStreams.entrySet()) {
      if (e.getKey().getOperatorMeta() == om) {
        if (e.getValue().getSinks().size() == 1) {
          // drop stream
          e.getValue().remove();
        }
      }
    }
    */
    logicalPlan.removeOperator(om.getOperator());
    if (physicalPlan != null) {
        physicalPlan.removeLogicalOperator(om);
    }
}
Also used : StreamMeta(com.datatorrent.stram.plan.logical.LogicalPlan.StreamMeta) ValidationException(javax.validation.ValidationException) OperatorMeta(com.datatorrent.stram.plan.logical.LogicalPlan.OperatorMeta) InputPortMeta(com.datatorrent.stram.plan.logical.LogicalPlan.InputPortMeta) Map(java.util.Map)

Example 10 with InputPortMeta

use of com.datatorrent.stram.plan.logical.LogicalPlan.InputPortMeta in project apex-malhar by apache.

the class ApexStreamImplTest method testAddOperator.

@Test
public void testAddOperator() {
    LogicalPlan dag = new LogicalPlan();
    TestOperator<String, Integer> firstOperator = new TestOperator<>();
    TestOperator<Integer, Date> secondOperator = new TestOperator<>();
    new ApexStreamImpl<String>().addOperator(firstOperator, null, firstOperator.output, name("first")).endWith(secondOperator, secondOperator.input, name("second")).with(DAG.Locality.THREAD_LOCAL).with(Context.OperatorContext.AUTO_RECORD, true).with("prop", "TestProp").populateDag(dag);
    Assert.assertTrue(dag.getAllOperators().size() == 2);
    Set<String> opNames = new HashSet<>();
    opNames.add("first");
    opNames.add("second");
    for (LogicalPlan.OperatorMeta operatorMeta : dag.getAllOperators()) {
        Assert.assertTrue(operatorMeta.getOperator() instanceof TestOperator);
        Assert.assertTrue(opNames.contains(operatorMeta.getName()));
        if (operatorMeta.getName().equals("second")) {
            // Assert the Context.OperatorContext.AUTO_RECORD attribute has been set to true for second operator
            Assert.assertTrue(operatorMeta.getAttributes().get(Context.OperatorContext.AUTO_RECORD));
            // Assert the prop has been set to TestProp for second operator
            Assert.assertEquals("TestProp", ((TestOperator) operatorMeta.getOperator()).prop);
        } else {
            // Assert the Context.OperatorContext.AUTO_RECORD attribute keeps as default false for first operator
            Assert.assertNull(operatorMeta.getAttributes().get(Context.OperatorContext.AUTO_RECORD));
            // Assert the prop has not been set for first operator
            Assert.assertNull(((TestOperator) operatorMeta.getOperator()).prop);
        }
    }
    Collection<LogicalPlan.StreamMeta> streams = dag.getAllStreams();
    // Assert there is only one stream
    Assert.assertTrue(streams.size() == 1);
    for (LogicalPlan.StreamMeta stream : streams) {
        // Assert the stream is from first operator to second operator
        Assert.assertEquals("first", stream.getSource().getOperatorMeta().getName());
        Collection<InputPortMeta> portMetaCollection = stream.getSinks();
        Assert.assertTrue(1 == portMetaCollection.size());
        for (InputPortMeta inputPortMeta : portMetaCollection) {
            Assert.assertEquals("second", inputPortMeta.getOperatorMeta().getName());
        }
        // Assert the stream is thread local
        Assert.assertTrue(stream.getLocality() == DAG.Locality.THREAD_LOCAL);
    }
}
Also used : InputPortMeta(com.datatorrent.stram.plan.logical.LogicalPlan.InputPortMeta) Date(java.util.Date) LogicalPlan(com.datatorrent.stram.plan.logical.LogicalPlan) HashSet(java.util.HashSet) Test(org.junit.Test)

Aggregations

InputPortMeta (com.datatorrent.stram.plan.logical.LogicalPlan.InputPortMeta)18 StreamMeta (com.datatorrent.stram.plan.logical.LogicalPlan.StreamMeta)10 Map (java.util.Map)10 OperatorMeta (com.datatorrent.stram.plan.logical.LogicalPlan.OperatorMeta)9 HashMap (java.util.HashMap)7 LinkedHashMap (java.util.LinkedHashMap)7 OutputPortMeta (com.datatorrent.stram.plan.logical.LogicalPlan.OutputPortMeta)5 ConcurrentMap (java.util.concurrent.ConcurrentMap)5 PTOperator (com.datatorrent.stram.plan.physical.PTOperator)4 PTOutput (com.datatorrent.stram.plan.physical.PTOperator.PTOutput)4 IOException (java.io.IOException)4 PartitionKeys (com.datatorrent.api.Partitioner.PartitionKeys)3 StreamCodec (com.datatorrent.api.StreamCodec)3 LogicalPlan (com.datatorrent.stram.plan.logical.LogicalPlan)3 StreamCodecWrapperForPersistance (com.datatorrent.stram.plan.logical.StreamCodecWrapperForPersistance)3 PTContainer (com.datatorrent.stram.plan.physical.PTContainer)3 PTInput (com.datatorrent.stram.plan.physical.PTOperator.PTInput)3 ArrayList (java.util.ArrayList)3 ObjectMapperString (com.datatorrent.common.util.ObjectMapperString)2 Checkpoint (com.datatorrent.stram.api.Checkpoint)2