diff --git a/CHANGELOG.md b/CHANGELOG.md index e4e96d222f74d..87f03871bf7f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,10 +30,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Add support for `matched_fields` with the unified highlighter ([#18164](https://github.com/opensearch-project/OpenSearch/issues/18164)) - [repository-s3] Add support for SSE-KMS and S3 bucket owner verification ([#18312](https://github.com/opensearch-project/OpenSearch/pull/18312)) - Added File Cache Stats - Involves Block level as well as full file level stats ([#17538](https://github.com/opensearch-project/OpenSearch/issues/17479)) +- Added File Cache Pinning ([#17617](https://github.com/opensearch-project/OpenSearch/issues/13648)) ### Changed - Create generic DocRequest to better categorize ActionRequests ([#18269](https://github.com/opensearch-project/OpenSearch/pull/18269))) - + ### Dependencies - Update Apache Lucene from 10.1.0 to 10.2.1 ([#17961](https://github.com/opensearch-project/OpenSearch/pull/17961)) - Bump `com.google.code.gson:gson` from 2.12.1 to 2.13.1 ([#17923](https://github.com/opensearch-project/OpenSearch/pull/17923), [#18266](https://github.com/opensearch-project/OpenSearch/pull/18266)) diff --git a/server/src/main/java/org/opensearch/index/store/CompositeDirectory.java b/server/src/main/java/org/opensearch/index/store/CompositeDirectory.java index f22f5165d3709..38190ebd64499 100644 --- a/server/src/main/java/org/opensearch/index/store/CompositeDirectory.java +++ b/server/src/main/java/org/opensearch/index/store/CompositeDirectory.java @@ -327,19 +327,15 @@ public String toString() { */ public void afterSyncToRemote(String file) { ensureOpen(); - /* - Decrementing the refCount here for the path so that it becomes eligible for eviction - This is a temporary solution until pinning support is added - TODO - Unpin the files here from FileCache so that they become eligible for eviction, once pinning/unpinning support is added in FileCache - Uncomment the below commented line(to remove the file from cache once uploaded) to test block based functionality - */ + logger.trace( "Composite Directory[{}]: File {} uploaded to Remote Store and now can be eligible for eviction in FileCache", this::toString, () -> file ); - fileCache.decRef(getFilePath(file)); - // fileCache.remove(getFilePath(fileName)); + final Path filePath = getFilePath(file); + fileCache.unpin(filePath); + // fileCache.remove(filePath); } // Visibility public since we need it in IT tests @@ -390,12 +386,10 @@ private String[] getRemoteFiles() throws IOException { protected void cacheFile(String name) throws IOException { Path filePath = getFilePath(name); - // put will increase the refCount for the path, making sure it is not evicted, will decrease the ref after it is uploaded to Remote - // so that it can be evicted after that - // this is just a temporary solution, will pin the file once support for that is added in FileCache - // TODO : Pin the above filePath in the file cache once pinning support is added so that it cannot be evicted unless it has been - // successfully uploaded to Remote + fileCache.put(filePath, new CachedFullFileIndexInput(fileCache, filePath, localDirectory.openInput(name, IOContext.DEFAULT))); + fileCache.pin(filePath); + fileCache.decRef(filePath); } } diff --git a/server/src/main/java/org/opensearch/index/store/remote/filecache/AggregateFileCacheStats.java b/server/src/main/java/org/opensearch/index/store/remote/filecache/AggregateFileCacheStats.java index 237724ed7a6a8..c5129a7b4c346 100644 --- a/server/src/main/java/org/opensearch/index/store/remote/filecache/AggregateFileCacheStats.java +++ b/server/src/main/java/org/opensearch/index/store/remote/filecache/AggregateFileCacheStats.java @@ -39,17 +39,20 @@ public class AggregateFileCacheStats implements Writeable, ToXContentFragment { private final FileCacheStats overallFileCacheStats; private final FileCacheStats fullFileCacheStats; private final FileCacheStats blockFileCacheStats; + private final FileCacheStats pinnedFileCacheStats; public AggregateFileCacheStats( final long timestamp, final FileCacheStats overallFileCacheStats, final FileCacheStats fullFileCacheStats, - final FileCacheStats blockFileCacheStats + final FileCacheStats blockFileCacheStats, + FileCacheStats pinnedFileCacheStats ) { this.timestamp = timestamp; this.overallFileCacheStats = overallFileCacheStats; this.fullFileCacheStats = fullFileCacheStats; this.blockFileCacheStats = blockFileCacheStats; + this.pinnedFileCacheStats = pinnedFileCacheStats; } public AggregateFileCacheStats(final StreamInput in) throws IOException { @@ -57,6 +60,7 @@ public AggregateFileCacheStats(final StreamInput in) throws IOException { this.overallFileCacheStats = new FileCacheStats(in); this.fullFileCacheStats = new FileCacheStats(in); this.blockFileCacheStats = new FileCacheStats(in); + this.pinnedFileCacheStats = new FileCacheStats(in); } public static short calculatePercentage(long used, long max) { @@ -69,6 +73,7 @@ public void writeTo(final StreamOutput out) throws IOException { overallFileCacheStats.writeTo(out); fullFileCacheStats.writeTo(out); blockFileCacheStats.writeTo(out); + pinnedFileCacheStats.writeTo(out); } public long getTimestamp() { @@ -91,6 +96,10 @@ public ByteSizeValue getUsed() { return new ByteSizeValue(overallFileCacheStats.getUsed()); } + public ByteSizeValue getPinnedUsage() { + return new ByteSizeValue(overallFileCacheStats.getPinnedUsage()); + } + public short getUsedPercent() { return calculatePercentage(getUsed().getBytes(), getTotal().getBytes()); } @@ -114,6 +123,7 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws builder.humanReadableField(Fields.ACTIVE_IN_BYTES, Fields.ACTIVE, getActive()); builder.humanReadableField(Fields.TOTAL_IN_BYTES, Fields.TOTAL, getTotal()); builder.humanReadableField(Fields.USED_IN_BYTES, Fields.USED, getUsed()); + builder.humanReadableField(Fields.PINNED_IN_BYTES, Fields.PINNED, getPinnedUsage()); builder.humanReadableField(Fields.EVICTIONS_IN_BYTES, Fields.EVICTIONS, getEvicted()); builder.field(Fields.ACTIVE_PERCENT, getActivePercent()); builder.field(Fields.USED_PERCENT, getUsedPercent()); @@ -122,7 +132,7 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws overallFileCacheStats.toXContent(builder, params); fullFileCacheStats.toXContent(builder, params); blockFileCacheStats.toXContent(builder, params); - + pinnedFileCacheStats.toXContent(builder, params); builder.endObject(); return builder; } @@ -134,6 +144,8 @@ static final class Fields { static final String ACTIVE_IN_BYTES = "active_in_bytes"; static final String USED = "used"; static final String USED_IN_BYTES = "used_in_bytes"; + static final String PINNED = "pinned"; + static final String PINNED_IN_BYTES = "pinned_in_bytes"; static final String EVICTIONS = "evictions"; static final String EVICTIONS_IN_BYTES = "evictions_in_bytes"; static final String TOTAL = "total"; @@ -153,7 +165,8 @@ static final class Fields { public enum FileCacheStatsType { FULL_FILE_STATS("full_file_stats"), BLOCK_FILE_STATS("block_file_stats"), - OVER_ALL_STATS("over_all_stats"); + OVER_ALL_STATS("over_all_stats"), + PINNED_FILE_STATS("pinned_file_stats"); private final String fileCacheStatsType; diff --git a/server/src/main/java/org/opensearch/index/store/remote/filecache/FileCache.java b/server/src/main/java/org/opensearch/index/store/remote/filecache/FileCache.java index c43cc7d1f3b18..92ee2d08f9d5f 100644 --- a/server/src/main/java/org/opensearch/index/store/remote/filecache/FileCache.java +++ b/server/src/main/java/org/opensearch/index/store/remote/filecache/FileCache.java @@ -124,6 +124,26 @@ public void decRef(Path key) { theCache.decRef(key); } + /** + * Pins the key in the cache, preventing it from being evicted. + * + * @param key + */ + @Override + public void pin(Path key) { + theCache.pin(key); + } + + /** + * Unpins the key in the cache, allowing it to be evicted. + * + * @param key + */ + @Override + public void unpin(Path key) { + theCache.unpin(key); + } + @Override public Integer getRef(Path key) { return theCache.getRef(key); @@ -141,14 +161,22 @@ public long prune(Predicate keyPredicate) { @Override public long usage() { - long l = theCache.usage(); - return l; + return theCache.usage(); } @Override public long activeUsage() { - long l = theCache.activeUsage(); - return l; + return theCache.activeUsage(); + } + + /** + * Returns the pinned usage of this cache. + * + * @return the combined pinned weight of the values in this cache. + */ + @Override + public long pinnedUsage() { + return theCache.pinnedUsage(); } @Override @@ -225,12 +253,14 @@ public AggregateFileCacheStats fileCacheStats() { final RefCountedCacheStats overallCacheStats = stats.getOverallCacheStats(); final RefCountedCacheStats fullFileCacheStats = stats.getFullFileCacheStats(); final RefCountedCacheStats blockFileCacheStats = stats.getBlockFileCacheStats(); + final RefCountedCacheStats pinnedFileCacheStats = stats.getPinnedFileCacheStats(); return new AggregateFileCacheStats( System.currentTimeMillis(), new FileCacheStats( overallCacheStats.activeUsage(), capacity(), overallCacheStats.usage(), + overallCacheStats.pinnedUsage(), overallCacheStats.evictionWeight(), overallCacheStats.hitCount(), overallCacheStats.missCount(), @@ -240,6 +270,7 @@ public AggregateFileCacheStats fileCacheStats() { fullFileCacheStats.activeUsage(), capacity(), fullFileCacheStats.usage(), + fullFileCacheStats.pinnedUsage(), fullFileCacheStats.evictionWeight(), fullFileCacheStats.hitCount(), fullFileCacheStats.missCount(), @@ -249,10 +280,21 @@ public AggregateFileCacheStats fileCacheStats() { blockFileCacheStats.activeUsage(), capacity(), blockFileCacheStats.usage(), + blockFileCacheStats.pinnedUsage(), blockFileCacheStats.evictionWeight(), blockFileCacheStats.hitCount(), blockFileCacheStats.missCount(), FileCacheStatsType.BLOCK_FILE_STATS + ), + new FileCacheStats( + pinnedFileCacheStats.activeUsage(), + capacity(), + pinnedFileCacheStats.usage(), + pinnedFileCacheStats.pinnedUsage(), + pinnedFileCacheStats.evictionWeight(), + pinnedFileCacheStats.hitCount(), + pinnedFileCacheStats.missCount(), + FileCacheStatsType.PINNED_FILE_STATS ) ); } diff --git a/server/src/main/java/org/opensearch/index/store/remote/filecache/FileCacheStats.java b/server/src/main/java/org/opensearch/index/store/remote/filecache/FileCacheStats.java index ee3410914fd92..f14e11880ac44 100644 --- a/server/src/main/java/org/opensearch/index/store/remote/filecache/FileCacheStats.java +++ b/server/src/main/java/org/opensearch/index/store/remote/filecache/FileCacheStats.java @@ -38,6 +38,7 @@ public class FileCacheStats implements Writeable, ToXContentFragment { private final long active; private final long total; private final long used; + private final long pinned; private final long evicted; private final long hits; private final long misses; @@ -47,6 +48,7 @@ public FileCacheStats( final long active, long total, final long used, + final long pinned, final long evicted, final long hits, long misses, @@ -55,6 +57,7 @@ public FileCacheStats( this.active = active; this.total = total; this.used = used; + this.pinned = pinned; this.evicted = evicted; this.hits = hits; this.misses = misses; @@ -66,6 +69,7 @@ public FileCacheStats(final StreamInput in) throws IOException { this.active = in.readLong(); this.total = in.readLong(); this.used = in.readLong(); + this.pinned = in.readLong(); this.evicted = in.readLong(); this.hits = in.readLong(); this.misses = in.readLong(); @@ -77,6 +81,7 @@ public void writeTo(final StreamOutput out) throws IOException { out.writeLong(active); out.writeLong(total); out.writeLong(used); + out.writeLong(pinned); out.writeLong(evicted); out.writeLong(hits); out.writeLong(misses); @@ -106,6 +111,10 @@ public long getTotal() { return total; } + public long getPinnedUsage() { + return pinned; + } + public short getUsedPercent() { return calculatePercentage(getUsed(), total); } @@ -122,6 +131,7 @@ static final class Fields { static final String ACTIVE = "active"; static final String ACTIVE_IN_BYTES = "active_in_bytes"; static final String USED = "used"; + static final String PINNED = "pinned"; static final String USED_IN_BYTES = "used_in_bytes"; static final String EVICTIONS = "evictions"; static final String EVICTIONS_IN_BYTES = "evictions_in_bytes"; @@ -134,6 +144,7 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws builder.startObject(statsType.toString()); builder.humanReadableField(FileCacheStats.Fields.ACTIVE_IN_BYTES, FileCacheStats.Fields.ACTIVE, new ByteSizeValue(getActive())); builder.humanReadableField(FileCacheStats.Fields.USED_IN_BYTES, FileCacheStats.Fields.USED, new ByteSizeValue(getUsed())); + builder.humanReadableField(FileCacheStats.Fields.USED_IN_BYTES, Fields.PINNED, new ByteSizeValue(getPinnedUsage())); builder.humanReadableField( FileCacheStats.Fields.EVICTIONS_IN_BYTES, FileCacheStats.Fields.EVICTIONS, diff --git a/server/src/main/java/org/opensearch/index/store/remote/utils/cache/LRUCache.java b/server/src/main/java/org/opensearch/index/store/remote/utils/cache/LRUCache.java index c0ce53ff51471..f1ba326f82445 100644 --- a/server/src/main/java/org/opensearch/index/store/remote/utils/cache/LRUCache.java +++ b/server/src/main/java/org/opensearch/index/store/remote/utils/cache/LRUCache.java @@ -28,7 +28,8 @@ import java.util.function.Predicate; /** - * LRU implementation of {@link RefCountedCache}. As long as {@link Node#refCount} greater than 0 then node is not eligible for eviction. + * LRU implementation of {@link RefCountedCache}. + * As long as {@link Node#refCount} greater than 0 or is pinned then node is not eligible for eviction. * So this is the best effort lazy cache to maintain capacity.
* For more context why in-house cache implementation exist look at * this comment and @@ -39,6 +40,7 @@ *
  • This cache has max capacity and this cache will best-effort maintain it's size to not exceed defined capacity
  • *
  • Cache capacity is computed as the sum of all {@link Weigher#weightOf(Object)}
  • *
  • Supports RemovalListener
  • + *
  • Supports Cache Pinning.
  • *
  • Cache maintains it's capacity using LRU Eviction while ignoring entries with {@link Node#refCount} greater than 0 from eviction
  • * * @see RefCountedCache @@ -71,15 +73,18 @@ static class Node { int refCount; + boolean pinned; + Node(K key, V value, long weight) { this.key = key; this.value = value; this.weight = weight; this.refCount = 0; + this.pinned = false; } public boolean evictable() { - return (refCount == 0); + return ((refCount == 0) && (pinned == false)); } } @@ -107,7 +112,7 @@ public V get(K key) { } // hit incRef(key); - statsCounter.recordHits(key, node.value, 1); + statsCounter.recordHits(key, node.value, node.pinned, 1); return node.value; } finally { lock.unlock(); @@ -127,7 +132,7 @@ public V put(K key, V value) { replaceNode(node, value); return oldValue; } else { - addNode(key, value); + addNode(key, false, value); return null; } } finally { @@ -148,7 +153,7 @@ public V compute(K key, BiFunction remappingF // Remapping function asked for removal, but nothing to remove return null; } else { - addNode(key, newValue); + addNode(key, false, newValue); statsCounter.recordMisses(key, 1); return newValue; } @@ -158,7 +163,7 @@ public V compute(K key, BiFunction remappingF removeNode(key); return null; } else { - statsCounter.recordHits(key, node.value, 1); + statsCounter.recordHits(key, node.value, node.pinned, 1); replaceNode(node, newValue); return newValue; } @@ -188,11 +193,12 @@ public void clear() { while (iterator.hasNext()) { Node node = iterator.next(); iterator.remove(); - statsCounter.recordRemoval(node.value, node.weight); + statsCounter.recordRemoval(node.value, node.pinned, node.weight); listener.onRemoval(new RemovalNotification<>(node.key, node.value, RemovalReason.EXPLICIT)); } statsCounter.resetUsage(); statsCounter.resetActiveUsage(); + statsCounter.resetPinnedUsage(); } finally { lock.unlock(); } @@ -212,7 +218,7 @@ public void incRef(K key) { if (node != null) { if (node.refCount == 0) { // if it was inactive, we should add the weight to active usage from now - statsCounter.recordActiveUsage(node.value, node.weight, false); + statsCounter.recordActiveUsage(node.value, node.weight, node.pinned, false); } if (node.evictable()) { @@ -244,9 +250,66 @@ public void decRef(K key) { if (node.refCount == 0) { // if it was active, we should remove its weight from active usage - statsCounter.recordActiveUsage(node.value, node.weight, true); + statsCounter.recordActiveUsage(node.value, node.weight, node.pinned, true); + } + } + } finally { + lock.unlock(); + } + } + + /** + * Pins the key in the cache, preventing it from being evicted. + * + * @param key + */ + @Override + public void pin(K key) { + Objects.requireNonNull(key); + lock.lock(); + try { + Node node = data.get(key); + if (node != null) { + if (node.pinned == false) { + statsCounter.recordPinnedUsage(node.value, node.weight, false); + } + + if (node.evictable()) { + // since its pinned, we should remove it from eviction list + lru.remove(node.key, node); + } + + node.pinned = true; + } + } finally { + lock.unlock(); + } + } + + /** + * Unpins the key in the cache, allowing it to be evicted. + * + * @param key + */ + @Override + public void unpin(K key) { + Objects.requireNonNull(key); + lock.lock(); + + try { + Node node = data.get(key); + if (node != null && (node.pinned == true)) { + + node.pinned = false; + + if (node.evictable()) { + // if it becomes evictable, we should add it to eviction list + lru.put(node.key, node); } + + statsCounter.recordPinnedUsage(node.value, node.weight, true); } + } finally { lock.unlock(); } @@ -281,7 +344,7 @@ public long prune(Predicate keyPredicate) { iterator.remove(); data.remove(node.key, node); sum += node.weight; - statsCounter.recordRemoval(node.value, node.weight); + statsCounter.recordRemoval(node.value, node.pinned, node.weight); listener.onRemoval(new RemovalNotification<>(node.key, node.value, RemovalReason.EXPLICIT)); } } finally { @@ -301,7 +364,6 @@ public long usage() { } @Override - public long activeUsage() { lock.lock(); try { @@ -311,6 +373,21 @@ public long activeUsage() { } } + /** + * Returns the pinned usage of this cache. + * + * @return the combined pinned weight of the values in this cache. + */ + @Override + public long pinnedUsage() { + lock.lock(); + try { + return statsCounter.pinnedUsage(); + } finally { + lock.unlock(); + } + } + @Override public IRefCountedCacheStats stats() { lock.lock(); @@ -344,11 +421,11 @@ public void logCurrentState() { } } - private void addNode(K key, V value) { + private void addNode(K key, boolean pinned, V value) { final long weight = weigher.weightOf(value); Node newNode = new Node<>(key, value, weight); data.put(key, newNode); - statsCounter.recordUsage(value, weight, false); + statsCounter.recordUsage(value, weight, pinned, false); incRef(key); evict(); } @@ -363,7 +440,7 @@ private void replaceNode(Node node, V newValue) { node.weight = newWeight; // update stats - statsCounter.recordReplacement(oldValue, newValue, oldWeight, newWeight, node.refCount > 0); + statsCounter.recordReplacement(oldValue, newValue, oldWeight, newWeight, node.refCount > 0, node.pinned); listener.onRemoval(new RemovalNotification<>(node.key, oldValue, RemovalReason.REPLACED)); } incRef(node.key); @@ -374,12 +451,17 @@ private void removeNode(K key) { Node node = data.remove(key); if (node != null) { if (node.refCount > 0) { - statsCounter.recordActiveUsage(node.value, node.weight, true); + statsCounter.recordActiveUsage(node.value, node.weight, node.pinned, true); } if (node.evictable()) { lru.remove(node.key); } - statsCounter.recordRemoval(node.value, node.weight); + + if (node.pinned) { + statsCounter.recordPinnedUsage(node.value, node.weight, true); + } + + statsCounter.recordRemoval(node.value, node.pinned, node.weight); listener.onRemoval(new RemovalNotification<>(node.key, node.value, RemovalReason.EXPLICIT)); } } diff --git a/server/src/main/java/org/opensearch/index/store/remote/utils/cache/RefCountedCache.java b/server/src/main/java/org/opensearch/index/store/remote/utils/cache/RefCountedCache.java index ff72b190932aa..3d07d9eacf786 100644 --- a/server/src/main/java/org/opensearch/index/store/remote/utils/cache/RefCountedCache.java +++ b/server/src/main/java/org/opensearch/index/store/remote/utils/cache/RefCountedCache.java @@ -76,6 +76,18 @@ public interface RefCountedCache { */ void decRef(K key); + /** + * Pins the key in the cache, preventing it from being evicted. + * @param key + */ + void pin(K key); + + /** + * Unpins the key in the cache, allowing it to be evicted. + * @param key + */ + void unpin(K key); + /** * get the reference count for key {@code key}. */ @@ -112,6 +124,13 @@ default long prune() { */ long activeUsage(); + /** + * Returns the pinned usage of this cache. + * + * @return the combined pinned weight of the values in this cache. + */ + long pinnedUsage(); + /** * Returns a current snapshot of this cache's cumulative statistics. All statistics are * initialized to zero, and are monotonically increasing over the lifetime of the cache. diff --git a/server/src/main/java/org/opensearch/index/store/remote/utils/cache/SegmentedCache.java b/server/src/main/java/org/opensearch/index/store/remote/utils/cache/SegmentedCache.java index feb9c3dd4fcdd..562f7286df0fd 100644 --- a/server/src/main/java/org/opensearch/index/store/remote/utils/cache/SegmentedCache.java +++ b/server/src/main/java/org/opensearch/index/store/remote/utils/cache/SegmentedCache.java @@ -135,6 +135,18 @@ public void decRef(K key) { segmentFor(key).decRef(key); } + @Override + public void pin(K key) { + if (key == null) throw new NullPointerException(); + segmentFor(key).pin(key); + } + + @Override + public void unpin(K key) { + if (key == null) throw new NullPointerException(); + segmentFor(key).unpin(key); + } + @Override public Integer getRef(K key) { if (key == null) throw new NullPointerException(); @@ -180,22 +192,43 @@ public long activeUsage() { return totalActiveUsage; } + /** + * Returns the pinned usage of this cache. + * + * @return the combined pinned weight of the values in this cache. + */ @Override - public IRefCountedCacheStats stats() { + public long pinnedUsage() { + long totalPinnedUsage = 0L; + for (RefCountedCache cache : table) { + IRefCountedCacheStats c = cache.stats(); + totalPinnedUsage += c.pinnedUsage(); + } + return totalPinnedUsage; + } - final RefCountedCacheStats totalOverallCacheStats = new RefCountedCacheStats(0, 0, 0, 0, 0, 0, 0, 0, 0); - final RefCountedCacheStats totalFullFileCacheStats = new RefCountedCacheStats(0, 0, 0, 0, 0, 0, 0, 0, 0); - final RefCountedCacheStats totalBlockFileCacheStats = new RefCountedCacheStats(0, 0, 0, 0, 0, 0, 0, 0, 0); + @Override + public IRefCountedCacheStats stats() { + final RefCountedCacheStats totalOverallCacheStats = new RefCountedCacheStats(0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + final RefCountedCacheStats totalFullFileCacheStats = new RefCountedCacheStats(0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + final RefCountedCacheStats totalBlockFileCacheStats = new RefCountedCacheStats(0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + final RefCountedCacheStats totalPinnedFileCacheStats = new RefCountedCacheStats(0, 0, 0, 0, 0, 0, 0, 0, 0, 0); for (RefCountedCache cache : table) { AggregateRefCountedCacheStats aggregateStats = (AggregateRefCountedCacheStats) cache.stats(); totalOverallCacheStats.accumulate(aggregateStats.getOverallCacheStats()); totalFullFileCacheStats.accumulate(aggregateStats.getFullFileCacheStats()); totalBlockFileCacheStats.accumulate(aggregateStats.getBlockFileCacheStats()); + totalPinnedFileCacheStats.accumulate(aggregateStats.getPinnedFileCacheStats()); } - return new AggregateRefCountedCacheStats(totalOverallCacheStats, totalFullFileCacheStats, totalBlockFileCacheStats); + return new AggregateRefCountedCacheStats( + totalOverallCacheStats, + totalFullFileCacheStats, + totalBlockFileCacheStats, + totalPinnedFileCacheStats + ); } // To be used only for debugging purposes diff --git a/server/src/main/java/org/opensearch/index/store/remote/utils/cache/stats/AggregateRefCountedCacheStats.java b/server/src/main/java/org/opensearch/index/store/remote/utils/cache/stats/AggregateRefCountedCacheStats.java index 2ad0dd7428628..29bdecb9eef27 100644 --- a/server/src/main/java/org/opensearch/index/store/remote/utils/cache/stats/AggregateRefCountedCacheStats.java +++ b/server/src/main/java/org/opensearch/index/store/remote/utils/cache/stats/AggregateRefCountedCacheStats.java @@ -24,6 +24,7 @@ public final class AggregateRefCountedCacheStats implements IRefCountedCacheStat private final RefCountedCacheStats overallCacheStats; private final RefCountedCacheStats fullFileCacheStats; private final RefCountedCacheStats blockFileCacheStats; + private final RefCountedCacheStats pinnedFileCacheStats; /** * Constructs a new {@code AggregateRefCountedCacheStats} instance. @@ -35,11 +36,13 @@ public final class AggregateRefCountedCacheStats implements IRefCountedCacheStat public AggregateRefCountedCacheStats( RefCountedCacheStats overallCacheStats, RefCountedCacheStats fullFileCacheStats, - RefCountedCacheStats blockFileCacheStats + RefCountedCacheStats blockFileCacheStats, + RefCountedCacheStats pinnedFileCacheStats ) { this.overallCacheStats = overallCacheStats; this.fullFileCacheStats = fullFileCacheStats; this.blockFileCacheStats = blockFileCacheStats; + this.pinnedFileCacheStats = pinnedFileCacheStats; } /** @@ -58,6 +61,14 @@ public RefCountedCacheStats getBlockFileCacheStats() { return blockFileCacheStats; } + /** + * Getter for pinnedFileCacheStats. + * @return {@link RefCountedCacheStats} pinnedFileCacheStats. + */ + public RefCountedCacheStats getPinnedFileCacheStats() { + return pinnedFileCacheStats; + } + /** * Getter for fullFileCacheStats. * @return {@link RefCountedCacheStats} fullFileCacheStats. @@ -191,6 +202,16 @@ public long activeUsage() { return this.overallCacheStats.activeUsage(); } + /** + * Returns the total pinned weight of the cache. + * + * @return the total pinned weight of the cache + */ + @Override + public long pinnedUsage() { + return this.pinnedFileCacheStats.pinnedUsage(); + } + /** * Accumulates the values of another {@link IRefCountedCacheStats} into this one. * @@ -209,6 +230,7 @@ public IRefCountedCacheStats accumulate(IRefCountedCacheStats other) { this.overallCacheStats.accumulate(otherStats.overallCacheStats); this.fullFileCacheStats.accumulate(otherStats.fullFileCacheStats); this.blockFileCacheStats.accumulate(otherStats.blockFileCacheStats); + this.pinnedFileCacheStats.accumulate(otherStats.pinnedFileCacheStats); return this; } @@ -228,7 +250,8 @@ public boolean equals(Object o) { AggregateRefCountedCacheStats other = (AggregateRefCountedCacheStats) o; return overallCacheStats.equals(other.overallCacheStats) && fullFileCacheStats.equals(other.fullFileCacheStats) - && blockFileCacheStats.equals(other.blockFileCacheStats); + && blockFileCacheStats.equals(other.blockFileCacheStats) + && pinnedFileCacheStats.equals(other.pinnedFileCacheStats); } @Override @@ -243,6 +266,9 @@ public String toString() { + ", " + "blockRefCountedCacheStats=" + blockFileCacheStats.toString() + + ", " + + "pinnedRefCountedCacheStats=" + + pinnedFileCacheStats.toString() + '}'; } } diff --git a/server/src/main/java/org/opensearch/index/store/remote/utils/cache/stats/DefaultStatsCounter.java b/server/src/main/java/org/opensearch/index/store/remote/utils/cache/stats/DefaultStatsCounter.java index 9d3b144cd5a11..b768e6ceb65f4 100644 --- a/server/src/main/java/org/opensearch/index/store/remote/utils/cache/stats/DefaultStatsCounter.java +++ b/server/src/main/java/org/opensearch/index/store/remote/utils/cache/stats/DefaultStatsCounter.java @@ -31,6 +31,11 @@ public class DefaultStatsCounter implements StatsCounter { */ private long activeUsage; + /** + * this tracks cache usage only by pinned entries. + */ + private long pinnedUsage; + public DefaultStatsCounter() { this.hitCount = 0L; this.missCount = 0L; @@ -44,7 +49,7 @@ public DefaultStatsCounter() { } @Override - public void recordHits(K key, V value, int count) { + public void recordHits(K key, V value, boolean pinned, int count) { hitCount += count; } @@ -54,16 +59,24 @@ public void recordMisses(K key, int count) { } @Override - public void recordRemoval(V value, long weight) { + public void recordRemoval(V value, boolean pinned, long weight) { removeCount++; removeWeight += weight; usage -= weight; } @Override - public void recordReplacement(V oldValue, V newValue, long oldWeight, long newWeight, boolean shouldUpdateActiveUsage) { + public void recordReplacement( + V oldValue, + V newValue, + long oldWeight, + long newWeight, + boolean shouldUpdateActiveUsage, + boolean isPinned + ) { replaceCount++; if (shouldUpdateActiveUsage) activeUsage = activeUsage - oldWeight + newWeight; + if (isPinned) pinnedUsage = pinnedUsage - oldWeight + newWeight; usage = usage - oldWeight + newWeight; } @@ -76,22 +89,44 @@ public void recordEviction(V value, long weight) { } @Override - public void recordUsage(V value, long weight, boolean shouldDecrease) { + public void recordUsage(V value, long weight, boolean pinned, boolean shouldDecrease) { weight = shouldDecrease ? -1 * weight : weight; usage += weight; } @Override - public void recordActiveUsage(V value, long weight, boolean shouldDecrease) { + public void recordActiveUsage(V value, long weight, boolean pinned, boolean shouldDecrease) { weight = shouldDecrease ? -1 * weight : weight; activeUsage += weight; } + /** + * Records the cache usage by entries which are pinned. + * This should be called when an entry is pinned/unpinned in the cache. + * + * @param weight Weight of the entry. + * @param shouldDecrease Should the pinned usage of the cache be decreased or not. + */ + @Override + public void recordPinnedUsage(V value, long weight, boolean shouldDecrease) { + weight = shouldDecrease ? -1 * weight : weight; + pinnedUsage += weight; + } + @Override public void resetActiveUsage() { this.activeUsage = 0; } + /** + * Resets the cache usage by entries which are pinned. + * This should be called when cache is cleared. + */ + @Override + public void resetPinnedUsage() { + this.pinnedUsage = 0L; + } + @Override public void resetUsage() { this.usage = 0; @@ -107,6 +142,16 @@ public long usage() { return this.usage; } + /** + * Returns the pinned usage of the cache. + * + * @return Pinned usage of the cache. + */ + @Override + public long pinnedUsage() { + return this.pinnedUsage; + } + @Override public IRefCountedCacheStats snapshot() { return new RefCountedCacheStats( @@ -118,7 +163,8 @@ public IRefCountedCacheStats snapshot() { evictionCount, evictionWeight, usage, - activeUsage + activeUsage, + pinnedUsage ); } diff --git a/server/src/main/java/org/opensearch/index/store/remote/utils/cache/stats/FileStatsCounter.java b/server/src/main/java/org/opensearch/index/store/remote/utils/cache/stats/FileStatsCounter.java index 0589a6f34006c..4003f619574f0 100644 --- a/server/src/main/java/org/opensearch/index/store/remote/utils/cache/stats/FileStatsCounter.java +++ b/server/src/main/java/org/opensearch/index/store/remote/utils/cache/stats/FileStatsCounter.java @@ -20,18 +20,21 @@ public class FileStatsCounter implements StatsCounter { private final DefaultStatsCounter overallStatsCounter; private final DefaultStatsCounter fullFileStatsCounter; private final DefaultStatsCounter blockFileStatsCounter; + private final DefaultStatsCounter pinnedFileStatsCounter; public FileStatsCounter() { overallStatsCounter = new DefaultStatsCounter<>(); fullFileStatsCounter = new DefaultStatsCounter<>(); blockFileStatsCounter = new DefaultStatsCounter<>(); + pinnedFileStatsCounter = new DefaultStatsCounter<>(); } @Override - public void recordHits(K key, V value, int count) { - overallStatsCounter.recordHits(key, value, count); - if (isFullFile(value)) fullFileStatsCounter.recordHits(key, value, count); - else blockFileStatsCounter.recordHits(key, value, count); + public void recordHits(K key, V value, boolean pinned, int count) { + overallStatsCounter.recordHits(key, value, pinned, count); + if (isFullFile(value)) fullFileStatsCounter.recordHits(key, value, pinned, count); + else blockFileStatsCounter.recordHits(key, value, pinned, count); + if (pinned) pinnedFileStatsCounter.recordHits(key, value, pinned, count); } @Override @@ -42,33 +45,44 @@ public void recordMisses(K key, int count) { } @Override - public void recordRemoval(V value, long weight) { + public void recordRemoval(V value, boolean pinned, long weight) { + + overallStatsCounter.recordRemoval(value, pinned, weight); + if (isFullFile(value)) fullFileStatsCounter.recordRemoval(value, pinned, weight); + else blockFileStatsCounter.recordRemoval(value, pinned, weight); + if (pinned) pinnedFileStatsCounter.recordRemoval(value, pinned, weight); - overallStatsCounter.recordRemoval(value, weight); - if (isFullFile(value)) fullFileStatsCounter.recordRemoval(value, weight); - else blockFileStatsCounter.recordRemoval(value, weight); } @Override - public void recordReplacement(V oldValue, V newValue, long oldWeight, long newWeight, boolean shouldUpdateActiveUsage) { + public void recordReplacement( + V oldValue, + V newValue, + long oldWeight, + long newWeight, + boolean shouldUpdateActiveUsage, + boolean isPinned + ) { boolean isOldFullFile = isFullFile(oldValue); boolean isNewFullFile = isFullFile(newValue); - overallStatsCounter.recordReplacement(oldValue, newValue, oldWeight, newWeight, shouldUpdateActiveUsage); + overallStatsCounter.recordReplacement(oldValue, newValue, oldWeight, newWeight, shouldUpdateActiveUsage, isPinned); fullFileStatsCounter.recordReplacement( oldValue, newValue, isOldFullFile ? oldWeight : 0, isNewFullFile ? newWeight : 0, - shouldUpdateActiveUsage + shouldUpdateActiveUsage, + isPinned ); blockFileStatsCounter.recordReplacement( oldValue, newValue, isOldFullFile ? 0 : oldWeight, isNewFullFile ? 0 : newWeight, - shouldUpdateActiveUsage + shouldUpdateActiveUsage, + isPinned ); } @@ -81,19 +95,36 @@ public void recordEviction(V value, long weight) { } @Override - public void recordUsage(V value, long weight, boolean shouldDecrease) { + public void recordUsage(V value, long weight, boolean pinned, boolean shouldDecrease) { - overallStatsCounter.recordUsage(value, weight, shouldDecrease); - if (isFullFile(value)) fullFileStatsCounter.recordUsage(value, weight, shouldDecrease); - else blockFileStatsCounter.recordUsage(value, weight, shouldDecrease); + overallStatsCounter.recordUsage(value, weight, pinned, shouldDecrease); + if (isFullFile(value)) fullFileStatsCounter.recordUsage(value, weight, pinned, shouldDecrease); + else blockFileStatsCounter.recordUsage(value, weight, pinned, shouldDecrease); + if (pinned) pinnedFileStatsCounter.recordUsage(value, weight, pinned, shouldDecrease); } @Override - public void recordActiveUsage(V value, long weight, boolean shouldDecrease) { + public void recordActiveUsage(V value, long weight, boolean pinned, boolean shouldDecrease) { - overallStatsCounter.recordActiveUsage(value, weight, shouldDecrease); - if (isFullFile(value)) fullFileStatsCounter.recordActiveUsage(value, weight, shouldDecrease); - else blockFileStatsCounter.recordActiveUsage(value, weight, shouldDecrease); + overallStatsCounter.recordActiveUsage(value, weight, pinned, shouldDecrease); + if (isFullFile(value)) fullFileStatsCounter.recordActiveUsage(value, weight, pinned, shouldDecrease); + else blockFileStatsCounter.recordActiveUsage(value, weight, pinned, shouldDecrease); + if (pinned) pinnedFileStatsCounter.recordActiveUsage(value, weight, pinned, shouldDecrease); + } + + /** + * Records the cache usage by entries which are pinned. + * This should be called when an entry is pinned/unpinned in the cache. + * + * @param weight Weight of the entry. + * @param shouldDecrease Should the pinned usage of the cache be decreased or not. + */ + @Override + public void recordPinnedUsage(V value, long weight, boolean shouldDecrease) { + overallStatsCounter.recordPinnedUsage(value, weight, shouldDecrease); + if (isFullFile(value)) fullFileStatsCounter.recordPinnedUsage(value, weight, shouldDecrease); + else blockFileStatsCounter.recordPinnedUsage(value, weight, shouldDecrease); + pinnedFileStatsCounter.recordPinnedUsage(value, weight, shouldDecrease); } @Override @@ -101,7 +132,19 @@ public void resetActiveUsage() { overallStatsCounter.resetActiveUsage(); fullFileStatsCounter.resetActiveUsage(); blockFileStatsCounter.resetActiveUsage(); + pinnedFileStatsCounter.resetActiveUsage(); + } + /** + * Resets the cache usage by entries which are pinned. + * This should be called when cache is cleared. + */ + @Override + public void resetPinnedUsage() { + overallStatsCounter.resetPinnedUsage(); + fullFileStatsCounter.resetPinnedUsage(); + blockFileStatsCounter.resetPinnedUsage(); + pinnedFileStatsCounter.resetPinnedUsage(); } @Override @@ -109,6 +152,7 @@ public void resetUsage() { overallStatsCounter.resetUsage(); fullFileStatsCounter.resetUsage(); blockFileStatsCounter.resetUsage(); + pinnedFileStatsCounter.resetUsage(); } @Override @@ -121,12 +165,23 @@ public long usage() { return overallStatsCounter.usage(); } + /** + * Returns the pinned usage of the cache. + * + * @return Pinned usage of the cache. + */ + @Override + public long pinnedUsage() { + return pinnedFileStatsCounter.pinnedUsage(); + } + @Override public IRefCountedCacheStats snapshot() { return new AggregateRefCountedCacheStats( (RefCountedCacheStats) overallStatsCounter.snapshot(), (RefCountedCacheStats) fullFileStatsCounter.snapshot(), - (RefCountedCacheStats) blockFileStatsCounter.snapshot() + (RefCountedCacheStats) blockFileStatsCounter.snapshot(), + (RefCountedCacheStats) pinnedFileStatsCounter.snapshot() ); } diff --git a/server/src/main/java/org/opensearch/index/store/remote/utils/cache/stats/IRefCountedCacheStats.java b/server/src/main/java/org/opensearch/index/store/remote/utils/cache/stats/IRefCountedCacheStats.java index ed74d0542dd79..9fdd7ef083628 100644 --- a/server/src/main/java/org/opensearch/index/store/remote/utils/cache/stats/IRefCountedCacheStats.java +++ b/server/src/main/java/org/opensearch/index/store/remote/utils/cache/stats/IRefCountedCacheStats.java @@ -114,6 +114,13 @@ public interface IRefCountedCacheStats { */ public long activeUsage(); + /** + * Returns the total pinned weight of the cache. + * + * @return the total pinned weight of the cache + */ + public long pinnedUsage(); + /** * Accumulates the values of another {@link IRefCountedCacheStats} into this one. * @param other another {@link IRefCountedCacheStats} diff --git a/server/src/main/java/org/opensearch/index/store/remote/utils/cache/stats/RefCountedCacheStats.java b/server/src/main/java/org/opensearch/index/store/remote/utils/cache/stats/RefCountedCacheStats.java index 0f2895a8d7727..a2afa385be0eb 100644 --- a/server/src/main/java/org/opensearch/index/store/remote/utils/cache/stats/RefCountedCacheStats.java +++ b/server/src/main/java/org/opensearch/index/store/remote/utils/cache/stats/RefCountedCacheStats.java @@ -29,6 +29,7 @@ public final class RefCountedCacheStats implements IRefCountedCacheStats { private long evictionWeight; private long usage; private long activeUsage; + private long pinnedUsage; /** * Constructs a new {@code AggregateRefCountedCacheStats} instance. @@ -53,7 +54,8 @@ public RefCountedCacheStats( long evictionCount, long evictionWeight, long usage, - long activeUsage + long activeUsage, + long pinnedUsage ) { if ((hitCount < 0) || (missCount < 0) @@ -73,6 +75,7 @@ public RefCountedCacheStats( this.evictionWeight = evictionWeight; this.usage = usage; this.activeUsage = activeUsage; + this.pinnedUsage = pinnedUsage; } /** @@ -212,6 +215,16 @@ public long activeUsage() { return activeUsage; } + /** + * Returns the total pinned weight of the cache. + * + * @return the total pinned weight of the cache + */ + @Override + public long pinnedUsage() { + return pinnedUsage; + } + /** * Accumulates the values of another {@link RefCountedCacheStats} into this one. * @@ -270,7 +283,8 @@ public boolean equals(Object o) { && evictionCount == other.evictionCount && evictionWeight == other.evictionWeight && usage == other.usage - && activeUsage == other.activeUsage; + && activeUsage == other.activeUsage + && pinnedUsage == other.pinnedUsage; } @Override @@ -303,6 +317,9 @@ public String toString() { + ", " + "activeUsage=" + activeUsage + + ", " + + "pinnedUsage=" + + pinnedUsage + '}'; } } diff --git a/server/src/main/java/org/opensearch/index/store/remote/utils/cache/stats/StatsCounter.java b/server/src/main/java/org/opensearch/index/store/remote/utils/cache/stats/StatsCounter.java index aeb910869904e..43b8e904fdc95 100644 --- a/server/src/main/java/org/opensearch/index/store/remote/utils/cache/stats/StatsCounter.java +++ b/server/src/main/java/org/opensearch/index/store/remote/utils/cache/stats/StatsCounter.java @@ -25,7 +25,7 @@ public interface StatsCounter { * * @param count the number of hits to record */ - void recordHits(K key, V value, int count); + void recordHits(K key, V value, boolean pinned, int count); /** * Records cache misses. This should be called when a cache request returns a value that was not @@ -35,7 +35,7 @@ public interface StatsCounter { * {@code recordLoadFailure} and multiple calls to this method, despite all being served by the * results of a single load operation. * - * @param count the number of misses to record + * @param count the number of misses to record */ void recordMisses(K key, int count); @@ -47,7 +47,7 @@ public interface StatsCounter { * * @param weight the weight of the removed entry */ - void recordRemoval(V value, long weight); + void recordRemoval(V value, boolean pinned, long weight); /** * Records the replacement of an entry from the cache. This should only been called when an entry is @@ -55,7 +55,7 @@ public interface StatsCounter { * {@link RefCountedCache#put(Object, Object)} * {@link RefCountedCache#compute(Object, BiFunction)} */ - void recordReplacement(V oldValue, V newValue, long oldWeight, long newWeight, boolean shouldUpdateActiveUsage); + void recordReplacement(V oldValue, V newValue, long oldWeight, long newWeight, boolean shouldUpdateActiveUsage, boolean isPinned); /** * Records the eviction of an entry from the cache. This should only been called when an entry is @@ -69,20 +69,31 @@ public interface StatsCounter { /** * Records the usage of the cache. This should be called when an entry is created/removed/replaced in the cache. * - * @param value Entry of the cache. - * @param weight Weight of the entry. + * @param value Entry of the cache. + * @param weight Weight of the entry. + * @param pinned * @param shouldDecrease Should the usage of the cache be decreased or not. */ - void recordUsage(V value, long weight, boolean shouldDecrease); + void recordUsage(V value, long weight, boolean pinned, boolean shouldDecrease); /** * Records the cache usage by entries which are active (being referenced). * This should be called when an active entry is created/removed/replaced in the cache. - * @param value Entry of the cache. - * @param weight Weight of the entry. + * + * @param value Entry of the cache. + * @param weight Weight of the entry. + * @param pinned * @param shouldDecrease Should the active usage of the cache be decreased or not. */ - void recordActiveUsage(V value, long weight, boolean shouldDecrease); + void recordActiveUsage(V value, long weight, boolean pinned, boolean shouldDecrease); + + /** + * Records the cache usage by entries which are pinned. + * This should be called when an entry is pinned/unpinned in the cache. + * @param weight Weight of the entry. + * @param shouldDecrease Should the pinned usage of the cache be decreased or not. + */ + void recordPinnedUsage(V value, long weight, boolean shouldDecrease); /** * Resets the cache usage by entries which are active (being referenced). @@ -90,6 +101,12 @@ public interface StatsCounter { */ void resetActiveUsage(); + /** + * Resets the cache usage by entries which are pinned. + * This should be called when cache is cleared. + */ + void resetPinnedUsage(); + /** * Resets the cache usage. * This should be called when cache is cleared. @@ -108,6 +125,12 @@ public interface StatsCounter { */ long usage(); + /** + * Returns the pinned usage of the cache. + * @return Pinned usage of the cache. + */ + long pinnedUsage(); + /** * Returns a snapshot of this counter's values. Note that this may be an inconsistent view, as it * may be interleaved with update operations. diff --git a/server/src/test/java/org/opensearch/cluster/ClusterInfoTests.java b/server/src/test/java/org/opensearch/cluster/ClusterInfoTests.java index a218e9d50c11e..a47c338213a7f 100644 --- a/server/src/test/java/org/opensearch/cluster/ClusterInfoTests.java +++ b/server/src/test/java/org/opensearch/cluster/ClusterInfoTests.java @@ -98,7 +98,8 @@ private static Map randomFileCacheStats() { randomLong(), randomLong(), randomLong(), - FileCacheStatsType.FULL_FILE_STATS + randomLong(), + FileCacheStatsType.OVER_ALL_STATS ), new FileCacheStats( randomLong(), @@ -107,6 +108,7 @@ private static Map randomFileCacheStats() { randomLong(), randomLong(), randomLong(), + randomLong(), FileCacheStatsType.FULL_FILE_STATS ), new FileCacheStats( @@ -116,7 +118,18 @@ private static Map randomFileCacheStats() { randomLong(), randomLong(), randomLong(), + randomLong(), FileCacheStatsType.BLOCK_FILE_STATS + ), + new FileCacheStats( + randomLong(), + randomLong(), + randomLong(), + randomLong(), + randomLong(), + randomLong(), + randomLong(), + FileCacheStatsType.PINNED_FILE_STATS ) ); builder.put(key, fileCacheStats); diff --git a/server/src/test/java/org/opensearch/cluster/routing/allocation/decider/DiskThresholdDeciderTests.java b/server/src/test/java/org/opensearch/cluster/routing/allocation/decider/DiskThresholdDeciderTests.java index f8f4ee169f36e..fe21c68c4e977 100644 --- a/server/src/test/java/org/opensearch/cluster/routing/allocation/decider/DiskThresholdDeciderTests.java +++ b/server/src/test/java/org/opensearch/cluster/routing/allocation/decider/DiskThresholdDeciderTests.java @@ -307,27 +307,31 @@ public void testDiskThresholdForRemoteShards() { "node1", new AggregateFileCacheStats( 0, - new FileCacheStats(0, 0, 1000, 0, 0, 0, FileCacheStatsType.OVER_ALL_STATS), - new FileCacheStats(0, 0, 0, 0, 0, 0, FileCacheStatsType.FULL_FILE_STATS), - new FileCacheStats(0, 0, 1000, 0, 0, 0, FileCacheStatsType.BLOCK_FILE_STATS) + new FileCacheStats(0, 0, 1000, 0, 0, 0, 0, FileCacheStatsType.OVER_ALL_STATS), + new FileCacheStats(0, 0, 0, 0, 0, 0, 0, FileCacheStatsType.FULL_FILE_STATS), + new FileCacheStats(0, 0, 1000, 0, 0, 0, 0, FileCacheStatsType.BLOCK_FILE_STATS), + new FileCacheStats(0, 0, 1000, 0, 0, 0, 0, FileCacheStatsType.PINNED_FILE_STATS) ) ); fileCacheStatsMap.put( "node2", new AggregateFileCacheStats( 0, - new FileCacheStats(0, 0, 1000, 0, 0, 0, FileCacheStatsType.OVER_ALL_STATS), - new FileCacheStats(0, 0, 0, 0, 0, 0, FileCacheStatsType.FULL_FILE_STATS), - new FileCacheStats(0, 0, 1000, 0, 0, 0, FileCacheStatsType.BLOCK_FILE_STATS) + new FileCacheStats(0, 0, 1000, 0, 0, 0, 0, FileCacheStatsType.OVER_ALL_STATS), + new FileCacheStats(0, 0, 0, 0, 0, 0, 0, FileCacheStatsType.FULL_FILE_STATS), + new FileCacheStats(0, 0, 1000, 0, 0, 0, 0, FileCacheStatsType.BLOCK_FILE_STATS), + new FileCacheStats(0, 0, 1000, 0, 0, 0, 0, FileCacheStatsType.PINNED_FILE_STATS) ) ); fileCacheStatsMap.put( "node3", new AggregateFileCacheStats( 0, - new FileCacheStats(0, 0, 1000, 0, 0, 0, FileCacheStatsType.OVER_ALL_STATS), - new FileCacheStats(0, 0, 0, 0, 0, 0, FileCacheStatsType.FULL_FILE_STATS), - new FileCacheStats(0, 0, 1000, 0, 0, 0, FileCacheStatsType.BLOCK_FILE_STATS) + new FileCacheStats(0, 0, 1000, 0, 0, 0, 0, FileCacheStatsType.OVER_ALL_STATS), + new FileCacheStats(0, 0, 0, 0, 0, 0, 0, FileCacheStatsType.FULL_FILE_STATS), + new FileCacheStats(0, 0, 1000, 0, 0, 0, 0, FileCacheStatsType.BLOCK_FILE_STATS), + new FileCacheStats(0, 0, 1000, 0, 0, 0, 0, FileCacheStatsType.PINNED_FILE_STATS) + ) ); final ClusterInfo clusterInfo = new DevNullClusterInfo(usages, usages, shardSizes, fileCacheStatsMap); diff --git a/server/src/test/java/org/opensearch/cluster/routing/allocation/decider/WarmDiskThresholdDeciderTests.java b/server/src/test/java/org/opensearch/cluster/routing/allocation/decider/WarmDiskThresholdDeciderTests.java index 27220b07b3549..b516e6bb72976 100644 --- a/server/src/test/java/org/opensearch/cluster/routing/allocation/decider/WarmDiskThresholdDeciderTests.java +++ b/server/src/test/java/org/opensearch/cluster/routing/allocation/decider/WarmDiskThresholdDeciderTests.java @@ -99,19 +99,21 @@ public void testCanAllocateSufficientFreeSpace() { "node1", new AggregateFileCacheStats( randomNonNegativeInt(), - new FileCacheStats(0, 1000, 0, 0, 0, 0, FileCacheStatsType.OVER_ALL_STATS), - new FileCacheStats(0, 1000, 0, 0, 0, 0, FileCacheStatsType.FULL_FILE_STATS), - new FileCacheStats(0, 1000, 0, 0, 0, 0, FileCacheStatsType.BLOCK_FILE_STATS) - + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.OVER_ALL_STATS), + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.FULL_FILE_STATS), + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.BLOCK_FILE_STATS), + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.PINNED_FILE_STATS) ) ); fileCacheStatsMap.put( "node2", new AggregateFileCacheStats( randomNonNegativeInt(), - new FileCacheStats(0, 1000, 0, 0, 0, 0, FileCacheStatsType.OVER_ALL_STATS), - new FileCacheStats(0, 1000, 0, 0, 0, 0, FileCacheStatsType.FULL_FILE_STATS), - new FileCacheStats(0, 1000, 0, 0, 0, 0, FileCacheStatsType.BLOCK_FILE_STATS) + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.OVER_ALL_STATS), + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.FULL_FILE_STATS), + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.BLOCK_FILE_STATS), + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.PINNED_FILE_STATS) + ) ); @@ -183,9 +185,10 @@ public void testCanAllocateInSufficientFreeSpace() { "node1", new AggregateFileCacheStats( randomNonNegativeInt(), - new FileCacheStats(0, 1000, 0, 0, 0, 0, FileCacheStatsType.OVER_ALL_STATS), - new FileCacheStats(0, 1000, 0, 0, 0, 0, FileCacheStatsType.FULL_FILE_STATS), - new FileCacheStats(0, 1000, 0, 0, 0, 0, FileCacheStatsType.BLOCK_FILE_STATS) + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.OVER_ALL_STATS), + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.FULL_FILE_STATS), + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.BLOCK_FILE_STATS), + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.PINNED_FILE_STATS) ) ); @@ -193,9 +196,10 @@ public void testCanAllocateInSufficientFreeSpace() { "node2", new AggregateFileCacheStats( randomNonNegativeInt(), - new FileCacheStats(0, 1000, 0, 0, 0, 0, FileCacheStatsType.OVER_ALL_STATS), - new FileCacheStats(0, 1000, 0, 0, 0, 0, FileCacheStatsType.FULL_FILE_STATS), - new FileCacheStats(0, 1000, 0, 0, 0, 0, FileCacheStatsType.BLOCK_FILE_STATS) + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.OVER_ALL_STATS), + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.FULL_FILE_STATS), + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.BLOCK_FILE_STATS), + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.PINNED_FILE_STATS) ) ); @@ -274,9 +278,10 @@ public void testCanRemainSufficientSpace() { "node1", new AggregateFileCacheStats( randomNonNegativeInt(), - new FileCacheStats(0, 1000, 0, 0, 0, 0, FileCacheStatsType.OVER_ALL_STATS), - new FileCacheStats(0, 1000, 0, 0, 0, 0, FileCacheStatsType.FULL_FILE_STATS), - new FileCacheStats(0, 1000, 0, 0, 0, 0, FileCacheStatsType.BLOCK_FILE_STATS) + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.OVER_ALL_STATS), + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.FULL_FILE_STATS), + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.BLOCK_FILE_STATS), + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.PINNED_FILE_STATS) ) ); @@ -284,9 +289,10 @@ public void testCanRemainSufficientSpace() { "node2", new AggregateFileCacheStats( randomNonNegativeInt(), - new FileCacheStats(0, 1000, 0, 0, 0, 0, FileCacheStatsType.OVER_ALL_STATS), - new FileCacheStats(0, 1000, 0, 0, 0, 0, FileCacheStatsType.FULL_FILE_STATS), - new FileCacheStats(0, 1000, 0, 0, 0, 0, FileCacheStatsType.BLOCK_FILE_STATS) + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.OVER_ALL_STATS), + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.FULL_FILE_STATS), + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.BLOCK_FILE_STATS), + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.PINNED_FILE_STATS) ) ); @@ -358,9 +364,10 @@ public void testCanRemainInsufficientSpace() { "node1", new AggregateFileCacheStats( randomNonNegativeInt(), - new FileCacheStats(0, 1000, 0, 0, 0, 0, FileCacheStatsType.OVER_ALL_STATS), - new FileCacheStats(0, 1000, 0, 0, 0, 0, FileCacheStatsType.FULL_FILE_STATS), - new FileCacheStats(0, 1000, 0, 0, 0, 0, FileCacheStatsType.BLOCK_FILE_STATS) + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.OVER_ALL_STATS), + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.FULL_FILE_STATS), + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.BLOCK_FILE_STATS), + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.PINNED_FILE_STATS) ) ); @@ -368,9 +375,10 @@ public void testCanRemainInsufficientSpace() { "node2", new AggregateFileCacheStats( randomNonNegativeInt(), - new FileCacheStats(0, 1000, 0, 0, 0, 0, FileCacheStatsType.OVER_ALL_STATS), - new FileCacheStats(0, 1000, 0, 0, 0, 0, FileCacheStatsType.FULL_FILE_STATS), - new FileCacheStats(0, 1000, 0, 0, 0, 0, FileCacheStatsType.BLOCK_FILE_STATS) + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.OVER_ALL_STATS), + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.FULL_FILE_STATS), + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.BLOCK_FILE_STATS), + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.PINNED_FILE_STATS) ) ); @@ -442,19 +450,20 @@ public void testCanRemainSufficientSpaceAfterRelocation() { "node1", new AggregateFileCacheStats( randomNonNegativeInt(), - new FileCacheStats(0, 1000, 0, 0, 0, 0, FileCacheStatsType.OVER_ALL_STATS), - new FileCacheStats(0, 1000, 0, 0, 0, 0, FileCacheStatsType.FULL_FILE_STATS), - new FileCacheStats(0, 1000, 0, 0, 0, 0, FileCacheStatsType.BLOCK_FILE_STATS) - + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.OVER_ALL_STATS), + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.FULL_FILE_STATS), + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.BLOCK_FILE_STATS), + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.PINNED_FILE_STATS) ) ); fileCacheStatsMap.put( "node2", new AggregateFileCacheStats( randomNonNegativeInt(), - new FileCacheStats(0, 1000, 0, 0, 0, 0, FileCacheStatsType.OVER_ALL_STATS), - new FileCacheStats(0, 1000, 0, 0, 0, 0, FileCacheStatsType.FULL_FILE_STATS), - new FileCacheStats(0, 1000, 0, 0, 0, 0, FileCacheStatsType.BLOCK_FILE_STATS) + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.OVER_ALL_STATS), + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.FULL_FILE_STATS), + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.BLOCK_FILE_STATS), + new FileCacheStats(0, 1000, 0, 0, 0, 0, 0, FileCacheStatsType.PINNED_FILE_STATS) ) ); diff --git a/server/src/test/java/org/opensearch/index/store/remote/filecache/AggregateFileCacheStatsTests.java b/server/src/test/java/org/opensearch/index/store/remote/filecache/AggregateFileCacheStatsTests.java index 56998cd59bf34..10a4d697b91dd 100644 --- a/server/src/test/java/org/opensearch/index/store/remote/filecache/AggregateFileCacheStatsTests.java +++ b/server/src/test/java/org/opensearch/index/store/remote/filecache/AggregateFileCacheStatsTests.java @@ -30,6 +30,7 @@ public static AggregateRefCountedCacheStats getMockCacheStats() { final long hits = randomLongBetween(0, 10000); final long miss = randomLongBetween(0, 10000); final long usage = randomLongBetween(10000, BYTES_IN_GB); + final long pinnedUsage = randomLongBetween(10000, BYTES_IN_GB); final long activeUsage = randomLongBetween(10000, BYTES_IN_GB); final long fullFileHitCount = randomLongBetween(0, 10000); final long fullFileRemoveCount = randomLongBetween(0, 10000); @@ -42,7 +43,7 @@ public static AggregateRefCountedCacheStats getMockCacheStats() { return new AggregateRefCountedCacheStats( - new RefCountedCacheStats(hits, miss, 0, removed, replaced, 0, evicted, usage, activeUsage), + new RefCountedCacheStats(hits, miss, 0, removed, replaced, 0, evicted, usage, activeUsage, pinnedUsage), new RefCountedCacheStats( fullFileHitCount, 0, @@ -52,7 +53,8 @@ public static AggregateRefCountedCacheStats getMockCacheStats() { fullFileEvictionCount, fullFileEvictionWeight, fullFileUsage, - fullFileActiveUsage + fullFileActiveUsage, + pinnedUsage ), new RefCountedCacheStats( fullFileHitCount, @@ -63,7 +65,20 @@ public static AggregateRefCountedCacheStats getMockCacheStats() { fullFileEvictionCount, fullFileEvictionWeight, fullFileUsage, - fullFileActiveUsage + fullFileActiveUsage, + pinnedUsage + ), + new RefCountedCacheStats( + fullFileHitCount, + 0, + fullFileRemoveCount, + fullFileRemoveWeight, + fullFileReplaceCount, + fullFileEvictionCount, + fullFileEvictionWeight, + fullFileUsage, + fullFileActiveUsage, + pinnedUsage ) ); @@ -81,6 +96,7 @@ public static AggregateFileCacheStats getFileCacheStats(final long fileCacheCapa stats.activeUsage(), fileCacheCapacity, stats.usage(), + stats.pinnedUsage(), stats.evictionWeight(), stats.hitCount(), stats.missCount(), @@ -90,6 +106,7 @@ public static AggregateFileCacheStats getFileCacheStats(final long fileCacheCapa stats.activeUsage(), fileCacheCapacity, stats.usage(), + stats.pinnedUsage(), stats.evictionWeight(), stats.hitCount(), stats.missCount(), @@ -99,10 +116,21 @@ public static AggregateFileCacheStats getFileCacheStats(final long fileCacheCapa stats.activeUsage(), fileCacheCapacity, stats.usage(), + stats.pinnedUsage(), stats.evictionWeight(), stats.hitCount(), stats.missCount(), FileCacheStatsType.BLOCK_FILE_STATS + ), + new FileCacheStats( + stats.activeUsage(), + fileCacheCapacity, + stats.usage(), + stats.pinnedUsage(), + stats.evictionWeight(), + stats.hitCount(), + stats.missCount(), + FileCacheStatsType.PINNED_FILE_STATS ) ); } @@ -111,10 +139,11 @@ public static FileCacheStats getMockFullFileCacheStats() { final long active = randomLongBetween(100000, BYTES_IN_GB); final long total = randomLongBetween(100000, BYTES_IN_GB); final long used = randomLongBetween(100000, BYTES_IN_GB); + final long pinned = randomLongBetween(100000, BYTES_IN_GB); final long evicted = randomLongBetween(0, getMockCacheStats().getFullFileCacheStats().evictionWeight()); final long hit = randomLongBetween(0, 10); final long misses = randomLongBetween(0, 10); - return new FileCacheStats(active, total, used, evicted, hit, misses, FileCacheStatsType.OVER_ALL_STATS); + return new FileCacheStats(active, total, used, pinned, evicted, hit, misses, FileCacheStatsType.OVER_ALL_STATS); } public static AggregateFileCacheStats getMockFileCacheStats() throws IOException { diff --git a/server/src/test/java/org/opensearch/index/store/remote/filecache/FileCacheStatsTests.java b/server/src/test/java/org/opensearch/index/store/remote/filecache/FileCacheStatsTests.java index 6f0d676b46090..abae2c94e91d8 100644 --- a/server/src/test/java/org/opensearch/index/store/remote/filecache/FileCacheStatsTests.java +++ b/server/src/test/java/org/opensearch/index/store/remote/filecache/FileCacheStatsTests.java @@ -22,11 +22,21 @@ public static FileCacheStats getMockFullFileCacheStats() { final long active = randomLongBetween(100000, BYTES_IN_GB); final long total = randomLongBetween(100000, BYTES_IN_GB); final long used = randomLongBetween(100000, BYTES_IN_GB); + final long pinned = randomLongBetween(100000, BYTES_IN_GB); final long evicted = randomLongBetween(0, active); final long hits = randomLongBetween(0, 10); final long misses = randomLongBetween(0, 10); - return new FileCacheStats(active, total, used, evicted, hits, misses, AggregateFileCacheStats.FileCacheStatsType.OVER_ALL_STATS); + return new FileCacheStats( + active, + total, + used, + pinned, + evicted, + hits, + misses, + AggregateFileCacheStats.FileCacheStatsType.OVER_ALL_STATS + ); } public static void validateFullFileCacheStats(FileCacheStats expected, FileCacheStats actual) { diff --git a/server/src/test/java/org/opensearch/snapshots/SnapshotResiliencyTests.java b/server/src/test/java/org/opensearch/snapshots/SnapshotResiliencyTests.java index aa30eda474ef1..bd869b3a1d161 100644 --- a/server/src/test/java/org/opensearch/snapshots/SnapshotResiliencyTests.java +++ b/server/src/test/java/org/opensearch/snapshots/SnapshotResiliencyTests.java @@ -467,9 +467,10 @@ public void testSearchableSnapshotOverSubscription() { node.node.getId(), new AggregateFileCacheStats( 0, - new FileCacheStats(1, 0, 0, 0, 0, 0, FileCacheStatsType.OVER_ALL_STATS), - new FileCacheStats(0, 0, 0, 0, 0, 0, FileCacheStatsType.FULL_FILE_STATS), - new FileCacheStats(1, 0, 0, 0, 0, 0, FileCacheStatsType.BLOCK_FILE_STATS) + new FileCacheStats(1, 0, 0, 0, 0, 0, 0, FileCacheStatsType.OVER_ALL_STATS), + new FileCacheStats(0, 0, 0, 0, 0, 0, 0, FileCacheStatsType.FULL_FILE_STATS), + new FileCacheStats(1, 0, 0, 0, 0, 0, 0, FileCacheStatsType.BLOCK_FILE_STATS), + new FileCacheStats(1, 0, 0, 0, 0, 0, 0, FileCacheStatsType.PINNED_FILE_STATS) ) ); }