Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id D4053200B95 for ; Tue, 27 Sep 2016 18:42:51 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id D29FC160AE5; Tue, 27 Sep 2016 16:42:51 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 25C3A160AD2 for ; Tue, 27 Sep 2016 18:42:50 +0200 (CEST) Received: (qmail 96688 invoked by uid 500); 27 Sep 2016 16:42:49 -0000 Mailing-List: contact dev-help@drill.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@drill.apache.org Delivered-To: mailing list dev@drill.apache.org Received: (qmail 95874 invoked by uid 99); 27 Sep 2016 16:42:48 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 27 Sep 2016 16:42:48 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 89868E008F; Tue, 27 Sep 2016 16:42:48 +0000 (UTC) From: arina-ielchiieva To: dev@drill.apache.org Reply-To: dev@drill.apache.org References: In-Reply-To: Subject: [GitHub] drill pull request #574: DRILL-4726: Dynamic UDFs support Content-Type: text/plain Message-Id: <20160927164248.89868E008F@git1-us-west.apache.org> Date: Tue, 27 Sep 2016 16:42:48 +0000 (UTC) archived-at: Tue, 27 Sep 2016 16:42:52 -0000 Github user arina-ielchiieva commented on a diff in the pull request: https://github.com/apache/drill/pull/574#discussion_r80648171 --- Diff: exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/FunctionImplementationRegistry.java --- @@ -301,29 +323,120 @@ private ScanResult scan(ClassLoader classLoader, Path path, URL[] urls) throws I return RunTimeScan.dynamicPackageScan(drillConfig, Sets.newHashSet(urls)); } } - throw new FunctionValidationException(String.format("Marker file %s is missing in %s.", + throw new JarValidationException(String.format("Marker file %s is missing in %s", CommonConstants.DRILL_JAR_MARKER_FILE_RESOURCE_PATHNAME, path.getName())); } - private static String getUdfDir() { - return Preconditions.checkNotNull(System.getenv("DRILL_UDF_DIR"), "DRILL_UDF_DIR variable is not set"); + /** + * Return list of jars that are missing in local function registry + * but present in remote function registry. + * + * @param remoteFunctionRegistry remote function registry + * @param localFunctionRegistry local function registry + * @return list of missing jars + */ + private List getMissingJars(RemoteFunctionRegistry remoteFunctionRegistry, + LocalFunctionRegistry localFunctionRegistry) { + List remoteJars = remoteFunctionRegistry.getRegistry().getJarList(); + List localJars = localFunctionRegistry.getAllJarNames(); + List missingJars = Lists.newArrayList(); + for (Jar jar : remoteJars) { + if (!localJars.contains(jar.getName())) { + missingJars.add(jar.getName()); + } + } + return missingJars; + } + + /** + * Creates local udf directory, if it doesn't exist. + * Checks if local is a directory and if current application has write rights on it. + * Attempts to clean up local idf directory in case jars were left after previous drillbit run. + * + * @return path to local udf directory + */ + private Path getLocalUdfDir() { + String confDir = getConfDir(); + File udfDir = new File(confDir, "udf"); + String udfPath = udfDir.getPath(); + udfDir.mkdirs(); + Preconditions.checkState(udfDir.exists(), "Local udf directory [%s] must exist", udfPath); + Preconditions.checkState(udfDir.isDirectory(), "Local udf directory [%s] must be a directory", udfPath); + Preconditions.checkState(udfDir.canWrite(), "Local udf directory [%s] must be writable for application user", udfPath); + try { + FileUtils.cleanDirectory(udfDir); + } catch (IOException e) { + throw new DrillRuntimeException("Error during local udf directory clean up", e); + } + return new Path(udfDir.toURI()); + } + + /** + * First tries to get drill conf directory value from system properties, + * if value is missing, checks environment properties. + * Throws exception is value is null. + * @return drill conf dir path + */ + private String getConfDir() { + String drillConfDir = "DRILL_CONF_DIR"; + String value = System.getProperty(drillConfDir); + if (value == null) { + value = Preconditions.checkNotNull(System.getenv(drillConfDir), "%s variable is not set", drillConfDir); + } + return value; + } + + /** + * Copies jar from remote udf area to local udf area with numeric suffix, + * in order to achieve uniqueness for each locally copied jar. + * Ex: DrillUDF-1.0.jar -> DrillUDF-1.0_12200255588.jar + * + * @param jarName jar name to be copied + * @param remoteFunctionRegistry remote function registry + * @return local path to jar that was copied + * @throws IOException in case of problems during jar coping process + */ + private Path copyJarToLocal(String jarName, RemoteFunctionRegistry remoteFunctionRegistry) throws IOException { + String generatedName = String.format(generated_jar_name_pattern, + Files.getNameWithoutExtension(jarName), System.nanoTime(), Files.getFileExtension(jarName)); + Path registryArea = remoteFunctionRegistry.getRegistryArea(); + FileSystem fs = remoteFunctionRegistry.getFs(); + Path remoteJar = new Path(registryArea, jarName); + Path localJar = new Path(localUdfDir, generatedName); + try { + fs.copyToLocalFile(remoteJar, localJar); + } catch (IOException e) { + String message = String.format("Error during jar [%s] coping from [%s] to [%s]", + jarName, registryArea.toUri().getPath(), localUdfDir.toUri().getPath()); + throw new IOException(message, e); + } + return localJar; } /** * Fires when jar name is submitted for unregistration. * Will unregister all functions associated with the jar name - * and delete binary and source associated with the jar from local DRILL_UDF_DIR. + * and delete binary and source associated with the jar from local udf directory + * according to pattern jar name + {@link #jar_suffix_pattern}. --- End diff -- As noted in design doc and in previous discussions, we do not ensure that query will execute even if UDF gets deletes. It's a limitation of unregistration process. Currently Drill doesn't have mechanisms to ensure such behavior. --- If your project is set up for it, you can reply to this email and have your reply appear on GitHub as well. If your project does not have this feature enabled and wishes so, or if the feature is enabled but not working, please contact infrastructure at infrastructure@apache.org or file a JIRA ticket with INFRA. ---