LRUListWithAsyncSorting extends AbstractEvictionList { @Override public void incrementRecentlyUsed() { int recentlyUsedCount = recentlyUsedCounter.incrementAndGet(); if (hasThresholdBeenMet(recentlyUsedCount)) { scanIfNeeded(); } } LRUListWithAsyncSorting(EvictionController controller);   LRUListWithAsyncSorting(EvictionController controller, ExecutorService executor,
      int maxEvictionAttempts); @Override void clear(RegionVersionVector regionVersionVector, BucketRegion bucketRegion); @Override EvictableEntry getEvictableEntry(); @Override void incrementRecentlyUsed();  }
@Test public void scansOnlyWhenOverThreshold() throws Exception { LRUListWithAsyncSorting list = new LRUListWithAsyncSorting(controller, executor, 1); for (int i = 0; i < 5; i++) { list.appendEntry(mock(EvictionNode.class)); } list.incrementRecentlyUsed(); verifyNoMoreInteractions(executor); list.incrementRecentlyUsed(); verify(executor).submit(any(Runnable.class)); }
@Test public void doesNotRunScanOnEmptyList() throws Exception { LRUListWithAsyncSorting list = new LRUListWithAsyncSorting(controller, executor, 1); list.incrementRecentlyUsed(); verifyNoMoreInteractions(executor); }
@Test public void usesSystemPropertyThresholdIfSpecified() throws Exception { System.setProperty("geode." + SystemPropertyHelper.EVICTION_SCAN_THRESHOLD_PERCENT, "55"); try { LRUListWithAsyncSorting list = new LRUListWithAsyncSorting(controller, executor, 1); list.appendEntry(mock(EvictionNode.class)); list.appendEntry(mock(EvictionNode.class)); list.incrementRecentlyUsed(); verifyNoMoreInteractions(executor); list.incrementRecentlyUsed(); verify(executor).submit(any(Runnable.class)); } finally { System.clearProperty("geode." + SystemPropertyHelper.EVICTION_SCAN_THRESHOLD_PERCENT); } }
@Test public void scanUnsetsRecentlyUsedOnNode() throws Exception { ExecutorService realExecutor = Executors.newSingleThreadExecutor(); LRUListWithAsyncSorting list = new LRUListWithAsyncSorting(controller, realExecutor, 1); EvictionNode recentlyUsedNode = mock(EvictableEntry.class); when(recentlyUsedNode.previous()).thenReturn(list.head); when(recentlyUsedNode.isRecentlyUsed()).thenReturn(true); list.appendEntry(recentlyUsedNode); when(recentlyUsedNode.next()).thenReturn(list.tail); list.incrementRecentlyUsed(); await() .untilAsserted(() -> verify(recentlyUsedNode, times(1)).unsetRecentlyUsed()); realExecutor.shutdown(); }
@Test public void scanEndsOnlyUpToSize() throws Exception { ExecutorService realExecutor = Executors.newSingleThreadExecutor(); LRUListWithAsyncSorting list = new LRUListWithAsyncSorting(controller, realExecutor, 1); EvictionNode recentlyUsedNode = mock(EvictableEntry.class); when(recentlyUsedNode.previous()).thenReturn(list.head); when(recentlyUsedNode.isRecentlyUsed()).thenReturn(true); list.appendEntry(recentlyUsedNode); when(recentlyUsedNode.next()).thenReturn(recentlyUsedNode); list.incrementRecentlyUsed(); await() .untilAsserted(() -> verify(recentlyUsedNode, times(1)).unsetRecentlyUsed()); realExecutor.shutdown(); }
@Test public void scanMovesRecentlyUsedNodeToTail() throws Exception { ExecutorService realExecutor = Executors.newSingleThreadExecutor(); LRUListWithAsyncSorting list = new LRUListWithAsyncSorting(controller, realExecutor, 1); EvictionNode recentlyUsedNode = mock(EvictableEntry.class, "first"); EvictionNode secondNode = mock(EvictableEntry.class, "second"); EvictionNode thirdNode = mock(EvictableEntry.class, "third"); list.appendEntry(recentlyUsedNode); list.appendEntry(secondNode); list.appendEntry(thirdNode); when(recentlyUsedNode.next()).thenReturn(secondNode); when(recentlyUsedNode.previous()).thenReturn(list.head); when(secondNode.next()).thenReturn(thirdNode); when(secondNode.previous()).thenReturn(list.head); when(thirdNode.next()).thenReturn(list.tail); when(thirdNode.previous()).thenReturn(secondNode); when(recentlyUsedNode.isRecentlyUsed()).thenReturn(true); list.incrementRecentlyUsed(); await().untilAsserted(() -> assertThat(list.tail.previous()).isEqualTo(recentlyUsedNode)); verify(recentlyUsedNode, times(1)).unsetRecentlyUsed(); realExecutor.shutdown(); }
@Test public void scanNotStartedIfSizeBelowMaxEvictionAttempts() { LRUListWithAsyncSorting list = new LRUListWithAsyncSorting(controller, executor, 2); EvictionNode recentlyUsedNode = mock(EvictableEntry.class, "first"); EvictionNode secondNode = mock(EvictableEntry.class, "second"); list.appendEntry(recentlyUsedNode); list.incrementRecentlyUsed(); verifyNoMoreInteractions(executor); list.appendEntry(secondNode); list.incrementRecentlyUsed(); verify(executor).submit(any(Runnable.class)); }