From dfc7ca72147d11b2757c5feec84aa1dedcfef4b3 Mon Sep 17 00:00:00 2001 From: Jay Modi Date: Fri, 20 Apr 2018 07:21:08 -0600 Subject: [PATCH] Implement Iterator#remove for Cache values iter (#29633) This commit implements the ability to remove values from a Cache using the values iterator. This brings the values iterator in line with the keys iterator and adds support for removing items in the cache that are not easily found by the key used for the cache. --- .../org/elasticsearch/common/cache/Cache.java | 8 ++++- .../common/cache/CacheTests.java | 31 +++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/server/src/main/java/org/elasticsearch/common/cache/Cache.java b/server/src/main/java/org/elasticsearch/common/cache/Cache.java index 91d011ba03cad..620612619104b 100644 --- a/server/src/main/java/org/elasticsearch/common/cache/Cache.java +++ b/server/src/main/java/org/elasticsearch/common/cache/Cache.java @@ -580,7 +580,8 @@ public void remove() { /** * An LRU sequencing of the values in the cache. This sequence is not protected from mutations - * to the cache. The result of iteration under mutation is undefined. + * to the cache (except for {@link Iterator#remove()}. The result of iteration under any other mutation is + * undefined. * * @return an LRU-ordered {@link Iterable} over the values in the cache */ @@ -597,6 +598,11 @@ public boolean hasNext() { public V next() { return iterator.next().value; } + + @Override + public void remove() { + iterator.remove(); + } }; } diff --git a/server/src/test/java/org/elasticsearch/common/cache/CacheTests.java b/server/src/test/java/org/elasticsearch/common/cache/CacheTests.java index 5675a7b524bd3..773585cc3b494 100644 --- a/server/src/test/java/org/elasticsearch/common/cache/CacheTests.java +++ b/server/src/test/java/org/elasticsearch/common/cache/CacheTests.java @@ -27,6 +27,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Random; @@ -824,4 +825,34 @@ public void testTorture() throws BrokenBarrierException, InterruptedException { cache.refresh(); assertEquals(500, cache.count()); } + + public void testRemoveUsingValuesIterator() { + final List> removalNotifications = new ArrayList<>(); + Cache cache = + CacheBuilder.builder() + .setMaximumWeight(numberOfEntries) + .removalListener(removalNotifications::add) + .build(); + + for (int i = 0; i < numberOfEntries; i++) { + cache.put(i, Integer.toString(i)); + } + + assertThat(removalNotifications.size(), is(0)); + final List expectedRemovals = new ArrayList<>(); + Iterator valueIterator = cache.values().iterator(); + while (valueIterator.hasNext()) { + String value = valueIterator.next(); + if (randomBoolean()) { + valueIterator.remove(); + expectedRemovals.add(value); + } + } + + assertEquals(expectedRemovals.size(), removalNotifications.size()); + for (int i = 0; i < expectedRemovals.size(); i++) { + assertEquals(expectedRemovals.get(i), removalNotifications.get(i).getValue()); + assertEquals(RemovalNotification.RemovalReason.INVALIDATED, removalNotifications.get(i).getRemovalReason()); + } + } }