@@ -307,18 +307,23 @@ public V computeIfAbsent(ICacheKey<K> key, LoadAwareCacheLoader<ICacheKey<K>, V>
307
307
// Add the value to the onHeap cache. We are calling computeIfAbsent which does another get inside.
308
308
// This is needed as there can be many requests for the same key at the same time and we only want to load
309
309
// the value once.
310
- Tuple <V , Boolean > computedValueTuple = compute (key , loader , future );
311
- // Handle stats
312
- if (computedValueTuple .v2 ()) {
313
- // The value was just computed and added to the cache by this thread, or it was rejected by the policy.
314
- // Register a miss for the heap cache, and the disk cache if present
315
- statsHolder .incrementMisses (heapDimensionValues );
316
- if (caches .get (diskCache ).isEnabled ()) {
317
- statsHolder .incrementMisses (diskDimensionValues );
310
+ Tuple <V , Tuple <Boolean , Boolean >> computedValueTuple = compute (key , loader , future );
311
+ boolean wasCacheMiss = computedValueTuple .v2 ().v1 ();
312
+ boolean wasRejectedByPolicy = computedValueTuple .v2 ().v2 ();
313
+ // If the value was rejected by policy, it counts as neither a hit or miss.
314
+ if (!wasRejectedByPolicy ) {
315
+ // Handle stats
316
+ if (wasCacheMiss ) {
317
+ // The value was just computed and added to the cache by this thread.
318
+ // Register a miss for the heap cache, and the disk cache if present
319
+ statsHolder .incrementMisses (heapDimensionValues );
320
+ if (caches .get (diskCache ).isEnabled ()) {
321
+ statsHolder .incrementMisses (diskDimensionValues );
322
+ }
323
+ } else {
324
+ // Another thread requesting this key already loaded the value. Register a hit for the heap cache
325
+ statsHolder .incrementHits (heapDimensionValues );
318
326
}
319
- } else {
320
- // Another thread requesting this key already loaded the value. Register a hit for the heap cache
321
- statsHolder .incrementHits (heapDimensionValues );
322
327
}
323
328
return computedValueTuple .v1 ();
324
329
} else {
@@ -335,14 +340,15 @@ public V computeIfAbsent(ICacheKey<K> key, LoadAwareCacheLoader<ICacheKey<K>, V>
335
340
return cacheValueTuple .v1 ();
336
341
}
337
342
338
- private Tuple <V , Boolean > compute (
343
+ private Tuple <V , Tuple < Boolean , Boolean > > compute (
339
344
ICacheKey <K > key ,
340
345
LoadAwareCacheLoader <ICacheKey <K >, V > loader ,
341
346
CompletableFuture <Tuple <ICacheKey <K >, V >> future
342
347
) throws Exception {
343
348
// Handler to handle results post-processing. Takes a tuple<key, value> or exception as an input and returns
344
349
// the value. Also before returning value, puts the value in cache.
345
350
boolean wasCacheMiss = false ;
351
+ boolean wasRejectedByPolicy = false ;
346
352
BiFunction <Tuple <ICacheKey <K >, V >, Throwable , Void > handler = (pair , ex ) -> {
347
353
if (pair != null ) {
348
354
boolean didAddToCache = false ;
@@ -381,33 +387,34 @@ private Tuple<V, Boolean> compute(
381
387
future .completeExceptionally (npe );
382
388
throw new ExecutionException (npe );
383
389
} else {
384
- wasCacheMiss = true ;
385
390
if (evaluatePoliciesList (value , policies )) {
386
391
future .complete (new Tuple <>(key , value ));
392
+ wasCacheMiss = true ;
387
393
} else {
388
394
future .complete (null ); // Passing null would skip the logic to put this into onHeap cache.
389
395
// Signal to the caller that the key didn't enter the cache by sending a removal notification.
390
- // This case also counts as a cache miss.
396
+ // This case does not count as a cache miss.
391
397
removalListener .onRemoval (new RemovalNotification <>(key , value , RemovalReason .EXPLICIT ));
398
+ wasRejectedByPolicy = true ;
392
399
}
393
400
}
394
401
} else {
395
402
try {
396
403
Tuple <ICacheKey <K >, V > futureTuple = future .get ();
397
404
if (futureTuple == null ) {
398
405
// This case can happen if we earlier completed the future with null to skip putting the value into the cache.
399
- // It should behave the same as a cache miss.
400
- wasCacheMiss = true ;
406
+ // It does not count as a cache miss.
401
407
value = loader .load (key );
402
408
removalListener .onRemoval (new RemovalNotification <>(key , value , RemovalReason .EXPLICIT ));
409
+ wasRejectedByPolicy = true ;
403
410
} else {
404
411
value = futureTuple .v2 ();
405
412
}
406
413
} catch (InterruptedException ex ) {
407
414
throw new IllegalStateException (ex );
408
415
}
409
416
}
410
- return new Tuple <>(value , wasCacheMiss );
417
+ return new Tuple <>(value , new Tuple <>( wasCacheMiss , wasRejectedByPolicy ) );
411
418
}
412
419
413
420
@ Override
0 commit comments