From 8b78ed2c47339a950534c46f7da9ed69d4016b1f Mon Sep 17 00:00:00 2001 From: Tanguy Leroux Date: Mon, 18 Oct 2021 17:55:28 +0200 Subject: [PATCH] Create cache files with CREATE_NEW & SPARSE options --- .../cache/common/CacheFile.java | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/xpack/searchablesnapshots/cache/common/CacheFile.java b/x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/xpack/searchablesnapshots/cache/common/CacheFile.java index b70c55e7a2a54..2d2a9ce4b26ba 100644 --- a/x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/xpack/searchablesnapshots/cache/common/CacheFile.java +++ b/x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/xpack/searchablesnapshots/cache/common/CacheFile.java @@ -53,12 +53,14 @@ public interface ModificationListener { void onCacheFileDelete(CacheFile cacheFile); } - private static final StandardOpenOption[] OPEN_OPTIONS = new StandardOpenOption[] { + private static final StandardOpenOption[] CREATE_OPTIONS = new StandardOpenOption[] { StandardOpenOption.READ, StandardOpenOption.WRITE, - StandardOpenOption.CREATE, + StandardOpenOption.CREATE_NEW, StandardOpenOption.SPARSE }; + private static final StandardOpenOption[] OPEN_OPTIONS = new StandardOpenOption[] { StandardOpenOption.READ, StandardOpenOption.WRITE }; + /** * Reference counter that counts the number of eviction listeners referencing this cache file plus the number of open file channels * for it. Once this instance has been evicted, all listeners notified and all {@link FileChannelReference} for it released, @@ -100,8 +102,8 @@ private final class FileChannelReference extends AbstractRefCounted { private final FileChannel fileChannel; - FileChannelReference() throws IOException { - this.fileChannel = FileChannel.open(file, OPEN_OPTIONS); + FileChannelReference(StandardOpenOption[] options) throws IOException { + this.fileChannel = FileChannel.open(file, options); refCounter.incRef(); } @@ -124,19 +126,26 @@ protected void closeInternal() { @Nullable private volatile FileChannelReference channelRef; + /** + * Indicates if the file has already been created. + * This is useful to pass the right options when opening the file. + */ + private volatile boolean created; + public CacheFile(CacheKey cacheKey, long length, Path file, ModificationListener listener) { - this(cacheKey, new SparseFileTracker(file.toString(), length), file, listener); + this(cacheKey, new SparseFileTracker(file.toString(), length), file, listener, false); } public CacheFile(CacheKey cacheKey, long length, Path file, SortedSet ranges, ModificationListener listener) { - this(cacheKey, new SparseFileTracker(file.toString(), length, ranges), file, listener); + this(cacheKey, new SparseFileTracker(file.toString(), length, ranges), file, listener, true); } - private CacheFile(CacheKey cacheKey, SparseFileTracker tracker, Path file, ModificationListener listener) { + private CacheFile(CacheKey cacheKey, SparseFileTracker tracker, Path file, ModificationListener listener, boolean fileExists) { this.cacheKey = Objects.requireNonNull(cacheKey); this.tracker = Objects.requireNonNull(tracker); this.file = Objects.requireNonNull(file); this.listener = Objects.requireNonNull(listener); + this.created = fileExists; assert invariant(); } @@ -182,7 +191,8 @@ public void acquire(final EvictionListener listener) throws IOException { ensureOpen(); if (listeners.isEmpty()) { assert channelRef == null; - channelRef = new FileChannelReference(); + channelRef = new FileChannelReference(created ? OPEN_OPTIONS : CREATE_OPTIONS); + created = true; } final boolean added = listeners.add(listener); assert added : "listener already exists " + listener;