Skip to content

Commit d72a0c0

Browse files
Merge branch 'main' into avoid-walking-all-contexts
2 parents 546a0d8 + af686b2 commit d72a0c0

File tree

355 files changed

+9438
-5833
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

355 files changed

+9438
-5833
lines changed

.buildkite/scripts/dra-workflow.sh

+1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ echo --- Building release artifacts
7070
$VERSION_QUALIFIER_ARG \
7171
buildReleaseArtifacts \
7272
exportCompressedDockerImages \
73+
exportDockerContexts \
7374
:distribution:generateDependenciesReport
7475

7576
PATH="$PATH:${JAVA_HOME}/bin" # Required by the following script

benchmarks/src/main/java/org/elasticsearch/benchmark/routing/allocation/AllocationBenchmark.java

+9-5
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@
1414
import org.elasticsearch.cluster.ClusterState;
1515
import org.elasticsearch.cluster.metadata.IndexMetadata;
1616
import org.elasticsearch.cluster.metadata.Metadata;
17+
import org.elasticsearch.cluster.metadata.ProjectId;
18+
import org.elasticsearch.cluster.metadata.ProjectMetadata;
1719
import org.elasticsearch.cluster.node.DiscoveryNodes;
20+
import org.elasticsearch.cluster.routing.GlobalRoutingTable;
1821
import org.elasticsearch.cluster.routing.RoutingTable;
1922
import org.elasticsearch.cluster.routing.ShardRouting;
2023
import org.elasticsearch.cluster.routing.allocation.AllocationService;
@@ -126,19 +129,20 @@ public void setUp() throws Exception {
126129
Settings.builder().put("cluster.routing.allocation.awareness.attributes", "tag").build()
127130
);
128131

129-
Metadata.Builder mb = Metadata.builder();
132+
final ProjectId projectId = ProjectId.DEFAULT;
133+
ProjectMetadata.Builder pmb = ProjectMetadata.builder(projectId);
130134
for (int i = 1; i <= numIndices; i++) {
131-
mb.put(
135+
pmb.put(
132136
IndexMetadata.builder("test_" + i)
133137
.settings(Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, IndexVersion.current()))
134138
.numberOfShards(numShards)
135139
.numberOfReplicas(numReplicas)
136140
);
137141
}
138-
Metadata metadata = mb.build();
142+
Metadata metadata = Metadata.builder().put(pmb).build();
139143
RoutingTable.Builder rb = RoutingTable.builder(TestShardRoutingRoleStrategies.DEFAULT_ROLE_ONLY);
140144
for (int i = 1; i <= numIndices; i++) {
141-
rb.addAsNew(metadata.getProject().index("test_" + i));
145+
rb.addAsNew(metadata.getProject(projectId).index("test_" + i));
142146
}
143147
RoutingTable routingTable = rb.build();
144148
DiscoveryNodes.Builder nb = DiscoveryNodes.builder();
@@ -151,7 +155,7 @@ public void setUp() throws Exception {
151155
}
152156
initialClusterState = ClusterState.builder(ClusterName.DEFAULT)
153157
.metadata(metadata)
154-
.routingTable(routingTable)
158+
.routingTable(GlobalRoutingTable.builder().put(projectId, routingTable).build())
155159
.nodes(nb)
156160
.nodeIdsToCompatibilityVersions(compatibilityVersions)
157161
.build();

benchmarks/src/main/java/org/elasticsearch/benchmark/vector/VectorScorerBenchmark.java

+13-8
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import org.apache.lucene.store.MMapDirectory;
2020
import org.apache.lucene.util.hnsw.RandomVectorScorer;
2121
import org.apache.lucene.util.hnsw.RandomVectorScorerSupplier;
22+
import org.apache.lucene.util.hnsw.UpdateableRandomVectorScorer;
2223
import org.apache.lucene.util.quantization.QuantizedByteVectorValues;
2324
import org.apache.lucene.util.quantization.ScalarQuantizer;
2425
import org.elasticsearch.common.logging.LogConfigurator;
@@ -76,10 +77,10 @@ public class VectorScorerBenchmark {
7677
float vec2Offset;
7778
float scoreCorrectionConstant;
7879

79-
RandomVectorScorer luceneDotScorer;
80-
RandomVectorScorer luceneSqrScorer;
81-
RandomVectorScorer nativeDotScorer;
82-
RandomVectorScorer nativeSqrScorer;
80+
UpdateableRandomVectorScorer luceneDotScorer;
81+
UpdateableRandomVectorScorer luceneSqrScorer;
82+
UpdateableRandomVectorScorer nativeDotScorer;
83+
UpdateableRandomVectorScorer nativeSqrScorer;
8384

8485
RandomVectorScorer luceneDotScorerQuery;
8586
RandomVectorScorer nativeDotScorerQuery;
@@ -118,12 +119,16 @@ public void setup() throws IOException {
118119
in = dir.openInput("vector.data", IOContext.DEFAULT);
119120
var values = vectorValues(dims, 2, in, VectorSimilarityFunction.DOT_PRODUCT);
120121
scoreCorrectionConstant = values.getScalarQuantizer().getConstantMultiplier();
121-
luceneDotScorer = luceneScoreSupplier(values, VectorSimilarityFunction.DOT_PRODUCT).scorer(0);
122+
luceneDotScorer = luceneScoreSupplier(values, VectorSimilarityFunction.DOT_PRODUCT).scorer();
123+
luceneDotScorer.setScoringOrdinal(0);
122124
values = vectorValues(dims, 2, in, VectorSimilarityFunction.EUCLIDEAN);
123-
luceneSqrScorer = luceneScoreSupplier(values, VectorSimilarityFunction.EUCLIDEAN).scorer(0);
125+
luceneSqrScorer = luceneScoreSupplier(values, VectorSimilarityFunction.EUCLIDEAN).scorer();
126+
luceneSqrScorer.setScoringOrdinal(0);
124127

125-
nativeDotScorer = factory.getInt7SQVectorScorerSupplier(DOT_PRODUCT, in, values, scoreCorrectionConstant).get().scorer(0);
126-
nativeSqrScorer = factory.getInt7SQVectorScorerSupplier(EUCLIDEAN, in, values, scoreCorrectionConstant).get().scorer(0);
128+
nativeDotScorer = factory.getInt7SQVectorScorerSupplier(DOT_PRODUCT, in, values, scoreCorrectionConstant).get().scorer();
129+
nativeDotScorer.setScoringOrdinal(0);
130+
nativeSqrScorer = factory.getInt7SQVectorScorerSupplier(EUCLIDEAN, in, values, scoreCorrectionConstant).get().scorer();
131+
nativeSqrScorer.setScoringOrdinal(0);
127132

128133
// setup for getInt7SQVectorScorer / query vector scoring
129134
float[] queryVec = new float[dims];
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
package org.elasticsearch.gradle.internal.dependencies.patches;
11+
12+
import org.objectweb.asm.ClassVisitor;
13+
import org.objectweb.asm.ClassWriter;
14+
15+
import java.util.Arrays;
16+
import java.util.HexFormat;
17+
import java.util.function.Function;
18+
19+
public final class PatcherInfo {
20+
private final String jarEntryName;
21+
private final byte[] classSha256;
22+
private final Function<ClassWriter, ClassVisitor> visitorFactory;
23+
24+
private PatcherInfo(String jarEntryName, byte[] classSha256, Function<ClassWriter, ClassVisitor> visitorFactory) {
25+
this.jarEntryName = jarEntryName;
26+
this.classSha256 = classSha256;
27+
this.visitorFactory = visitorFactory;
28+
}
29+
30+
/**
31+
* Creates a patcher info entry, linking a jar entry path name and its SHA256 digest to a patcher factory (a factory to create an ASM
32+
* visitor)
33+
*
34+
* @param jarEntryName the jar entry path, as a string
35+
* @param classSha256 the SHA256 digest of the class bytes, as a HEX string
36+
* @param visitorFactory the factory to create an ASM visitor from a ASM writer
37+
*/
38+
public static PatcherInfo classPatcher(String jarEntryName, String classSha256, Function<ClassWriter, ClassVisitor> visitorFactory) {
39+
return new PatcherInfo(jarEntryName, HexFormat.of().parseHex(classSha256), visitorFactory);
40+
}
41+
42+
boolean matches(byte[] otherClassSha256) {
43+
return Arrays.equals(this.classSha256, otherClassSha256);
44+
}
45+
46+
public String jarEntryName() {
47+
return jarEntryName;
48+
}
49+
50+
public byte[] classSha256() {
51+
return classSha256;
52+
}
53+
54+
public ClassVisitor createVisitor(ClassWriter classWriter) {
55+
return visitorFactory.apply(classWriter);
56+
}
57+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
package org.elasticsearch.gradle.internal.dependencies.patches;
11+
12+
import org.objectweb.asm.ClassReader;
13+
import org.objectweb.asm.ClassWriter;
14+
15+
import java.io.File;
16+
import java.io.FileOutputStream;
17+
import java.io.IOException;
18+
import java.io.InputStream;
19+
import java.security.MessageDigest;
20+
import java.security.NoSuchAlgorithmException;
21+
import java.util.ArrayList;
22+
import java.util.Collection;
23+
import java.util.Enumeration;
24+
import java.util.HexFormat;
25+
import java.util.Locale;
26+
import java.util.function.Function;
27+
import java.util.jar.JarEntry;
28+
import java.util.jar.JarFile;
29+
import java.util.jar.JarOutputStream;
30+
import java.util.stream.Collectors;
31+
32+
import static org.objectweb.asm.ClassWriter.COMPUTE_FRAMES;
33+
import static org.objectweb.asm.ClassWriter.COMPUTE_MAXS;
34+
35+
public class Utils {
36+
37+
private static final MessageDigest SHA_256;
38+
39+
static {
40+
try {
41+
SHA_256 = MessageDigest.getInstance("SHA-256");
42+
} catch (NoSuchAlgorithmException e) {
43+
throw new RuntimeException(e);
44+
}
45+
}
46+
47+
private record MismatchInfo(String jarEntryName, String expectedClassSha256, String foundClassSha256) {
48+
@Override
49+
public String toString() {
50+
return "[class='"
51+
+ jarEntryName
52+
+ '\''
53+
+ ", expected='"
54+
+ expectedClassSha256
55+
+ '\''
56+
+ ", found='"
57+
+ foundClassSha256
58+
+ '\''
59+
+ ']';
60+
}
61+
}
62+
63+
/**
64+
* Patches the classes in the input JAR file, using the collection of patchers. Each patcher specifies a target class (its jar entry
65+
* name) and the SHA256 digest on the class bytes.
66+
* This digest is checked against the class bytes in the JAR, and if it does not match, an IllegalArgumentException is thrown.
67+
* If the input file does not contain all the classes to patch specified in the patcher info collection, an IllegalArgumentException
68+
* is also thrown.
69+
* @param inputFile the JAR file to patch
70+
* @param outputFile the output (patched) JAR file
71+
* @param patchers list of patcher info (classes to patch (jar entry name + optional SHA256 digest) and ASM visitor to transform them)
72+
*/
73+
public static void patchJar(File inputFile, File outputFile, Collection<PatcherInfo> patchers) {
74+
var classPatchers = patchers.stream().collect(Collectors.toMap(PatcherInfo::jarEntryName, Function.identity()));
75+
var mismatchedClasses = new ArrayList<MismatchInfo>();
76+
try (JarFile jarFile = new JarFile(inputFile); JarOutputStream jos = new JarOutputStream(new FileOutputStream(outputFile))) {
77+
Enumeration<JarEntry> entries = jarFile.entries();
78+
while (entries.hasMoreElements()) {
79+
JarEntry entry = entries.nextElement();
80+
String entryName = entry.getName();
81+
// Add the entry to the new JAR file
82+
jos.putNextEntry(new JarEntry(entryName));
83+
84+
var classPatcher = classPatchers.remove(entryName);
85+
if (classPatcher != null) {
86+
byte[] classToPatch = jarFile.getInputStream(entry).readAllBytes();
87+
var classSha256 = SHA_256.digest(classToPatch);
88+
89+
if (classPatcher.matches(classSha256)) {
90+
ClassReader classReader = new ClassReader(classToPatch);
91+
ClassWriter classWriter = new ClassWriter(classReader, COMPUTE_MAXS | COMPUTE_FRAMES);
92+
classReader.accept(classPatcher.createVisitor(classWriter), 0);
93+
jos.write(classWriter.toByteArray());
94+
} else {
95+
mismatchedClasses.add(
96+
new MismatchInfo(
97+
classPatcher.jarEntryName(),
98+
HexFormat.of().formatHex(classPatcher.classSha256()),
99+
HexFormat.of().formatHex(classSha256)
100+
)
101+
);
102+
}
103+
} else {
104+
// Read the entry's data and write it to the new JAR
105+
try (InputStream is = jarFile.getInputStream(entry)) {
106+
is.transferTo(jos);
107+
}
108+
}
109+
jos.closeEntry();
110+
}
111+
} catch (IOException ex) {
112+
throw new RuntimeException(ex);
113+
}
114+
115+
if (mismatchedClasses.isEmpty() == false) {
116+
throw new IllegalArgumentException(
117+
String.format(
118+
Locale.ROOT,
119+
"""
120+
Error patching JAR [%s]: SHA256 digest mismatch (%s). This JAR was updated to a version that contains different \
121+
classes, for which this patcher was not designed. Please check if the patcher still \
122+
applies correctly, and update the SHA256 digest(s).""",
123+
inputFile.getName(),
124+
mismatchedClasses.stream().map(MismatchInfo::toString).collect(Collectors.joining())
125+
)
126+
);
127+
}
128+
129+
if (classPatchers.isEmpty() == false) {
130+
throw new IllegalArgumentException(
131+
String.format(
132+
Locale.ROOT,
133+
"error patching [%s]: the jar does not contain [%s]",
134+
inputFile.getName(),
135+
String.join(", ", classPatchers.keySet())
136+
)
137+
);
138+
}
139+
}
140+
}

0 commit comments

Comments
 (0)