Skip to content

Commit 05ca1da

Browse files
committed
Merge commit '83fe2eda5cabce7a1a6e8191d63a33ae25b40291' into 2025/05/23/ES-11815
2 parents ab50b34 + 83fe2ed commit 05ca1da

File tree

44 files changed

+751
-200
lines changed

Some content is hidden

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

44 files changed

+751
-200
lines changed

docs/changelog/126581.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
pr: 126581
2+
summary: "Optimize shared blob cache evictions on shard removal
3+
Shared blob cache evictions occur on the cluster applier thread when shards are
4+
removed from a node. These can be expensive if a large number of shards are
5+
being removed. This change uses the context of the removal to avoid unnecessary
6+
evictions that might hold up the applier thread.
7+
"
8+
area: Snapshot/Restore
9+
type: enhancement
10+
issues: []

docs/reference/aggregations/search-aggregations-bucket-significantterms-aggregation.md

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -253,8 +253,8 @@ Like most design decisions, this is the basis of a trade-off in which we have ch
253253
The JLH score can be used as a significance score by adding the parameter
254254

255255
```js
256-
"jlh": {
257-
}
256+
"jlh": {
257+
}
258258
```
259259

260260
The scores are derived from the doc frequencies in *foreground* and *background* sets. The *absolute* change in popularity (foregroundPercent - backgroundPercent) would favor common terms whereas the *relative* change in popularity (foregroundPercent/ backgroundPercent) would favor rare terms. Rare vs common is essentially a precision vs recall balance and so the absolute and relative changes are multiplied to provide a sweet spot between precision and recall.
@@ -265,9 +265,9 @@ The scores are derived from the doc frequencies in *foreground* and *background*
265265
Mutual information as described in "Information Retrieval", Manning et al., Chapter 13.5.1 can be used as significance score by adding the parameter
266266

267267
```js
268-
"mutual_information": {
269-
"include_negatives": true
270-
}
268+
"mutual_information": {
269+
"include_negatives": true
270+
}
271271
```
272272

273273
Mutual information does not differentiate between terms that are descriptive for the subset or for documents outside the subset. The significant terms therefore can contain terms that appear more or less frequent in the subset than outside the subset. To filter out the terms that appear less often in the subset than in documents outside the subset, `include_negatives` can be set to `false`.
@@ -284,8 +284,8 @@ Per default, the assumption is that the documents in the bucket are also contain
284284
Chi square as described in "Information Retrieval", Manning et al., Chapter 13.5.2 can be used as significance score by adding the parameter
285285

286286
```js
287-
"chi_square": {
288-
}
287+
"chi_square": {
288+
}
289289
```
290290

291291
Chi square behaves like mutual information and can be configured with the same parameters `include_negatives` and `background_is_superset`.
@@ -296,8 +296,8 @@ Chi square behaves like mutual information and can be configured with the same p
296296
Google normalized distance as described in ["The Google Similarity Distance", Cilibrasi and Vitanyi, 2007](https://arxiv.org/pdf/cs/0412098v3.pdf) can be used as significance score by adding the parameter
297297

298298
```js
299-
"gnd": {
300-
}
299+
"gnd": {
300+
}
301301
```
302302

303303
`gnd` also accepts the `background_is_superset` parameter.
@@ -394,8 +394,8 @@ The benefit of this heuristic is that the scoring logic is simple to explain to
394394
It would be hard for a seasoned boxer to win a championship if the prize was awarded purely on the basis of percentage of fights won - by these rules a newcomer with only one fight under their belt would be impossible to beat. Multiple observations are typically required to reinforce a view so it is recommended in these cases to set both `min_doc_count` and `shard_min_doc_count` to a higher value such as 10 in order to filter out the low-frequency terms that otherwise take precedence.
395395

396396
```js
397-
"percentage": {
398-
}
397+
"percentage": {
398+
}
399399
```
400400

401401

@@ -413,11 +413,11 @@ If none of the above measures suits your usecase than another option is to imple
413413
Customized scores can be implemented via a script:
414414

415415
```js
416-
"script_heuristic": {
416+
"script_heuristic": {
417417
"script": {
418-
"lang": "painless",
419-
"source": "params._subset_freq/(params._superset_freq - params._subset_freq + 1)"
420-
}
418+
"lang": "painless",
419+
"source": "params._subset_freq/(params._superset_freq - params._subset_freq + 1)"
420+
}
421421
}
422422
```
423423

docs/reference/elasticsearch-plugins/discovery-azure-classic-scale.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ mapped_pages:
33
- https://www.elastic.co/guide/en/elasticsearch/plugins/current/discovery-azure-classic-scale.html
44
---
55

6-
# Scaling out! [discovery-azure-classic-scale]
6+
# Scaling out [discovery-azure-classic-scale]
77

88
You need first to create an image of your previous machine. Disconnect from your machine and run locally the following commands:
99

muted-tests.yml

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -474,15 +474,6 @@ tests:
474474
- class: org.elasticsearch.packaging.test.TemporaryDirectoryConfigTests
475475
method: test21AcceptsCustomPathInDocker
476476
issue: https://github.com/elastic/elasticsearch/issues/128114
477-
- class: org.elasticsearch.reservedstate.service.FileSettingsServiceIT
478-
method: testSymlinkUpdateTriggerReload
479-
issue: https://github.com/elastic/elasticsearch/issues/128369
480-
- class: org.elasticsearch.xpack.esql.qa.single_node.PushQueriesIT
481-
method: testEqualityAndOther {semantic_text}
482-
issue: https://github.com/elastic/elasticsearch/issues/128414
483-
- class: org.elasticsearch.index.query.MultiMatchQueryBuilderTests
484-
method: testToQuery
485-
issue: https://github.com/elastic/elasticsearch/issues/128416
486477
- class: org.elasticsearch.xpack.ml.integration.InferenceIngestIT
487478
method: testPipelineIngestWithModelAliases
488479
issue: https://github.com/elastic/elasticsearch/issues/128417

server/src/internalClusterTest/java/org/elasticsearch/plugins/IndexFoldersDeletionListenerIT.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.elasticsearch.index.IndexSettings;
2323
import org.elasticsearch.index.shard.ShardId;
2424
import org.elasticsearch.indices.IndicesService;
25+
import org.elasticsearch.indices.cluster.IndexRemovalReason;
2526
import org.elasticsearch.test.ESIntegTestCase;
2627
import org.elasticsearch.test.junit.annotations.TestLogging;
2728

@@ -345,12 +346,22 @@ public static class IndexFoldersDeletionListenerPlugin extends Plugin implements
345346
public List<IndexFoldersDeletionListener> getIndexFoldersDeletionListeners() {
346347
return List.of(new IndexFoldersDeletionListener() {
347348
@Override
348-
public void beforeIndexFoldersDeleted(Index index, IndexSettings indexSettings, Path[] indexPaths) {
349+
public void beforeIndexFoldersDeleted(
350+
Index index,
351+
IndexSettings indexSettings,
352+
Path[] indexPaths,
353+
IndexRemovalReason reason
354+
) {
349355
deletedIndices.add(index);
350356
}
351357

352358
@Override
353-
public void beforeShardFoldersDeleted(ShardId shardId, IndexSettings indexSettings, Path[] shardPaths) {
359+
public void beforeShardFoldersDeleted(
360+
ShardId shardId,
361+
IndexSettings indexSettings,
362+
Path[] shardPaths,
363+
IndexRemovalReason reason
364+
) {
354365
deletedShards.computeIfAbsent(shardId.getIndex(), i -> Collections.synchronizedList(new ArrayList<>())).add(shardId);
355366
}
356367
});

server/src/internalClusterTest/java/org/elasticsearch/reservedstate/service/FileSettingsServiceIT.java

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -196,21 +196,18 @@ public void clusterChanged(ClusterChangedEvent event) {
196196
return new Tuple<>(savedClusterState, metadataVersion);
197197
}
198198

199-
private Tuple<CountDownLatch, AtomicLong> setupClusterStateListener(String node) {
199+
private Tuple<CountDownLatch, AtomicLong> setupClusterStateListener(String node, long version) {
200200
ClusterService clusterService = internalCluster().clusterService(node);
201201
CountDownLatch savedClusterState = new CountDownLatch(1);
202202
AtomicLong metadataVersion = new AtomicLong(-1);
203203
clusterService.addListener(new ClusterStateListener() {
204204
@Override
205205
public void clusterChanged(ClusterChangedEvent event) {
206206
ReservedStateMetadata reservedState = event.state().metadata().reservedStateMetadata().get(FileSettingsService.NAMESPACE);
207-
if (reservedState != null) {
208-
ReservedStateHandlerMetadata handlerMetadata = reservedState.handlers().get(ReservedClusterSettingsAction.NAME);
209-
if (handlerMetadata != null && handlerMetadata.keys().contains("indices.recovery.max_bytes_per_sec")) {
210-
clusterService.removeListener(this);
211-
metadataVersion.set(event.state().metadata().version());
212-
savedClusterState.countDown();
213-
}
207+
if (reservedState != null && reservedState.version() == version) {
208+
clusterService.removeListener(this);
209+
metadataVersion.set(event.state().metadata().version());
210+
savedClusterState.countDown();
214211
}
215212
}
216213
});
@@ -258,14 +255,14 @@ public void testSettingsApplied() throws Exception {
258255
logger.info("--> start master node");
259256
final String masterNode = internalCluster().startMasterOnlyNode();
260257
assertMasterNode(internalCluster().nonMasterClient(), masterNode);
261-
var savedClusterState = setupClusterStateListener(masterNode);
258+
var savedClusterState = setupClusterStateListener(masterNode, versionCounter.incrementAndGet());
262259

263260
FileSettingsService masterFileSettingsService = internalCluster().getInstance(FileSettingsService.class, masterNode);
264261

265262
assertBusy(() -> assertTrue(masterFileSettingsService.watching()));
266263
assertFalse(dataFileSettingsService.watching());
267264

268-
writeJSONFile(masterNode, testJSON, logger, versionCounter.incrementAndGet());
265+
writeJSONFile(masterNode, testJSON, logger, versionCounter.get());
269266
assertClusterStateSaveOK(savedClusterState.v1(), savedClusterState.v2(), "50mb");
270267
}
271268

@@ -276,11 +273,11 @@ public void testSettingsAppliedOnStart() throws Exception {
276273
FileSettingsService dataFileSettingsService = internalCluster().getInstance(FileSettingsService.class, dataNode);
277274

278275
assertFalse(dataFileSettingsService.watching());
279-
var savedClusterState = setupClusterStateListener(dataNode);
276+
var savedClusterState = setupClusterStateListener(dataNode, versionCounter.incrementAndGet());
280277

281278
// In internal cluster tests, the nodes share the config directory, so when we write with the data node path
282279
// the master will pick it up on start
283-
writeJSONFile(dataNode, testJSON, logger, versionCounter.incrementAndGet());
280+
writeJSONFile(dataNode, testJSON, logger, versionCounter.get());
284281

285282
logger.info("--> start master node");
286283
final String masterNode = internalCluster().startMasterOnlyNode();
@@ -301,14 +298,14 @@ public void testReservedStatePersistsOnRestart() throws Exception {
301298
Settings.builder().put(INITIAL_STATE_TIMEOUT_SETTING.getKey(), "0s").build()
302299
);
303300
assertMasterNode(internalCluster().masterClient(), masterNode);
304-
var savedClusterState = setupClusterStateListener(masterNode);
301+
var savedClusterState = setupClusterStateListener(masterNode, versionCounter.incrementAndGet());
305302

306303
FileSettingsService masterFileSettingsService = internalCluster().getInstance(FileSettingsService.class, masterNode);
307304

308305
assertBusy(() -> assertTrue(masterFileSettingsService.watching()));
309306

310307
logger.info("--> write some settings");
311-
writeJSONFile(masterNode, testJSON, logger, versionCounter.incrementAndGet());
308+
writeJSONFile(masterNode, testJSON, logger, versionCounter.get());
312309
assertClusterStateSaveOK(savedClusterState.v1(), savedClusterState.v2(), "50mb");
313310

314311
logger.info("--> restart master");
@@ -476,12 +473,12 @@ public void testSettingsAppliedOnMasterReElection() throws Exception {
476473
assertFalse(master1FS.watching());
477474
assertFalse(master2FS.watching());
478475

479-
var savedClusterState = setupClusterStateListener(masterNode);
476+
var savedClusterState = setupClusterStateListener(masterNode, versionCounter.incrementAndGet());
480477
FileSettingsService masterFileSettingsService = internalCluster().getInstance(FileSettingsService.class, masterNode);
481478

482479
assertBusy(() -> assertTrue(masterFileSettingsService.watching()));
483480

484-
writeJSONFile(masterNode, testJSON, logger, versionCounter.incrementAndGet());
481+
writeJSONFile(masterNode, testJSON, logger, versionCounter.get());
485482
assertClusterStateSaveOK(savedClusterState.v1(), savedClusterState.v2(), "50mb");
486483

487484
internalCluster().stopCurrentMasterNode();
@@ -501,8 +498,8 @@ public void testSettingsAppliedOnMasterReElection() throws Exception {
501498
boolean awaitSuccessful = savedClusterState.v1().await(20, TimeUnit.SECONDS);
502499
assertTrue(awaitSuccessful);
503500

504-
savedClusterState = setupClusterStateListener(internalCluster().getMasterName());
505-
writeJSONFile(internalCluster().getMasterName(), testJSON43mb, logger, versionCounter.incrementAndGet());
501+
savedClusterState = setupClusterStateListener(internalCluster().getMasterName(), versionCounter.incrementAndGet());
502+
writeJSONFile(internalCluster().getMasterName(), testJSON43mb, logger, versionCounter.get());
506503

507504
assertClusterStateSaveOK(savedClusterState.v1(), savedClusterState.v2(), "43mb");
508505
}
@@ -515,21 +512,21 @@ public void testSymlinkUpdateTriggerReload() throws Exception {
515512
assertBusy(() -> assertTrue(masterFileSettingsService.watching()));
516513

517514
{
518-
var savedClusterState = setupClusterStateListener(masterNode);
515+
var savedClusterState = setupClusterStateListener(masterNode, versionCounter.incrementAndGet());
519516
// Create the settings.json as a symlink to simulate k8 setup
520517
// settings.json -> ..data/settings.json
521518
// ..data -> ..TIMESTAMP_TEMP_FOLDER_1
522519
var fileDir = Files.createDirectories(baseDir.resolve("..TIMESTAMP_TEMP_FOLDER_1"));
523-
writeJSONFile(masterNode, testJSON, logger, versionCounter.incrementAndGet(), fileDir.resolve("settings.json"));
520+
writeJSONFile(masterNode, testJSON, logger, versionCounter.get(), fileDir.resolve("settings.json"));
524521
var dataDir = Files.createSymbolicLink(baseDir.resolve("..data"), fileDir.getFileName());
525522
Files.createSymbolicLink(baseDir.resolve("settings.json"), dataDir.getFileName().resolve("settings.json"));
526523
assertClusterStateSaveOK(savedClusterState.v1(), savedClusterState.v2(), "50mb");
527524
}
528525
{
529-
var savedClusterState = setupClusterStateListener(masterNode);
526+
var savedClusterState = setupClusterStateListener(masterNode, versionCounter.incrementAndGet());
530527
// Update ..data symlink to ..data -> ..TIMESTAMP_TEMP_FOLDER_2 to simulate kubernetes secret update
531528
var fileDir = Files.createDirectories(baseDir.resolve("..TIMESTAMP_TEMP_FOLDER_2"));
532-
writeJSONFile(masterNode, testJSON43mb, logger, versionCounter.incrementAndGet(), fileDir.resolve("settings.json"));
529+
writeJSONFile(masterNode, testJSON43mb, logger, versionCounter.get(), fileDir.resolve("settings.json"));
533530
Files.deleteIfExists(baseDir.resolve("..data"));
534531
Files.createSymbolicLink(baseDir.resolve("..data"), fileDir.getFileName());
535532
assertClusterStateSaveOK(savedClusterState.v1(), savedClusterState.v2(), "43mb");

server/src/main/java/org/elasticsearch/cluster/metadata/MetadataIndexAliasesService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848

4949
import static java.util.Collections.emptyList;
5050
import static java.util.Collections.emptyMap;
51-
import static org.elasticsearch.indices.cluster.IndicesClusterStateService.AllocatedIndices.IndexRemovalReason.NO_LONGER_ASSIGNED;
51+
import static org.elasticsearch.indices.cluster.IndexRemovalReason.NO_LONGER_ASSIGNED;
5252

5353
/**
5454
* Service responsible for submitting add and remove aliases requests

server/src/main/java/org/elasticsearch/cluster/metadata/MetadataIndexTemplateService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@
8383

8484
import static java.util.Collections.emptyMap;
8585
import static org.elasticsearch.cluster.metadata.MetadataCreateDataStreamService.validateTimestampFieldMapping;
86-
import static org.elasticsearch.indices.cluster.IndicesClusterStateService.AllocatedIndices.IndexRemovalReason.NO_LONGER_ASSIGNED;
86+
import static org.elasticsearch.indices.cluster.IndexRemovalReason.NO_LONGER_ASSIGNED;
8787

8888
/**
8989
* Service responsible for submitting index templates updates

server/src/main/java/org/elasticsearch/index/CompositeIndexEventListener.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
import org.elasticsearch.index.shard.IndexShard;
2222
import org.elasticsearch.index.shard.IndexShardState;
2323
import org.elasticsearch.index.shard.ShardId;
24-
import org.elasticsearch.indices.cluster.IndicesClusterStateService.AllocatedIndices.IndexRemovalReason;
24+
import org.elasticsearch.indices.cluster.IndexRemovalReason;
2525
import org.elasticsearch.threadpool.ThreadPool;
2626

2727
import java.util.Collection;

server/src/main/java/org/elasticsearch/index/IndexService.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
import org.elasticsearch.index.store.Store;
8484
import org.elasticsearch.index.translog.Translog;
8585
import org.elasticsearch.indices.breaker.CircuitBreakerService;
86+
import org.elasticsearch.indices.cluster.IndexRemovalReason;
8687
import org.elasticsearch.indices.cluster.IndicesClusterStateService;
8788
import org.elasticsearch.indices.fielddata.cache.IndicesFieldDataCache;
8889
import org.elasticsearch.indices.recovery.RecoveryState;
@@ -494,7 +495,12 @@ public synchronized IndexShard createShard(
494495
nodeEnv,
495496
lock,
496497
this.indexSettings,
497-
shardPaths -> indexFoldersDeletionListener.beforeShardFoldersDeleted(shardId, this.indexSettings, shardPaths)
498+
shardPaths -> indexFoldersDeletionListener.beforeShardFoldersDeleted(
499+
shardId,
500+
this.indexSettings,
501+
shardPaths,
502+
IndexRemovalReason.FAILURE
503+
)
498504
);
499505
path = ShardPath.loadShardPath(logger, nodeEnv, shardId, this.indexSettings.customDataPath());
500506
} catch (Exception inner) {
@@ -704,11 +710,11 @@ private void onShardClose(ShardLock lock) {
704710
try {
705711
eventListener.beforeIndexShardDeleted(lock.getShardId(), indexSettings.getSettings());
706712
} finally {
707-
shardStoreDeleter.deleteShardStore("delete index", lock, indexSettings);
713+
shardStoreDeleter.deleteShardStore("delete index", lock, indexSettings, IndexRemovalReason.DELETED);
708714
eventListener.afterIndexShardDeleted(lock.getShardId(), indexSettings.getSettings());
709715
}
710716
} catch (IOException e) {
711-
shardStoreDeleter.addPendingDelete(lock.getShardId(), indexSettings);
717+
shardStoreDeleter.addPendingDelete(lock.getShardId(), indexSettings, IndexRemovalReason.DELETED);
712718
logger.debug(() -> "[" + lock.getShardId().id() + "] failed to delete shard content - scheduled a retry", e);
713719
}
714720
}
@@ -1062,9 +1068,9 @@ public static Function<String, String> dateMathExpressionResolverAt(long instant
10621068
}
10631069

10641070
public interface ShardStoreDeleter {
1065-
void deleteShardStore(String reason, ShardLock lock, IndexSettings indexSettings) throws IOException;
1071+
void deleteShardStore(String reasonText, ShardLock lock, IndexSettings indexSettings, IndexRemovalReason reason) throws IOException;
10661072

1067-
void addPendingDelete(ShardId shardId, IndexSettings indexSettings);
1073+
void addPendingDelete(ShardId shardId, IndexSettings indexSettings, IndexRemovalReason reason);
10681074
}
10691075

10701076
public final EngineFactory getEngineFactory() {

0 commit comments

Comments
 (0)