Skip to content

Commit cc22310

Browse files
peteralfonsiPeter Alfonsi
and
Peter Alfonsi
authored
[Tiered Caching] Stats rework (1/3): Interfaces and implementations for individual tiers (#12531)
As part of tiered caching stats, changes the common ICache interface to use ICacheKey as its key. This key contains dimensions (for example, shard ID, index name, or tier) that can be used to aggregate stats. Also changes the CacheStats interface to store the necessary cache stats, and to support getting stats either as a total or aggregated by these dimensions. Integrates these changes with OpenSearchOnHeapCache and EhcacheDiskCache. The stats implementation for the TieredSpilloverCache will be in a followup PR. --------- Signed-off-by: Peter Alfonsi <petealft@amazon.com> Co-authored-by: Peter Alfonsi <petealft@amazon.com>
1 parent f2e2a85 commit cc22310

File tree

25 files changed

+2411
-331
lines changed

25 files changed

+2411
-331
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
1818
- [Remote Store] Make translog transfer timeout configurable ([#12704](https://github.com/opensearch-project/OpenSearch/pull/12704))
1919
- Reject Resize index requests (i.e, split, shrink and clone), While DocRep to SegRep migration is in progress.([#12686](https://github.com/opensearch-project/OpenSearch/pull/12686))
2020
- Add support for more than one protocol for transport ([#12967](https://github.com/opensearch-project/OpenSearch/pull/12967))
21+
- [Tiered Caching] Add dimension-based stats to ICache implementations. ([#12531](https://github.com/opensearch-project/OpenSearch/pull/12531))
2122
- Add changes for overriding remote store and replication settings during snapshot restore. ([#11868](https://github.com/opensearch-project/OpenSearch/pull/11868))
2223

2324
### Dependencies

modules/cache-common/src/main/java/org/opensearch/cache/common/tier/TieredSpilloverCache.java

+26-14
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@
1212
import org.opensearch.common.annotation.ExperimentalApi;
1313
import org.opensearch.common.cache.CacheType;
1414
import org.opensearch.common.cache.ICache;
15+
import org.opensearch.common.cache.ICacheKey;
1516
import org.opensearch.common.cache.LoadAwareCacheLoader;
1617
import org.opensearch.common.cache.RemovalListener;
1718
import org.opensearch.common.cache.RemovalNotification;
1819
import org.opensearch.common.cache.RemovalReason;
1920
import org.opensearch.common.cache.policy.CachedQueryResult;
21+
import org.opensearch.common.cache.stats.ImmutableCacheStatsHolder;
2022
import org.opensearch.common.cache.store.config.CacheConfig;
2123
import org.opensearch.common.settings.Setting;
2224
import org.opensearch.common.settings.Settings;
@@ -54,7 +56,11 @@ public class TieredSpilloverCache<K, V> implements ICache<K, V> {
5456

5557
private final ICache<K, V> diskCache;
5658
private final ICache<K, V> onHeapCache;
57-
private final RemovalListener<K, V> removalListener;
59+
60+
// The listener for removals from the spillover cache as a whole
61+
// TODO: In TSC stats PR, each tier will have its own separate removal listener.
62+
private final RemovalListener<ICacheKey<K>, V> removalListener;
63+
private final List<String> dimensionNames;
5864
ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
5965
ReleasableLock readLock = new ReleasableLock(readWriteLock.readLock());
6066
ReleasableLock writeLock = new ReleasableLock(readWriteLock.writeLock());
@@ -70,9 +76,9 @@ public class TieredSpilloverCache<K, V> implements ICache<K, V> {
7076
this.removalListener = Objects.requireNonNull(builder.removalListener, "Removal listener can't be null");
7177

7278
this.onHeapCache = builder.onHeapCacheFactory.create(
73-
new CacheConfig.Builder<K, V>().setRemovalListener(new RemovalListener<K, V>() {
79+
new CacheConfig.Builder<K, V>().setRemovalListener(new RemovalListener<ICacheKey<K>, V>() {
7480
@Override
75-
public void onRemoval(RemovalNotification<K, V> notification) {
81+
public void onRemoval(RemovalNotification<ICacheKey<K>, V> notification) {
7682
try (ReleasableLock ignore = writeLock.acquire()) {
7783
if (SPILLOVER_REMOVAL_REASONS.contains(notification.getRemovalReason())
7884
&& evaluatePolicies(notification.getValue())) {
@@ -87,6 +93,7 @@ && evaluatePolicies(notification.getValue())) {
8793
.setValueType(builder.cacheConfig.getValueType())
8894
.setSettings(builder.cacheConfig.getSettings())
8995
.setWeigher(builder.cacheConfig.getWeigher())
96+
.setDimensionNames(builder.cacheConfig.getDimensionNames())
9097
.setMaxSizeInBytes(builder.cacheConfig.getMaxSizeInBytes())
9198
.setExpireAfterAccess(builder.cacheConfig.getExpireAfterAccess())
9299
.setClusterSettings(builder.cacheConfig.getClusterSettings())
@@ -97,7 +104,7 @@ && evaluatePolicies(notification.getValue())) {
97104
);
98105
this.diskCache = builder.diskCacheFactory.create(builder.cacheConfig, builder.cacheType, builder.cacheFactories);
99106
this.cacheList = Arrays.asList(onHeapCache, diskCache);
100-
107+
this.dimensionNames = builder.cacheConfig.getDimensionNames();
101108
this.policies = builder.policies; // Will never be null; builder initializes it to an empty list
102109
}
103110

@@ -112,19 +119,19 @@ ICache<K, V> getDiskCache() {
112119
}
113120

114121
@Override
115-
public V get(K key) {
122+
public V get(ICacheKey<K> key) {
116123
return getValueFromTieredCache().apply(key);
117124
}
118125

119126
@Override
120-
public void put(K key, V value) {
127+
public void put(ICacheKey<K> key, V value) {
121128
try (ReleasableLock ignore = writeLock.acquire()) {
122129
onHeapCache.put(key, value);
123130
}
124131
}
125132

126133
@Override
127-
public V computeIfAbsent(K key, LoadAwareCacheLoader<K, V> loader) throws Exception {
134+
public V computeIfAbsent(ICacheKey<K> key, LoadAwareCacheLoader<ICacheKey<K>, V> loader) throws Exception {
128135

129136
V cacheValue = getValueFromTieredCache().apply(key);
130137
if (cacheValue == null) {
@@ -141,7 +148,7 @@ public V computeIfAbsent(K key, LoadAwareCacheLoader<K, V> loader) throws Except
141148
}
142149

143150
@Override
144-
public void invalidate(K key) {
151+
public void invalidate(ICacheKey<K> key) {
145152
// We are trying to invalidate the key from all caches though it would be present in only of them.
146153
// Doing this as we don't know where it is located. We could do a get from both and check that, but what will
147154
// also trigger a hit/miss listener event, so ignoring it for now.
@@ -167,9 +174,9 @@ public void invalidateAll() {
167174
*/
168175
@SuppressWarnings({ "unchecked" })
169176
@Override
170-
public Iterable<K> keys() {
171-
Iterable<K>[] iterables = (Iterable<K>[]) new Iterable<?>[] { onHeapCache.keys(), diskCache.keys() };
172-
return new ConcatenatedIterables<K>(iterables);
177+
public Iterable<ICacheKey<K>> keys() {
178+
Iterable<ICacheKey<K>>[] iterables = (Iterable<ICacheKey<K>>[]) new Iterable<?>[] { onHeapCache.keys(), diskCache.keys() };
179+
return new ConcatenatedIterables<ICacheKey<K>>(iterables);
173180
}
174181

175182
@Override
@@ -197,7 +204,12 @@ public void close() throws IOException {
197204
}
198205
}
199206

200-
private Function<K, V> getValueFromTieredCache() {
207+
@Override
208+
public ImmutableCacheStatsHolder stats() {
209+
return null; // TODO: in TSC stats PR
210+
}
211+
212+
private Function<ICacheKey<K>, V> getValueFromTieredCache() {
201213
return key -> {
202214
try (ReleasableLock ignore = readLock.acquire()) {
203215
for (ICache<K, V> cache : cacheList) {
@@ -354,7 +366,7 @@ public String getCacheName() {
354366
public static class Builder<K, V> {
355367
private ICache.Factory onHeapCacheFactory;
356368
private ICache.Factory diskCacheFactory;
357-
private RemovalListener<K, V> removalListener;
369+
private RemovalListener<ICacheKey<K>, V> removalListener;
358370
private CacheConfig<K, V> cacheConfig;
359371
private CacheType cacheType;
360372
private Map<String, ICache.Factory> cacheFactories;
@@ -390,7 +402,7 @@ public Builder<K, V> setDiskCacheFactory(ICache.Factory diskCacheFactory) {
390402
* @param removalListener Removal listener
391403
* @return builder
392404
*/
393-
public Builder<K, V> setRemovalListener(RemovalListener<K, V> removalListener) {
405+
public Builder<K, V> setRemovalListener(RemovalListener<ICacheKey<K>, V> removalListener) {
394406
this.removalListener = removalListener;
395407
return this;
396408
}

modules/cache-common/src/test/java/org/opensearch/cache/common/tier/MockDiskCache.java

+16-9
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@
1010

1111
import org.opensearch.common.cache.CacheType;
1212
import org.opensearch.common.cache.ICache;
13+
import org.opensearch.common.cache.ICacheKey;
1314
import org.opensearch.common.cache.LoadAwareCacheLoader;
1415
import org.opensearch.common.cache.RemovalListener;
1516
import org.opensearch.common.cache.RemovalNotification;
1617
import org.opensearch.common.cache.RemovalReason;
1718
import org.opensearch.common.cache.serializer.Serializer;
19+
import org.opensearch.common.cache.stats.ImmutableCacheStatsHolder;
1820
import org.opensearch.common.cache.store.builders.ICacheBuilder;
1921
import org.opensearch.common.cache.store.config.CacheConfig;
2022

@@ -25,27 +27,27 @@
2527

2628
public class MockDiskCache<K, V> implements ICache<K, V> {
2729

28-
Map<K, V> cache;
30+
Map<ICacheKey<K>, V> cache;
2931
int maxSize;
3032
long delay;
3133

32-
private final RemovalListener<K, V> removalListener;
34+
private final RemovalListener<ICacheKey<K>, V> removalListener;
3335

34-
public MockDiskCache(int maxSize, long delay, RemovalListener<K, V> removalListener) {
36+
public MockDiskCache(int maxSize, long delay, RemovalListener<ICacheKey<K>, V> removalListener) {
3537
this.maxSize = maxSize;
3638
this.delay = delay;
3739
this.removalListener = removalListener;
38-
this.cache = new ConcurrentHashMap<K, V>();
40+
this.cache = new ConcurrentHashMap<ICacheKey<K>, V>();
3941
}
4042

4143
@Override
42-
public V get(K key) {
44+
public V get(ICacheKey<K> key) {
4345
V value = cache.get(key);
4446
return value;
4547
}
4648

4749
@Override
48-
public void put(K key, V value) {
50+
public void put(ICacheKey<K> key, V value) {
4951
if (this.cache.size() >= maxSize) { // For simplification
5052
this.removalListener.onRemoval(new RemovalNotification<>(key, value, RemovalReason.EVICTED));
5153
}
@@ -58,7 +60,7 @@ public void put(K key, V value) {
5860
}
5961

6062
@Override
61-
public V computeIfAbsent(K key, LoadAwareCacheLoader<K, V> loader) {
63+
public V computeIfAbsent(ICacheKey<K> key, LoadAwareCacheLoader<ICacheKey<K>, V> loader) {
6264
V value = cache.computeIfAbsent(key, key1 -> {
6365
try {
6466
return loader.load(key);
@@ -70,7 +72,7 @@ public V computeIfAbsent(K key, LoadAwareCacheLoader<K, V> loader) {
7072
}
7173

7274
@Override
73-
public void invalidate(K key) {
75+
public void invalidate(ICacheKey<K> key) {
7476
this.cache.remove(key);
7577
}
7678

@@ -80,7 +82,7 @@ public void invalidateAll() {
8082
}
8183

8284
@Override
83-
public Iterable<K> keys() {
85+
public Iterable<ICacheKey<K>> keys() {
8486
return () -> new CacheKeyIterator<>(cache, removalListener);
8587
}
8688

@@ -92,6 +94,11 @@ public long count() {
9294
@Override
9395
public void refresh() {}
9496

97+
@Override
98+
public ImmutableCacheStatsHolder stats() {
99+
return null;
100+
}
101+
95102
@Override
96103
public void close() {
97104

0 commit comments

Comments
 (0)