Skip to content

Commit 2f4ed7d

Browse files
committed
Merge remote-tracking branch 'elastic/master' into cat-recovery-start-stop-time
* elastic/master: [DOCS] Adds notable highlights tags (elastic#40330) [ML] making test more determinate (elastic#40374) [ML] adds support for non-numeric mapped types (elastic#40220) Move outbound message handling to OutboundHandler (elastic#40336) Add implicit this for class binding in Painless (elastic#40285)
2 parents 59e9d48 + 67f78c6 commit 2f4ed7d

File tree

32 files changed

+856
-297
lines changed

32 files changed

+856
-297
lines changed

docs/reference/release-notes/highlights-8.0.0.asciidoc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,12 @@
77
coming[8.0.0]
88

99
See also <<breaking-changes-8.0>> and <<release-notes-8.0.0-alpha1>>.
10+
11+
////
12+
The following section is re-used in the Installation and Upgrade Guide
13+
[[notable-highlights-8.0.0]]
14+
=== Notable breaking changes
15+
////
16+
// tag::notable-highlights[]
17+
18+
// end::notable-highlights[]

modules/lang-painless/src/main/java/org/elasticsearch/painless/BindingTest.java

Lines changed: 0 additions & 32 deletions
This file was deleted.

modules/lang-painless/src/main/java/org/elasticsearch/painless/Locals.java

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ public static Locals newLocalScope(Locals currentScope) {
9090
*/
9191
public static Locals newLambdaScope(Locals programScope, String name, Class<?> returnType, List<Parameter> parameters,
9292
int captureCount, int maxLoopCounter) {
93-
Locals locals = new Locals(programScope, programScope.painlessLookup, returnType, KEYWORDS);
93+
Locals locals = new Locals(programScope, programScope.painlessLookup, programScope.baseClass, returnType, KEYWORDS);
9494
locals.methods = programScope.methods;
9595
List<Class<?>> typeParameters = parameters.stream().map(parameter -> typeToJavaType(parameter.clazz)).collect(Collectors.toList());
9696
locals.methods.put(buildLocalMethodKey(name, parameters.size()), new LocalMethod(name, returnType, typeParameters,
@@ -113,7 +113,7 @@ public static Locals newLambdaScope(Locals programScope, String name, Class<?> r
113113

114114
/** Creates a new function scope inside the current scope */
115115
public static Locals newFunctionScope(Locals programScope, Class<?> returnType, List<Parameter> parameters, int maxLoopCounter) {
116-
Locals locals = new Locals(programScope, programScope.painlessLookup, returnType, KEYWORDS);
116+
Locals locals = new Locals(programScope, programScope.painlessLookup, programScope.baseClass, returnType, KEYWORDS);
117117
locals.methods = programScope.methods;
118118
for (Parameter parameter : parameters) {
119119
locals.addVariable(parameter.location, parameter.clazz, parameter.name, false);
@@ -127,8 +127,8 @@ public static Locals newFunctionScope(Locals programScope, Class<?> returnType,
127127

128128
/** Creates a new main method scope */
129129
public static Locals newMainMethodScope(ScriptClassInfo scriptClassInfo, Locals programScope, int maxLoopCounter) {
130-
Locals locals = new Locals(
131-
programScope, programScope.painlessLookup, scriptClassInfo.getExecuteMethodReturnType(), KEYWORDS);
130+
Locals locals = new Locals(programScope, programScope.painlessLookup,
131+
scriptClassInfo.getBaseClass(), scriptClassInfo.getExecuteMethodReturnType(), KEYWORDS);
132132
locals.methods = programScope.methods;
133133
// This reference. Internal use only.
134134
locals.defineVariable(null, Object.class, THIS, true);
@@ -146,8 +146,8 @@ public static Locals newMainMethodScope(ScriptClassInfo scriptClassInfo, Locals
146146
}
147147

148148
/** Creates a new program scope: the list of methods. It is the parent for all methods */
149-
public static Locals newProgramScope(PainlessLookup painlessLookup, Collection<LocalMethod> methods) {
150-
Locals locals = new Locals(null, painlessLookup, null, null);
149+
public static Locals newProgramScope(ScriptClassInfo scriptClassInfo, PainlessLookup painlessLookup, Collection<LocalMethod> methods) {
150+
Locals locals = new Locals(null, painlessLookup, scriptClassInfo.getBaseClass(), null, null);
151151
locals.methods = new HashMap<>();
152152
for (LocalMethod method : methods) {
153153
locals.addMethod(method);
@@ -214,10 +214,17 @@ public PainlessLookup getPainlessLookup() {
214214
return painlessLookup;
215215
}
216216

217+
/** Base class for the compiled script. */
218+
public Class<?> getBaseClass() {
219+
return baseClass;
220+
}
221+
217222
///// private impl
218223

219224
/** Whitelist against which this script is being compiled. */
220225
private final PainlessLookup painlessLookup;
226+
/** Base class for the compiled script. */
227+
private final Class<?> baseClass;
221228
// parent scope
222229
private final Locals parent;
223230
// return type of this scope
@@ -235,15 +242,16 @@ public PainlessLookup getPainlessLookup() {
235242
* Create a new Locals
236243
*/
237244
private Locals(Locals parent) {
238-
this(parent, parent.painlessLookup, parent.returnType, parent.keywords);
245+
this(parent, parent.painlessLookup, parent.baseClass, parent.returnType, parent.keywords);
239246
}
240247

241248
/**
242249
* Create a new Locals with specified return type
243250
*/
244-
private Locals(Locals parent, PainlessLookup painlessLookup, Class<?> returnType, Set<String> keywords) {
251+
private Locals(Locals parent, PainlessLookup painlessLookup, Class<?> baseClass, Class<?> returnType, Set<String> keywords) {
245252
this.parent = parent;
246253
this.painlessLookup = painlessLookup;
254+
this.baseClass = baseClass;
247255
this.returnType = returnType;
248256
this.keywords = keywords;
249257
if (parent == null) {

modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ECallLocal.java

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ public final class ECallLocal extends AExpression {
4949
private LocalMethod localMethod = null;
5050
private PainlessMethod importedMethod = null;
5151
private PainlessClassBinding classBinding = null;
52+
private int classBindingOffset = 0;
5253
private PainlessInstanceBinding instanceBinding = null;
5354

5455
public ECallLocal(Location location, String name, List<AExpression> arguments) {
@@ -75,12 +76,37 @@ void analyze(Locals locals) {
7576
if (importedMethod == null) {
7677
classBinding = locals.getPainlessLookup().lookupPainlessClassBinding(name, arguments.size());
7778

79+
// check to see if this class binding requires an implicit this reference
80+
if (classBinding != null && classBinding.typeParameters.isEmpty() == false &&
81+
classBinding.typeParameters.get(0) == locals.getBaseClass()) {
82+
classBinding = null;
83+
}
84+
7885
if (classBinding == null) {
79-
instanceBinding = locals.getPainlessLookup().lookupPainlessInstanceBinding(name, arguments.size());
86+
// This extra check looks for a possible match where the class binding requires an implicit this
87+
// reference. This is a temporary solution to allow the class binding access to data from the
88+
// base script class without need for a user to add additional arguments. A long term solution
89+
// will likely involve adding a class instance binding where any instance can have a class binding
90+
// as part of its API. However, the situation at run-time is difficult and will modifications that
91+
// are a substantial change if even possible to do.
92+
classBinding = locals.getPainlessLookup().lookupPainlessClassBinding(name, arguments.size() + 1);
93+
94+
if (classBinding != null) {
95+
if (classBinding.typeParameters.isEmpty() == false &&
96+
classBinding.typeParameters.get(0) == locals.getBaseClass()) {
97+
classBindingOffset = 1;
98+
} else {
99+
classBinding = null;
100+
}
101+
}
80102

81-
if (instanceBinding == null) {
82-
throw createError(
83-
new IllegalArgumentException("Unknown call [" + name + "] with [" + arguments.size() + "] arguments."));
103+
if (classBinding == null) {
104+
instanceBinding = locals.getPainlessLookup().lookupPainlessInstanceBinding(name, arguments.size());
105+
106+
if (instanceBinding == null) {
107+
throw createError(new IllegalArgumentException(
108+
"Unknown call [" + name + "] with [" + arguments.size() + "] arguments."));
109+
}
84110
}
85111
}
86112
}
@@ -104,10 +130,13 @@ void analyze(Locals locals) {
104130
throw new IllegalStateException("Illegal tree structure.");
105131
}
106132

133+
// if the class binding is using an implicit this reference then the arguments counted must
134+
// be incremented by 1 as the this reference will not be part of the arguments passed into
135+
// the class binding call
107136
for (int argument = 0; argument < arguments.size(); ++argument) {
108137
AExpression expression = arguments.get(argument);
109138

110-
expression.expected = typeParameters.get(argument);
139+
expression.expected = typeParameters.get(argument + classBindingOffset);
111140
expression.internal = true;
112141
expression.analyze(locals);
113142
arguments.set(argument, expression.cast(locals));
@@ -136,7 +165,7 @@ void write(MethodWriter writer, Globals globals) {
136165
} else if (classBinding != null) {
137166
String name = globals.addClassBinding(classBinding.javaConstructor.getDeclaringClass());
138167
Type type = Type.getType(classBinding.javaConstructor.getDeclaringClass());
139-
int javaConstructorParameterCount = classBinding.javaConstructor.getParameterCount();
168+
int javaConstructorParameterCount = classBinding.javaConstructor.getParameterCount() - classBindingOffset;
140169

141170
Label nonNull = new Label();
142171

@@ -147,6 +176,10 @@ void write(MethodWriter writer, Globals globals) {
147176
writer.newInstance(type);
148177
writer.dup();
149178

179+
if (classBindingOffset == 1) {
180+
writer.loadThis();
181+
}
182+
150183
for (int argument = 0; argument < javaConstructorParameterCount; ++argument) {
151184
arguments.get(argument).write(writer, globals);
152185
}

modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SSource.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ public void analyze(PainlessLookup painlessLookup) {
178178
}
179179
}
180180

181-
Locals locals = Locals.newProgramScope(painlessLookup, methods.values());
181+
Locals locals = Locals.newProgramScope(scriptClassInfo, painlessLookup, methods.values());
182182
analyze(locals);
183183
}
184184

modules/lang-painless/src/main/resources/org/elasticsearch/painless/spi/org.elasticsearch.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,5 +266,4 @@ class org.elasticsearch.painless.FeatureTest no_import {
266266
static_import {
267267
int staticAddIntsTest(int, int) from_class org.elasticsearch.painless.StaticTest
268268
float staticAddFloatsTest(float, float) from_class org.elasticsearch.painless.FeatureTest
269-
int testAddWithState(int, int, int, double) bound_to org.elasticsearch.painless.BindingTest
270269
}

modules/lang-painless/src/test/java/org/elasticsearch/painless/BindingsTests.java

Lines changed: 68 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import org.elasticsearch.painless.spi.Whitelist;
2323
import org.elasticsearch.painless.spi.WhitelistInstanceBinding;
24+
import org.elasticsearch.painless.spi.WhitelistLoader;
2425
import org.elasticsearch.script.ScriptContext;
2526

2627
import java.util.ArrayList;
@@ -30,6 +31,44 @@
3031

3132
public class BindingsTests extends ScriptTestCase {
3233

34+
public static class BindingTestClass {
35+
public int state;
36+
37+
public BindingTestClass(int state0, int state1) {
38+
this.state = state0 + state1;
39+
}
40+
41+
public int addWithState(int istateless, double dstateless) {
42+
return istateless + state + (int)dstateless;
43+
}
44+
}
45+
46+
public static class ThisBindingTestClass {
47+
private BindingsTestScript bindingsTestScript;
48+
private int state;
49+
50+
public ThisBindingTestClass(BindingsTestScript bindingsTestScript, int state0, int state1) {
51+
this.bindingsTestScript = bindingsTestScript;
52+
this.state = state0 + state1;
53+
}
54+
55+
public int addThisWithState(int istateless, double dstateless) {
56+
return istateless + state + (int)dstateless + bindingsTestScript.getTestValue();
57+
}
58+
}
59+
60+
public static class EmptyThisBindingTestClass {
61+
private BindingsTestScript bindingsTestScript;
62+
63+
public EmptyThisBindingTestClass(BindingsTestScript bindingsTestScript) {
64+
this.bindingsTestScript = bindingsTestScript;
65+
}
66+
67+
public int addEmptyThisWithState(int istateless) {
68+
return istateless + bindingsTestScript.getTestValue();
69+
}
70+
}
71+
3372
public static class InstanceBindingTestClass {
3473
private int value;
3574

@@ -48,6 +87,7 @@ public int getInstanceBindingValue() {
4887

4988
public abstract static class BindingsTestScript {
5089
public static final String[] PARAMETERS = { "test", "bound" };
90+
public int getTestValue() {return 7;}
5191
public abstract int execute(int test, int bound);
5292
public interface Factory {
5393
BindingsTestScript newInstance();
@@ -59,6 +99,7 @@ public interface Factory {
5999
protected Map<ScriptContext<?>, List<Whitelist>> scriptContexts() {
60100
Map<ScriptContext<?>, List<Whitelist>> contexts = super.scriptContexts();
61101
List<Whitelist> whitelists = new ArrayList<>(Whitelist.BASE_WHITELISTS);
102+
whitelists.add(WhitelistLoader.loadFromResourceFiles(Whitelist.class, "org.elasticsearch.painless.test"));
62103

63104
InstanceBindingTestClass instanceBindingTestClass = new InstanceBindingTestClass(1);
64105
WhitelistInstanceBinding getter = new WhitelistInstanceBinding("test", instanceBindingTestClass,
@@ -77,11 +118,15 @@ protected Map<ScriptContext<?>, List<Whitelist>> scriptContexts() {
77118
}
78119

79120
public void testBasicClassBinding() {
80-
assertEquals(15, exec("testAddWithState(4, 5, 6, 0.0)"));
121+
String script = "addWithState(4, 5, 6, 0.0)";
122+
BindingsTestScript.Factory factory = scriptEngine.compile(null, script, BindingsTestScript.CONTEXT, Collections.emptyMap());
123+
BindingsTestScript executableScript = factory.newInstance();
124+
125+
assertEquals(15, executableScript.execute(0, 0));
81126
}
82127

83128
public void testRepeatedClassBinding() {
84-
String script = "testAddWithState(4, 5, test, 0.0)";
129+
String script = "addWithState(4, 5, test, 0.0)";
85130
BindingsTestScript.Factory factory = scriptEngine.compile(null, script, BindingsTestScript.CONTEXT, Collections.emptyMap());
86131
BindingsTestScript executableScript = factory.newInstance();
87132

@@ -91,14 +136,34 @@ public void testRepeatedClassBinding() {
91136
}
92137

93138
public void testBoundClassBinding() {
94-
String script = "testAddWithState(4, bound, test, 0.0)";
139+
String script = "addWithState(4, bound, test, 0.0)";
95140
BindingsTestScript.Factory factory = scriptEngine.compile(null, script, BindingsTestScript.CONTEXT, Collections.emptyMap());
96141
BindingsTestScript executableScript = factory.newInstance();
97142

98143
assertEquals(10, executableScript.execute(5, 1));
99144
assertEquals(9, executableScript.execute(4, 2));
100145
}
101146

147+
public void testThisClassBinding() {
148+
String script = "addThisWithState(4, bound, test, 0.0)";
149+
150+
BindingsTestScript.Factory factory = scriptEngine.compile(null, script, BindingsTestScript.CONTEXT, Collections.emptyMap());
151+
BindingsTestScript executableScript = factory.newInstance();
152+
153+
assertEquals(17, executableScript.execute(5, 1));
154+
assertEquals(16, executableScript.execute(4, 2));
155+
}
156+
157+
public void testEmptyThisClassBinding() {
158+
String script = "addEmptyThisWithState(test)";
159+
160+
BindingsTestScript.Factory factory = scriptEngine.compile(null, script, BindingsTestScript.CONTEXT, Collections.emptyMap());
161+
BindingsTestScript executableScript = factory.newInstance();
162+
163+
assertEquals(8, executableScript.execute(1, 0));
164+
assertEquals(9, executableScript.execute(2, 0));
165+
}
166+
102167
public void testInstanceBinding() {
103168
String script = "getInstanceBindingValue() + test + bound";
104169
BindingsTestScript.Factory factory = scriptEngine.compile(null, script, BindingsTestScript.CONTEXT, Collections.emptyMap());
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# whitelist for tests
2+
class org.elasticsearch.painless.BindingsTests$BindingsTestScript {
3+
}
4+
5+
static_import {
6+
int addWithState(int, int, int, double) bound_to org.elasticsearch.painless.BindingsTests$BindingTestClass
7+
int addThisWithState(BindingsTests.BindingsTestScript, int, int, int, double) bound_to org.elasticsearch.painless.BindingsTests$ThisBindingTestClass
8+
int addEmptyThisWithState(BindingsTests.BindingsTestScript, int) bound_to org.elasticsearch.painless.BindingsTests$EmptyThisBindingTestClass
9+
}

modules/transport-netty4/src/test/java/org/elasticsearch/transport/netty4/Netty4TransportIT.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ public ExceptionThrowingNetty4Transport(
111111
}
112112

113113
@Override
114-
protected void handleRequest(TcpChannel channel, InboundMessage.RequestMessage request, int messageLengthBytes) throws IOException {
114+
protected void handleRequest(TcpChannel channel, InboundMessage.Request request, int messageLengthBytes) throws IOException {
115115
super.handleRequest(channel, request, messageLengthBytes);
116116
channelProfileName = TransportSettings.DEFAULT_PROFILE;
117117
}

plugins/transport-nio/src/test/java/org/elasticsearch/transport/nio/NioTransportIT.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ public Map<String, Supplier<Transport>> getTransports(Settings settings, ThreadP
113113
}
114114

115115
@Override
116-
protected void handleRequest(TcpChannel channel, InboundMessage.RequestMessage request, int messageLengthBytes) throws IOException {
116+
protected void handleRequest(TcpChannel channel, InboundMessage.Request request, int messageLengthBytes) throws IOException {
117117
super.handleRequest(channel, request, messageLengthBytes);
118118
channelProfileName = TransportSettings.DEFAULT_PROFILE;
119119
}

0 commit comments

Comments
 (0)