Skip to content

Commit c36aa5c

Browse files
authored
Merge branch 'apache:master' into DRILL-8521
2 parents 48395fd + 582dc40 commit c36aa5c

File tree

13 files changed

+147
-126
lines changed

13 files changed

+147
-126
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,8 @@ jobs:
3434
strategy:
3535
matrix:
3636
# Java versions to run unit tests
37-
java: [ '8', '11', '17' ]
37+
java: [ '11', '17', '21' ]
3838
profile: ['default-hadoop']
39-
include:
40-
- java: '8'
41-
profile: 'hadoop-2'
4239
fail-fast: false
4340
steps:
4441
- name: Checkout
@@ -82,7 +79,7 @@ jobs:
8279
uses: actions/setup-java@v4
8380
with:
8481
distribution: 'temurin'
85-
java-version: '8'
82+
java-version: '11'
8683
cache: 'maven'
8784
# Caches built protobuf library
8885
- name: Cache protobufs

exec/java-exec/src/main/java/org/apache/drill/exec/compile/ClassCompilerSelector.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,6 @@
1717
*/
1818
package org.apache.drill.exec.compile;
1919

20-
import java.io.IOException;
21-
import java.util.Arrays;
22-
import java.util.Map;
23-
2420
import org.apache.drill.common.config.DrillConfig;
2521
import org.apache.drill.common.exceptions.UserException;
2622
import org.apache.drill.exec.compile.ClassTransformer.ClassNames;
@@ -34,6 +30,12 @@
3430
import org.apache.drill.exec.server.options.TypeValidators.LongValidator;
3531
import org.apache.drill.exec.server.options.TypeValidators.StringValidator;
3632
import org.codehaus.commons.compiler.CompileException;
33+
import org.slf4j.Logger;
34+
import org.slf4j.LoggerFactory;
35+
36+
import java.io.IOException;
37+
import java.util.Arrays;
38+
import java.util.Map;
3739

3840
/**
3941
* Selects between the two supported Java compilers: Janino and
@@ -65,7 +67,7 @@
6567
*/
6668

6769
public class ClassCompilerSelector {
68-
private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(ClassCompilerSelector.class);
70+
private static final Logger logger = LoggerFactory.getLogger(ClassCompilerSelector.class);
6971

7072
public enum CompilerPolicy {
7173
DEFAULT, JDK, JANINO;

exec/java-exec/src/main/java/org/apache/drill/exec/compile/ClassTransformer.java

Lines changed: 41 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@
1717
*/
1818
package org.apache.drill.exec.compile;
1919

20-
import java.io.IOException;
21-
import java.util.LinkedList;
22-
import java.util.Map;
23-
import java.util.Set;
24-
20+
import com.google.common.annotations.VisibleForTesting;
21+
import com.google.common.base.Preconditions;
22+
import com.google.common.collect.Lists;
23+
import com.google.common.collect.Maps;
24+
import com.google.common.collect.Sets;
2525
import org.apache.commons.lang3.tuple.Pair;
2626
import org.apache.drill.common.config.DrillConfig;
2727
import org.apache.drill.common.util.DrillFileUtils;
@@ -35,11 +35,10 @@
3535
import org.objectweb.asm.ClassReader;
3636
import org.objectweb.asm.tree.ClassNode;
3737

38-
import com.google.common.annotations.VisibleForTesting;
39-
import com.google.common.base.Preconditions;
40-
import com.google.common.collect.Lists;
41-
import com.google.common.collect.Maps;
42-
import com.google.common.collect.Sets;
38+
import java.io.IOException;
39+
import java.util.LinkedList;
40+
import java.util.Map;
41+
import java.util.Set;
4342

4443
/**
4544
* Compiles generated code, merges the resulting class with the
@@ -52,7 +51,7 @@
5251
public class ClassTransformer {
5352
private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(ClassTransformer.class);
5453

55-
private static final int MAX_SCALAR_REPLACE_CODE_SIZE = 2*1024*1024; // 2meg
54+
private static final int MAX_SCALAR_REPLACE_CODE_SIZE = 2 * 1024 * 1024; // 2meg
5655

5756
private final ByteCodeLoader byteCodeLoader = new ByteCodeLoader();
5857
private final DrillConfig config;
@@ -72,7 +71,7 @@ public enum ScalarReplacementOption {
7271
* @throws IllegalArgumentException if the string doesn't match any of the enum values
7372
*/
7473
public static ScalarReplacementOption fromString(final String s) {
75-
switch(s) {
74+
switch (s) {
7675
case "off":
7776
return OFF;
7877
case "try":
@@ -228,8 +227,11 @@ public Class<?> getImplementationClass(
228227
final TemplateClassDefinition<?> templateDefinition,
229228
final String entireClass,
230229
final String materializedClassName) throws ClassTransformationException {
231-
// unfortunately, this hasn't been set up at construction time, so we have to do it here
232-
final ScalarReplacementOption scalarReplacementOption = ScalarReplacementOption.fromString(optionManager.getOption(ExecConstants.SCALAR_REPLACEMENT_VALIDATOR));
230+
final ScalarReplacementOption scalarReplacementOption =
231+
ScalarReplacementOption.fromString(optionManager.getOption(ExecConstants.SCALAR_REPLACEMENT_VALIDATOR));
232+
233+
// Track injected class names to avoid duplicates
234+
Set<String> injectedClassNames = new java.util.HashSet<>();
233235

234236
try {
235237
final long t1 = System.nanoTime();
@@ -251,53 +253,32 @@ public Class<?> getImplementationClass(
251253
final Set<ClassSet> namesCompleted = Sets.newHashSet();
252254
names.add(set);
253255

254-
while ( !names.isEmpty() ) {
256+
while (!names.isEmpty()) {
255257
final ClassSet nextSet = names.removeFirst();
256258
if (namesCompleted.contains(nextSet)) {
257259
continue;
258260
}
259261
final ClassNames nextPrecompiled = nextSet.precompiled;
260262
final byte[] precompiledBytes = byteCodeLoader.getClassByteCodeFromPath(nextPrecompiled.clazz);
261263
final ClassNames nextGenerated = nextSet.generated;
262-
// keeps only classes that have not be merged
264+
// keeps only classes that have not been merged
263265
Pair<byte[], ClassNode> classNodePair = classesToMerge.remove(nextGenerated.slash);
264-
final ClassNode generatedNode;
265-
if (classNodePair != null) {
266-
generatedNode = classNodePair.getValue();
267-
} else {
268-
generatedNode = null;
269-
}
266+
final ClassNode generatedNode = (classNodePair != null) ? classNodePair.getValue() : null;
270267

271-
/*
272-
* TODO
273-
* We're having a problem with some cases of scalar replacement, but we want to get
274-
* the code in so it doesn't rot anymore.
275-
*
276-
* Here, we use the specified replacement option. The loop will allow us to retry if
277-
* we're using TRY.
278-
*/
279268
MergedClassResult result = null;
280-
boolean scalarReplace = scalarReplacementOption != ScalarReplacementOption.OFF && entireClass.length() < MAX_SCALAR_REPLACE_CODE_SIZE;
281-
while(true) {
269+
boolean scalarReplace = scalarReplacementOption != ScalarReplacementOption.OFF
270+
&& entireClass.length() < MAX_SCALAR_REPLACE_CODE_SIZE;
271+
while (true) {
282272
try {
283273
result = MergeAdapter.getMergedClass(nextSet, precompiledBytes, generatedNode, scalarReplace);
284274
break;
285-
} catch(RuntimeException e) {
286-
// if we had a problem without using scalar replacement, then rethrow
275+
} catch (RuntimeException e) {
287276
if (!scalarReplace) {
288277
throw e;
289278
}
290-
291-
// if we did try to use scalar replacement, decide if we need to retry or not
292279
if (scalarReplacementOption == ScalarReplacementOption.ON) {
293-
// option is forced on, so this is a hard error
294280
throw e;
295281
}
296-
297-
/*
298-
* We tried to use scalar replacement, with the option to fall back to not using it.
299-
* Log this failure before trying again without scalar replacement.
300-
*/
301282
logger.info("scalar replacement failure (retrying)\n", e);
302283
scalarReplace = false;
303284
}
@@ -307,26 +288,38 @@ public Class<?> getImplementationClass(
307288
s = s.replace(DrillFileUtils.SEPARATOR_CHAR, '.');
308289
names.add(nextSet.getChild(s));
309290
}
310-
classLoader.injectByteCode(nextGenerated.dot, result.bytes);
291+
292+
// Only inject bytecode if not already injected
293+
if (!injectedClassNames.contains(nextGenerated.dot)) {
294+
classLoader.injectByteCode(nextGenerated.dot, result.bytes);
295+
injectedClassNames.add(nextGenerated.dot);
296+
}
297+
311298
namesCompleted.add(nextSet);
312299
}
313300

314301
// adds byte code of the classes that have not been merged to make them accessible for outer class
315302
for (Map.Entry<String, Pair<byte[], ClassNode>> clazz : classesToMerge.entrySet()) {
316-
classLoader.injectByteCode(clazz.getKey().replace(DrillFileUtils.SEPARATOR_CHAR, '.'), clazz.getValue().getKey());
303+
String classNameDot = clazz.getKey().replace(DrillFileUtils.SEPARATOR_CHAR, '.');
304+
if (!injectedClassNames.contains(classNameDot)) {
305+
classLoader.injectByteCode(classNameDot, clazz.getValue().getKey());
306+
injectedClassNames.add(classNameDot);
307+
}
317308
}
309+
318310
Class<?> c = classLoader.findClass(set.generated.dot);
319311
if (templateDefinition.getExternalInterface().isAssignableFrom(c)) {
320312
logger.debug("Compiled and merged {}: bytecode size = {}, time = {} ms.",
321-
c.getSimpleName(),
322-
DrillStringUtils.readable(totalBytecodeSize),
323-
(System.nanoTime() - t1 + 500_000) / 1_000_000);
313+
c.getSimpleName(),
314+
DrillStringUtils.readable(totalBytecodeSize),
315+
(System.nanoTime() - t1 + 500_000) / 1_000_000);
324316
return c;
325317
}
326318

327319
throw new ClassTransformationException("The requested class did not implement the expected interface.");
328320
} catch (CompileException | IOException | ClassNotFoundException e) {
329-
throw new ClassTransformationException(String.format("Failure generating transformation classes for value: \n %s", entireClass), e);
321+
throw new ClassTransformationException(
322+
String.format("Failure generating transformation classes for value: \n %s", entireClass), e);
330323
}
331324
}
332325
}

exec/java-exec/src/main/java/org/apache/drill/exec/compile/QueryClassLoader.java

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,32 +17,33 @@
1717
*/
1818
package org.apache.drill.exec.compile;
1919

20-
import java.io.IOException;
21-
import java.net.URL;
22-
import java.net.URLClassLoader;
23-
import java.util.concurrent.ConcurrentMap;
24-
import java.util.concurrent.atomic.AtomicLong;
25-
20+
import com.google.common.collect.MapMaker;
2621
import org.apache.drill.common.config.DrillConfig;
2722
import org.apache.drill.exec.compile.ClassTransformer.ClassNames;
2823
import org.apache.drill.exec.exception.ClassTransformationException;
2924
import org.apache.drill.exec.server.options.OptionSet;
3025
import org.codehaus.commons.compiler.CompileException;
26+
import org.slf4j.Logger;
27+
import org.slf4j.LoggerFactory;
3128

32-
import com.google.common.collect.MapMaker;
29+
import java.io.IOException;
30+
import java.net.URL;
31+
import java.net.URLClassLoader;
32+
import java.util.concurrent.ConcurrentMap;
33+
import java.util.concurrent.atomic.AtomicLong;
3334

3435
/**
3536
* Per-compilation unit class loader that holds both caching and compilation
3637
* steps. */
3738

3839
public class QueryClassLoader extends URLClassLoader {
39-
static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(QueryClassLoader.class);
40+
static final Logger logger = LoggerFactory.getLogger(QueryClassLoader.class);
4041

41-
private ClassCompilerSelector compilerSelector;
42+
private final ClassCompilerSelector compilerSelector;
4243

4344
private AtomicLong index = new AtomicLong(0);
4445

45-
private ConcurrentMap<String, byte[]> customClasses = new MapMaker().concurrencyLevel(4).makeMap();
46+
private final ConcurrentMap<String, byte[]> customClasses = new MapMaker().concurrencyLevel(4).makeMap();
4647

4748
public QueryClassLoader(DrillConfig config, OptionSet sessionOptions) {
4849
super(new URL[0], Thread.currentThread().getContextClassLoader());

exec/java-exec/src/test/java/org/apache/drill/PlanningBase.java

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,29 +17,26 @@
1717
*/
1818
package org.apache.drill;
1919

20-
import java.io.IOException;
21-
import java.net.URL;
22-
import java.nio.charset.StandardCharsets;
23-
24-
import org.apache.calcite.jdbc.DynamicSchema;
25-
import org.apache.drill.exec.alias.AliasRegistryProvider;
26-
import org.apache.drill.exec.ops.ViewExpansionContext;
20+
import com.codahale.metrics.MetricRegistry;
2721
import com.google.common.base.Function;
22+
import com.google.common.collect.ImmutableList;
23+
import com.google.common.io.Resources;
2824
import io.netty.buffer.DrillBuf;
25+
import org.apache.calcite.jdbc.DynamicSchema;
2926
import org.apache.calcite.schema.SchemaPlus;
3027
import org.apache.drill.common.config.DrillConfig;
3128
import org.apache.drill.common.config.LogicalPlanPersistence;
3229
import org.apache.drill.common.scanner.ClassPathScanner;
3330
import org.apache.drill.common.scanner.persistence.ScanResult;
3431
import org.apache.drill.common.types.TypeProtos;
35-
import org.apache.drill.exec.expr.holders.ValueHolder;
36-
import org.apache.drill.exec.vector.ValueHolderHelper;
37-
import org.apache.drill.test.TestTools;
3832
import org.apache.drill.exec.ExecTest;
33+
import org.apache.drill.exec.alias.AliasRegistryProvider;
3934
import org.apache.drill.exec.expr.fn.FunctionImplementationRegistry;
35+
import org.apache.drill.exec.expr.holders.ValueHolder;
4036
import org.apache.drill.exec.memory.BufferAllocator;
4137
import org.apache.drill.exec.memory.RootAllocatorFactory;
4238
import org.apache.drill.exec.ops.QueryContext;
39+
import org.apache.drill.exec.ops.ViewExpansionContext;
4340
import org.apache.drill.exec.physical.PhysicalPlan;
4441
import org.apache.drill.exec.planner.physical.PlannerSettings;
4542
import org.apache.drill.exec.planner.sql.DrillOperatorTable;
@@ -55,16 +52,18 @@
5552
import org.apache.drill.exec.store.StoragePluginRegistryImpl;
5653
import org.apache.drill.exec.store.sys.store.provider.LocalPersistentStoreProvider;
5754
import org.apache.drill.exec.testing.ExecutionControls;
55+
import org.apache.drill.exec.vector.ValueHolderHelper;
56+
import org.apache.drill.test.TestTools;
5857
import org.junit.Rule;
5958
import org.junit.rules.TestRule;
59+
import org.mockito.ArgumentMatchers;
6060

61-
import com.codahale.metrics.MetricRegistry;
62-
import com.google.common.collect.ImmutableList;
63-
import com.google.common.io.Resources;
64-
import org.mockito.Matchers;
61+
import java.io.IOException;
62+
import java.net.URL;
63+
import java.nio.charset.StandardCharsets;
6564

6665
import static org.mockito.ArgumentMatchers.anyString;
67-
import static org.mockito.Matchers.eq;
66+
import static org.mockito.ArgumentMatchers.eq;
6867
import static org.mockito.Mockito.mock;
6968
import static org.mockito.Mockito.when;
7069

@@ -131,11 +130,11 @@ protected void testSqlPlan(String sqlCommands) throws Exception {
131130
when(context.getManagedBuffer()).thenReturn(allocator.buffer(4));
132131
when(context.getConstantValueHolder(eq("0.03"),
133132
eq(TypeProtos.MinorType.VARDECIMAL),
134-
Matchers.<Function<DrillBuf, ValueHolder>>any()))
133+
ArgumentMatchers.<Function<DrillBuf, ValueHolder>>any()))
135134
.thenReturn(ValueHolderHelper.getVarDecimalHolder(allocator.buffer(4), "0.03"));
136135
when(context.getConstantValueHolder(eq("0.01"),
137136
eq(TypeProtos.MinorType.VARDECIMAL),
138-
Matchers.<Function<DrillBuf, ValueHolder>>any()))
137+
ArgumentMatchers.<Function<DrillBuf, ValueHolder>>any()))
139138
.thenReturn(ValueHolderHelper.getVarDecimalHolder(allocator.buffer(4), "0.01"));
140139
when(context.getOption(anyString())).thenCallRealMethod();
141140
when(context.getViewExpansionContext()).thenReturn(viewExpansionContext);

exec/java-exec/src/test/java/org/apache/drill/exec/compile/TestClassTransformation.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,32 +17,34 @@
1717
*/
1818
package org.apache.drill.exec.compile;
1919

20-
import java.io.IOException;
21-
import java.util.Arrays;
22-
import java.util.List;
23-
2420
import org.apache.drill.common.util.DrillFileUtils;
2521
import org.apache.drill.exec.ExecConstants;
26-
import org.apache.drill.exec.compile.bytecode.ValueHolderReplacementVisitor;
27-
import org.apache.drill.test.BaseTestQuery;
2822
import org.apache.drill.exec.compile.ClassTransformer.ClassSet;
23+
import org.apache.drill.exec.compile.bytecode.ValueHolderReplacementVisitor;
2924
import org.apache.drill.exec.compile.sig.GeneratorMapping;
3025
import org.apache.drill.exec.compile.sig.MappingSet;
3126
import org.apache.drill.exec.exception.ClassTransformationException;
3227
import org.apache.drill.exec.expr.ClassGenerator;
3328
import org.apache.drill.exec.expr.CodeGenerator;
3429
import org.apache.drill.exec.rpc.user.UserSession;
3530
import org.apache.drill.exec.server.options.SessionOptionManager;
31+
import org.apache.drill.test.BaseTestQuery;
3632
import org.codehaus.commons.compiler.CompileException;
3733
import org.junit.Assert;
3834
import org.junit.BeforeClass;
3935
import org.junit.Test;
4036
import org.objectweb.asm.ClassReader;
4137
import org.objectweb.asm.ClassWriter;
4238
import org.objectweb.asm.tree.ClassNode;
39+
import org.slf4j.Logger;
40+
import org.slf4j.LoggerFactory;
41+
42+
import java.io.IOException;
43+
import java.util.Arrays;
44+
import java.util.List;
4345

4446
public class TestClassTransformation extends BaseTestQuery {
45-
private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(TestClassTransformation.class);
47+
private static final Logger logger = LoggerFactory.getLogger(TestClassTransformation.class);
4648

4749
private static final int ITERATION_COUNT = Integer.parseInt(System.getProperty("TestClassTransformation.iteration", "1"));
4850

0 commit comments

Comments
 (0)