44
44
import java .util .Collection ;
45
45
import java .util .Collections ;
46
46
import java .util .Iterator ;
47
+ import java .util .Objects ;
47
48
import java .util .Set ;
48
49
import java .util .concurrent .ConcurrentMap ;
49
50
import java .util .function .Supplier ;
50
51
51
52
/**
52
53
* The indices request cache allows to cache a shard level request stage responses, helping with improving
53
54
* similar requests that are potentially expensive (because of aggs for example). The cache is fully coherent
54
- * with the semantics of NRT (the index reader version is part of the cache key), and relies on size based
55
+ * with the semantics of NRT (the index reader cache key is part of the cache key), and relies on size based
55
56
* eviction to evict old reader associated cache entries as well as scheduler reaper to clean readers that
56
57
* are no longer used or closed shards.
57
58
* <p>
@@ -100,7 +101,7 @@ public void close() {
100
101
}
101
102
102
103
void clear (CacheEntity entity ) {
103
- keysToClean .add (new CleanupKey (entity , - 1 ));
104
+ keysToClean .add (new CleanupKey (entity , null ));
104
105
cleanCache ();
105
106
}
106
107
@@ -111,13 +112,14 @@ public void onRemoval(RemovalNotification<Key, BytesReference> notification) {
111
112
112
113
BytesReference getOrCompute (CacheEntity cacheEntity , Supplier <BytesReference > loader ,
113
114
DirectoryReader reader , BytesReference cacheKey ) throws Exception {
114
- final Key key = new Key (cacheEntity , reader .getVersion (), cacheKey );
115
+ assert reader .getReaderCacheHelper () != null ;
116
+ final Key key = new Key (cacheEntity , reader .getReaderCacheHelper ().getKey (), cacheKey );
115
117
Loader cacheLoader = new Loader (cacheEntity , loader );
116
118
BytesReference value = cache .computeIfAbsent (key , cacheLoader );
117
119
if (cacheLoader .isLoaded ()) {
118
120
key .entity .onMiss ();
119
121
// see if its the first time we see this reader, and make sure to register a cleanup key
120
- CleanupKey cleanupKey = new CleanupKey (cacheEntity , reader .getVersion ());
122
+ CleanupKey cleanupKey = new CleanupKey (cacheEntity , reader .getReaderCacheHelper (). getKey ());
121
123
if (!registeredClosedListeners .containsKey (cleanupKey )) {
122
124
Boolean previous = registeredClosedListeners .putIfAbsent (cleanupKey , Boolean .TRUE );
123
125
if (previous == null ) {
@@ -137,7 +139,8 @@ BytesReference getOrCompute(CacheEntity cacheEntity, Supplier<BytesReference> lo
137
139
* @param cacheKey the cache key to invalidate
138
140
*/
139
141
void invalidate (CacheEntity cacheEntity , DirectoryReader reader , BytesReference cacheKey ) {
140
- cache .invalidate (new Key (cacheEntity , reader .getVersion (), cacheKey ));
142
+ assert reader .getReaderCacheHelper () != null ;
143
+ cache .invalidate (new Key (cacheEntity , reader .getReaderCacheHelper ().getKey (), cacheKey ));
141
144
}
142
145
143
146
private static class Loader implements CacheLoader <Key , BytesReference > {
@@ -206,12 +209,12 @@ static class Key implements Accountable {
206
209
private static final long BASE_RAM_BYTES_USED = RamUsageEstimator .shallowSizeOfInstance (Key .class );
207
210
208
211
public final CacheEntity entity ; // use as identity equality
209
- public final long readerVersion ; // use the reader version to now keep a reference to a "short" lived reader until its reaped
212
+ public final IndexReader . CacheKey readerCacheKey ;
210
213
public final BytesReference value ;
211
214
212
- Key (CacheEntity entity , long readerVersion , BytesReference value ) {
215
+ Key (CacheEntity entity , IndexReader . CacheKey readerCacheKey , BytesReference value ) {
213
216
this .entity = entity ;
214
- this .readerVersion = readerVersion ;
217
+ this .readerCacheKey = Objects . requireNonNull ( readerCacheKey ) ;
215
218
this .value = value ;
216
219
}
217
220
@@ -231,7 +234,7 @@ public boolean equals(Object o) {
231
234
if (this == o ) return true ;
232
235
if (o == null || getClass () != o .getClass ()) return false ;
233
236
Key key = (Key ) o ;
234
- if (readerVersion != key .readerVersion ) return false ;
237
+ if (Objects . equals ( readerCacheKey , key .readerCacheKey ) == false ) return false ;
235
238
if (!entity .getCacheIdentity ().equals (key .entity .getCacheIdentity ())) return false ;
236
239
if (!value .equals (key .value )) return false ;
237
240
return true ;
@@ -240,19 +243,19 @@ public boolean equals(Object o) {
240
243
@ Override
241
244
public int hashCode () {
242
245
int result = entity .getCacheIdentity ().hashCode ();
243
- result = 31 * result + Long .hashCode (readerVersion );
246
+ result = 31 * result + readerCacheKey .hashCode ();
244
247
result = 31 * result + value .hashCode ();
245
248
return result ;
246
249
}
247
250
}
248
251
249
252
private class CleanupKey implements IndexReader .ClosedListener {
250
253
final CacheEntity entity ;
251
- final long readerVersion ; // use the reader version to now keep a reference to a "short" lived reader until its reaped
254
+ final IndexReader . CacheKey readerCacheKey ;
252
255
253
- private CleanupKey (CacheEntity entity , long readerVersion ) {
256
+ private CleanupKey (CacheEntity entity , IndexReader . CacheKey readerCacheKey ) {
254
257
this .entity = entity ;
255
- this .readerVersion = readerVersion ;
258
+ this .readerCacheKey = readerCacheKey ;
256
259
}
257
260
258
261
@ Override
@@ -270,15 +273,15 @@ public boolean equals(Object o) {
270
273
return false ;
271
274
}
272
275
CleanupKey that = (CleanupKey ) o ;
273
- if (readerVersion != that .readerVersion ) return false ;
276
+ if (Objects . equals ( readerCacheKey , that .readerCacheKey ) == false ) return false ;
274
277
if (!entity .getCacheIdentity ().equals (that .entity .getCacheIdentity ())) return false ;
275
278
return true ;
276
279
}
277
280
278
281
@ Override
279
282
public int hashCode () {
280
283
int result = entity .getCacheIdentity ().hashCode ();
281
- result = 31 * result + Long .hashCode (readerVersion );
284
+ result = 31 * result + Objects .hashCode (readerCacheKey );
282
285
return result ;
283
286
}
284
287
}
@@ -293,7 +296,7 @@ synchronized void cleanCache() {
293
296
for (Iterator <CleanupKey > iterator = keysToClean .iterator (); iterator .hasNext (); ) {
294
297
CleanupKey cleanupKey = iterator .next ();
295
298
iterator .remove ();
296
- if (cleanupKey .readerVersion == - 1 || cleanupKey .entity .isOpen () == false ) {
299
+ if (cleanupKey .readerCacheKey == null || cleanupKey .entity .isOpen () == false ) {
297
300
// -1 indicates full cleanup, as does a closed shard
298
301
currentFullClean .add (cleanupKey .entity .getCacheIdentity ());
299
302
} else {
@@ -306,7 +309,7 @@ synchronized void cleanCache() {
306
309
if (currentFullClean .contains (key .entity .getCacheIdentity ())) {
307
310
iterator .remove ();
308
311
} else {
309
- if (currentKeysToClean .contains (new CleanupKey (key .entity , key .readerVersion ))) {
312
+ if (currentKeysToClean .contains (new CleanupKey (key .entity , key .readerCacheKey ))) {
310
313
iterator .remove ();
311
314
}
312
315
}
0 commit comments