diff --git a/Util/src/main/java/io/deephaven/util/NoExecutionContextRegisteredException.java b/Util/src/main/java/io/deephaven/util/NoExecutionContextRegisteredException.java index 1045ccf3408..347305a0693 100644 --- a/Util/src/main/java/io/deephaven/util/NoExecutionContextRegisteredException.java +++ b/Util/src/main/java/io/deephaven/util/NoExecutionContextRegisteredException.java @@ -3,8 +3,8 @@ import io.deephaven.UncheckedDeephavenException; /** - * This exception is thrown when the thread-local QueryScope, QueryLibrary, or CompilerTools.Context are accessed from - * user-code without an explicit ExecutionContext. + * This exception is thrown when the thread-local QueryScope, QueryLibrary, or QueryCompiler are accessed from user-code + * without an explicit ExecutionContext. */ public final class NoExecutionContextRegisteredException extends UncheckedDeephavenException { public NoExecutionContextRegisteredException() { diff --git a/engine/api/src/main/java/io/deephaven/engine/table/PartitionedTable.java b/engine/api/src/main/java/io/deephaven/engine/table/PartitionedTable.java index 448e7ff6188..2d1f2838d33 100644 --- a/engine/api/src/main/java/io/deephaven/engine/table/PartitionedTable.java +++ b/engine/api/src/main/java/io/deephaven/engine/table/PartitionedTable.java @@ -203,7 +203,7 @@ default Proxy proxy() { * * @apiNote {@code transformer} must be stateless, safe for concurrent use, and able to return a valid result for an * empty input table. It is required to install an ExecutionContext to access any - * QueryLibrary/QueryScope/CompilerContext functionality from the {@code transformer}. + * QueryLibrary/QueryScope/QueryCompiler functionality from the {@code transformer}. * * @param transformer The {@link UnaryOperator} to apply to all constituent {@link Table tables} * @return The new PartitionedTable containing the resulting constituents @@ -245,7 +245,7 @@ default PartitionedTable transform(@NotNull UnaryOperator transformer) { * * @apiNote {@code transformer} must be stateless, safe for concurrent use, and able to return a valid result for * empty input tables. It is required to install an ExecutionContext to access any - * QueryLibrary/QueryScope/CompilerContext functionality from the {@code transformer}. + * QueryLibrary/QueryScope/QueryCompiler functionality from the {@code transformer}. * * @param other The other PartitionedTable to find constituents in * @param transformer The {@link BinaryOperator} to apply to all pairs of constituent {@link Table tables} @@ -275,7 +275,7 @@ default PartitionedTable partitionedTransform( * *

* {@code transformer} must be stateless, safe for concurrent use, and able to return a valid result for empty input - * tables. It is required to install an ExecutionContext to access any QueryLibrary/QueryScope/CompilerContext + * tables. It is required to install an ExecutionContext to access any QueryLibrary/QueryScope/QueryCompiler * functionality from the {@code transformer}. * * @param other The other PartitionedTable to find constituents in diff --git a/engine/context/build.gradle b/engine/context/build.gradle index d6716f5eec2..11e6288abe8 100644 --- a/engine/context/build.gradle +++ b/engine/context/build.gradle @@ -3,7 +3,7 @@ plugins { id 'io.deephaven.project.register' } -description 'Engine Context: QueryScope, QueryLibrary and CompilerTools via ExecutionContext' +description 'Engine Context: QueryScope, QueryLibrary and QueryCompiler via ExecutionContext' configurations { testCompile.extendsFrom junit diff --git a/engine/context/src/main/java/io/deephaven/engine/context/ExecutionContext.java b/engine/context/src/main/java/io/deephaven/engine/context/ExecutionContext.java index 21157401555..3b7a8e2b2f6 100644 --- a/engine/context/src/main/java/io/deephaven/engine/context/ExecutionContext.java +++ b/engine/context/src/main/java/io/deephaven/engine/context/ExecutionContext.java @@ -26,7 +26,7 @@ public static ExecutionContext makeSystemicExecutionContext() { return ExecutionContext.newBuilder() .captureQueryScope() .captureQueryLibrary() - .captureCompilerContext() + .captureQueryCompiler() .markSystemic() .build(); } @@ -37,7 +37,7 @@ public static ExecutionContext createForUnitTests() { .markSystemic() .newQueryScope() .newQueryLibrary() - .setCompilerContext(CompilerTools.createContextForUnitTests()) + .setQueryCompiler(QueryCompiler.createForUnitTests()) .build(); } @@ -96,17 +96,17 @@ static void setContext(final ExecutionContext context) { private final QueryLibrary queryLibrary; private final QueryScope queryScope; - private final CompilerTools.Context compilerContext; + private final QueryCompiler queryCompiler; private ExecutionContext( final boolean isSystemic, final QueryLibrary queryLibrary, final QueryScope queryScope, - final CompilerTools.Context compilerContext) { + final QueryCompiler queryCompiler) { this.isSystemic = isSystemic; this.queryLibrary = queryLibrary; this.queryScope = queryScope; - this.compilerContext = compilerContext; + this.queryCompiler = queryCompiler; } /** @@ -154,8 +154,8 @@ public QueryScope getQueryScope() { return queryScope; } - public CompilerTools.Context getCompilerContext() { - return compilerContext; + public QueryCompiler getQueryCompiler() { + return queryCompiler; } @SuppressWarnings("unused") @@ -164,7 +164,7 @@ public static class Builder { private QueryLibrary queryLibrary = PoisonedQueryLibrary.INSTANCE; private QueryScope queryScope = PoisonedQueryScope.INSTANCE; - private CompilerTools.Context compilerContext = PoisonedCompilerToolsContext.INSTANCE; + private QueryCompiler queryCompiler = PoisonedQueryCompiler.INSTANCE; /** * A systemic execution context is one that is supplied by the system and not the user. A systemic context will @@ -213,20 +213,20 @@ public Builder captureQueryLibrary() { } /** - * Use the provided CompilerTools.Context. + * Use the provided QueryCompiler */ @ScriptApi - public Builder setCompilerContext(final CompilerTools.Context compilerContext) { - this.compilerContext = compilerContext; + public Builder setQueryCompiler(final QueryCompiler queryCompiler) { + this.queryCompiler = queryCompiler; return this; } /** - * Use the current ExecutionContext's CompilerTools.Context instance. + * Use the current ExecutionContext's QueryCompiler instance. */ @ScriptApi - public Builder captureCompilerContext() { - compilerContext = currentContext.get().getCompilerContext(); + public Builder captureQueryCompiler() { + queryCompiler = currentContext.get().getQueryCompiler(); return this; } @@ -297,7 +297,7 @@ public Builder captureQueryScopeVars(String... vars) { */ @ScriptApi public ExecutionContext build() { - return new ExecutionContext(isSystemic, queryLibrary, queryScope, compilerContext); + return new ExecutionContext(isSystemic, queryLibrary, queryScope, queryCompiler); } } } diff --git a/engine/context/src/main/java/io/deephaven/engine/context/PoisonedCompilerToolsContext.java b/engine/context/src/main/java/io/deephaven/engine/context/PoisonedQueryCompiler.java similarity index 52% rename from engine/context/src/main/java/io/deephaven/engine/context/PoisonedCompilerToolsContext.java rename to engine/context/src/main/java/io/deephaven/engine/context/PoisonedQueryCompiler.java index fb3c094bf63..e12653801b7 100644 --- a/engine/context/src/main/java/io/deephaven/engine/context/PoisonedCompilerToolsContext.java +++ b/engine/context/src/main/java/io/deephaven/engine/context/PoisonedQueryCompiler.java @@ -6,49 +6,36 @@ import io.deephaven.internal.log.LoggerFactory; import io.deephaven.io.logger.Logger; import io.deephaven.util.NoExecutionContextRegisteredException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.io.File; import java.util.Map; -import java.util.concurrent.CompletableFuture; -public class PoisonedCompilerToolsContext implements CompilerTools.Context { - private static final Logger logger = LoggerFactory.getLogger(PoisonedCompilerToolsContext.class); - public static final PoisonedCompilerToolsContext INSTANCE = new PoisonedCompilerToolsContext(); +public class PoisonedQueryCompiler extends QueryCompiler { + private static final Logger logger = LoggerFactory.getLogger(PoisonedQueryCompiler.class); + public static final PoisonedQueryCompiler INSTANCE = new PoisonedQueryCompiler(); - private PoisonedCompilerToolsContext() {} + private PoisonedQueryCompiler() {} private T fail() { - logger.error().append("No ExecutionContext provided; cannot use CompilerTools").endl(); + logger.error().append("No ExecutionContext provided; cannot use QueryCompiler").endl(); throw new NoExecutionContextRegisteredException(); } @Override - public Map>> getKnownClasses() { - return fail(); - } - - @Override - public ClassLoader getClassLoaderForFormula(Map> parameterClasses) { - return fail(); - } - - @Override - public File getClassDestination() { + public File getFakeClassDestination() { return fail(); } @Override - public String getClassPath() { - return fail(); + public void setParentClassLoader(ClassLoader parentClassLoader) { + fail(); } @Override - public File getFakeClassDestination() { + public Class compile(@NotNull String className, @NotNull String classBody, @NotNull String packageNameRoot, + @Nullable StringBuilder codeLog, @NotNull Map> parameterClasses) { return fail(); } - - @Override - public void setParentClassLoader(ClassLoader parentClassLoader) { - fail(); - } } diff --git a/engine/context/src/main/java/io/deephaven/engine/context/CompilerTools.java b/engine/context/src/main/java/io/deephaven/engine/context/QueryCompiler.java similarity index 71% rename from engine/context/src/main/java/io/deephaven/engine/context/CompilerTools.java rename to engine/context/src/main/java/io/deephaven/engine/context/QueryCompiler.java index 919dacc8588..afd8375dca1 100644 --- a/engine/context/src/main/java/io/deephaven/engine/context/CompilerTools.java +++ b/engine/context/src/main/java/io/deephaven/engine/context/QueryCompiler.java @@ -41,8 +41,8 @@ import static java.security.AccessController.doPrivileged; -public class CompilerTools { - private static final Logger log = LoggerFactory.getLogger(CompilerTools.class); +public class QueryCompiler { + private static final Logger log = LoggerFactory.getLogger(QueryCompiler.class); /** * We pick a number just shy of 65536, leaving a little elbow room for good luck. */ @@ -53,15 +53,78 @@ public class CompilerTools { private static final String IDENTIFYING_FIELD_NAME = "_CLASS_BODY_"; - private static final String CODEGEN_TIMEOUT_PROP = "CompilerTools.codegen.timeoutMs"; + private static final String CODEGEN_TIMEOUT_PROP = "QueryCompiler.codegen.timeoutMs"; private static final long CODEGEN_TIMEOUT_MS_DEFAULT = TimeUnit.SECONDS.toMillis(10); // 10 seconds - private static final String CODEGEN_LOOP_DELAY_PROP = "CompilerTools.codegen.retry.delay"; + private static final String CODEGEN_LOOP_DELAY_PROP = "QueryCompiler.codegen.retry.delay"; private static final long CODEGEN_LOOP_DELAY_MS_DEFAULT = 100; private static final long codegenTimeoutMs = Configuration.getInstance().getLongWithDefault(CODEGEN_TIMEOUT_PROP, CODEGEN_TIMEOUT_MS_DEFAULT); private static final long codegenLoopDelayMs = Configuration.getInstance().getLongWithDefault(CODEGEN_LOOP_DELAY_PROP, CODEGEN_LOOP_DELAY_MS_DEFAULT); + private static boolean logEnabled = Configuration.getInstance().getBoolean("QueryCompiler.logEnabledDefault"); + + public static final String FORMULA_PREFIX = "io.deephaven.temp"; + public static final String DYNAMIC_GROOVY_CLASS_PREFIX = "io.deephaven.dynamic"; + + public static QueryCompiler create(File cacheDirectory, ClassLoader classLoader) { + return new QueryCompiler(cacheDirectory, classLoader, true); + } + + static QueryCompiler createForUnitTests() { + return new QueryCompiler(new File(Configuration.getInstance().getWorkspacePath() + + File.separator + "cache" + File.separator + "classes")); + } + + private final Map>> knownClasses = new HashMap<>(); + + private final String[] dynamicPatterns = new String[] {DYNAMIC_GROOVY_CLASS_PREFIX, FORMULA_PREFIX}; + + private final File classDestination; + private final boolean isCacheDirectory; + private final Set additionalClassLocations; + private volatile WritableURLClassLoader ucl; + + /** package-private constructor for {@link io.deephaven.engine.context.PoisonedQueryCompiler} */ + QueryCompiler() { + classDestination = null; + isCacheDirectory = false; + additionalClassLocations = null; + } + + private QueryCompiler(File classDestination) { + this(classDestination, null, false); + } + + private QueryCompiler( + final File classDestination, + final ClassLoader parentClassLoader, + final boolean isCacheDirectory) { + final ClassLoader parentClassLoaderToUse = parentClassLoader == null + ? QueryCompiler.class.getClassLoader() + : parentClassLoader; + this.classDestination = classDestination; + this.isCacheDirectory = isCacheDirectory; + ensureDirectories(this.classDestination, () -> "Failed to create missing class destination directory " + + classDestination.getAbsolutePath()); + additionalClassLocations = new LinkedHashSet<>(); + + URL[] urls = new URL[1]; + try { + urls[0] = (classDestination.toURI().toURL()); + } catch (MalformedURLException e) { + throw new RuntimeException("", e); + } + // We should be able to create this class loader, even if this is invoked from external code + // that does not have sufficient security permissions. + this.ucl = doPrivileged((PrivilegedAction) () -> new WritableURLClassLoader(urls, + parentClassLoaderToUse)); + + if (isCacheDirectory) { + addClassSource(classDestination); + } + } + /** * Enables or disables compilation logging. * @@ -69,8 +132,8 @@ public class CompilerTools { * @return The value of {@code logEnabled} before calling this method. */ public static boolean setLogEnabled(boolean logEnabled) { - boolean original = CompilerTools.logEnabled; - CompilerTools.logEnabled = logEnabled; + boolean original = QueryCompiler.logEnabled; + QueryCompiler.logEnabled = logEnabled; return original; } @@ -84,18 +147,6 @@ public static void writeClass(final File destinationDirectory, final String clas writeClass(destinationDirectory, className, data, null); } - private static void ensureDirectories(final File file, final Supplier runtimeErrMsg) { - // File.mkdirs() checks for existrance on entry, in which case it returns false. - // It may also return false on a failure to create. - // Also note, two separate threads or JVMs may be running this code in parallel. It's possible that we could - // lose the race - // (and therefore mkdirs() would return false), but still get the directory we need (and therefore exists() - // would return true) - if (!file.mkdirs() && !file.isDirectory()) { - throw new RuntimeException(runtimeErrMsg.get()); - } - } - /* * NB: This is (obviously) not thread safe if code tries to write the same className to the same * destinationDirectory from multiple threads. Seeing as we don't currently have this use case, leaving @@ -144,327 +195,257 @@ public static void writeClass(final File destinationDirectory, final String clas fileOutStream.close(); } - public static final String FORMULA_PREFIX = "io.deephaven.temp"; - public static final String DYNAMIC_GROOVY_CLASS_PREFIX = "io.deephaven.dynamic"; - - public interface Context { - Map>> getKnownClasses(); - - ClassLoader getClassLoaderForFormula(Map> parameterClasses); - - File getClassDestination(); - - File getFakeClassDestination(); - - String getClassPath(); + public File getFakeClassDestination() { + // Groovy classes need to be written out to a location where they can be found by the compiler + // (so that filters and formulae can use them). + // + // We don't want the regular runtime class loader to find them, because then they get "stuck" in there + // even if the class itself changes, and we can't forget it. So instead we use a single-use class loader + // for each formula, that will always read the class from disk. + return isCacheDirectory ? classDestination : null; + } - void setParentClassLoader(ClassLoader parentClassLoader); + public void setParentClassLoader(final ClassLoader parentClassLoader) { + // The system should always be able to create this class loader, even if invoked from something that + // doesn't have the right security permissions for it. + ucl = doPrivileged( + (PrivilegedAction) () -> new WritableURLClassLoader(ucl.getURLs(), + parentClassLoader)); } - public static Context newContext(File cacheDirectory, ClassLoader classLoader) { - return new CompilerTools.ContextImpl(cacheDirectory, classLoader, true); + public final Class compile(String className, String classBody, String packageNameRoot) { + return compile(className, classBody, packageNameRoot, null, Collections.emptyMap()); } - private static class ContextImpl implements Context { - private final Map>> knownClasses = new HashMap<>(); + public final Class compile(String className, String classBody, String packageNameRoot, + Map> parameterClasses) { + return compile(className, classBody, packageNameRoot, null, parameterClasses); + } - String[] dynamicPatterns = new String[] {DYNAMIC_GROOVY_CLASS_PREFIX, FORMULA_PREFIX}; + public final Class compile(String className, String classBody, String packageNameRoot, StringBuilder codeLog) { + return compile(className, classBody, packageNameRoot, codeLog, Collections.emptyMap()); + } - private final File classDestination; - private final boolean isCacheDirectory; - private final Set additionalClassLocations; - private volatile WritableURLClassLoader ucl; + /** + * Compile a class. + * + * @param className Class name + * @param classBody Class body, before update with "$CLASS_NAME$" replacement and package name prefixing + * @param packageNameRoot Package name prefix + * @param codeLog Optional "log" for final class code + * @param parameterClasses Generic parameters, empty if none required + * @return The compiled class + */ + public Class compile(@NotNull final String className, + @NotNull final String classBody, + @NotNull final String packageNameRoot, + @Nullable final StringBuilder codeLog, + @NotNull final Map> parameterClasses) { + CompletableFuture> promise; + final boolean promiseAlreadyMade; - private ContextImpl(File classDestination) { - this(classDestination, Context.class.getClassLoader(), false); + synchronized (this) { + promise = knownClasses.get(classBody); + if (promise != null) { + promiseAlreadyMade = true; + } else { + promise = new CompletableFuture<>(); + knownClasses.put(classBody, promise); + promiseAlreadyMade = false; + } } - private ContextImpl(File classDestination, ClassLoader parentClassLoader, boolean isCacheDirectory) { - this.classDestination = classDestination; - this.isCacheDirectory = isCacheDirectory; - ensureDirectories(this.classDestination, () -> "Failed to create missing class destination directory " + - classDestination.getAbsolutePath()); - additionalClassLocations = new LinkedHashSet<>(); - - URL[] urls = new URL[1]; + // Someone else has already made the promise. I'll just wait for the answer. + if (promiseAlreadyMade) { try { - urls[0] = (classDestination.toURI().toURL()); - } catch (MalformedURLException e) { - throw new RuntimeException("", e); - } - // We should be able to create this class loader, even if this is invoked from external code - // that does not have sufficient security permissions. - this.ucl = doPrivileged((PrivilegedAction) () -> new WritableURLClassLoader(urls, - parentClassLoader)); - - if (isCacheDirectory) { - addClassSource(classDestination); + return promise.get(); + } catch (InterruptedException | ExecutionException error) { + throw new UncheckedDeephavenException(error); } } - @Override - public Map>> getKnownClasses() { - return knownClasses; + // It's my job to fulfill the promise + try { + return compileHelper(className, classBody, packageNameRoot, codeLog, parameterClasses); + } catch (RuntimeException e) { + promise.completeExceptionally(e); + throw e; } + } - @Override - public ClassLoader getClassLoaderForFormula(final Map> parameterClasses) { - // We should always be able to get our own class loader, even if this is invoked from external code - // that doesn't have security permissions to make ITS own class loader. - return doPrivileged((PrivilegedAction) () -> new URLClassLoader(ucl.getURLs(), ucl) { - // Once we find a class that is missing, we should not attempt to load it again, - // otherwise we can end up with a StackOverflow Exception - final HashSet missingClasses = new HashSet<>(); - - @Override - protected Class findClass(String name) throws ClassNotFoundException { - // If we have a parameter that uses this class, return it - final Class paramClass = parameterClasses.get(name); - if (paramClass != null) { - return paramClass; - } - - // Unless we are looking for a formula or Groovy class, we should use the default behavior - if (!isFormulaClass(name)) { - return super.findClass(name); - } - - // if it is a groovy class, always try to use the instance in the shell - if (name.startsWith(DYNAMIC_GROOVY_CLASS_PREFIX)) { - try { - return ucl.getParent().loadClass(name); - } catch (final ClassNotFoundException ignored) { - // we'll try to load it otherwise - } - } + private static void ensureDirectories(final File file, final Supplier runtimeErrMsg) { + // File.mkdirs() checks for existence on entry, in which case it returns false. + // It may also return false on a failure to create. + // Also note, two separate threads or JVMs may be running this code in parallel. It's possible that we could + // lose the race + // (and therefore mkdirs() would return false), but still get the directory we need (and therefore exists() + // would return true) + if (!file.mkdirs() && !file.isDirectory()) { + throw new RuntimeException(runtimeErrMsg.get()); + } + } - // We've already not found this class, so we should not try to search again - if (missingClasses.contains(name)) { - return super.findClass(name); - } + private ClassLoader getClassLoaderForFormula(final Map> parameterClasses) { + // We should always be able to get our own class loader, even if this is invoked from external code + // that doesn't have security permissions to make ITS own class loader. + return doPrivileged((PrivilegedAction) () -> new URLClassLoader(ucl.getURLs(), ucl) { + // Once we find a class that is missing, we should not attempt to load it again, + // otherwise we can end up with a StackOverflow Exception + final HashSet missingClasses = new HashSet<>(); - final byte[] bytes; - try { - bytes = loadClassData(name); - } catch (IOException ioe) { - missingClasses.add(name); - return super.loadClass(name); - } - return defineClass(name, bytes, 0, bytes.length); + @Override + protected Class findClass(String name) throws ClassNotFoundException { + // If we have a parameter that uses this class, return it + final Class paramClass = parameterClasses.get(name); + if (paramClass != null) { + return paramClass; } - @SuppressWarnings("BooleanMethodIsAlwaysInverted") - private boolean isFormulaClass(String name) { - return Arrays.stream(dynamicPatterns).anyMatch(name::startsWith); + // Unless we are looking for a formula or Groovy class, we should use the default behavior + if (!isFormulaClass(name)) { + return super.findClass(name); } - @Override - public Class loadClass(String name) throws ClassNotFoundException { - if (!isFormulaClass(name)) { - return super.loadClass(name); + // if it is a groovy class, always try to use the instance in the shell + if (name.startsWith(DYNAMIC_GROOVY_CLASS_PREFIX)) { + try { + return ucl.getParent().loadClass(name); + } catch (final ClassNotFoundException ignored) { + // we'll try to load it otherwise } - return findClass(name); } - private byte[] loadClassData(String name) throws IOException { - try { - // The compiler should always have access to the class-loader directories, - // even if code that invokes this does not. - return doPrivileged((PrivilegedExceptionAction) () -> { - final File destFile = new File(classDestination, - name.replace('.', File.separatorChar) + JavaFileObject.Kind.CLASS.extension); - if (destFile.exists()) { - return Files.readAllBytes(destFile.toPath()); - } - - for (File location : additionalClassLocations) { - final File checkFile = new File(location, - name.replace('.', File.separatorChar) + JavaFileObject.Kind.CLASS.extension); - if (checkFile.exists()) { - return Files.readAllBytes(checkFile.toPath()); - } - } + // We've already not found this class, so we should not try to search again + if (missingClasses.contains(name)) { + return super.findClass(name); + } - throw new FileNotFoundException(name); - }); - } catch (final PrivilegedActionException pae) { - final Exception inner = pae.getException(); - if (inner instanceof IOException) { - throw (IOException) inner; - } else { - throw new RuntimeException(inner); - } - } + final byte[] bytes; + try { + bytes = loadClassData(name); + } catch (IOException ioe) { + missingClasses.add(name); + return super.loadClass(name); } - }); - } + return defineClass(name, bytes, 0, bytes.length); + } - private static class WritableURLClassLoader extends URLClassLoader { - private WritableURLClassLoader(URL[] urls, ClassLoader parent) { - super(urls, parent); + @SuppressWarnings("BooleanMethodIsAlwaysInverted") + private boolean isFormulaClass(String name) { + return Arrays.stream(dynamicPatterns).anyMatch(name::startsWith); } @Override - protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException { - Class clazz = findLoadedClass(name); - if (clazz != null) { - return clazz; + public Class loadClass(String name) throws ClassNotFoundException { + if (!isFormulaClass(name)) { + return super.loadClass(name); } + return findClass(name); + } + private byte[] loadClassData(String name) throws IOException { try { - clazz = findClass(name); - } catch (ClassNotFoundException e) { - clazz = getParent().loadClass(name); - } + // The compiler should always have access to the class-loader directories, + // even if code that invokes this does not. + return doPrivileged((PrivilegedExceptionAction) () -> { + final File destFile = new File(classDestination, + name.replace('.', File.separatorChar) + JavaFileObject.Kind.CLASS.extension); + if (destFile.exists()) { + return Files.readAllBytes(destFile.toPath()); + } - if (resolve) { - resolveClass(clazz); + for (File location : additionalClassLocations) { + final File checkFile = new File(location, + name.replace('.', File.separatorChar) + JavaFileObject.Kind.CLASS.extension); + if (checkFile.exists()) { + return Files.readAllBytes(checkFile.toPath()); + } + } + + throw new FileNotFoundException(name); + }); + } catch (final PrivilegedActionException pae) { + final Exception inner = pae.getException(); + if (inner instanceof IOException) { + throw (IOException) inner; + } else { + throw new RuntimeException(inner); + } } - return clazz; } + }); + } - @Override - public synchronized void addURL(URL url) { - super.addURL(url); - } + private static class WritableURLClassLoader extends URLClassLoader { + private WritableURLClassLoader(URL[] urls, ClassLoader parent) { + super(urls, parent); } - protected void addClassSource(File classSourceDirectory) { - synchronized (additionalClassLocations) { - if (additionalClassLocations.contains(classSourceDirectory)) { - return; - } - additionalClassLocations.add(classSourceDirectory); + @Override + protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + Class clazz = findLoadedClass(name); + if (clazz != null) { + return clazz; } + try { - ucl.addURL(classSourceDirectory.toURI().toURL()); - } catch (MalformedURLException e) { - throw new RuntimeException("", e); + clazz = findClass(name); + } catch (ClassNotFoundException e) { + if (getParent() != null) { + clazz = getParent().loadClass(name); + } } - } - public File getFakeClassDestination() { - // Groovy classes need to be written out to a location where they can be found by the compiler - // (so that filters and formulae can use them). - // - // We don't want the regular runtime class loader to find them, because then they get "stuck" in there - // even if the class itself changes, and we can't forget it. So instead we use a single-use class loader - // for each formula, that will always read the class from disk. - return isCacheDirectory ? classDestination : null; + if (resolve) { + resolveClass(clazz); + } + return clazz; } @Override - public File getClassDestination() { - return classDestination; + public synchronized void addURL(URL url) { + super.addURL(url); } + } - public String getClassPath() { - StringBuilder sb = new StringBuilder(); - sb.append(classDestination.getAbsolutePath()); - synchronized (additionalClassLocations) { - for (File classLoc : additionalClassLocations) { - sb.append(File.pathSeparatorChar).append(classLoc.getAbsolutePath()); - } + private void addClassSource(File classSourceDirectory) { + synchronized (additionalClassLocations) { + if (additionalClassLocations.contains(classSourceDirectory)) { + return; } - return sb.toString(); - } - - public WritableURLClassLoader getClassLoader() { - return ucl; - } - - public void setParentClassLoader(final ClassLoader parentClassLoader) { - // The system should always be able to create this class loader, even if invoked from something that - // doesn't have the right security permissions for it. - ucl = doPrivileged( - (PrivilegedAction) () -> new WritableURLClassLoader(ucl.getURLs(), - parentClassLoader)); + additionalClassLocations.add(classSourceDirectory); } - - public void cleanup() { - FileUtils.deleteRecursively(classDestination); + try { + ucl.addURL(classSourceDirectory.toURI().toURL()); + } catch (MalformedURLException e) { + throw new RuntimeException("", e); } } - static Context createContextForUnitTests() { - return new ContextImpl(new File(Configuration.getInstance().getWorkspacePath() + - File.separator + "cache" + File.separator + "classes")); - } - - public static Context getContext() { - return ExecutionContext.getContext().getCompilerContext(); - } - - private static boolean logEnabled = Configuration.getInstance().getBoolean("CompilerTools.logEnabledDefault"); - - public static Class compile(String className, String classBody, String packageNameRoot) { - return compile(className, classBody, packageNameRoot, null, Collections.emptyMap()); - } - - public static Class compile(String className, String classBody, String packageNameRoot, - Map> parameterClasses) { - return compile(className, classBody, packageNameRoot, null, parameterClasses); + private File getClassDestination() { + return classDestination; } - public static Class compile(String className, String classBody, String packageNameRoot, StringBuilder codeLog) { - return compile(className, classBody, packageNameRoot, codeLog, Collections.emptyMap()); - } - - /** - * Compile a class. - * - * @param className Class name - * @param classBody Class body, before update with "$CLASS_NAME$" replacement and package name prefixing - * @param packageNameRoot Package name prefix - * @param codeLog Optional "log" for final class code - * @param parameterClasses Generic parameters, empty if none required - * @return The compiled class - */ - public static Class compile(@NotNull final String className, - @NotNull final String classBody, - @NotNull final String packageNameRoot, - @Nullable final StringBuilder codeLog, - @NotNull final Map> parameterClasses) { - CompletableFuture> promise; - final boolean promiseAlreadyMade; - - final Context context = getContext(); - - synchronized (context) { - promise = context.getKnownClasses().get(classBody); - if (promise != null) { - promiseAlreadyMade = true; - } else { - promise = new CompletableFuture<>(); - context.getKnownClasses().put(classBody, promise); - promiseAlreadyMade = false; - } - } - - // Someone else has already made the promise. I'll just wait for the answer. - if (promiseAlreadyMade) { - try { - return promise.get(); - } catch (InterruptedException | ExecutionException error) { - throw new UncheckedDeephavenException(error); + private String getClassPath() { + StringBuilder sb = new StringBuilder(); + sb.append(classDestination.getAbsolutePath()); + synchronized (additionalClassLocations) { + for (File classLoc : additionalClassLocations) { + sb.append(File.pathSeparatorChar).append(classLoc.getAbsolutePath()); } } + return sb.toString(); + } - // It's my job to fulfill the promise - try { - return compileHelper(className, classBody, packageNameRoot, codeLog, parameterClasses, context); - } catch (RuntimeException e) { - promise.completeExceptionally(e); - throw e; - } + private WritableURLClassLoader getClassLoader() { + return ucl; } - private static Class compileHelper(@NotNull final String className, + private Class compileHelper(@NotNull final String className, @NotNull final String classBody, @NotNull final String packageNameRoot, @Nullable final StringBuilder codeLog, - @NotNull final Map> parameterClasses, - @NotNull final Context context) { + @NotNull final Map> parameterClasses) { // NB: We include class name hash in order to (hopefully) account for case insensitive file systems. final int classNameHash = className.hashCode(); final int classBodyHash = classBody.hashCode(); @@ -518,13 +499,13 @@ private static Class compileHelper(@NotNull final String className, // We have a class. It either contains the formula we are looking for (cases 2, A, and B) or a different // formula with the same name (cases 3 and C). In either case, we should store the result in our cache, // either fulfilling an existing promise or making a new, fulfilled promise. - synchronized (context) { + synchronized (this) { // Note we are doing something kind of subtle here. We are removing an entry whose key was matched by // value equality and replacing it with a value-equal but reference-different string that is a static // member of the class we just loaded. This should be easier on the garbage collector because we are // replacing a calculated value with a classloaded value and so in effect we are "canonicalizing" the // string. This is important because these long strings stay in knownClasses forever. - CompletableFuture> p = context.getKnownClasses().remove(identifyingFieldValue); + CompletableFuture> p = knownClasses.remove(identifyingFieldValue); if (p == null) { // If we encountered a different class than the one we're looking for, make a fresh promise and // immediately fulfill it. This is for the purpose of populating the cache in case someone comes @@ -532,7 +513,7 @@ private static Class compileHelper(@NotNull final String className, // throwing it away now, even though this is not the class we're looking for. p = new CompletableFuture<>(); } - context.getKnownClasses().put(identifyingFieldValue, p); + knownClasses.put(identifyingFieldValue, p); // It's also possible that some other code has already fulfilled this promise with exactly the same // class. That's ok though: the promise code does not reject multiple sets to the identical value. p.complete(result); @@ -554,9 +535,9 @@ private static Class compileHelper(@NotNull final String className, + ", class body hash=" + classBodyHash + " - contact Deephaven support!"); } - private static Class tryLoadClassByFqName(String fqClassName, Map> parameterClasses) { + private Class tryLoadClassByFqName(String fqClassName, Map> parameterClasses) { try { - return getContext().getClassLoaderForFormula(parameterClasses).loadClass(fqClassName); + return getClassLoaderForFormula(parameterClasses).loadClass(fqClassName); } catch (ClassNotFoundException cnfe) { return null; } @@ -641,7 +622,7 @@ private static int calcBytesConsumed(final char ch) { return 3; } - static class JavaSourceFromString extends SimpleJavaFileObject { + private static class JavaSourceFromString extends SimpleJavaFileObject { final String code; JavaSourceFromString(String name, String code) { @@ -654,11 +635,11 @@ public CharSequence getCharContent(boolean ignoreEncodingErrors) { } } - static class JavaSourceFromFile extends SimpleJavaFileObject { + private static class JavaSourceFromFile extends SimpleJavaFileObject { private static final int JAVA_LENGTH = Kind.SOURCE.extension.length(); final String code; - JavaSourceFromFile(File basePath, File file) { + private JavaSourceFromFile(File basePath, File file) { super(URI.create("string:///" + createName(basePath, file).replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE); try { @@ -682,12 +663,13 @@ private static String createName(File basePath, File file) { } } + @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) { return code; } } - private static void maybeCreateClass(String className, String code, String packageName, String fqClassName) { + private void maybeCreateClass(String className, String code, String packageName, String fqClassName) { final String finalCode = makeFinalCode(className, code, packageName); // The 'compile' action does a bunch of things that need security permissions; this always needs to run @@ -696,8 +678,7 @@ private static void maybeCreateClass(String className, String code, String packa log.info().append("Generating code ").append(finalCode).endl(); } - final Context ctx = getContext(); - final File ctxClassDestination = ctx.getClassDestination(); + final File ctxClassDestination = getClassDestination(); final String[] splitPackageName = packageName.split("\\."); if (splitPackageName.length == 0) { @@ -735,7 +716,7 @@ private static void maybeCreateClass(String className, String code, String packa } try { - maybeCreateClassHelper(fqClassName, finalCode, splitPackageName, ctx, rootPathAsString, tempDirAsString); + maybeCreateClassHelper(fqClassName, finalCode, splitPackageName, rootPathAsString, tempDirAsString); } finally { AccessController.doPrivileged((PrivilegedAction) () -> { try { @@ -748,8 +729,8 @@ private static void maybeCreateClass(String className, String code, String packa } } - private static void maybeCreateClassHelper(String fqClassName, String finalCode, String[] splitPackageName, - Context ctx, String rootPathAsString, String tempDirAsString) { + private void maybeCreateClassHelper(String fqClassName, String finalCode, String[] splitPackageName, + String rootPathAsString, String tempDirAsString) { final StringWriter compilerOutput = new StringWriter(); final JavaCompiler compiler = @@ -758,7 +739,7 @@ private static void maybeCreateClassHelper(String fqClassName, String finalCode, throw new RuntimeException("No Java compiler provided - are you using a JRE instead of a JDK?"); } - final String classPathAsString = ctx.getClassPath() + File.pathSeparator + getJavaClassPath(); + final String classPathAsString = getClassPath() + File.pathSeparator + getJavaClassPath(); final List compilerOptions = AccessController.doPrivileged( (PrivilegedAction>) () -> Arrays.asList("-d", tempDirAsString, "-cp", classPathAsString)); @@ -772,14 +753,13 @@ private static void maybeCreateClassHelper(String fqClassName, String finalCode, Collections.singletonList(new JavaSourceFromString(fqClassName, finalCode))) .call(); if (!result) { - throw new RuntimeException("Error compiling class " + fqClassName + ":\n" + compilerOutput.toString()); + throw new RuntimeException("Error compiling class " + fqClassName + ":\n" + compilerOutput); } // The above has compiled into into e.g. // /tmp/workspace/cache/classes/temporaryCompilationDirectory12345/io/deephaven/test/cm12862183232603186v52_0/{various // class files} // We want to atomically move it to e.g. // /tmp/workspace/cache/classes/io/deephaven/test/cm12862183232603186v52_0/{various class files} - // Our strategy try { AccessController.doPrivileged((PrivilegedExceptionAction) () -> { Path srcDir = Paths.get(tempDirAsString, splitPackageName); @@ -809,7 +789,7 @@ private static void maybeCreateClassHelper(String fqClassName, String finalCode, * @param javaFiles the java source files * @return a Pair of success, and the compiler output */ - public static Pair tryCompile(File basePath, Collection javaFiles) throws IOException { + private Pair tryCompile(File basePath, Collection javaFiles) throws IOException { try { // We need multiple filesystem accesses et al, so make this whole section privileged. return AccessController.doPrivileged((PrivilegedExceptionAction>) () -> { @@ -823,7 +803,6 @@ public static Pair tryCompile(File basePath, Collection j try { final StringWriter compilerOutput = new StringWriter(); - final Context ctx = getContext(); final String javaClasspath = getJavaClassPath(); final Collection javaFileObjects = javaFiles.stream() @@ -831,7 +810,7 @@ public static Pair tryCompile(File basePath, Collection j final boolean result = compiler.getTask(compilerOutput, null, null, Arrays.asList("-d", outputDirectory.getAbsolutePath(), "-cp", - ctx.getClassPath() + File.pathSeparator + javaClasspath), + getClassPath() + File.pathSeparator + javaClasspath), null, javaFileObjects).call(); return new Pair<>(result, compilerOutput.toString()); @@ -854,7 +833,7 @@ public static Pair tryCompile(File basePath, Collection j * * @return */ - public static String getJavaClassPath() { + private static String getJavaClassPath() { String javaClasspath; { final StringBuilder javaClasspathBuilder = new StringBuilder(System.getProperty("java.class.path")); @@ -862,18 +841,18 @@ public static String getJavaClassPath() { final String teamCityWorkDir = System.getProperty("teamcity.build.workingDir"); if (teamCityWorkDir != null) { // We are running in TeamCity, get the classpath differently - final File classDirs[] = new File(teamCityWorkDir + "/_out_/classes").listFiles(); + final File[] classDirs = new File(teamCityWorkDir + "/_out_/classes").listFiles(); for (File f : classDirs) { javaClasspathBuilder.append(File.pathSeparator).append(f.getAbsolutePath()); } - final File testDirs[] = new File(teamCityWorkDir + "/_out_/test-classes").listFiles(); + final File[] testDirs = new File(teamCityWorkDir + "/_out_/test-classes").listFiles(); for (File f : testDirs) { javaClasspathBuilder.append(File.pathSeparator).append(f.getAbsolutePath()); } - final File jars[] = FileUtils.findAllFiles(new File(teamCityWorkDir + "/lib")); + final File[] jars = FileUtils.findAllFiles(new File(teamCityWorkDir + "/lib")); for (File f : jars) { if (f.getName().endsWith(".jar")) { javaClasspathBuilder.append(File.pathSeparator).append(f.getAbsolutePath()); @@ -890,7 +869,7 @@ public static String getJavaClassPath() { if (javaClasspath.matches(intellijClassPathJarRegex)) { try { final Enumeration resources = - CompilerTools.class.getClassLoader().getResources("META-INF/MANIFEST.MF"); + QueryCompiler.class.getClassLoader().getResources("META-INF/MANIFEST.MF"); final Attributes.Name createdByAttribute = new Attributes.Name("Created-By"); final Attributes.Name classPathAttribute = new Attributes.Name("Class-Path"); while (resources.hasMoreElements()) { diff --git a/engine/context/src/test/java/io/deephaven/engine/context/TestCompilerTools.java b/engine/context/src/test/java/io/deephaven/engine/context/TestQueryCompiler.java similarity index 93% rename from engine/context/src/test/java/io/deephaven/engine/context/TestCompilerTools.java rename to engine/context/src/test/java/io/deephaven/engine/context/TestQueryCompiler.java index f43ac9b6d08..6d22a650162 100644 --- a/engine/context/src/test/java/io/deephaven/engine/context/TestCompilerTools.java +++ b/engine/context/src/test/java/io/deephaven/engine/context/TestQueryCompiler.java @@ -17,7 +17,7 @@ import java.util.Collections; import java.util.List; -public class TestCompilerTools { +public class TestQueryCompiler { private final static int NUM_THREADS = 500; private final static int NUM_METHODS = 5000; private final static long WAIT_BETWEEN_THREAD_START_MILLIS = 5; @@ -158,7 +158,8 @@ private void compile(boolean printDetails, final String className) throws Except } else { startMillis = 0; } - CompilerTools.compile(className, CLASS_CODE, "io.deephaven.temp"); + ExecutionContext.getContext().getQueryCompiler() + .compile(className, CLASS_CODE, "io.deephaven.temp"); if (printDetails) { final long endMillis = System.currentTimeMillis(); System.out.println(printMillis(endMillis) + ": Thread 0 ending compile: (" + (endMillis - startMillis) @@ -185,8 +186,8 @@ public void testSimpleCompile() throws Exception { "}"); StringBuilder codeLog = new StringBuilder(); - final Class clazz1 = - CompilerTools.compile("Test", program1Text, "com.deephaven.test", codeLog, Collections.emptyMap()); + final Class clazz1 = ExecutionContext.getContext().getQueryCompiler() + .compile("Test", program1Text, "com.deephaven.test", codeLog, Collections.emptyMap()); final Method m1 = clazz1.getMethod("main", String[].class); Object[] args1 = new Object[] {new String[] {"hello", "there"}}; m1.invoke(null, args1); @@ -208,8 +209,9 @@ public void testCollidingCompile() throws Exception { Thread t = new Thread(() -> { StringBuilder codeLog = new StringBuilder(); try { - final Class clazz1 = CompilerTools.compile("Test", program1Text, "com.deephaven.test", codeLog, - Collections.emptyMap()); + final Class clazz1 = ExecutionContext.getContext().getQueryCompiler() + .compile("Test", program1Text, "com.deephaven.test", codeLog, + Collections.emptyMap()); final Method m1 = clazz1.getMethod("main", String[].class); Object[] args1 = new Object[] {new String[] {"hello", "there"}}; m1.invoke(null, args1); diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/TypedHasherFactory.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/TypedHasherFactory.java index 1025d408ab5..ecc83cc6a16 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/TypedHasherFactory.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/typed/TypedHasherFactory.java @@ -10,7 +10,8 @@ import io.deephaven.chunk.*; import io.deephaven.chunk.attributes.Values; import io.deephaven.chunk.util.hashing.CharChunkHasher; -import io.deephaven.engine.context.CompilerTools; +import io.deephaven.engine.context.ExecutionContext; +import io.deephaven.engine.context.QueryCompiler; import io.deephaven.configuration.Configuration; import io.deephaven.engine.rowset.*; import io.deephaven.engine.rowset.chunkattributes.OrderedRowKeys; @@ -33,11 +34,11 @@ import io.deephaven.util.compare.CharComparisons; import org.apache.commons.lang3.mutable.MutableInt; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import javax.lang.model.element.Modifier; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; +import java.security.spec.ECField; import java.util.*; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -476,7 +477,7 @@ public static T make(HasherConfig hasherConfig, ColumnSource[] tableKe final String javaString = Arrays.stream(javaStrings).filter(s -> !s.startsWith("package ")).collect(Collectors.joining("\n")); - final Class clazz = CompilerTools.compile(className, javaString, + final Class clazz = ExecutionContext.getContext().getQueryCompiler().compile(className, javaString, "io.deephaven.engine.table.impl.by.typed." + hasherConfig.packageMiddle + ".gen"); if (!hasherConfig.baseClass.isAssignableFrom(clazz)) { throw new IllegalStateException("Generated class is not a " + hasherConfig.baseClass.getCanonicalName()); diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/partitioned/PartitionedTableProxyImpl.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/partitioned/PartitionedTableProxyImpl.java index 7738d7ec678..4960878ec81 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/partitioned/PartitionedTableProxyImpl.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/partitioned/PartitionedTableProxyImpl.java @@ -132,7 +132,7 @@ private static ExecutionContext getOrCreateExecutionContext(final boolean requir ExecutionContext context = ExecutionContext.getContextToRecord(); if (context == null) { final ExecutionContext.Builder builder = ExecutionContext.newBuilder() - .captureCompilerContext() + .captureQueryCompiler() .markSystemic(); if (requiresFullContext) { builder.newQueryLibrary(); diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/select/ConditionFilter.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/select/ConditionFilter.java index fbeb6ed341f..0bb90ca9505 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/select/ConditionFilter.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/select/ConditionFilter.java @@ -5,7 +5,7 @@ import io.deephaven.base.Pair; import io.deephaven.chunk.attributes.Any; -import io.deephaven.engine.context.CompilerTools; +import io.deephaven.engine.context.QueryCompiler; import io.deephaven.engine.context.ExecutionContext; import io.deephaven.engine.rowset.RowSetFactory; import io.deephaven.engine.table.Context; @@ -390,8 +390,9 @@ protected void generateFilterCode(TableDefinition tableDefinition, DateTimeUtils addParamClass.accept(QueryScopeParamTypeUtil.getDeclaredClass(param.getValue())); } - filterKernelClass = CompilerTools.compile("GeneratedFilterKernel", this.classBody = classBody.toString(), - CompilerTools.FORMULA_PREFIX, QueryScopeParamTypeUtil.expandParameterClasses(paramClasses)); + filterKernelClass = ExecutionContext.getContext().getQueryCompiler() + .compile("GeneratedFilterKernel", this.classBody = classBody.toString(), + QueryCompiler.FORMULA_PREFIX, QueryScopeParamTypeUtil.expandParameterClasses(paramClasses)); } finally { nugget.done(); } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/select/DhFormulaColumn.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/select/DhFormulaColumn.java index dd1fe98b2d9..da4de5afd46 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/select/DhFormulaColumn.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/select/DhFormulaColumn.java @@ -4,7 +4,7 @@ package io.deephaven.engine.table.impl.select; import io.deephaven.configuration.Configuration; -import io.deephaven.engine.context.CompilerTools; +import io.deephaven.engine.context.QueryCompiler; import io.deephaven.engine.context.ExecutionContext; import io.deephaven.engine.table.ColumnDefinition; import io.deephaven.engine.table.Table; @@ -344,7 +344,7 @@ private CodeGenerator generateApplyFormulaPerItem(final TypeAnalyzer ta) { g.replace("ARGS", makeCommaSeparatedList(args)); g.replace("FORMULA_STRING", ta.wrapWithCastIfNecessary(formulaString)); g.replace("COLUMN_NAME", StringEscapeUtils.escapeJava(columnName)); - final String joinedFormulaString = CompilerTools.createEscapedJoinedString(formulaString); + final String joinedFormulaString = QueryCompiler.createEscapedJoinedString(formulaString); g.replace("JOINED_FORMULA_STRING", joinedFormulaString); g.replace("EXCEPTION_TYPE", EVALUATION_EXCEPTION_CLASSNAME); return g.freeze(); @@ -765,10 +765,11 @@ private Class compileFormula(final String what, final String classBody, final addParamClass.accept(p.type); return null; }); + final QueryCompiler compiler = ExecutionContext.getContext().getQueryCompiler(); return AccessController .doPrivileged( - (PrivilegedExceptionAction>) () -> CompilerTools.compile(className, classBody, - CompilerTools.FORMULA_PREFIX, + (PrivilegedExceptionAction>) () -> compiler.compile(className, classBody, + QueryCompiler.FORMULA_PREFIX, QueryScopeParamTypeUtil.expandParameterClasses(paramClasses))); } catch (PrivilegedActionException pae) { throw new FormulaCompilationException("Formula compilation error for: " + what, pae.getException()); diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/select/QueryScopeParamTypeUtil.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/select/QueryScopeParamTypeUtil.java index c1a25668420..eff4220e584 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/select/QueryScopeParamTypeUtil.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/select/QueryScopeParamTypeUtil.java @@ -4,7 +4,7 @@ package io.deephaven.engine.table.impl.select; import groovy.lang.Closure; -import io.deephaven.engine.context.CompilerTools; +import io.deephaven.engine.context.QueryCompiler; import io.deephaven.util.type.TypeUtils; import java.lang.reflect.Modifier; @@ -48,7 +48,7 @@ private static void visitParameterClass(final Map> found, Class } final String name = cls.getName(); - if (!name.startsWith(CompilerTools.DYNAMIC_GROOVY_CLASS_PREFIX)) { + if (!name.startsWith(QueryCompiler.DYNAMIC_GROOVY_CLASS_PREFIX)) { return; } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/select/SelectColumn.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/select/SelectColumn.java index f1aec384ff6..f4fbe37fa48 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/select/SelectColumn.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/select/SelectColumn.java @@ -8,6 +8,7 @@ import io.deephaven.api.Selectable; import io.deephaven.api.expression.Expression; import io.deephaven.api.value.Value; +import io.deephaven.engine.context.QueryCompiler; import io.deephaven.engine.table.*; import io.deephaven.engine.table.WritableColumnSource; import io.deephaven.engine.rowset.TrackingRowSet; @@ -69,8 +70,7 @@ static SelectColumn[] copyFrom(SelectColumn[] selectColumns) { * * @return a list of columns on which the result of this is dependent * @apiNote Any {@link io.deephaven.engine.context.QueryLibrary}, {@link io.deephaven.engine.context.QueryScope}, or - * {@link io.deephaven.engine.context.CompilerTools} usage needs to be resolved within initDef. - * Implementations must be idempotent. + * {@link QueryCompiler} usage needs to be resolved within initDef. Implementations must be idempotent. */ List initDef(Map> columnDefinitionMap); diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/select/WhereFilter.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/select/WhereFilter.java index 38a349cf544..e17bf6fca8d 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/select/WhereFilter.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/select/WhereFilter.java @@ -8,6 +8,7 @@ import io.deephaven.api.Strings; import io.deephaven.api.filter.*; import io.deephaven.api.value.Value; +import io.deephaven.engine.context.QueryCompiler; import io.deephaven.engine.rowset.WritableRowSet; import io.deephaven.engine.table.Table; import io.deephaven.engine.table.TableDefinition; @@ -107,8 +108,7 @@ interface RecomputeListener { * * @param tableDefinition the definition of the table that will be filtered * @apiNote Any {@link io.deephaven.engine.context.QueryLibrary}, {@link io.deephaven.engine.context.QueryScope}, or - * {@link io.deephaven.engine.context.CompilerTools} usage needs to be resolved within init. - * Implementations must be idempotent. + * {@link QueryCompiler} usage needs to be resolved within init. Implementations must be idempotent. */ void init(TableDefinition tableDefinition); diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/select/codegen/JavaKernelBuilder.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/select/codegen/JavaKernelBuilder.java index f650ec164c8..3cd97dbe1d7 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/select/codegen/JavaKernelBuilder.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/select/codegen/JavaKernelBuilder.java @@ -3,7 +3,7 @@ */ package io.deephaven.engine.table.impl.select.codegen; -import io.deephaven.engine.context.CompilerTools; +import io.deephaven.engine.context.QueryCompiler; import io.deephaven.engine.context.ExecutionContext; import io.deephaven.vector.Vector; import io.deephaven.engine.context.QueryScopeParam; @@ -217,7 +217,7 @@ private CodeGenerator generateApplyFormulaPerItem(final TypeAnalyzer ta) { null); g.replace("ARGS", makeCommaSeparatedList(args)); g.replace("FORMULA_STRING", ta.wrapWithCastIfNecessary(cookedFormulaString)); - final String joinedFormulaString = CompilerTools.createEscapedJoinedString(cookedFormulaString); + final String joinedFormulaString = QueryCompiler.createEscapedJoinedString(cookedFormulaString); g.replace("JOINED_FORMULA_STRING", joinedFormulaString); g.replace("EXCEPTION_TYPE", FormulaEvaluationException.class.getCanonicalName()); return g.freeze(); @@ -266,8 +266,9 @@ private static Class compileFormula(final String what, final String classBody try (final QueryPerformanceNugget nugget = QueryPerformanceRecorder.getInstance().getNugget("Compile:" + what)) { // Compilation needs to take place with elevated privileges, but the created object should not have them. - return AccessController.doPrivileged((PrivilegedExceptionAction>) () -> CompilerTools - .compile(className, classBody, CompilerTools.FORMULA_PREFIX)); + final QueryCompiler compiler = ExecutionContext.getContext().getQueryCompiler(); + return AccessController.doPrivileged((PrivilegedExceptionAction>) () -> compiler.compile(className, + classBody, QueryCompiler.FORMULA_PREFIX)); } catch (PrivilegedActionException pae) { throw new FormulaCompilationException("Formula compilation error for: " + what, pae.getException()); } diff --git a/engine/table/src/main/java/io/deephaven/engine/util/AbstractScriptSession.java b/engine/table/src/main/java/io/deephaven/engine/util/AbstractScriptSession.java index c2afafea72a..8caa1b24282 100644 --- a/engine/table/src/main/java/io/deephaven/engine/util/AbstractScriptSession.java +++ b/engine/table/src/main/java/io/deephaven/engine/util/AbstractScriptSession.java @@ -7,14 +7,13 @@ import io.deephaven.UncheckedDeephavenException; import io.deephaven.api.util.NameValidator; import io.deephaven.base.FileUtils; -import io.deephaven.engine.context.CompilerTools; +import io.deephaven.engine.context.QueryCompiler; import io.deephaven.engine.context.ExecutionContext; import io.deephaven.engine.liveness.LivenessScope; import io.deephaven.engine.liveness.LivenessScopeStack; import io.deephaven.engine.table.PartitionedTable; import io.deephaven.engine.table.Table; import io.deephaven.engine.table.TableDefinition; -import io.deephaven.engine.context.QueryLibrary; import io.deephaven.engine.context.QueryScope; import io.deephaven.engine.context.QueryScopeParam; import io.deephaven.plugin.type.ObjectType; @@ -75,14 +74,13 @@ protected AbstractScriptSession(ObjectTypeLookup objectTypeLookup, @Nullable Lis createOrClearDirectory(classCacheDirectory); final QueryScope queryScope = newQueryScope(); - final CompilerTools.Context compilerContext = - CompilerTools.newContext(classCacheDirectory, getClass().getClassLoader()); + final QueryCompiler compilerContext = QueryCompiler.create(classCacheDirectory, getClass().getClassLoader()); executionContext = ExecutionContext.newBuilder() .markSystemic() .newQueryLibrary() .setQueryScope(queryScope) - .setCompilerContext(compilerContext) + .setQueryCompiler(compilerContext) .build(); } diff --git a/engine/table/src/main/java/io/deephaven/engine/util/DynamicCompileUtils.java b/engine/table/src/main/java/io/deephaven/engine/util/DynamicCompileUtils.java index b9e79e81865..6991153b155 100644 --- a/engine/table/src/main/java/io/deephaven/engine/util/DynamicCompileUtils.java +++ b/engine/table/src/main/java/io/deephaven/engine/util/DynamicCompileUtils.java @@ -3,7 +3,8 @@ */ package io.deephaven.engine.util; -import io.deephaven.engine.context.CompilerTools; +import io.deephaven.engine.context.ExecutionContext; +import io.deephaven.engine.context.QueryCompiler; import java.util.*; import java.util.function.Supplier; @@ -51,8 +52,8 @@ public static Supplier compileSimpleFunction(final Class res classBody.append(" }\n"); classBody.append("}\n"); - final Class partitionClass = - CompilerTools.compile("Function", classBody.toString(), CompilerTools.FORMULA_PREFIX); + final Class partitionClass = ExecutionContext.getContext().getQueryCompiler() + .compile("Function", classBody.toString(), QueryCompiler.FORMULA_PREFIX); try { // noinspection unchecked @@ -70,8 +71,8 @@ public static Class getClassThroughCompilation(final String object) { classBody.append(" public Class get() { return ").append(object).append(".class; }\n"); classBody.append("}\n"); - final Class partitionClass = - CompilerTools.compile("Function", classBody.toString(), CompilerTools.FORMULA_PREFIX); + final Class partitionClass = ExecutionContext.getContext().getQueryCompiler() + .compile("Function", classBody.toString(), QueryCompiler.FORMULA_PREFIX); try { // noinspection unchecked diff --git a/engine/table/src/main/java/io/deephaven/engine/util/GroovyDeephavenSession.java b/engine/table/src/main/java/io/deephaven/engine/util/GroovyDeephavenSession.java index 814cd175363..bac9aa5c942 100644 --- a/engine/table/src/main/java/io/deephaven/engine/util/GroovyDeephavenSession.java +++ b/engine/table/src/main/java/io/deephaven/engine/util/GroovyDeephavenSession.java @@ -11,7 +11,8 @@ import io.deephaven.base.FileUtils; import io.deephaven.base.Pair; import io.deephaven.base.StringUtils; -import io.deephaven.engine.context.CompilerTools; +import io.deephaven.engine.context.ExecutionContext; +import io.deephaven.engine.context.QueryCompiler; import io.deephaven.configuration.Configuration; import io.deephaven.engine.exceptions.CancellationException; import io.deephaven.engine.updategraph.UpdateGraphProcessor; @@ -58,7 +59,7 @@ public class GroovyDeephavenSession extends AbstractScriptSession fullCommand(String command) { } public static byte[] getDynamicClass(String name) { - return readClass(CompilerTools.getContext().getFakeClassDestination(), name); + return readClass(ExecutionContext.getContext().getQueryCompiler().getFakeClassDestination(), name); } private static byte[] readClass(final File rootDirectory, final String className) { @@ -573,7 +574,7 @@ private void updateClassloader(String currentCommand) { } catch (RuntimeException e) { throw new GroovyExceptionWrapper(e); } - final File dynamicClassDestination = CompilerTools.getContext().getFakeClassDestination(); + final File dynamicClassDestination = ExecutionContext.getContext().getQueryCompiler().getFakeClassDestination(); if (dynamicClassDestination == null) { return; } @@ -601,7 +602,7 @@ && isAnInteger(aClass.getName().substring(SCRIPT_PREFIX.length()))) { } try { - CompilerTools.writeClass(dynamicClassDestination, entry.getKey(), entry.getValue()); + QueryCompiler.writeClass(dynamicClassDestination, entry.getKey(), entry.getValue()); } catch (IOException e) { throw new RuntimeException(e); } @@ -714,7 +715,7 @@ public Throwable sanitizeThrowable(Throwable e) { @Override public void onApplicationInitializationBegin(Supplier pathLoaderSupplier, ScriptPathLoaderState scriptLoaderState) { - CompilerTools.getContext().setParentClassLoader(getShell().getClassLoader()); + ExecutionContext.getContext().getQueryCompiler().setParentClassLoader(getShell().getClassLoader()); setScriptPathLoader(pathLoaderSupplier, true); } @@ -764,7 +765,7 @@ public boolean setUseOriginalScriptLoaderState(boolean useOriginal) { } } else { log.warn().append("Incorrect closure type for query: ") - .append(sourceClosure == null ? "(null)" : sourceClosure.getClass().toString()).endl(); + .append(sourceClosure.getClass().toString()).endl(); } return false; diff --git a/engine/table/src/test/java/io/deephaven/engine/table/impl/PartitionedTableTest.java b/engine/table/src/test/java/io/deephaven/engine/table/impl/PartitionedTableTest.java index b01e68201b0..d435f55615c 100644 --- a/engine/table/src/test/java/io/deephaven/engine/table/impl/PartitionedTableTest.java +++ b/engine/table/src/test/java/io/deephaven/engine/table/impl/PartitionedTableTest.java @@ -465,7 +465,7 @@ public void testCrossDependencies() { final ExecutionContext executionContext = ExecutionContext.newBuilder() .captureQueryScopeVars("pauseHelper2") .captureQueryLibrary() - .captureCompilerContext() + .captureQueryCompiler() .build(); final PartitionedTable result2 = sourceTable2.update("SlowItDown=pauseHelper.pauseValue(k)").partitionBy("USym2") @@ -552,7 +552,7 @@ public void testCrossDependencies2() { final ExecutionContext executionContext = ExecutionContext.newBuilder() .captureQueryScopeVars("pauseHelper") .captureQueryLibrary() - .captureCompilerContext() + .captureQueryCompiler() .build(); final PartitionedTable result2 = sourceTable2.partitionBy("USym2") .transform(executionContext, t -> t.update("SlowItDown2=pauseHelper.pauseValue(2 * k)")); @@ -755,7 +755,7 @@ public void testMergeConstituentChanges() { final Table underlying; try (final SafeCloseable ignored = ExecutionContext.newBuilder() .captureQueryLibrary() - .captureCompilerContext() + .captureQueryCompiler() .captureQueryScope() .build().open()) { underlying = base.update( @@ -818,7 +818,7 @@ private EvalNugget newExecutionContextNugget( protected Table e() { // note we cannot reuse the execution context and remove the values as the table is built each iteration try (final SafeCloseable ignored = ExecutionContext.newBuilder() - .captureCompilerContext() + .captureQueryCompiler() .captureQueryLibrary() .newQueryScope() .build().open()) { diff --git a/engine/table/src/test/java/io/deephaven/engine/table/impl/RefreshingTableTestCase.java b/engine/table/src/test/java/io/deephaven/engine/table/impl/RefreshingTableTestCase.java index a3d6bb2574d..bb050f156f5 100644 --- a/engine/table/src/test/java/io/deephaven/engine/table/impl/RefreshingTableTestCase.java +++ b/engine/table/src/test/java/io/deephaven/engine/table/impl/RefreshingTableTestCase.java @@ -6,7 +6,7 @@ import io.deephaven.base.testing.BaseArrayTestCase; import io.deephaven.chunk.util.pools.ChunkPoolReleaseTracking; import io.deephaven.configuration.Configuration; -import io.deephaven.engine.context.CompilerTools; +import io.deephaven.engine.context.QueryCompiler; import io.deephaven.engine.context.ExecutionContext; import io.deephaven.engine.liveness.LivenessScope; import io.deephaven.engine.liveness.LivenessScopeStack; @@ -30,8 +30,8 @@ abstract public class RefreshingTableTestCase extends BaseArrayTestCase implements UpdateErrorReporter { public static boolean printTableUpdates = Configuration.getInstance() .getBooleanForClassWithDefault(RefreshingTableTestCase.class, "printTableUpdates", false); - private static final boolean ENABLE_COMPILER_TOOLS_LOGGING = Configuration.getInstance() - .getBooleanForClassWithDefault(RefreshingTableTestCase.class, "CompilerTools.logEnabled", false); + private static final boolean ENABLE_QUERY_COMPILER_LOGGING = Configuration.getInstance() + .getBooleanForClassWithDefault(RefreshingTableTestCase.class, "QueryCompile.logEnabled", false); private boolean oldMemoize; private UpdateErrorReporter oldReporter; @@ -62,7 +62,7 @@ protected void setUp() throws Exception { // initialize the unit test's execution context executionContext = ExecutionContext.createForUnitTests().open(); - oldLogEnabled = CompilerTools.setLogEnabled(ENABLE_COMPILER_TOOLS_LOGGING); + oldLogEnabled = QueryCompiler.setLogEnabled(ENABLE_QUERY_COMPILER_LOGGING); oldCheckLtm = UpdateGraphProcessor.DEFAULT.setCheckTableOperations(false); UpdatePerformanceTracker.getInstance().enableUnitTestMode(); ChunkPoolReleaseTracking.enableStrict(); @@ -72,7 +72,7 @@ protected void setUp() throws Exception { protected void tearDown() throws Exception { ChunkPoolReleaseTracking.checkAndDisable(); UpdateGraphProcessor.DEFAULT.setCheckTableOperations(oldCheckLtm); - CompilerTools.setLogEnabled(oldLogEnabled); + QueryCompiler.setLogEnabled(oldLogEnabled); // reset the execution context executionContext.close(); diff --git a/engine/table/src/test/java/io/deephaven/engine/table/impl/TestSort.java b/engine/table/src/test/java/io/deephaven/engine/table/impl/TestSort.java index 67c3d70b30c..284c1a3327a 100644 --- a/engine/table/src/test/java/io/deephaven/engine/table/impl/TestSort.java +++ b/engine/table/src/test/java/io/deephaven/engine/table/impl/TestSort.java @@ -4,7 +4,7 @@ package io.deephaven.engine.table.impl; import io.deephaven.base.testing.BaseArrayTestCase; -import io.deephaven.engine.context.CompilerTools; +import io.deephaven.engine.context.QueryCompiler; import io.deephaven.configuration.Configuration; import io.deephaven.engine.exceptions.NotSortableException; import io.deephaven.engine.table.DataColumn; @@ -32,11 +32,11 @@ @Category(OutOfBandTest.class) public class TestSort extends BaseArrayTestCase { - private static final boolean ENABLE_COMPILER_TOOLS_LOGGING = Configuration.getInstance() - .getBooleanForClassWithDefault(TestSort.class, "CompilerTools.logEnabled", false); + private static final boolean ENABLE_QUERY_COMPILER_LOGGING = Configuration.getInstance() + .getBooleanForClassWithDefault(TestSort.class, "QueryCompiler.logEnabled", false); private boolean lastMemoize = false; - private boolean oldCompilerToolsLogEnabled; + private boolean oldQueryCompilerLogEnabled; private SafeCloseable executionContext; @Override @@ -45,14 +45,14 @@ protected void setUp() throws Exception { UpdateGraphProcessor.DEFAULT.enableUnitTestMode(); UpdateGraphProcessor.DEFAULT.resetForUnitTests(false); lastMemoize = QueryTable.setMemoizeResults(false); - oldCompilerToolsLogEnabled = CompilerTools.setLogEnabled(ENABLE_COMPILER_TOOLS_LOGGING); + oldQueryCompilerLogEnabled = QueryCompiler.setLogEnabled(ENABLE_QUERY_COMPILER_LOGGING); executionContext = ExecutionContext.createForUnitTests().open(); } @Override protected void tearDown() throws Exception { super.tearDown(); - CompilerTools.setLogEnabled(oldCompilerToolsLogEnabled); + QueryCompiler.setLogEnabled(oldQueryCompilerLogEnabled); QueryTable.setMemoizeResults(lastMemoize); UpdateGraphProcessor.DEFAULT.resetForUnitTests(true); executionContext.close(); diff --git a/engine/table/src/test/java/io/deephaven/engine/table/impl/select/TestConditionFilterGeneration.java b/engine/table/src/test/java/io/deephaven/engine/table/impl/select/TestConditionFilterGeneration.java index 05fd0dea8d7..af6571a86f8 100644 --- a/engine/table/src/test/java/io/deephaven/engine/table/impl/select/TestConditionFilterGeneration.java +++ b/engine/table/src/test/java/io/deephaven/engine/table/impl/select/TestConditionFilterGeneration.java @@ -27,7 +27,7 @@ public class TestConditionFilterGeneration { public void setUp() { executionContext = ExecutionContext.newBuilder() .newQueryLibrary("DEFAULT") - .captureCompilerContext() + .captureQueryCompiler() .captureQueryScope() .build().open(); diff --git a/engine/table/src/test/java/io/deephaven/engine/table/impl/select/TestFormulaColumn.java b/engine/table/src/test/java/io/deephaven/engine/table/impl/select/TestFormulaColumn.java index 6daf482aa16..372cd34f166 100644 --- a/engine/table/src/test/java/io/deephaven/engine/table/impl/select/TestFormulaColumn.java +++ b/engine/table/src/test/java/io/deephaven/engine/table/impl/select/TestFormulaColumn.java @@ -189,8 +189,8 @@ public void testArrayEvaluation() { @Test public void testNoInput() { - final String oldValue = Configuration.getInstance().getProperty("CompilerTools.logEnabledDefault"); - Configuration.getInstance().setProperty("CompilerTools.logEnabledDefault", "true"); + final String oldValue = Configuration.getInstance().getProperty("QueryCompiler.logEnabledDefault"); + Configuration.getInstance().setProperty("QueryCompiler.logEnabledDefault", "true"); try { FormulaColumn formulaColumn = FormulaColumn.createFormulaColumn("Foo", "(String)\"1234\""); formulaColumn.initDef(Collections.emptyMap()); @@ -202,7 +202,7 @@ public void testNoInput() { final long longResult = longFormulaColumn.getDataView().getLong(0); assertEquals(longResult, 1234L); } finally { - Configuration.getInstance().setProperty("CompilerTools.logEnabledDefault", oldValue); + Configuration.getInstance().setProperty("QueryCompiler.logEnabledDefault", oldValue); } } diff --git a/engine/table/src/test/java/io/deephaven/engine/table/impl/select/TestFormulaColumnGeneration.java b/engine/table/src/test/java/io/deephaven/engine/table/impl/select/TestFormulaColumnGeneration.java index 28190f20058..356d85a5fce 100644 --- a/engine/table/src/test/java/io/deephaven/engine/table/impl/select/TestFormulaColumnGeneration.java +++ b/engine/table/src/test/java/io/deephaven/engine/table/impl/select/TestFormulaColumnGeneration.java @@ -5,7 +5,6 @@ import io.deephaven.engine.context.ExecutionContext; import io.deephaven.engine.table.Table; -import io.deephaven.engine.context.QueryLibrary; import io.deephaven.engine.context.QueryScope; import io.deephaven.engine.util.TableTools; import io.deephaven.engine.table.impl.util.ModelFileGenerator; @@ -48,7 +47,7 @@ public void generateFiles() throws FileNotFoundException { public void setUp() { executionContext = ExecutionContext.newBuilder() .newQueryLibrary("DEFAULT") - .captureCompilerContext() + .captureQueryCompiler() .captureQueryScope() .build().open(); } diff --git a/engine/table/src/test/java/io/deephaven/engine/util/TestTableTools.java b/engine/table/src/test/java/io/deephaven/engine/util/TestTableTools.java index 67eff6709c8..20b2bfe9c53 100644 --- a/engine/table/src/test/java/io/deephaven/engine/util/TestTableTools.java +++ b/engine/table/src/test/java/io/deephaven/engine/util/TestTableTools.java @@ -5,7 +5,7 @@ import io.deephaven.chunk.attributes.Values; import io.deephaven.configuration.Configuration; -import io.deephaven.engine.context.CompilerTools; +import io.deephaven.engine.context.QueryCompiler; import io.deephaven.datastructures.util.CollectionUtil; import io.deephaven.engine.context.ExecutionContext; import io.deephaven.engine.rowset.RowSet; @@ -48,8 +48,8 @@ @Category(OutOfBandTest.class) public class TestTableTools extends TestCase implements UpdateErrorReporter { - private static final boolean ENABLE_COMPILER_TOOLS_LOGGING = Configuration.getInstance() - .getBooleanForClassWithDefault(TestTableTools.class, "CompilerTools.logEnabled", false); + private static final boolean ENABLE_QUERY_COMPILER_LOGGING = Configuration.getInstance() + .getBooleanForClassWithDefault(TestTableTools.class, "QueryCompiler.logEnabled", false); private UpdateErrorReporter oldReporter; @@ -68,7 +68,7 @@ public void setUp() throws Exception { super.setUp(); oldCheckUgp = UpdateGraphProcessor.DEFAULT.setCheckTableOperations(false); - oldLogEnabled = CompilerTools.setLogEnabled(ENABLE_COMPILER_TOOLS_LOGGING); + oldLogEnabled = QueryCompiler.setLogEnabled(ENABLE_QUERY_COMPILER_LOGGING); UpdateGraphProcessor.DEFAULT.enableUnitTestMode(); UpdateGraphProcessor.DEFAULT.resetForUnitTests(false); UpdatePerformanceTracker.getInstance().enableUnitTestMode(); @@ -97,7 +97,7 @@ public void tearDown() throws Exception { LivenessScopeStack.pop(scope); scope.release(); executionContext.close(); - CompilerTools.setLogEnabled(oldLogEnabled); + QueryCompiler.setLogEnabled(oldLogEnabled); UpdateGraphProcessor.DEFAULT.setCheckTableOperations(oldCheckUgp); AsyncClientErrorNotifier.setReporter(oldReporter); UpdateGraphProcessor.DEFAULT.resetForUnitTests(true); diff --git a/props/configs/src/main/resources/dh-defaults.prop b/props/configs/src/main/resources/dh-defaults.prop index 0b76987dac1..24a71e5ffaf 100644 --- a/props/configs/src/main/resources/dh-defaults.prop +++ b/props/configs/src/main/resources/dh-defaults.prop @@ -1,4 +1,4 @@ -CompilerTools.logEnabledDefault=false +QueryCompiler.logEnabledDefault=false UpdatePerformanceTracker.reportingMode=LISTENER_ONLY UpdatePerformanceTracker.reportIntervalMillis=60000 measurement.per_thread_cpu=false diff --git a/props/test-configs/src/main/resources/dh-tests.prop b/props/test-configs/src/main/resources/dh-tests.prop index 3001014dc3c..e270fa9e6de 100644 --- a/props/test-configs/src/main/resources/dh-tests.prop +++ b/props/test-configs/src/main/resources/dh-tests.prop @@ -3,7 +3,7 @@ include= measurement.per_thread_cpu=false -CompilerTools.logEnabledDefault=false +QueryCompiler.logEnabledDefault=false UpdatePerformanceTracker.reportingMode=NONE UpdatePerformanceTracker.reportIntervalMillis=60000 diff --git a/py/server/tests/test_partitioned_table.py b/py/server/tests/test_partitioned_table.py index f64625daa17..dd2b7c89bb5 100644 --- a/py/server/tests/test_partitioned_table.py +++ b/py/server/tests/test_partitioned_table.py @@ -119,7 +119,7 @@ def test_constituents(self): def test_transform(self): _JExecutionContext = jpy.get_type("io.deephaven.engine.context.ExecutionContext") context = _JExecutionContext.newBuilder() \ - .captureCompilerContext() \ + .captureQueryCompiler() \ .captureQueryLibrary() \ .emptyQueryScope() \ .build().open() @@ -137,7 +137,7 @@ def test_transform(self): def test_partitioned_transform(self): _JExecutionContext = jpy.get_type("io.deephaven.engine.context.ExecutionContext") context = _JExecutionContext.newBuilder() \ - .captureCompilerContext() \ + .captureQueryCompiler() \ .captureQueryLibrary() \ .emptyQueryScope() \ .build().open() diff --git a/py/server/tests/test_table.py b/py/server/tests/test_table.py index 592babc66aa..31e7913d7d3 100644 --- a/py/server/tests/test_table.py +++ b/py/server/tests/test_table.py @@ -625,7 +625,7 @@ def closure_fn() -> str: def test_nested_scopes(self): _JExecutionContext = jpy.get_type("io.deephaven.engine.context.ExecutionContext") context = _JExecutionContext.newBuilder() \ - .captureCompilerContext() \ + .captureQueryCompiler() \ .captureQueryLibrary() \ .captureQueryScope() \ .build() @@ -642,7 +642,7 @@ def test_nested_scope_ticking(self): import jpy _JExecutionContext = jpy.get_type("io.deephaven.engine.context.ExecutionContext") j_context = (_JExecutionContext.newBuilder() - .captureCompilerContext() + .captureQueryCompiler() .captureQueryLibrary() .captureQueryScope() .build()) diff --git a/py/server/tests/test_ugp.py b/py/server/tests/test_ugp.py index 033721ecb7d..b49b85975e7 100644 --- a/py/server/tests/test_ugp.py +++ b/py/server/tests/test_ugp.py @@ -209,11 +209,11 @@ def test_auto_locking_partitioned_table(self): _ExecutionContext = jpy.get_type("io.deephaven.engine.context.ExecutionContext") _context = _ExecutionContext.newBuilder() \ - .captureCompilerContext() \ - .captureQueryLibrary() \ - .emptyQueryScope() \ - .build() \ - .open() + .captureQueryCompiler() \ + .captureQueryLibrary() \ + .emptyQueryScope() \ + .build() \ + .open() with self.subTest("Merge"): ugp.auto_locking = False diff --git a/python-engine-test/src/test/java/io/deephaven/engine/table/impl/select/TestConditionFilter.java b/python-engine-test/src/test/java/io/deephaven/engine/table/impl/select/TestConditionFilter.java index bf989294696..89cb4e93029 100644 --- a/python-engine-test/src/test/java/io/deephaven/engine/table/impl/select/TestConditionFilter.java +++ b/python-engine-test/src/test/java/io/deephaven/engine/table/impl/select/TestConditionFilter.java @@ -13,7 +13,7 @@ import io.deephaven.io.log.LogLevel; import io.deephaven.io.logger.StreamLoggerImpl; import io.deephaven.util.process.ProcessEnvironment; -import io.deephaven.engine.context.CompilerTools; +import io.deephaven.engine.context.QueryCompiler; import io.deephaven.engine.table.Table; import io.deephaven.engine.context.QueryScopeParam; import io.deephaven.engine.context.QueryScope; @@ -48,11 +48,11 @@ public class TestConditionFilter extends PythonTest { } } - private static final boolean ENABLE_COMPILER_TOOLS_LOGGING = Configuration.getInstance() - .getBooleanForClassWithDefault(TestConditionFilter.class, "CompilerTools.logEnabled", false); + private static final boolean ENABLE_QUERY_COMPILER_LOGGING = Configuration.getInstance() + .getBooleanForClassWithDefault(TestConditionFilter.class, "QueryCompiler.logEnabled", false); private final Table testDataTable; - private boolean compilerToolsLogEnabledInitial = false; + private boolean queryCompilerLogEnabledInitial = false; public TestConditionFilter() { testDataTable = getTestDataTable(); @@ -67,12 +67,12 @@ public void setUp() throws Exception { ProcessEnvironment.basicInteractiveProcessInitialization(Configuration.getInstance(), PythonMatchFilterTest.class.getCanonicalName(), new StreamLoggerImpl(System.out, LogLevel.INFO)); } - compilerToolsLogEnabledInitial = CompilerTools.setLogEnabled(ENABLE_COMPILER_TOOLS_LOGGING); + queryCompilerLogEnabledInitial = QueryCompiler.setLogEnabled(ENABLE_QUERY_COMPILER_LOGGING); } @After public void tearDown() throws Exception { - CompilerTools.setLogEnabled(compilerToolsLogEnabledInitial); + QueryCompiler.setLogEnabled(queryCompilerLogEnabledInitial); } @Test