Skip to content

Commit 67f7b9a

Browse files
committed
Prevent cache invalidation to trigger more gets on shutdown
1 parent cea36b2 commit 67f7b9a

File tree

1 file changed

+24
-10
lines changed
  • x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/xpack/searchablesnapshots/cache

1 file changed

+24
-10
lines changed

x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/xpack/searchablesnapshots/cache/CacheService.java

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@
1515
import org.elasticsearch.common.settings.Settings;
1616
import org.elasticsearch.common.unit.ByteSizeUnit;
1717
import org.elasticsearch.common.unit.ByteSizeValue;
18+
import org.elasticsearch.common.util.concurrent.ReleasableLock;
1819

1920
import java.nio.file.Files;
2021
import java.nio.file.Path;
22+
import java.util.concurrent.locks.ReentrantReadWriteLock;
2123
import java.util.function.Predicate;
2224

2325
/**
@@ -31,6 +33,8 @@ public class CacheService extends AbstractLifecycleComponent {
3133
new ByteSizeValue(Long.MAX_VALUE, ByteSizeUnit.BYTES), // max
3234
Setting.Property.NodeScope);
3335

36+
private final ReleasableLock cacheInvalidationLock;
37+
private final ReleasableLock cacheAccessLock;
3438
private final Cache<String, CacheFile> cache;
3539

3640
public CacheService(final Settings settings) {
@@ -41,6 +45,13 @@ public CacheService(final Settings settings) {
4145
// are done with reading/writing the cache file
4246
.removalListener(notification -> Releasables.closeWhileHandlingException(notification.getValue()))
4347
.build();
48+
49+
// Prevent new CacheFile objects to be added to the cache while the cache is being fully or partially invalidated
50+
// This can happen because CacheFile objects might execute listeners at eviction time, potentially forcing more
51+
// objects (like CacheDirectory's index inputs) to get new CacheFile.
52+
final ReentrantReadWriteLock cacheLock = new ReentrantReadWriteLock();
53+
this.cacheInvalidationLock = new ReleasableLock(cacheLock.writeLock());
54+
this.cacheAccessLock = new ReleasableLock(cacheLock.readLock());
4455
}
4556

4657
@Override
@@ -50,7 +61,9 @@ protected void doStart() {
5061

5162
@Override
5263
protected void doStop() {
53-
cache.invalidateAll();
64+
try (ReleasableLock ignored = cacheInvalidationLock.acquire()) {
65+
cache.invalidateAll();
66+
}
5467
}
5568

5669
@Override
@@ -66,17 +79,18 @@ private void ensureLifecycleStarted() {
6679

6780
public CacheFile get(final String name, final long length, final Path file) throws Exception {
6881
ensureLifecycleStarted();
69-
return cache.computeIfAbsent(toCacheKey(file), key -> {
82+
try (ReleasableLock ignored = cacheAccessLock.acquire()) {
7083
ensureLifecycleStarted();
84+
return cache.computeIfAbsent(toCacheKey(file), key -> {
85+
// generate a random UUID for the name of the cache file on disk
86+
final String uuid = UUIDs.randomBase64UUID();
87+
// resolve the cache file on disk w/ the expected cached file
88+
final Path path = file.getParent().resolve(uuid);
89+
assert Files.notExists(path) : "cache file already exists " + path;
7190

72-
// generate a random UUID for the name of the cache file on disk
73-
final String uuid = UUIDs.randomBase64UUID();
74-
// resolve the cache file on disk w/ the expected cached file
75-
final Path path = file.getParent().resolve(uuid);
76-
assert Files.notExists(path) : "cache file already exists " + path;
77-
78-
return new CacheFile(name, length, path);
79-
});
91+
return new CacheFile(name, length, path);
92+
});
93+
}
8094
}
8195

8296
/**

0 commit comments

Comments
 (0)