Search in sources :

Example 1 with AnnotatedClassDescriptor

use of org.apache.drill.common.scanner.persistence.AnnotatedClassDescriptor in project drill by apache.

the class TestClassPathScanner method test.

@Test
public void test() throws Exception {
    ScanResult result = ClassPathScanner.fromPrescan(DrillConfig.create());
    // if the build has run properly. BuildTimeScan.REGISTRY_FILE was created with a prescan
    //    assertListEqualsUnordered(result.getPrescannedPackages(),
    //      "org.apache.drill.common.logical",
    //      "org.apache.drill.exec.expr",
    //      "org.apache.drill.exec.physical.base",
    //      "org.apache.drill.exec.expr.fn.impl",
    //      "org.apache.drill.exec.physical.impl",
    //      "org.apache.drill.exec.rpc.user.security",
    //      "org.apache.drill.exec.store",
    //      "org.apache.drill.exec.store.mock",
    //      "org.apache.drill.exec.physical.config",
    //      "org.apache.drill.storage"
    //    );
    //    // this is added in the unit test folder that was not scanned so far
    //    assertListEqualsUnordered(result.getScannedPackages(),
    //      "org.apache.drill.exec.testing",
    //      "org.apache.drill.exec.fn.impl.testing",
    //      "org.apache.drill.exec.rpc.user.security.testing"
    //    );
    List<AnnotatedClassDescriptor> functions = result.getAnnotatedClasses();
    Set<String> scanned = new HashSet<>();
    AnnotatedClassDescriptor functionRandomBigIntGauss = null;
    for (AnnotatedClassDescriptor function : functions) {
        assertTrue(function.getClassName() + " scanned twice", scanned.add(function.getClassName()));
        if (function.getClassName().equals(RandomBigIntGauss.class.getName())) {
            functionRandomBigIntGauss = function;
        }
    }
    if (functionRandomBigIntGauss == null) {
        Assert.fail("functionRandomBigIntGauss not found");
    }
    // TODO: use Andrew's randomized test framework to verify a subset of the functions
    for (AnnotatedClassDescriptor function : functions) {
        Class<?> c = Class.forName(function.getClassName(), false, this.getClass().getClassLoader());
        Field[] fields = c.getDeclaredFields();
        assertEquals("fields count for " + function, fields.length, function.getFields().size());
        for (int i = 0; i < fields.length; i++) {
            FieldDescriptor fieldDescriptor = function.getFields().get(i);
            Field field = fields[i];
            assertEquals("Class fields:\n" + Arrays.toString(fields) + "\n != \nDescriptor fields:\n" + function.getFields(), field.getName(), fieldDescriptor.getName());
            verifyAnnotations(field.getDeclaredAnnotations(), fieldDescriptor.getAnnotations());
            assertEquals(field.getType(), fieldDescriptor.getFieldClass());
        }
        Annotation[] annotations = c.getDeclaredAnnotations();
        List<AnnotationDescriptor> scannedAnnotations = function.getAnnotations();
        verifyAnnotations(annotations, scannedAnnotations);
        FunctionTemplate bytecodeAnnotation = function.getAnnotationProxy(FunctionTemplate.class);
        FunctionTemplate reflectionAnnotation = c.getAnnotation(FunctionTemplate.class);
        assertEquals(reflectionAnnotation.name(), bytecodeAnnotation.name());
        assertArrayEquals(reflectionAnnotation.names(), bytecodeAnnotation.names());
        assertEquals(reflectionAnnotation.scope(), bytecodeAnnotation.scope());
        assertEquals(reflectionAnnotation.nulls(), bytecodeAnnotation.nulls());
        assertEquals(reflectionAnnotation.isBinaryCommutative(), bytecodeAnnotation.isBinaryCommutative());
        assertEquals(reflectionAnnotation.desc(), bytecodeAnnotation.desc());
        assertEquals(reflectionAnnotation.costCategory(), bytecodeAnnotation.costCategory());
    }
    for (String baseType : result.getScannedClasses()) {
        validateType(result, baseType);
    }
    assertTrue(result.getImplementations(PhysicalOperator.class).size() > 0);
    assertTrue(result.getImplementations(DrillFunc.class).size() > 0);
}
Also used : AnnotationDescriptor(org.apache.drill.common.scanner.persistence.AnnotationDescriptor) ScanResult(org.apache.drill.common.scanner.persistence.ScanResult) Annotation(java.lang.annotation.Annotation) FieldDescriptor(org.apache.drill.common.scanner.persistence.FieldDescriptor) AnnotatedClassDescriptor(org.apache.drill.common.scanner.persistence.AnnotatedClassDescriptor) Field(java.lang.reflect.Field) FunctionTemplate(org.apache.drill.exec.expr.annotations.FunctionTemplate) PhysicalOperator(org.apache.drill.exec.physical.base.PhysicalOperator) RandomBigIntGauss(org.apache.drill.exec.fn.impl.testing.GeneratorFunctions.RandomBigIntGauss) HashSet(java.util.HashSet) DrillFunc(org.apache.drill.exec.expr.DrillFunc) Test(org.junit.Test)

Example 2 with AnnotatedClassDescriptor

use of org.apache.drill.common.scanner.persistence.AnnotatedClassDescriptor in project drill by apache.

the class ClassPathScanner method scan.

/**
   *
   * @param pathsToScan the locations to scan for .class files
   * @param packagePrefixes the whitelist of package prefixes to scan
   * @param parentResult if there was a prescan, its result
   * @return the merged scan
   */
static ScanResult scan(Collection<URL> pathsToScan, Collection<String> packagePrefixes, Collection<String> scannedClasses, Collection<String> scannedAnnotations, ScanResult parentResult) {
    Stopwatch watch = Stopwatch.createStarted();
    try {
        AnnotationScanner annotationScanner = new AnnotationScanner(scannedAnnotations);
        SubTypesScanner subTypesScanner = new SubTypesScanner(parentResult.getImplementations());
        if (packagePrefixes.size() > 0) {
            final FilterBuilder filter = new FilterBuilder();
            for (String prefix : packagePrefixes) {
                filter.include(FilterBuilder.prefix(prefix));
            }
            ConfigurationBuilder conf = new ConfigurationBuilder().setUrls(pathsToScan).setMetadataAdapter(// Scanners depend on this
            METADATA_ADAPTER).filterInputsBy(filter).setScanners(annotationScanner, subTypesScanner);
            // scans stuff, but don't use the funky storage layer
            new Reflections(conf);
        }
        List<ParentClassDescriptor> implementations = new ArrayList<>();
        for (String baseTypeName : scannedClasses) {
            implementations.add(new ParentClassDescriptor(baseTypeName, new ArrayList<>(subTypesScanner.getChildrenOf(baseTypeName))));
        }
        List<AnnotatedClassDescriptor> annotated = annotationScanner.getAnnotatedClasses();
        verifyClassUnicity(annotated, pathsToScan);
        return new ScanResult(packagePrefixes, scannedClasses, scannedAnnotations, annotated, implementations);
    } finally {
        logger.info(format("Scanning packages %s in locations %s took %dms", packagePrefixes, pathsToScan, watch.elapsed(MILLISECONDS)));
    }
}
Also used : ConfigurationBuilder(org.reflections.util.ConfigurationBuilder) ScanResult(org.apache.drill.common.scanner.persistence.ScanResult) Stopwatch(com.google.common.base.Stopwatch) ArrayList(java.util.ArrayList) AnnotatedClassDescriptor(org.apache.drill.common.scanner.persistence.AnnotatedClassDescriptor) FilterBuilder(org.reflections.util.FilterBuilder) ParentClassDescriptor(org.apache.drill.common.scanner.persistence.ParentClassDescriptor) Reflections(org.reflections.Reflections)

Example 3 with AnnotatedClassDescriptor

use of org.apache.drill.common.scanner.persistence.AnnotatedClassDescriptor in project drill by apache.

the class LocalFunctionRegistry method validate.

/**
   * Validates all functions, present in jars.
   * Will throw {@link FunctionValidationException} if:
   * <ol>
   *  <li>Jar with the same name has been already registered.</li>
   *  <li>Conflicting function with the similar signature is found.</li>
   *  <li>Aggregating function is not deterministic.</li>
   *</ol>
   * @param jarName jar name to be validated
   * @param scanResult scan of all classes present in jar
   * @return list of validated function signatures
   */
public List<String> validate(String jarName, ScanResult scanResult) {
    List<String> functions = Lists.newArrayList();
    FunctionConverter converter = new FunctionConverter();
    List<AnnotatedClassDescriptor> providerClasses = scanResult.getAnnotatedClasses();
    if (registryHolder.containsJar(jarName)) {
        throw new JarValidationException(String.format("Jar with %s name has been already registered", jarName));
    }
    final ListMultimap<String, String> allFuncWithSignatures = registryHolder.getAllFunctionsWithSignatures();
    for (AnnotatedClassDescriptor func : providerClasses) {
        DrillFuncHolder holder = converter.getHolder(func, ClassLoader.getSystemClassLoader());
        if (holder != null) {
            String functionInput = holder.getInputParameters();
            String[] names = holder.getRegisteredNames();
            for (String name : names) {
                String functionName = name.toLowerCase();
                String functionSignature = String.format(functionSignaturePattern, functionName, functionInput);
                if (allFuncWithSignatures.get(functionName).contains(functionSignature)) {
                    throw new FunctionValidationException(String.format("Found duplicated function in %s: %s", registryHolder.getJarNameByFunctionSignature(functionName, functionSignature), functionSignature));
                } else if (holder.isAggregating() && !holder.isDeterministic()) {
                    throw new FunctionValidationException(String.format("Aggregate functions must be deterministic: %s", func.getClassName()));
                } else {
                    functions.add(functionSignature);
                    allFuncWithSignatures.put(functionName, functionSignature);
                }
            }
        } else {
            logger.warn("Unable to initialize function for class {}", func.getClassName());
        }
    }
    return functions;
}
Also used : AnnotatedClassDescriptor(org.apache.drill.common.scanner.persistence.AnnotatedClassDescriptor) FunctionValidationException(org.apache.drill.exec.exception.FunctionValidationException) DrillFuncHolder(org.apache.drill.exec.expr.fn.DrillFuncHolder) FunctionConverter(org.apache.drill.exec.expr.fn.FunctionConverter) JarValidationException(org.apache.drill.exec.exception.JarValidationException)

Example 4 with AnnotatedClassDescriptor

use of org.apache.drill.common.scanner.persistence.AnnotatedClassDescriptor in project drill by apache.

the class LocalFunctionRegistry method register.

/**
   * Registers all functions present in jar and updates registry version.
   * If jar name is already registered, all jar related functions will be overridden.
   * To prevent classpath collisions during loading and unloading jars,
   * each jar is shipped with its own class loader.
   *
   * @param jars list of jars to be registered
   * @param version remote function registry version number with which local function registry is synced
   */
public void register(List<JarScan> jars, long version) {
    Map<String, List<FunctionHolder>> newJars = Maps.newHashMap();
    for (JarScan jarScan : jars) {
        FunctionConverter converter = new FunctionConverter();
        List<AnnotatedClassDescriptor> providerClasses = jarScan.getScanResult().getAnnotatedClasses();
        List<FunctionHolder> functions = Lists.newArrayList();
        newJars.put(jarScan.getJarName(), functions);
        for (AnnotatedClassDescriptor func : providerClasses) {
            DrillFuncHolder holder = converter.getHolder(func, jarScan.getClassLoader());
            if (holder != null) {
                String functionInput = holder.getInputParameters();
                String[] names = holder.getRegisteredNames();
                for (String name : names) {
                    String functionName = name.toLowerCase();
                    String functionSignature = String.format(functionSignaturePattern, functionName, functionInput);
                    functions.add(new FunctionHolder(functionName, functionSignature, holder));
                }
            }
        }
    }
    registryHolder.addJars(newJars, version);
}
Also used : AnnotatedClassDescriptor(org.apache.drill.common.scanner.persistence.AnnotatedClassDescriptor) DrillFuncHolder(org.apache.drill.exec.expr.fn.DrillFuncHolder) List(java.util.List) FunctionConverter(org.apache.drill.exec.expr.fn.FunctionConverter)

Aggregations

AnnotatedClassDescriptor (org.apache.drill.common.scanner.persistence.AnnotatedClassDescriptor)4 ScanResult (org.apache.drill.common.scanner.persistence.ScanResult)2 DrillFuncHolder (org.apache.drill.exec.expr.fn.DrillFuncHolder)2 FunctionConverter (org.apache.drill.exec.expr.fn.FunctionConverter)2 Stopwatch (com.google.common.base.Stopwatch)1 Annotation (java.lang.annotation.Annotation)1 Field (java.lang.reflect.Field)1 ArrayList (java.util.ArrayList)1 HashSet (java.util.HashSet)1 List (java.util.List)1 AnnotationDescriptor (org.apache.drill.common.scanner.persistence.AnnotationDescriptor)1 FieldDescriptor (org.apache.drill.common.scanner.persistence.FieldDescriptor)1 ParentClassDescriptor (org.apache.drill.common.scanner.persistence.ParentClassDescriptor)1 FunctionValidationException (org.apache.drill.exec.exception.FunctionValidationException)1 JarValidationException (org.apache.drill.exec.exception.JarValidationException)1 DrillFunc (org.apache.drill.exec.expr.DrillFunc)1 FunctionTemplate (org.apache.drill.exec.expr.annotations.FunctionTemplate)1 RandomBigIntGauss (org.apache.drill.exec.fn.impl.testing.GeneratorFunctions.RandomBigIntGauss)1 PhysicalOperator (org.apache.drill.exec.physical.base.PhysicalOperator)1 Test (org.junit.Test)1