Skip to content

Commit e669f14

Browse files
authored
Add file type-based exclusion setting for searchable snapshots cache (#53492)
Allows configuring searchable snapshots to avoid caching certain types of files, for example "fdt" files for stored fields.
1 parent 8f41e61 commit e669f14

File tree

4 files changed

+56
-7
lines changed

4 files changed

+56
-7
lines changed

x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/index/store/SearchableSnapshotDirectory.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66
package org.elasticsearch.index.store;
77

8+
import org.apache.lucene.index.IndexFileNames;
89
import org.apache.lucene.store.BaseDirectory;
910
import org.apache.lucene.store.BufferedIndexInput;
1011
import org.apache.lucene.store.Directory;
@@ -37,17 +38,20 @@
3738
import java.nio.file.Path;
3839
import java.util.Collection;
3940
import java.util.Collections;
41+
import java.util.HashSet;
4042
import java.util.Map;
4143
import java.util.Objects;
4244
import java.util.Set;
4345
import java.util.concurrent.atomic.AtomicBoolean;
4446
import java.util.function.LongSupplier;
4547

48+
import static org.elasticsearch.xpack.searchablesnapshots.SearchableSnapshots.SNAPSHOT_CACHE_EXCLUDED_FILE_TYPES_SETTING;
4649
import static org.elasticsearch.xpack.searchablesnapshots.SearchableSnapshots.SNAPSHOT_CACHE_ENABLED_SETTING;
4750
import static org.elasticsearch.xpack.searchablesnapshots.SearchableSnapshots.SNAPSHOT_INDEX_ID_SETTING;
4851
import static org.elasticsearch.xpack.searchablesnapshots.SearchableSnapshots.SNAPSHOT_REPOSITORY_SETTING;
4952
import static org.elasticsearch.xpack.searchablesnapshots.SearchableSnapshots.SNAPSHOT_SNAPSHOT_ID_SETTING;
5053
import static org.elasticsearch.xpack.searchablesnapshots.SearchableSnapshots.SNAPSHOT_SNAPSHOT_NAME_SETTING;
54+
import static org.elasticsearch.xpack.searchablesnapshots.SearchableSnapshots.SNAPSHOT_UNCACHED_CHUNK_SIZE_SETTING;
5155

5256
/**
5357
* Implementation of {@link Directory} that exposes files from a snapshot as a Lucene directory. Because snapshot are immutable this
@@ -71,6 +75,8 @@ public class SearchableSnapshotDirectory extends BaseDirectory {
7175
private final Map<String, IndexInputStats> stats;
7276
private final CacheService cacheService;
7377
private final boolean useCache;
78+
private final Set<String> excludedFileTypes;
79+
private final long uncachedChunkSize;
7480
private final Path cacheDir;
7581
private final AtomicBoolean closed;
7682

@@ -97,6 +103,10 @@ public SearchableSnapshotDirectory(
97103
this.cacheDir = Objects.requireNonNull(cacheDir);
98104
this.closed = new AtomicBoolean(false);
99105
this.useCache = SNAPSHOT_CACHE_ENABLED_SETTING.get(indexSettings);
106+
this.excludedFileTypes = new HashSet<>(SNAPSHOT_CACHE_EXCLUDED_FILE_TYPES_SETTING.get(indexSettings));
107+
this.uncachedChunkSize = SNAPSHOT_UNCACHED_CHUNK_SIZE_SETTING.get(indexSettings).getBytes() < 0 ?
108+
blobContainer.readBlobPreferredLength() :
109+
SNAPSHOT_UNCACHED_CHUNK_SIZE_SETTING.get(indexSettings).getBytes();
100110
}
101111

102112
public BlobContainer blobContainer() {
@@ -223,14 +233,18 @@ public IndexInput openInput(final String name, final IOContext context) throws I
223233
ensureOpen();
224234
final BlobStoreIndexShardSnapshot.FileInfo fileInfo = fileInfo(name);
225235
final IndexInputStats inputStats = stats.computeIfAbsent(name, n -> createIndexInputStats(fileInfo.length()));
226-
if (useCache) {
236+
if (useCache && isExcludedFromCache(name) == false) {
227237
return new CacheBufferedIndexInput(this, fileInfo, context, inputStats);
228238
} else {
229-
long preferredLength = blobContainer.readBlobPreferredLength();
230-
return new SearchableSnapshotIndexInput(blobContainer, fileInfo, context, preferredLength, BufferedIndexInput.BUFFER_SIZE);
239+
return new SearchableSnapshotIndexInput(blobContainer, fileInfo, context, uncachedChunkSize, BufferedIndexInput.BUFFER_SIZE);
231240
}
232241
}
233242

243+
private boolean isExcludedFromCache(String name) {
244+
final String ext = IndexFileNames.getExtension(name);
245+
return ext != null && excludedFileTypes.contains(ext);
246+
}
247+
234248
@Override
235249
public String toString() {
236250
return this.getClass().getSimpleName() + "@" + snapshot.snapshot() + " lockFactory=" + lockFactory;

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
import org.elasticsearch.common.settings.Setting;
2020
import org.elasticsearch.common.settings.Settings;
2121
import org.elasticsearch.common.settings.SettingsFilter;
22+
import org.elasticsearch.common.unit.ByteSizeUnit;
23+
import org.elasticsearch.common.unit.ByteSizeValue;
2224
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
2325
import org.elasticsearch.env.Environment;
2426
import org.elasticsearch.env.NodeEnvironment;
@@ -77,6 +79,13 @@ public class SearchableSnapshots extends Plugin implements IndexStorePlugin, Rep
7779
Setting.simpleString("index.store.snapshot.index_uuid", Setting.Property.IndexScope, Setting.Property.PrivateIndex);
7880
public static final Setting<Boolean> SNAPSHOT_CACHE_ENABLED_SETTING =
7981
Setting.boolSetting("index.store.snapshot.cache.enabled", true, Setting.Property.IndexScope);
82+
// The file extensions that are excluded from the cache
83+
public static final Setting<List<String>> SNAPSHOT_CACHE_EXCLUDED_FILE_TYPES_SETTING =
84+
Setting.listSetting("index.store.snapshot.cache.excluded_file_types", Collections.emptyList(), Function.identity(),
85+
Setting.Property.IndexScope, Setting.Property.NodeScope);
86+
public static final Setting<ByteSizeValue> SNAPSHOT_UNCACHED_CHUNK_SIZE_SETTING =
87+
Setting.byteSizeSetting("index.store.snapshot.uncached_chunk_size", new ByteSizeValue(-1, ByteSizeUnit.BYTES),
88+
Setting.Property.IndexScope, Setting.Property.NodeScope);
8089

8190
public static final String SNAPSHOT_DIRECTORY_FACTORY_KEY = "snapshot";
8291

@@ -97,6 +106,8 @@ public List<Setting<?>> getSettings() {
97106
SNAPSHOT_SNAPSHOT_ID_SETTING,
98107
SNAPSHOT_INDEX_ID_SETTING,
99108
SNAPSHOT_CACHE_ENABLED_SETTING,
109+
SNAPSHOT_CACHE_EXCLUDED_FILE_TYPES_SETTING,
110+
SNAPSHOT_UNCACHED_CHUNK_SIZE_SETTING,
100111
CacheService.SNAPSHOT_CACHE_SIZE_SETTING,
101112
CacheService.SNAPSHOT_CACHE_RANGE_SIZE_SETTING
102113
);

x-pack/plugin/searchable-snapshots/src/test/java/org/elasticsearch/xpack/searchablesnapshots/SearchableSnapshotsIntegTests.java

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636

3737
import java.nio.file.Path;
3838
import java.util.ArrayList;
39+
import java.util.Arrays;
3940
import java.util.Collection;
4041
import java.util.Collections;
4142
import java.util.List;
@@ -122,12 +123,23 @@ public void testCreateAndRestoreSearchableSnapshot() throws Exception {
122123
final boolean cacheEnabled = randomBoolean();
123124
logger.info("--> restoring index [{}] with cache [{}]", restoredIndexName, cacheEnabled ? "enabled" : "disabled");
124125

126+
Settings.Builder indexSettingsBuilder = Settings.builder()
127+
.put(SearchableSnapshots.SNAPSHOT_CACHE_ENABLED_SETTING.getKey(), cacheEnabled)
128+
.put(IndexSettings.INDEX_CHECK_ON_STARTUP.getKey(), Boolean.FALSE.toString());
129+
final List<String> nonCachedExtensions;
130+
if (randomBoolean()) {
131+
nonCachedExtensions = randomSubsetOf(Arrays.asList("fdt", "fdx", "nvd", "dvd", "tip", "cfs", "dim"));
132+
indexSettingsBuilder.putList(SearchableSnapshots.SNAPSHOT_CACHE_EXCLUDED_FILE_TYPES_SETTING.getKey(), nonCachedExtensions);
133+
} else {
134+
nonCachedExtensions = Collections.emptyList();
135+
}
136+
if (randomBoolean()) {
137+
indexSettingsBuilder.put(SearchableSnapshots.SNAPSHOT_UNCACHED_CHUNK_SIZE_SETTING.getKey(),
138+
new ByteSizeValue(randomLongBetween(10, 100_000)));
139+
}
125140
final MountSearchableSnapshotRequest req = new MountSearchableSnapshotRequest(restoredIndexName, fsRepoName,
126141
snapshotInfo.snapshotId().getName(), indexName,
127-
Settings.builder()
128-
.put(SearchableSnapshots.SNAPSHOT_CACHE_ENABLED_SETTING.getKey(), cacheEnabled)
129-
.put(IndexSettings.INDEX_CHECK_ON_STARTUP.getKey(), Boolean.FALSE.toString())
130-
.build(), Strings.EMPTY_ARRAY, true);
142+
indexSettingsBuilder.build(), Strings.EMPTY_ARRAY, true);
131143

132144
final RestoreSnapshotResponse restoreSnapshotResponse = client().execute(MountSearchableSnapshotAction.INSTANCE, req).get();
133145
assertThat(restoreSnapshotResponse.getRestoreInfo().failedShards(), equalTo(0));
@@ -151,6 +163,13 @@ public void testCreateAndRestoreSearchableSnapshot() throws Exception {
151163
for (SearchableSnapshotShardStats stats : statsResponse.getStats()) {
152164
assertThat(stats.getShardRouting().getIndexName(), equalTo(restoredIndexName));
153165
assertThat(stats.getStats().size(), greaterThan(0));
166+
for (SearchableSnapshotShardStats.CacheIndexInputStats indexInputStats : stats.getStats()) {
167+
for (String ext : nonCachedExtensions) {
168+
if (indexInputStats.getFileName().endsWith(ext)) {
169+
assertEquals(indexInputStats.getFileName(), 0, indexInputStats.getOpenCount());
170+
}
171+
}
172+
}
154173
}
155174
} else {
156175
expectThrows(ResourceNotFoundException.class, future::actionGet);

x-pack/plugin/searchable-snapshots/src/test/java/org/elasticsearch/xpack/searchablesnapshots/cache/TestUtils.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,11 @@ public InputStream readBlob(String name, long position, long length) throws IOEx
7878
return Streams.limitStream(new ByteArrayInputStream(blobContent, Math.toIntExact(position), blobContent.length), length);
7979
}
8080

81+
@Override
82+
public long readBlobPreferredLength() {
83+
return Long.MAX_VALUE;
84+
}
85+
8186
@Override
8287
public Map<String, BlobMetaData> listBlobs() {
8388
throw unsupportedException();

0 commit comments

Comments
 (0)