Search in sources :

Example 11 with VersionMismatchException

use of org.apache.drill.exec.exception.VersionMismatchException in project drill by apache.

the class TestDynamicUDFSupport method testExceedRetryAttemptsDuringRegistration.

@Test
public void testExceedRetryAttemptsDuringRegistration() throws Exception {
    RemoteFunctionRegistry remoteFunctionRegistry = spyRemoteFunctionRegistry();
    Path registryPath = hadoopToJavaPath(remoteFunctionRegistry.getRegistryArea());
    Path stagingPath = hadoopToJavaPath(remoteFunctionRegistry.getStagingArea());
    Path tmpPath = hadoopToJavaPath(remoteFunctionRegistry.getTmpArea());
    copyDefaultJarsToStagingArea();
    doThrow(new VersionMismatchException("Version mismatch detected", 1)).when(remoteFunctionRegistry).updateRegistry(any(Registry.class), any(DataChangeVersion.class));
    String summary = "Failed to update remote function registry. Exceeded retry attempts limit.";
    testBuilder().sqlQuery("create function using jar '%s'", defaultBinaryJar).unOrdered().baselineColumns("ok", "summary").baselineValues(false, summary).go();
    verify(remoteFunctionRegistry, times(remoteFunctionRegistry.getRetryAttempts() + 1)).updateRegistry(any(Registry.class), any(DataChangeVersion.class));
    assertTrue("Binary should be present in staging area", stagingPath.resolve(defaultBinaryJar).toFile().exists());
    assertTrue("Source should be present in staging area", stagingPath.resolve(defaultSourceJar).toFile().exists());
    assertTrue("Registry area should be empty", ArrayUtils.isEmpty(registryPath.toFile().listFiles()));
    assertTrue("Temporary area should be empty", ArrayUtils.isEmpty(tmpPath.toFile().listFiles()));
    assertEquals("Registry should be empty", remoteFunctionRegistry.getRegistry(new DataChangeVersion()).getJarList().size(), 0);
}
Also used : RemoteFunctionRegistry(org.apache.drill.exec.expr.fn.registry.RemoteFunctionRegistry) HadoopUtils.hadoopToJavaPath(org.apache.drill.test.HadoopUtils.hadoopToJavaPath) Path(java.nio.file.Path) LocalFunctionRegistry(org.apache.drill.exec.expr.fn.registry.LocalFunctionRegistry) FunctionImplementationRegistry(org.apache.drill.exec.expr.fn.FunctionImplementationRegistry) RemoteFunctionRegistry(org.apache.drill.exec.expr.fn.registry.RemoteFunctionRegistry) Registry(org.apache.drill.exec.proto.UserBitShared.Registry) CoreMatchers.containsString(org.hamcrest.CoreMatchers.containsString) ArgumentMatchers.anyString(org.mockito.ArgumentMatchers.anyString) DataChangeVersion(org.apache.drill.exec.store.sys.store.DataChangeVersion) VersionMismatchException(org.apache.drill.exec.exception.VersionMismatchException) SlowTest(org.apache.drill.categories.SlowTest) SqlFunctionTest(org.apache.drill.categories.SqlFunctionTest) Test(org.junit.Test)

Example 12 with VersionMismatchException

use of org.apache.drill.exec.exception.VersionMismatchException in project drill by apache.

the class ZookeeperClient method put.

/**
 * Puts the given byte sequence into the given path.
 *
 * If path does not exists, this call creates it.
 *
 * If version holder is not null and path already exists, passes given version for comparison.
 * Zookeeper maintains stat structure that holds version number which increases each time znode data change is performed.
 * If we pass version that doesn't match the actual version of the data,
 * the update will fail {@link org.apache.zookeeper.KeeperException.BadVersionException}.
 * We catch such exception and re-throw it as {@link VersionMismatchException}.
 * Link to documentation - https://zookeeper.apache.org/doc/r3.2.2/zookeeperProgrammers.html#sc_zkDataModel_znodes
 *
 * @param path  target path
 * @param data  data to store
 * @param version version holder
 */
public void put(final String path, final byte[] data, DataChangeVersion version) {
    Preconditions.checkNotNull(path, "path is required");
    Preconditions.checkNotNull(data, "data is required");
    final String target = PathUtils.join(root, path);
    try {
        // we make a consistent read to ensure this call won't fail upon consecutive calls on the same path
        // before cache is updated
        boolean hasNode = hasPath(path, true);
        if (!hasNode) {
            try {
                curator.create().withMode(mode).forPath(target, data);
            } catch (NodeExistsException e) {
                // Handle race conditions since Drill is distributed and other
                // drillbits may have just created the node. This assumes that we do want to
                // override the new node. Makes sense here, because if the node had existed,
                // we'd have updated it.
                hasNode = true;
            }
        }
        if (hasNode) {
            if (version != null) {
                try {
                    curator.setData().withVersion(version.getVersion()).forPath(target, data);
                } catch (final KeeperException.BadVersionException e) {
                    throw new VersionMismatchException("Unable to put data. Version mismatch is detected.", version.getVersion(), e);
                }
            } else {
                curator.setData().forPath(target, data);
            }
        }
        getCache().rebuildNode(target);
    } catch (final VersionMismatchException e) {
        throw e;
    } catch (final Exception e) {
        throw new DrillRuntimeException("unable to put ", e);
    }
}
Also used : NodeExistsException(org.apache.zookeeper.KeeperException.NodeExistsException) DrillRuntimeException(org.apache.drill.common.exceptions.DrillRuntimeException) VersionMismatchException(org.apache.drill.exec.exception.VersionMismatchException) KeeperException(org.apache.zookeeper.KeeperException) KeeperException(org.apache.zookeeper.KeeperException) DrillRuntimeException(org.apache.drill.common.exceptions.DrillRuntimeException) VersionMismatchException(org.apache.drill.exec.exception.VersionMismatchException) NodeExistsException(org.apache.zookeeper.KeeperException.NodeExistsException)

Example 13 with VersionMismatchException

use of org.apache.drill.exec.exception.VersionMismatchException in project drill by apache.

the class CreateFunctionHandler method initRemoteRegistration.

/**
 * Instantiates remote registration. First gets remote function registry with version.
 * Version is used to ensure that we update the same registry we validated against.
 * Then validates against list of remote jars.
 * If validation is successful, first copies jars to registry area and starts updating remote function registry.
 * If during update {@link VersionMismatchException} was detected,
 * attempts to repeat remote registration process till retry attempts exceeds the limit.
 * If retry attempts number hits 0, throws exception that failed to update remote function registry.
 * In case of any error, if jars have been already copied to registry area, they will be deleted.
 *
 * @param functions list of functions present in jar
 * @param jarManager helper class for copying jars to registry area
 * @param remoteRegistry remote function registry
 * @throws IOException in case of problems with copying jars to registry area
 */
private void initRemoteRegistration(List<String> functions, JarManager jarManager, RemoteFunctionRegistry remoteRegistry) throws IOException {
    int retryAttempts = remoteRegistry.getRetryAttempts();
    boolean copyJars = true;
    try {
        while (retryAttempts >= 0) {
            DataChangeVersion version = new DataChangeVersion();
            List<Jar> remoteJars = remoteRegistry.getRegistry(version).getJarList();
            validateAgainstRemoteRegistry(remoteJars, jarManager.getBinaryName(), functions);
            if (copyJars) {
                jarManager.copyToRegistryArea();
                copyJars = false;
            }
            List<Jar> jars = Lists.newArrayList(remoteJars);
            jars.add(Jar.newBuilder().setName(jarManager.getBinaryName()).addAllFunctionSignature(functions).build());
            Registry updatedRegistry = Registry.newBuilder().addAllJar(jars).build();
            try {
                remoteRegistry.updateRegistry(updatedRegistry, version);
                return;
            } catch (VersionMismatchException ex) {
                logger.debug("Failed to update function registry during registration, version mismatch was detected.", ex);
                retryAttempts--;
            }
        }
        throw new DrillRuntimeException("Failed to update remote function registry. Exceeded retry attempts limit.");
    } catch (Exception e) {
        if (!copyJars) {
            jarManager.deleteQuietlyFromRegistryArea();
        }
        throw e;
    }
}
Also used : Jar(org.apache.drill.exec.proto.UserBitShared.Jar) FunctionImplementationRegistry(org.apache.drill.exec.expr.fn.FunctionImplementationRegistry) RemoteFunctionRegistry(org.apache.drill.exec.expr.fn.registry.RemoteFunctionRegistry) Registry(org.apache.drill.exec.proto.UserBitShared.Registry) DataChangeVersion(org.apache.drill.exec.store.sys.store.DataChangeVersion) DrillRuntimeException(org.apache.drill.common.exceptions.DrillRuntimeException) VersionMismatchException(org.apache.drill.exec.exception.VersionMismatchException) UserException(org.apache.drill.common.exceptions.UserException) DrillRuntimeException(org.apache.drill.common.exceptions.DrillRuntimeException) FunctionValidationException(org.apache.drill.exec.exception.FunctionValidationException) JarValidationException(org.apache.drill.exec.exception.JarValidationException) IOException(java.io.IOException) ForemanSetupException(org.apache.drill.exec.work.foreman.ForemanSetupException) VersionMismatchException(org.apache.drill.exec.exception.VersionMismatchException)

Example 14 with VersionMismatchException

use of org.apache.drill.exec.exception.VersionMismatchException in project drill by apache.

the class DropFunctionHandler method unregister.

/**
 * Gets remote function registry with version.
 * Version is used to ensure that we update the same registry we removed jars from.
 * Looks for a jar to be deleted, if founds one,
 * attempts to update remote registry with list of jars, that excludes jar to be deleted.
 * If during update {@link VersionMismatchException} was detected,
 * attempts to repeat unregistration process till retry attempts exceeds the limit.
 * If retry attempts number hits 0, throws exception that failed to update remote function registry.
 *
 * @param jarName jar name
 * @param remoteFunctionRegistry remote function registry
 * @return jar that was unregistered, null otherwise
 */
private Jar unregister(String jarName, RemoteFunctionRegistry remoteFunctionRegistry) {
    int retryAttempts = remoteFunctionRegistry.getRetryAttempts();
    while (retryAttempts >= 0) {
        DataChangeVersion version = new DataChangeVersion();
        Registry registry = remoteFunctionRegistry.getRegistry(version);
        Jar jarToBeDeleted = null;
        List<Jar> jars = Lists.newArrayList();
        for (Jar j : registry.getJarList()) {
            if (j.getName().equals(jarName)) {
                jarToBeDeleted = j;
            } else {
                jars.add(j);
            }
        }
        if (jarToBeDeleted == null) {
            return null;
        }
        Registry updatedRegistry = Registry.newBuilder().addAllJar(jars).build();
        try {
            remoteFunctionRegistry.updateRegistry(updatedRegistry, version);
            return jarToBeDeleted;
        } catch (VersionMismatchException ex) {
            logger.debug("Failed to update function registry during unregistration, version mismatch was detected.", ex);
            retryAttempts--;
        }
    }
    throw new DrillRuntimeException("Failed to update remote function registry. Exceeded retry attempts limit.");
}
Also used : Jar(org.apache.drill.exec.proto.UserBitShared.Jar) Registry(org.apache.drill.exec.proto.UserBitShared.Registry) RemoteFunctionRegistry(org.apache.drill.exec.expr.fn.registry.RemoteFunctionRegistry) DataChangeVersion(org.apache.drill.exec.store.sys.store.DataChangeVersion) DrillRuntimeException(org.apache.drill.common.exceptions.DrillRuntimeException) VersionMismatchException(org.apache.drill.exec.exception.VersionMismatchException)

Example 15 with VersionMismatchException

use of org.apache.drill.exec.exception.VersionMismatchException in project drill by apache.

the class TestDynamicUDFSupport method testSuccessfulRegistrationAfterSeveralRetryAttempts.

@Test
public void testSuccessfulRegistrationAfterSeveralRetryAttempts() throws Exception {
    RemoteFunctionRegistry remoteFunctionRegistry = spyRemoteFunctionRegistry();
    copyDefaultJarsToStagingArea();
    doThrow(new VersionMismatchException("Version mismatch detected", 1)).doThrow(new VersionMismatchException("Version mismatch detected", 1)).doCallRealMethod().when(remoteFunctionRegistry).updateRegistry(any(Registry.class), any(DataChangeVersion.class));
    String summary = "The following UDFs in jar %s have been registered:\n" + "[custom_lower(VARCHAR-REQUIRED)]";
    testBuilder().sqlQuery("create function using jar '%s'", default_binary_name).unOrdered().baselineColumns("ok", "summary").baselineValues(true, String.format(summary, default_binary_name)).go();
    verify(remoteFunctionRegistry, times(3)).updateRegistry(any(Registry.class), any(DataChangeVersion.class));
    FileSystem fs = remoteFunctionRegistry.getFs();
    assertFalse("Staging area should be empty", fs.listFiles(remoteFunctionRegistry.getStagingArea(), false).hasNext());
    assertFalse("Temporary area should be empty", fs.listFiles(remoteFunctionRegistry.getTmpArea(), false).hasNext());
    assertTrue("Binary should be present in registry area", fs.exists(new Path(remoteFunctionRegistry.getRegistryArea(), default_binary_name)));
    assertTrue("Source should be present in registry area", fs.exists(new Path(remoteFunctionRegistry.getRegistryArea(), default_source_name)));
    Registry registry = remoteFunctionRegistry.getRegistry(new DataChangeVersion());
    assertEquals("Registry should contain one jar", registry.getJarList().size(), 1);
    assertEquals(registry.getJar(0).getName(), default_binary_name);
}
Also used : RemoteFunctionRegistry(org.apache.drill.exec.expr.fn.registry.RemoteFunctionRegistry) Path(org.apache.hadoop.fs.Path) FileSystem(org.apache.hadoop.fs.FileSystem) LocalFunctionRegistry(org.apache.drill.exec.expr.fn.registry.LocalFunctionRegistry) FunctionImplementationRegistry(org.apache.drill.exec.expr.fn.FunctionImplementationRegistry) RemoteFunctionRegistry(org.apache.drill.exec.expr.fn.registry.RemoteFunctionRegistry) Registry(org.apache.drill.exec.proto.UserBitShared.Registry) Matchers.anyString(org.mockito.Matchers.anyString) CoreMatchers.containsString(org.hamcrest.CoreMatchers.containsString) DataChangeVersion(org.apache.drill.exec.store.sys.store.DataChangeVersion) VersionMismatchException(org.apache.drill.exec.exception.VersionMismatchException) Test(org.junit.Test)

Aggregations

VersionMismatchException (org.apache.drill.exec.exception.VersionMismatchException)23 RemoteFunctionRegistry (org.apache.drill.exec.expr.fn.registry.RemoteFunctionRegistry)16 Registry (org.apache.drill.exec.proto.UserBitShared.Registry)16 DataChangeVersion (org.apache.drill.exec.store.sys.store.DataChangeVersion)16 FunctionImplementationRegistry (org.apache.drill.exec.expr.fn.FunctionImplementationRegistry)14 LocalFunctionRegistry (org.apache.drill.exec.expr.fn.registry.LocalFunctionRegistry)12 CoreMatchers.containsString (org.hamcrest.CoreMatchers.containsString)12 Test (org.junit.Test)12 SlowTest (org.apache.drill.categories.SlowTest)8 SqlFunctionTest (org.apache.drill.categories.SqlFunctionTest)8 Matchers.anyString (org.mockito.Matchers.anyString)8 Path (java.nio.file.Path)6 DrillRuntimeException (org.apache.drill.common.exceptions.DrillRuntimeException)6 HadoopUtils.hadoopToJavaPath (org.apache.drill.test.HadoopUtils.hadoopToJavaPath)6 FileSystem (org.apache.hadoop.fs.FileSystem)6 Jar (org.apache.drill.exec.proto.UserBitShared.Jar)4 ArgumentMatchers.anyString (org.mockito.ArgumentMatchers.anyString)4 IOException (java.io.IOException)3 AutoCloseableLock (org.apache.drill.common.concurrent.AutoCloseableLock)3 Path (org.apache.hadoop.fs.Path)3