Search in sources :

Example 21 with ValidationException

use of javax.validation.ValidationException in project apex-core by apache.

the class LogicalPlanModificationTest method testRemoveOperator.

@Test
public void testRemoveOperator() {
    GenericTestOperator o1 = dag.addOperator("o1", GenericTestOperator.class);
    OperatorMeta o1Meta = dag.getMeta(o1);
    GenericTestOperator o12 = dag.addOperator("o12", GenericTestOperator.class);
    OperatorMeta o12Meta = dag.getMeta(o12);
    GenericTestOperator o2 = dag.addOperator("o2", GenericTestOperator.class);
    OperatorMeta o2Meta = dag.getMeta(o2);
    GenericTestOperator o3 = dag.addOperator("o3", GenericTestOperator.class);
    OperatorMeta o3Meta = dag.getMeta(o3);
    LogicalPlan.StreamMeta s1 = dag.addStream("o1.outport1", o1.outport1, o2.inport1, o12.inport1);
    LogicalPlan.StreamMeta s2 = dag.addStream("o2.outport1", o2.outport1, o3.inport1);
    TestPlanContext ctx = new TestPlanContext();
    dag.setAttribute(OperatorContext.STORAGE_AGENT, ctx);
    PhysicalPlan plan = new PhysicalPlan(dag, ctx);
    ctx.deploy.clear();
    ctx.undeploy.clear();
    Assert.assertEquals("containers " + plan.getContainers(), 4, plan.getContainers().size());
    Assert.assertEquals("physical operators " + plan.getAllOperators(), 4, plan.getAllOperators().size());
    Assert.assertEquals("sinks s1 " + s1.getSinks(), 2, s1.getSinks().size());
    List<PTOperator> o2PhysicalOpers = plan.getOperators(o2Meta);
    Assert.assertEquals("instances " + o2Meta, 1, o2PhysicalOpers.size());
    PlanModifier pm = new PlanModifier(plan);
    try {
        pm.removeOperator(o2Meta.getName());
        Assert.fail("validation error (connected output stream) expected");
    } catch (ValidationException ve) {
    // all good
    }
    // remove output stream required before removing operator
    pm.removeStream(s2.getName());
    pm.removeOperator(o2Meta.getName());
    pm.applyChanges(ctx);
    Assert.assertEquals("sinks s1 " + s1.getSinks(), 1, s1.getSinks().size());
    Assert.assertTrue("undeploy " + ctx.undeploy, ctx.undeploy.containsAll(o2PhysicalOpers));
    Assert.assertTrue("deploy " + ctx.deploy, !ctx.deploy.containsAll(o2PhysicalOpers));
    Assert.assertEquals("streams " + dag.getAllStreams(), 1, dag.getAllStreams().size());
    Assert.assertEquals("operators " + dag.getAllOperators(), 3, dag.getAllOperators().size());
    Assert.assertTrue("operators " + dag.getAllOperators(), dag.getAllOperators().containsAll(Sets.newHashSet(o1Meta, o3Meta)));
    try {
        plan.getOperators(o2Meta);
        Assert.fail("removed from physical plan: " + o2Meta);
    } catch (Exception e) {
    // all good
    }
    Assert.assertEquals("containers " + plan.getContainers(), 3, plan.getContainers().size());
    Assert.assertEquals("physical operators " + plan.getAllOperators(), 3, plan.getAllOperators().size());
    Assert.assertEquals("removed containers " + ctx.releaseContainers, 1, ctx.releaseContainers.size());
    try {
        pm.removeOperator(o12Meta.getName());
        Assert.fail("cannot remove operator prior to removing input stream");
    } catch (ValidationException ve) {
        Assert.assertTrue("" + ve.getMessage(), ve.getMessage().matches(".*Operator o12 connected to input streams.*"));
    }
    pm.removeStream(s1.getName());
    pm.removeOperator(o12Meta.getName());
}
Also used : PhysicalPlan(com.datatorrent.stram.plan.physical.PhysicalPlan) ValidationException(javax.validation.ValidationException) OperatorMeta(com.datatorrent.stram.plan.logical.LogicalPlan.OperatorMeta) PTOperator(com.datatorrent.stram.plan.physical.PTOperator) PlanModifier(com.datatorrent.stram.plan.physical.PlanModifier) GenericTestOperator(com.datatorrent.stram.engine.GenericTestOperator) TestPlanContext(com.datatorrent.stram.plan.TestPlanContext) LogicalPlan(com.datatorrent.stram.plan.logical.LogicalPlan) ValidationException(javax.validation.ValidationException) Test(org.junit.Test) PhysicalPlanTest(com.datatorrent.stram.plan.physical.PhysicalPlanTest)

Example 22 with ValidationException

use of javax.validation.ValidationException in project apex-core by apache.

the class PlanModifier method addStream.

/**
   * Add stream to logical plan. If a stream with same name and source already
   * exists, the new downstream operator will be attached to it.
   *
   * @param streamName
   * @param sourceOperName
   * @param sourcePortName
   * @param targetOperName
   * @param targetPortName
   */
public void addStream(String streamName, String sourceOperName, String sourcePortName, String targetOperName, String targetPortName) {
    OperatorMeta om = logicalPlan.getOperatorMeta(sourceOperName);
    if (om == null) {
        throw new ValidationException("Invalid operator name " + sourceOperName);
    }
    Operators.PortMappingDescriptor portMap = new Operators.PortMappingDescriptor();
    Operators.describe(om.getOperator(), portMap);
    PortContextPair<OutputPort<?>> sourcePort = portMap.outputPorts.get(sourcePortName);
    if (sourcePort == null) {
        throw new AssertionError(String.format("Invalid port %s (%s)", sourcePortName, om));
    }
    addStream(streamName, sourcePort.component, getInputPort(targetOperName, targetPortName));
}
Also used : OutputPort(com.datatorrent.api.Operator.OutputPort) Operators(com.datatorrent.stram.plan.logical.Operators) ValidationException(javax.validation.ValidationException) OperatorMeta(com.datatorrent.stram.plan.logical.LogicalPlan.OperatorMeta)

Example 23 with ValidationException

use of javax.validation.ValidationException in project apex-core by apache.

the class LogicalPlan method validateAffinityRules.

/**
   * validation for affinity rules validates following:
   *  1. The operator names specified in affinity rule are part of the dag
   *  2. Affinity rules do not conflict with anti-affinity rules directly or indirectly
   *  3. Anti-affinity rules do not conflict with Stream Locality
   *  4. Anti-affinity rules do not conflict with host-locality attribute
   *  5. Affinity rule between non stream operators does not have Thread_Local locality
   *  6. Affinity rules do not conflict with host-locality attribute
   */
private void validateAffinityRules() {
    AffinityRulesSet affinityRuleSet = getAttributes().get(DAGContext.AFFINITY_RULES_SET);
    if (affinityRuleSet == null || affinityRuleSet.getAffinityRules() == null) {
        return;
    }
    Collection<AffinityRule> affinityRules = affinityRuleSet.getAffinityRules();
    HashMap<String, Set<String>> containerAffinities = new HashMap<>();
    HashMap<String, Set<String>> nodeAffinities = new HashMap<>();
    HashMap<String, String> hostNamesMapping = new HashMap<>();
    HashMap<OperatorPair, AffinityRule> affinities = new HashMap<>();
    HashMap<OperatorPair, AffinityRule> antiAffinities = new HashMap<>();
    HashMap<OperatorPair, AffinityRule> threadLocalAffinities = new HashMap<>();
    List<String> operatorNames = new ArrayList<>();
    for (OperatorMeta operator : getAllOperators()) {
        operatorNames.add(operator.getName());
        Set<String> containerSet = new HashSet<>();
        containerSet.add(operator.getName());
        containerAffinities.put(operator.getName(), containerSet);
        Set<String> nodeSet = new HashSet<>();
        nodeSet.add(operator.getName());
        nodeAffinities.put(operator.getName(), nodeSet);
        if (operator.getAttributes().get(OperatorContext.LOCALITY_HOST) != null) {
            hostNamesMapping.put(operator.getName(), operator.getAttributes().get(OperatorContext.LOCALITY_HOST));
        }
    }
    // Identify operators set as Regex and add to list
    for (AffinityRule rule : affinityRules) {
        if (rule.getOperatorRegex() != null) {
            convertRegexToList(operatorNames, rule);
        }
    }
    // Convert operators with list of operator to rules with operator pairs for validation
    for (AffinityRule rule : affinityRules) {
        if (rule.getOperatorsList() != null) {
            List<String> list = rule.getOperatorsList();
            for (int i = 0; i < list.size(); i++) {
                for (int j = i + 1; j < list.size(); j++) {
                    OperatorPair pair = new OperatorPair(list.get(i), list.get(j));
                    if (rule.getType() == com.datatorrent.api.AffinityRule.Type.AFFINITY) {
                        addToMap(affinities, rule, pair);
                    } else {
                        addToMap(antiAffinities, rule, pair);
                    }
                }
            }
        }
    }
    for (Entry<OperatorPair, AffinityRule> ruleEntry : affinities.entrySet()) {
        OperatorPair pair = ruleEntry.getKey();
        AffinityRule rule = ruleEntry.getValue();
        if (hostNamesMapping.containsKey(pair.first) && hostNamesMapping.containsKey(pair.second) && !hostNamesMapping.get(pair.first).equals(hostNamesMapping.get(pair.second))) {
            throw new ValidationException(String.format("Host Locality for operators: %s(host: %s) & %s(host: %s) conflicts with affinity rules", pair.first, hostNamesMapping.get(pair.first), pair.second, hostNamesMapping.get(pair.second)));
        }
        if (rule.getLocality() == Locality.THREAD_LOCAL) {
            addToMap(threadLocalAffinities, rule, pair);
        } else if (rule.getLocality() == Locality.CONTAINER_LOCAL) {
            // Combine the sets
            combineSets(containerAffinities, pair);
            // Also update node list
            combineSets(nodeAffinities, pair);
        } else if (rule.getLocality() == Locality.NODE_LOCAL) {
            combineSets(nodeAffinities, pair);
        }
    }
    for (StreamMeta stream : getAllStreams()) {
        String source = stream.source.getOperatorMeta().getName();
        for (InputPortMeta sink : stream.sinks) {
            String sinkOperator = sink.getOperatorMeta().getName();
            OperatorPair pair = new OperatorPair(source, sinkOperator);
            if (stream.getLocality() != null && stream.getLocality().ordinal() <= Locality.NODE_LOCAL.ordinal() && hostNamesMapping.containsKey(pair.first) && hostNamesMapping.containsKey(pair.second) && !hostNamesMapping.get(pair.first).equals(hostNamesMapping.get(pair.second))) {
                throw new ValidationException(String.format("Host Locality for operators: %s(host: %s) & %s(host: %s) conflicts with stream locality", pair.first, hostNamesMapping.get(pair.first), pair.second, hostNamesMapping.get(pair.second)));
            }
            if (stream.locality == Locality.CONTAINER_LOCAL) {
                combineSets(containerAffinities, pair);
                combineSets(nodeAffinities, pair);
            } else if (stream.locality == Locality.NODE_LOCAL) {
                combineSets(nodeAffinities, pair);
            }
            if (affinities.containsKey(pair)) {
                // Choose the lower bound on locality
                AffinityRule rule = affinities.get(pair);
                if (rule.getLocality() == Locality.THREAD_LOCAL) {
                    stream.setLocality(rule.getLocality());
                    threadLocalAffinities.remove(rule);
                    affinityRules.remove(rule);
                }
                if (stream.locality != null && rule.getLocality().ordinal() > stream.getLocality().ordinal()) {
                    // Remove the affinity rule from attributes, as it is redundant
                    affinityRules.remove(rule);
                }
            }
        }
    }
    // Validate that all Thread local affinities were for stream connected operators
    if (!threadLocalAffinities.isEmpty()) {
        OperatorPair pair = threadLocalAffinities.keySet().iterator().next();
        throw new ValidationException(String.format("Affinity rule specified THREAD_LOCAL affinity for operators %s & %s which are not connected by stream", pair.first, pair.second));
    }
    for (Entry<OperatorPair, AffinityRule> ruleEntry : antiAffinities.entrySet()) {
        OperatorPair pair = ruleEntry.getKey();
        AffinityRule rule = ruleEntry.getValue();
        if (pair.first.equals(pair.second)) {
            continue;
        }
        if (rule.getLocality() == Locality.CONTAINER_LOCAL) {
            if (containerAffinities.get(pair.first).contains(pair.second)) {
                throw new ValidationException(String.format("Anti Affinity rule for operators %s & %s conflicts with affinity rules or Stream locality", pair.first, pair.second));
            }
        } else if (rule.getLocality() == Locality.NODE_LOCAL) {
            if (nodeAffinities.get(pair.first).contains(pair.second)) {
                throw new ValidationException(String.format("Anti Affinity rule for operators %s & %s conflicts with affinity rules or Stream locality", pair.first, pair.second));
            }
            // Check host locality for both operators
            // Check host attribute for all operators in node local set for both
            // anti-affinity operators
            String firstOperatorLocality = getHostLocality(nodeAffinities, pair.first, hostNamesMapping);
            String secondOperatorLocality = getHostLocality(nodeAffinities, pair.second, hostNamesMapping);
            if (firstOperatorLocality != null && secondOperatorLocality != null && firstOperatorLocality == secondOperatorLocality) {
                throw new ValidationException(String.format("Host Locality for operators: %s(host: %s) & %s(host: %s) conflict with anti-affinity rules", pair.first, firstOperatorLocality, pair.second, secondOperatorLocality));
            }
        }
    }
}
Also used : Set(java.util.Set) HashSet(java.util.HashSet) AffinityRulesSet(com.datatorrent.api.AffinityRulesSet) LinkedHashSet(java.util.LinkedHashSet) ValidationException(javax.validation.ValidationException) AffinityRule(com.datatorrent.api.AffinityRule) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) ArrayList(java.util.ArrayList) AffinityRulesSet(com.datatorrent.api.AffinityRulesSet) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet)

Example 24 with ValidationException

use of javax.validation.ValidationException in project apex-core by apache.

the class LogicalPlan method validateThreadLocal.

/*
   * Validates OIO constraints for operators with more than one input streams
   * For a node to be OIO,
   *  1. all its input streams should be OIO
   *  2. all its input streams should have OIO from single source node
   */
private void validateThreadLocal(OperatorMeta om) {
    Integer oioRoot = null;
    // already visited and validated
    if (om.oioRoot != null) {
        return;
    }
    if (om.getOperator() instanceof Operator.DelayOperator) {
        String msg = String.format("Locality %s invalid for delay operator %s", Locality.THREAD_LOCAL, om);
        throw new ValidationException(msg);
    }
    for (StreamMeta sm : om.inputStreams.values()) {
        // validation fail as each input stream should be OIO
        if (sm.locality != Locality.THREAD_LOCAL) {
            String msg = String.format("Locality %s invalid for operator %s with multiple input streams as at least one of the input streams is not %s", Locality.THREAD_LOCAL, om, Locality.THREAD_LOCAL);
            throw new ValidationException(msg);
        }
        if (sm.source.operatorMeta.getOperator() instanceof Operator.DelayOperator) {
            String msg = String.format("Locality %s invalid for delay operator %s", Locality.THREAD_LOCAL, sm.source.operatorMeta);
            throw new ValidationException(msg);
        }
        // gets oio root for input operator for the stream
        Integer oioStreamRoot = getOioRoot(sm.source.operatorMeta);
        // validation fail as each input stream should have a common OIO root
        if (om.oioRoot != null && oioStreamRoot != om.oioRoot) {
            String msg = String.format("Locality %s invalid for operator %s with multiple input streams as at least one of the input streams is not originating from common OIO owner node", Locality.THREAD_LOCAL, om, Locality.THREAD_LOCAL);
            throw new ValidationException(msg);
        }
        // populate oioRoot with root OIO node id for first stream, then validate for subsequent streams to have same root OIO node
        if (oioRoot == null) {
            oioRoot = oioStreamRoot;
        } else if (oioRoot.intValue() != oioStreamRoot.intValue()) {
            String msg = String.format("Locality %s invalid for operator %s with multiple input streams as they origin from different owner OIO operators", sm.locality, om);
            throw new ValidationException(msg);
        }
    }
    om.oioRoot = oioRoot;
}
Also used : AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ValidationException(javax.validation.ValidationException)

Example 25 with ValidationException

use of javax.validation.ValidationException in project apex-core by apache.

the class PlanModifier method setOperatorProperty.

/**
   * Set the property on a new operator. Since this is only intended to modify
   * previously added operators, no change to the physical plan is required.
   *
   * @param operatorName
   * @param propertyName
   * @param propertyValue
   */
public void setOperatorProperty(String operatorName, String propertyName, String propertyValue) {
    OperatorMeta om = assertGetOperator(operatorName);
    if (physicalPlan != null) {
        for (PTOperator oper : physicalPlan.getOperators(om)) {
            if (!physicalPlan.newOpers.containsKey(oper)) {
                throw new ValidationException("Properties can only be set on new operators: " + om + " " + propertyName + " " + propertyValue);
            }
        }
    }
    Map<String, String> props = Collections.singletonMap(propertyName, propertyValue);
    LogicalPlanConfiguration.setOperatorProperties(om.getOperator(), props);
}
Also used : ValidationException(javax.validation.ValidationException) OperatorMeta(com.datatorrent.stram.plan.logical.LogicalPlan.OperatorMeta)

Aggregations

ValidationException (javax.validation.ValidationException)34 Test (org.junit.Test)17 GenericTestOperator (com.datatorrent.stram.engine.GenericTestOperator)10 TestGeneratorInputOperator (com.datatorrent.stram.engine.TestGeneratorInputOperator)8 OperatorMeta (com.datatorrent.stram.plan.logical.LogicalPlan.OperatorMeta)6 StreamMeta (com.datatorrent.stram.plan.logical.LogicalPlan.StreamMeta)5 HashMap (java.util.HashMap)5 ConstraintViolationException (javax.validation.ConstraintViolationException)5 LogicalPlan (com.datatorrent.stram.plan.logical.LogicalPlan)4 ArrayList (java.util.ArrayList)4 HashSet (java.util.HashSet)4 Map (java.util.Map)4 IOException (java.io.IOException)3 Properties (java.util.Properties)3 ValidatorFactory (javax.validation.ValidatorFactory)3 AffinityRule (com.datatorrent.api.AffinityRule)2 AffinityRulesSet (com.datatorrent.api.AffinityRulesSet)2 Attribute (com.datatorrent.api.Attribute)2 InputOperator (com.datatorrent.api.InputOperator)2 Operator (com.datatorrent.api.Operator)2