Search in sources :

Example 6 with ValidationException

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

the class LogicalPlan method validateProcessingMode.

private void validateProcessingMode(OperatorMeta om, Set<OperatorMeta> visited) {
    for (StreamMeta is : om.getInputStreams().values()) {
        if (!visited.contains(is.getSource().getOperatorMeta())) {
            // process all inputs first
            return;
        }
    }
    visited.add(om);
    Operator.ProcessingMode pm = om.getValue(OperatorContext.PROCESSING_MODE);
    for (StreamMeta os : om.outputStreams.values()) {
        for (InputPortMeta sink : os.sinks) {
            OperatorMeta sinkOm = sink.getOperatorMeta();
            Operator.ProcessingMode sinkPm = sinkOm.attributes == null ? null : sinkOm.attributes.get(OperatorContext.PROCESSING_MODE);
            if (sinkPm == null) {
                // set it to AT_MOST_ONCE as well
                if (Operator.ProcessingMode.AT_MOST_ONCE.equals(pm)) {
                    LOG.warn("Setting processing mode for operator {} to {}", sinkOm.getName(), pm);
                    sinkOm.getAttributes().put(OperatorContext.PROCESSING_MODE, pm);
                } else if (Operator.ProcessingMode.EXACTLY_ONCE.equals(pm)) {
                    // If the source processing mode is EXACTLY_ONCE and a processing mode is not specified for the sink then
                    // throw a validation error
                    String msg = String.format("Processing mode for %s should be AT_MOST_ONCE for source %s/%s", sinkOm.getName(), om.getName(), pm);
                    throw new ValidationException(msg);
                }
            } else {
                /*
           * If the source processing mode is AT_MOST_ONCE and the processing mode for the sink is not AT_MOST_ONCE throw a validation error
           * If the source processing mode is EXACTLY_ONCE and the processing mode for the sink is not AT_MOST_ONCE throw a validation error
           */
                if ((Operator.ProcessingMode.AT_MOST_ONCE.equals(pm) && (sinkPm != pm)) || (Operator.ProcessingMode.EXACTLY_ONCE.equals(pm) && !Operator.ProcessingMode.AT_MOST_ONCE.equals(sinkPm))) {
                    String msg = String.format("Processing mode %s/%s not valid for source %s/%s", sinkOm.getName(), sinkPm, om.getName(), pm);
                    throw new ValidationException(msg);
                }
            }
            validateProcessingMode(sinkOm, visited);
        }
    }
}
Also used : Operator(com.datatorrent.api.Operator) InputOperator(com.datatorrent.api.InputOperator) ValidationException(javax.validation.ValidationException)

Example 7 with ValidationException

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

the class LogicalPlan method validate.

/**
   * Validate the plan. Includes checks that required ports are connected,
   * required configuration parameters specified, graph free of cycles etc.
   *
   * @throws ConstraintViolationException
   */
public void validate() throws ConstraintViolationException {
    ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
    Validator validator = factory.getValidator();
    checkAttributeValueSerializable(this.getAttributes(), DAG.class.getName());
    // clear oioRoot values in all operators
    for (OperatorMeta n : operators.values()) {
        n.oioRoot = null;
    }
    // clear visited on all operators
    for (OperatorMeta n : operators.values()) {
        n.nindex = null;
        n.lowlink = null;
        // validate configuration
        Set<ConstraintViolation<Operator>> constraintViolations = validator.validate(n.getOperator());
        if (!constraintViolations.isEmpty()) {
            Set<ConstraintViolation<?>> copySet = new HashSet<>(constraintViolations.size());
            // (should be public <T> ConstraintViolationException(String message, Set<ConstraintViolation<T>> constraintViolations) { ... })
            for (ConstraintViolation<Operator> cv : constraintViolations) {
                copySet.add(cv);
            }
            throw new ConstraintViolationException("Operator " + n.getName() + " violates constraints " + copySet, copySet);
        }
        OperatorMeta.PortMapping portMapping = n.getPortMapping();
        checkAttributeValueSerializable(n.getAttributes(), n.getName());
        // Check operator annotation
        if (n.operatorAnnotation != null) {
            // Check if partition property of the operator is being honored
            if (!n.operatorAnnotation.partitionable()) {
                // Check if any of the input ports have partition attributes set
                for (InputPortMeta pm : portMapping.inPortMap.values()) {
                    Boolean paralellPartition = pm.getValue(PortContext.PARTITION_PARALLEL);
                    if (paralellPartition) {
                        throw new ValidationException("Operator " + n.getName() + " is not partitionable but PARTITION_PARALLEL attribute is set");
                    }
                }
                // Check if the operator implements Partitioner
                if (n.getValue(OperatorContext.PARTITIONER) != null || n.attributes != null && !n.attributes.contains(OperatorContext.PARTITIONER) && Partitioner.class.isAssignableFrom(n.getOperator().getClass())) {
                    throw new ValidationException("Operator " + n.getName() + " provides partitioning capabilities but the annotation on the operator class declares it non partitionable!");
                }
            }
            // a multiple of application window count
            if (!n.operatorAnnotation.checkpointableWithinAppWindow()) {
                if (n.getValue(OperatorContext.CHECKPOINT_WINDOW_COUNT) % n.getValue(OperatorContext.APPLICATION_WINDOW_COUNT) != 0) {
                    throw new ValidationException("Operator " + n.getName() + " cannot be check-pointed between an application window " + "but the checkpoint-window-count " + n.getValue(OperatorContext.CHECKPOINT_WINDOW_COUNT) + " is not a multiple application-window-count " + n.getValue(OperatorContext.APPLICATION_WINDOW_COUNT));
                }
            }
        }
        // check that non-optional ports are connected
        for (InputPortMeta pm : portMapping.inPortMap.values()) {
            checkAttributeValueSerializable(pm.getAttributes(), n.getName() + "." + pm.getPortName());
            StreamMeta sm = n.inputStreams.get(pm);
            if (sm == null) {
                if ((pm.portAnnotation == null || !pm.portAnnotation.optional()) && pm.classDeclaringHiddenPort == null) {
                    throw new ValidationException("Input port connection required: " + n.name + "." + pm.getPortName());
                }
            } else {
                if (pm.classDeclaringHiddenPort != null) {
                    throw new ValidationException(String.format("Invalid port connected: %s.%s is hidden by %s.%s", pm.classDeclaringHiddenPort.getName(), pm.getPortName(), pm.operatorMeta.getOperator().getClass().getName(), pm.getPortName()));
                }
                // check locality constraints
                DAG.Locality locality = sm.getLocality();
                if (locality == DAG.Locality.THREAD_LOCAL) {
                    if (n.inputStreams.size() > 1) {
                        validateThreadLocal(n);
                    }
                }
                if (pm.portAnnotation != null && pm.portAnnotation.schemaRequired()) {
                    //since schema is required, the port attribute TUPLE_CLASS should be present
                    if (pm.attributes.get(PortContext.TUPLE_CLASS) == null) {
                        throw new ValidationException("Attribute " + PortContext.TUPLE_CLASS.getName() + " missing on port : " + n.name + "." + pm.getPortName());
                    }
                }
            }
        }
        for (OutputPortMeta pm : portMapping.outPortMap.values()) {
            checkAttributeValueSerializable(pm.getAttributes(), n.getName() + "." + pm.getPortName());
            if (!n.outputStreams.containsKey(pm)) {
                if ((pm.portAnnotation != null && !pm.portAnnotation.optional()) && pm.classDeclaringHiddenPort == null) {
                    throw new ValidationException("Output port connection required: " + n.name + "." + pm.getPortName());
                }
            } else {
                //port is connected
                if (pm.classDeclaringHiddenPort != null) {
                    throw new ValidationException(String.format("Invalid port connected: %s.%s is hidden by %s.%s", pm.classDeclaringHiddenPort.getName(), pm.getPortName(), pm.operatorMeta.getOperator().getClass().getName(), pm.getPortName()));
                }
                if (pm.portAnnotation != null && pm.portAnnotation.schemaRequired()) {
                    //since schema is required, the port attribute TUPLE_CLASS should be present
                    if (pm.attributes.get(PortContext.TUPLE_CLASS) == null) {
                        throw new ValidationException("Attribute " + PortContext.TUPLE_CLASS.getName() + " missing on port : " + n.name + "." + pm.getPortName());
                    }
                }
            }
        }
    }
    ValidationContext validatonContext = new ValidationContext();
    for (OperatorMeta n : operators.values()) {
        if (n.nindex == null) {
            findStronglyConnected(n, validatonContext);
        }
    }
    if (!validatonContext.invalidCycles.isEmpty()) {
        throw new ValidationException("Loops in graph: " + validatonContext.invalidCycles);
    }
    List<List<String>> invalidDelays = new ArrayList<>();
    for (OperatorMeta n : rootOperators) {
        findInvalidDelays(n, invalidDelays, new Stack<OperatorMeta>());
    }
    if (!invalidDelays.isEmpty()) {
        throw new ValidationException("Invalid delays in graph: " + invalidDelays);
    }
    for (StreamMeta s : streams.values()) {
        if (s.source == null) {
            throw new ValidationException("Stream source not connected: " + s.getName());
        }
        if (s.sinks.isEmpty()) {
            throw new ValidationException("Stream sink not connected: " + s.getName());
        }
    }
    // Validate root operators are input operators
    for (OperatorMeta om : this.rootOperators) {
        if (!(om.getOperator() instanceof InputOperator)) {
            throw new ValidationException(String.format("Root operator: %s is not a Input operator", om.getName()));
        }
    }
    // processing mode
    Set<OperatorMeta> visited = Sets.newHashSet();
    for (OperatorMeta om : this.rootOperators) {
        validateProcessingMode(om, visited);
    }
    validateAffinityRules();
}
Also used : Operator(com.datatorrent.api.Operator) InputOperator(com.datatorrent.api.InputOperator) ValidationException(javax.validation.ValidationException) ArrayList(java.util.ArrayList) ConstraintViolationException(javax.validation.ConstraintViolationException) List(java.util.List) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) ValidatorFactory(javax.validation.ValidatorFactory) DAG(com.datatorrent.api.DAG) ConstraintViolation(javax.validation.ConstraintViolation) InputOperator(com.datatorrent.api.InputOperator) Validator(javax.validation.Validator)

Example 8 with ValidationException

use of javax.validation.ValidationException 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 9 with ValidationException

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

the class DelayOperatorTest method testInvalidDelayDetection.

@Test
public void testInvalidDelayDetection() {
    LogicalPlan dag = new LogicalPlan();
    GenericTestOperator opB = dag.addOperator("B", GenericTestOperator.class);
    GenericTestOperator opC = dag.addOperator("C", GenericTestOperator.class);
    GenericTestOperator opD = dag.addOperator("D", GenericTestOperator.class);
    DefaultDelayOperator<Object> opDelay = dag.addOperator("opDelay", DefaultDelayOperator.class);
    dag.addStream("BtoC", opB.outport1, opC.inport1);
    dag.addStream("CtoD", opC.outport1, opD.inport1);
    dag.addStream("CtoDelay", opC.outport2, opDelay.input);
    dag.addStream("DelayToD", opDelay.output, opD.inport2);
    List<List<String>> invalidDelays = new ArrayList<>();
    dag.findInvalidDelays(dag.getMeta(opB), invalidDelays, new Stack<OperatorMeta>());
    assertEquals("operator invalid delay", 1, invalidDelays.size());
    try {
        dag.validate();
        fail("validation should fail");
    } catch (ValidationException e) {
    // expected
    }
    dag = new LogicalPlan();
    opB = dag.addOperator("B", GenericTestOperator.class);
    opC = dag.addOperator("C", GenericTestOperator.class);
    opD = dag.addOperator("D", GenericTestOperator.class);
    opDelay = dag.addOperator("opDelay", DefaultDelayOperator.class);
    dag.setOperatorAttribute(opDelay, Context.OperatorContext.APPLICATION_WINDOW_COUNT, 2);
    dag.addStream("BtoC", opB.outport1, opC.inport1);
    dag.addStream("CtoD", opC.outport1, opD.inport1);
    dag.addStream("CtoDelay", opC.outport2, opDelay.input);
    dag.addStream("DelayToC", opDelay.output, opC.inport2);
    invalidDelays = new ArrayList<>();
    dag.findInvalidDelays(dag.getMeta(opB), invalidDelays, new Stack<OperatorMeta>());
    assertEquals("operator invalid delay", 1, invalidDelays.size());
    try {
        dag.validate();
        fail("validation should fail");
    } catch (ValidationException e) {
    // expected
    }
    dag = new LogicalPlan();
    opB = dag.addOperator("B", GenericTestOperator.class);
    opC = dag.addOperator("C", GenericTestOperator.class);
    opD = dag.addOperator("D", GenericTestOperator.class);
    opDelay = dag.addOperator("opDelay", DefaultDelayOperator.class);
    dag.addStream("BtoC", opB.outport1, opC.inport1);
    dag.addStream("CtoD", opC.outport1, opD.inport1);
    dag.addStream("CtoDelay", opC.outport2, opDelay.input).setLocality(DAG.Locality.THREAD_LOCAL);
    dag.addStream("DelayToC", opDelay.output, opC.inport2).setLocality(DAG.Locality.THREAD_LOCAL);
    try {
        dag.validate();
        fail("validation should fail");
    } catch (ValidationException e) {
    // expected
    }
}
Also used : ValidationException(javax.validation.ValidationException) OperatorMeta(com.datatorrent.stram.plan.logical.LogicalPlan.OperatorMeta) GenericTestOperator(com.datatorrent.stram.engine.GenericTestOperator) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List) DefaultDelayOperator(com.datatorrent.common.util.DefaultDelayOperator) Test(org.junit.Test)

Example 10 with ValidationException

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

the class LogicalPlanConfigurationTest method testErrorSameAttrMultipleTypes.

/**
   * Note: If the same name is given to an Attribute specified in multiple Context classes, then the type of that
   * Attribute is required to be the same accross all Context classes. This is required because if a simple attribute
   * name is specified in a properties file at the top level context then that attribute needs to be set in all child configurations. If
   * there were multiple Attributes specified in different Contexts with the same name, but a different type, then
   * it would not be possible to set the values of Attributes specified by a simple attribute name in the root
   * context of a properties file. If this were the case, then adding another Attribute with the same name as a pre-existing Attribute to a new Context
   * class would be a backwards incompatible change.
   */
@Test
@SuppressWarnings("unchecked")
public void testErrorSameAttrMultipleTypes() {
    //Trigger initialization of attributes for existing Contexts.
    LogicalPlanConfiguration lpc = new LogicalPlanConfiguration(new Configuration());
    Exception ex = null;
    try {
        ContextUtils.buildAttributeMaps(Sets.newHashSet(MockContext1.class, MockContext2.class));
    } catch (ValidationException e) {
        ex = e;
    }
    Assert.assertNotNull(ex);
    Assert.assertTrue(ex.getMessage().contains("is defined with two different types in two different context classes:"));
    //Clear test data from Context.
    ContextUtils.initialize();
}
Also used : ValidationException(javax.validation.ValidationException) Configuration(org.apache.hadoop.conf.Configuration) IOException(java.io.IOException) ValidationException(javax.validation.ValidationException) Test(org.junit.Test)

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