Skip to content

Commit 123f2e4

Browse files
authored
Merge branch 'main' into non-issue/knn-k-param
2 parents c659629 + ceff3f1 commit 123f2e4

File tree

37 files changed

+864
-149
lines changed

37 files changed

+864
-149
lines changed

.buildkite/scripts/run-bc-upgrade-tests.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ select(.active_release == true) |
2424
(.build_candidates | to_entries | sort_by(.value.completed_at))) |
2525
last | .value.manifest_url")"
2626

27-
if [[ -z "$MANIFEST_URL" ]]; then
27+
if [[ -z "$MANIFEST_URL" ]] || [[ "$MANIFEST_URL" == "null" ]]; then
2828
echo "No snapshots or build candidates for branch [$BUILDKITE_BRANCH]."
2929
echo "Skipping BC upgrade tests."
3030
exit 0

build-tools-internal/src/main/resources/checkstyle_suppressions.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
<suppress files="qa[/\\]rolling-upgrade[/\\]src[/\\]javaRestTest[/\\]java[/\\]org[/\\]elasticsearch[/\\]upgrades[/\\]TsdbIT.java" checks="LineLength" />
3838
<suppress files="qa[/\\]rolling-upgrade[/\\]src[/\\]javaRestTest[/\\]java[/\\]org[/\\]elasticsearch[/\\]upgrades[/\\]TsdbIndexingRollingUpgradeIT.java" checks="LineLength" />
3939
<suppress files="qa[/\\]rolling-upgrade[/\\]src[/\\]javaRestTest[/\\]java[/\\]org[/\\]elasticsearch[/\\]upgrades[/\\]LogsdbIndexingRollingUpgradeIT.java" checks="LineLength" />
40+
<suppress files="plugin[/\\]logsdb[/\\]qa[/\\]rolling-upgrade[/\\]src[/\\]javaRestTest[/\\]java[/\\]org[/\\]elasticsearch[/\\]upgrades[/\\]MatchOnlyTextRollingUpgradeIT.java" checks="LineLength" />
4041

4142
<!-- Gradle requires inputs to be seriablizable -->
4243
<suppress files="build-tools-internal[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]gradle[/\\]internal[/\\]precommit[/\\]TestingConventionRule.java" checks="RegexpSinglelineJava" />

docs/changelog/125921.yaml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
pr: 125921
2+
summary: Allow direct IO for BBQ rescoring
3+
area: Vector Search
4+
type: feature
5+
highlight:
6+
title: Allow direct IO for BBQ rescoring
7+
body: |-
8+
BBQ rescoring performance can be drastically affected by the amount of available
9+
off-heap RAM for use by the system page cache. When there is not enough off-heap RAM
10+
to fit all the vector data in memory, BBQ search latencies can be affected by as much as 5000x.
11+
Specifying the `vector.rescoring.directio=true` Java option on all vector search
12+
nodes modifies rescoring to use direct IO, which eliminates these very high latencies
13+
from searches in low-memory scenarios, at a cost of a reduction
14+
in vector search performance for BBQ indices when the vectors do all fit in memory.
15+
16+
This option is released in 9.1 as a tech preview whilst we analyse its effect
17+
for a variety of use cases.
18+
issues: []

docs/changelog/129990.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 129990
2+
summary: Make forecast write load accurate when shard numbers change
3+
area: Allocation
4+
type: bug
5+
issues: []

docs/reference/elasticsearch/rest-apis/api-conventions.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,39 @@ GET /_nodes/ra*:2
421421
GET /_nodes/ra*:2*
422422
```
423423

424+
### Component Selectors [api-component-selectors]
425+
426+
A data stream component is a logical grouping of indices that help organize data inside a data stream. All data streams contain a `data` component by default. The `data` component comprises the data stream's backing indices. When searching, managing, or indexing into a data stream, the `data` component is what you are interacting with by default.
427+
428+
Some data stream features are exposed as additional components alongside its `data` component. These other components are comprised of separate sets of backing indices. These additional components store supplemental data independent of the data stream's regular backing indices. An example of another component is the `failures` component exposed by the data stream [failure store](docs-content://manage-data/data-store/data-streams/failure-store.md) feature, which captures documents that fail to be ingested in a separate set of backing indices on the data stream.
429+
430+
Some APIs that accept a `<data-stream>`, `<index>`, or `<target>` request path parameter also support *selector syntax* which defines which component on a data stream the API should operate on. To use a selector, it is appended to the index or data stream name. Selectors can be combined with other index pattern syntax like [date math](#api-date-math-index-names) and wildcards.
431+
432+
There are currently two selector suffixes supported by {{es}} APIs:
433+
434+
`::data`
435+
: Refers to a data stream's backing indices containing regular data. Data streams always contain a data component.
436+
437+
`::failures`
438+
: This component refers to the internal indices used for a data stream's [failure store](docs-content://manage-data/data-store/data-streams/failure-store.md).
439+
440+
As an example, [search]({{es-apis}}group/endpoint-search), [field capabilities]({{es-apis}}operation/operation-field-caps), and [index stats]({{es-apis}}operation/operation-indices-stats) APIs can all report results from a different component rather than from the default data.
441+
442+
```console
443+
# Search a data stream normally
444+
GET my-data-stream/_search
445+
# Search a data stream's failure data if present
446+
GET my-data-stream::failures/_search
447+
448+
# Syntax can be combined with other index pattern syntax (wildcards, multi-target, date math, cross cluster search, etc)
449+
GET logs-*::failures/_search
450+
GET logs-*::data,logs-*::failures/_count
451+
GET remote-cluster:logs-*-*::failures/_search
452+
GET *::data,*::failures,-logs-rdbms-*::failures/_stats
453+
GET <logs-{now/d}>::failures/_search
454+
```
455+
456+
424457
## Parameters [api-conventions-parameters]
425458

426459
Rest parameters (when using HTTP, map to HTTP URL parameters) follow the convention of using underscore casing.

modules/data-streams/src/main/java/org/elasticsearch/datastreams/action/TransportUpdateDataStreamSettingsAction.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -222,9 +222,7 @@ private void updateSettingsOnIndices(
222222
Map<String, Object> settingsToApply = new HashMap<>();
223223
List<String> appliedToDataStreamOnly = new ArrayList<>();
224224
List<String> appliedToDataStreamAndBackingIndices = new ArrayList<>();
225-
Settings effectiveSettings = dataStream.getEffectiveSettings(
226-
clusterService.state().projectState(projectResolver.getProjectId()).metadata()
227-
);
225+
Settings effectiveSettings = dataStream.getEffectiveSettings(projectResolver.getProjectMetadata(clusterService.state()));
228226
for (String settingName : requestSettings.keySet()) {
229227
if (APPLY_TO_BACKING_INDICES.contains(settingName)) {
230228
settingsToApply.put(settingName, effectiveSettings.get(settingName));

modules/ingest-geoip/src/main/java/org/elasticsearch/ingest/geoip/EnterpriseGeoIpTaskState.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ public void writeTo(StreamOutput out) throws IOException {
151151
@FixForMultiProject(description = "Replace ProjectId.DEFAULT")
152152
static EnterpriseGeoIpTaskState getEnterpriseGeoIpTaskState(ClusterState state) {
153153
PersistentTasksCustomMetadata.PersistentTask<?> task = getTaskWithId(
154-
state.projectState(ProjectId.DEFAULT).metadata(),
154+
state.metadata().getProject(ProjectId.DEFAULT),
155155
EnterpriseGeoIpTask.ENTERPRISE_GEOIP_DOWNLOADER
156156
);
157157
return (task == null) ? null : (EnterpriseGeoIpTaskState) task.getState();

modules/ingest-geoip/src/main/java/org/elasticsearch/ingest/geoip/direct/TransportPutDatabaseConfigurationAction.java

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020
import org.elasticsearch.cluster.SimpleBatchedExecutor;
2121
import org.elasticsearch.cluster.block.ClusterBlockException;
2222
import org.elasticsearch.cluster.block.ClusterBlockLevel;
23+
import org.elasticsearch.cluster.metadata.ProjectId;
2324
import org.elasticsearch.cluster.metadata.ProjectMetadata;
25+
import org.elasticsearch.cluster.project.ProjectResolver;
2426
import org.elasticsearch.cluster.service.ClusterService;
2527
import org.elasticsearch.cluster.service.MasterServiceTaskQueue;
2628
import org.elasticsearch.common.Priority;
@@ -58,13 +60,15 @@ public void taskSucceeded(UpdateDatabaseConfigurationTask task, Void unused) {
5860
};
5961

6062
private final MasterServiceTaskQueue<UpdateDatabaseConfigurationTask> updateDatabaseConfigurationTaskQueue;
63+
private final ProjectResolver projectResolver;
6164

6265
@Inject
6366
public TransportPutDatabaseConfigurationAction(
6467
TransportService transportService,
6568
ClusterService clusterService,
6669
ThreadPool threadPool,
67-
ActionFilters actionFilters
70+
ActionFilters actionFilters,
71+
ProjectResolver projectResolver
6872
) {
6973
super(
7074
PutDatabaseConfigurationAction.NAME,
@@ -81,6 +85,7 @@ public TransportPutDatabaseConfigurationAction(
8185
Priority.NORMAL,
8286
UPDATE_TASK_EXECUTOR
8387
);
88+
this.projectResolver = projectResolver;
8489
}
8590

8691
@Override
@@ -89,7 +94,7 @@ protected void masterOperation(Task task, Request request, ClusterState state, A
8994

9095
updateDatabaseConfigurationTaskQueue.submitTask(
9196
Strings.format("update-geoip-database-configuration-[%s]", id),
92-
new UpdateDatabaseConfigurationTask(listener, request.getDatabase()),
97+
new UpdateDatabaseConfigurationTask(projectResolver.getProjectId(), listener, request.getDatabase()),
9398
null
9499
);
95100
}
@@ -105,9 +110,9 @@ static boolean isNoopUpdate(@Nullable DatabaseConfigurationMetadata existingData
105110
}
106111
}
107112

108-
static void validatePrerequisites(DatabaseConfiguration database, ClusterState state) {
113+
static void validatePrerequisites(ProjectId projectId, DatabaseConfiguration database, ClusterState state) {
109114
// we need to verify that the database represents a unique file (name) among the various databases for this same provider
110-
IngestGeoIpMetadata geoIpMeta = state.metadata().getProject().custom(IngestGeoIpMetadata.TYPE, IngestGeoIpMetadata.EMPTY);
115+
IngestGeoIpMetadata geoIpMeta = state.metadata().getProject(projectId).custom(IngestGeoIpMetadata.TYPE, IngestGeoIpMetadata.EMPTY);
111116

112117
Optional<DatabaseConfiguration> sameName = geoIpMeta.getDatabases()
113118
.values()
@@ -125,12 +130,14 @@ static void validatePrerequisites(DatabaseConfiguration database, ClusterState s
125130
});
126131
}
127132

128-
private record UpdateDatabaseConfigurationTask(ActionListener<AcknowledgedResponse> listener, DatabaseConfiguration database)
129-
implements
130-
ClusterStateTaskListener {
133+
private record UpdateDatabaseConfigurationTask(
134+
ProjectId projectId,
135+
ActionListener<AcknowledgedResponse> listener,
136+
DatabaseConfiguration database
137+
) implements ClusterStateTaskListener {
131138

132139
ClusterState execute(ClusterState currentState) throws Exception {
133-
final var project = currentState.metadata().getProject();
140+
final var project = currentState.metadata().getProject(projectId);
134141
IngestGeoIpMetadata geoIpMeta = project.custom(IngestGeoIpMetadata.TYPE, IngestGeoIpMetadata.EMPTY);
135142

136143
String id = database.id();
@@ -140,7 +147,7 @@ ClusterState execute(ClusterState currentState) throws Exception {
140147
return currentState;
141148
}
142149

143-
validatePrerequisites(database, currentState);
150+
validatePrerequisites(projectId, database, currentState);
144151

145152
Map<String, DatabaseConfigurationMetadata> databases = new HashMap<>(geoIpMeta.getDatabases());
146153
databases.put(

modules/ingest-geoip/src/test/java/org/elasticsearch/ingest/geoip/direct/TransportPutDatabaseConfigurationActionTests.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
package org.elasticsearch.ingest.geoip.direct;
1111

1212
import org.elasticsearch.cluster.ClusterState;
13-
import org.elasticsearch.cluster.metadata.Metadata;
13+
import org.elasticsearch.cluster.metadata.ProjectId;
14+
import org.elasticsearch.cluster.metadata.ProjectMetadata;
1415
import org.elasticsearch.ingest.geoip.IngestGeoIpMetadata;
1516
import org.elasticsearch.test.ESTestCase;
1617

@@ -20,33 +21,34 @@
2021
public class TransportPutDatabaseConfigurationActionTests extends ESTestCase {
2122

2223
public void testValidatePrerequisites() {
24+
ProjectId projectId = randomProjectIdOrDefault();
2325
// Test that we reject two configurations with the same database name but different ids:
2426
String name = randomAlphaOfLengthBetween(1, 50);
2527
IngestGeoIpMetadata ingestGeoIpMetadata = randomIngestGeoIpMetadata(name);
2628
ClusterState state = ClusterState.builder(ClusterState.EMPTY_STATE)
27-
.metadata(Metadata.builder(Metadata.EMPTY_METADATA).putCustom(IngestGeoIpMetadata.TYPE, ingestGeoIpMetadata))
29+
.putProjectMetadata(ProjectMetadata.builder(projectId).putCustom(IngestGeoIpMetadata.TYPE, ingestGeoIpMetadata).build())
2830
.build();
2931
DatabaseConfiguration databaseConfiguration = randomDatabaseConfiguration(randomIdentifier(), name);
3032
expectThrows(
3133
IllegalArgumentException.class,
32-
() -> TransportPutDatabaseConfigurationAction.validatePrerequisites(databaseConfiguration, state)
34+
() -> TransportPutDatabaseConfigurationAction.validatePrerequisites(projectId, databaseConfiguration, state)
3335
);
3436

3537
// Test that we do not reject two configurations with different database names:
3638
String differentName = randomValueOtherThan(name, () -> randomAlphaOfLengthBetween(1, 50));
3739
DatabaseConfiguration databaseConfigurationForDifferentName = randomDatabaseConfiguration(randomIdentifier(), differentName);
38-
TransportPutDatabaseConfigurationAction.validatePrerequisites(databaseConfigurationForDifferentName, state);
40+
TransportPutDatabaseConfigurationAction.validatePrerequisites(projectId, databaseConfigurationForDifferentName, state);
3941

4042
// Test that we do not reject a configuration if none already exists:
41-
TransportPutDatabaseConfigurationAction.validatePrerequisites(databaseConfiguration, ClusterState.EMPTY_STATE);
43+
TransportPutDatabaseConfigurationAction.validatePrerequisites(projectId, databaseConfiguration, ClusterState.EMPTY_STATE);
4244

4345
// Test that we do not reject a configuration if one with the same database name AND id already exists:
4446
DatabaseConfiguration databaseConfigurationSameNameSameId = ingestGeoIpMetadata.getDatabases()
4547
.values()
4648
.iterator()
4749
.next()
4850
.database();
49-
TransportPutDatabaseConfigurationAction.validatePrerequisites(databaseConfigurationSameNameSameId, state);
51+
TransportPutDatabaseConfigurationAction.validatePrerequisites(projectId, databaseConfigurationSameNameSameId, state);
5052
}
5153

5254
private IngestGeoIpMetadata randomIngestGeoIpMetadata(String name) {

modules/mapper-extras/src/main/java/org/elasticsearch/index/mapper/extras/MatchOnlyTextFieldMapper.java

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -362,10 +362,38 @@ public Query phrasePrefixQuery(TokenStream stream, int slop, int maxExpansions,
362362
return toQuery(query, queryShardContext);
363363
}
364364

365+
private static class BytesFromMixedStringsBytesRefBlockLoader extends BlockStoredFieldsReader.StoredFieldsBlockLoader {
366+
BytesFromMixedStringsBytesRefBlockLoader(String field) {
367+
super(field);
368+
}
369+
370+
@Override
371+
public Builder builder(BlockFactory factory, int expectedCount) {
372+
return factory.bytesRefs(expectedCount);
373+
}
374+
375+
@Override
376+
public RowStrideReader rowStrideReader(LeafReaderContext context) throws IOException {
377+
return new BlockStoredFieldsReader.Bytes(field) {
378+
private final BytesRef scratch = new BytesRef();
379+
380+
@Override
381+
protected BytesRef toBytesRef(Object v) {
382+
if (v instanceof BytesRef b) {
383+
return b;
384+
} else {
385+
assert v instanceof String;
386+
return BlockSourceReader.toBytesRef(scratch, v.toString());
387+
}
388+
}
389+
};
390+
}
391+
}
392+
365393
@Override
366394
public BlockLoader blockLoader(BlockLoaderContext blContext) {
367395
if (textFieldType.isSyntheticSource()) {
368-
return new BlockStoredFieldsReader.BytesFromBytesRefsBlockLoader(storedFieldNameForSyntheticSource());
396+
return new BytesFromMixedStringsBytesRefBlockLoader(storedFieldNameForSyntheticSource());
369397
}
370398
SourceValueFetcher fetcher = SourceValueFetcher.toString(blContext.sourcePaths(name()));
371399
// MatchOnlyText never has norms, so we have to use the field names field
@@ -386,7 +414,12 @@ public IndexFieldData.Builder fielddataBuilder(FieldDataContext fieldDataContext
386414
) {
387415
@Override
388416
protected BytesRef storedToBytesRef(Object stored) {
389-
return (BytesRef) stored;
417+
if (stored instanceof BytesRef storedBytes) {
418+
return storedBytes;
419+
} else {
420+
assert stored instanceof String;
421+
return new BytesRef(stored.toString());
422+
}
390423
}
391424
};
392425
}
@@ -477,7 +510,12 @@ protected SyntheticSourceSupport syntheticSourceSupport() {
477510
() -> new StringStoredFieldFieldLoader(fieldType().storedFieldNameForSyntheticSource(), fieldType().name(), leafName()) {
478511
@Override
479512
protected void write(XContentBuilder b, Object value) throws IOException {
480-
b.value(((BytesRef) value).utf8ToString());
513+
if (value instanceof BytesRef valueBytes) {
514+
b.value(valueBytes.utf8ToString());
515+
} else {
516+
assert value instanceof String;
517+
b.value(value.toString());
518+
}
481519
}
482520
}
483521
);

0 commit comments

Comments
 (0)