Cleanup formatting

This commit is contained in:
Jason Tedor 2015-10-01 00:37:18 +02:00
parent 11d75226a9
commit 30bfea741e
2 changed files with 36 additions and 33 deletions

View File

@ -32,12 +32,12 @@ import java.util.function.ToLongBiFunction;
/** /**
* A simple concurrent cache. * A simple concurrent cache.
*<p> * <p>
* Cache is a simple concurrent cache that supports time-based and weight-based evictions, with notifications for all * Cache is a simple concurrent cache that supports time-based and weight-based evictions, with notifications for all
* evictions. The design goals for this cache were simplicity and read performance. This means that we are willing to * evictions. The design goals for this cache were simplicity and read performance. This means that we are willing to
* accept reduced write performance in exchange for easy-to-understand code. Cache statistics for hits, misses and * accept reduced write performance in exchange for easy-to-understand code. Cache statistics for hits, misses and
* evictions are exposed. * evictions are exposed.
*<p> * <p>
* The design of the cache is relatively simple. The cache is segmented into 256 segments which are backed by HashMaps. * The design of the cache is relatively simple. The cache is segmented into 256 segments which are backed by HashMaps.
* The segments are protected by a re-entrant read/write lock. The read/write locks permit multiple concurrent readers * The segments are protected by a re-entrant read/write lock. The read/write locks permit multiple concurrent readers
* without contention, and the segments gives us write throughput without impacting readers (so readers are blocked only * without contention, and the segments gives us write throughput without impacting readers (so readers are blocked only
@ -47,12 +47,12 @@ import java.util.function.ToLongBiFunction;
* LRU list is protected by a lock that serializes all writes to it. There are opportunities for improvements * LRU list is protected by a lock that serializes all writes to it. There are opportunities for improvements
* here if write throughput is a concern. * here if write throughput is a concern.
* <ol> * <ol>
* <li>LRU list mutations could be inserted into a blocking queue that a single thread is reading from * <li>LRU list mutations could be inserted into a blocking queue that a single thread is reading from
* and applying to the LRU list.</li> * and applying to the LRU list.</li>
* <li>Promotions could be deferred for entries that were "recently" promoted.</li> * <li>Promotions could be deferred for entries that were "recently" promoted.</li>
* <li>Locks on the list could be taken per node being modified instead of globally.</li> * <li>Locks on the list could be taken per node being modified instead of globally.</li>
* </ol> * </ol>
* * <p>
* Evictions only occur after a mutation to the cache (meaning an entry promotion, a cache insertion, or a manual * Evictions only occur after a mutation to the cache (meaning an entry promotion, a cache insertion, or a manual
* invalidation) or an explicit call to {@link #refresh()}. * invalidation) or an explicit call to {@link #refresh()}.
* *
@ -124,7 +124,9 @@ public class Cache<K, V> {
} }
// the state of an entry in the LRU list // the state of an entry in the LRU list
enum State {NEW, EXISTING, DELETED} enum State {
NEW, EXISTING, DELETED
}
static class Entry<K, V> { static class Entry<K, V> {
final K key; final K key;
@ -144,7 +146,7 @@ public class Cache<K, V> {
/** /**
* A cache segment. * A cache segment.
* * <p>
* A CacheSegment is backed by a HashMap and is protected by a read/write lock. * A CacheSegment is backed by a HashMap and is protected by a read/write lock.
* *
* @param <K> the type of the keys * @param <K> the type of the keys
@ -184,9 +186,9 @@ public class Cache<K, V> {
/** /**
* put an entry into the segment * put an entry into the segment
* *
* @param key the key of the entry to add to the cache * @param key the key of the entry to add to the cache
* @param value the value of the entry to add to the cache * @param value the value of the entry to add to the cache
* @param now the access time of this entry * @param now the access time of this entry
* @return a tuple of the new entry and the existing entry, if there was one otherwise null * @return a tuple of the new entry and the existing entry, if there was one otherwise null
*/ */
Tuple<Entry<K, V>, Entry<K, V>> put(K key, V value, long now) { Tuple<Entry<K, V>, Entry<K, V>> put(K key, V value, long now) {
@ -270,7 +272,7 @@ public class Cache<K, V> {
* If the specified key is not already associated with a value (or is mapped to null), attempts to compute its * If the specified key is not already associated with a value (or is mapped to null), attempts to compute its
* value using the given mapping function and enters it into this map unless null. * value using the given mapping function and enters it into this map unless null.
* *
* @param key the key whose associated value is to be returned or computed for if non-existant * @param key the key whose associated value is to be returned or computed for if non-existant
* @param mappingFunction the function to compute a value given a key * @param mappingFunction the function to compute a value given a key
* @return the current (existing or computed) value associated with the specified key, or null if the computed * @return the current (existing or computed) value associated with the specified key, or null if the computed
* value is null * value is null
@ -297,7 +299,7 @@ public class Cache<K, V> {
* Associates the specified value with the specified key in this map. If the map previously contained a mapping for * Associates the specified value with the specified key in this map. If the map previously contained a mapping for
* the key, the old value is replaced. * the key, the old value is replaced.
* *
* @param key key with which the specified value is to be associated * @param key key with which the specified value is to be associated
* @param value value to be associated with the specified key * @param value value to be associated with the specified key
*/ */
public void put(K key, V value) { public void put(K key, V value) {

View File

@ -22,13 +22,14 @@ package org.elasticsearch.common.cache;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.junit.Before; import org.junit.Before;
import java.util.*; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReferenceArray; import java.util.concurrent.atomic.AtomicReferenceArray;
import static org.hamcrest.Matchers.not;
public class CacheTests extends ESTestCase { public class CacheTests extends ESTestCase {
private int numberOfEntries; private int numberOfEntries;
@ -71,7 +72,7 @@ public class CacheTests extends ESTestCase {
} }
assertEquals(hits, cache.stats().getHits()); assertEquals(hits, cache.stats().getHits());
assertEquals(misses, cache.stats().getMisses()); assertEquals(misses, cache.stats().getMisses());
assertEquals((int)Math.ceil(numberOfEntries / 2.0), evictions.get()); assertEquals((int) Math.ceil(numberOfEntries / 2.0), evictions.get());
assertEquals(evictions.get(), cache.stats().getEvictions()); assertEquals(evictions.get(), cache.stats().getEvictions());
} }
@ -319,11 +320,11 @@ public class CacheTests extends ESTestCase {
Set<Integer> notifications = new HashSet<>(); Set<Integer> notifications = new HashSet<>();
Cache<Integer, String> cache = Cache<Integer, String> cache =
CacheBuilder.<Integer, String>builder() CacheBuilder.<Integer, String>builder()
.removalListener(notification -> { .removalListener(notification -> {
assertEquals(RemovalNotification.RemovalReason.INVALIDATED, notification.getRemovalReason()); assertEquals(RemovalNotification.RemovalReason.INVALIDATED, notification.getRemovalReason());
notifications.add(notification.getKey()); notifications.add(notification.getKey());
}) })
.build(); .build();
for (int i = 0; i < numberOfEntries; i++) { for (int i = 0; i < numberOfEntries; i++) {
cache.put(i, Integer.toString(i)); cache.put(i, Integer.toString(i));
} }
@ -353,11 +354,11 @@ public class CacheTests extends ESTestCase {
Set<Integer> notifications = new HashSet<>(); Set<Integer> notifications = new HashSet<>();
Cache<Integer, String> cache = Cache<Integer, String> cache =
CacheBuilder.<Integer, String>builder() CacheBuilder.<Integer, String>builder()
.removalListener(notification -> { .removalListener(notification -> {
assertEquals(RemovalNotification.RemovalReason.INVALIDATED, notification.getRemovalReason()); assertEquals(RemovalNotification.RemovalReason.INVALIDATED, notification.getRemovalReason());
notifications.add(notification.getKey()); notifications.add(notification.getKey());
}) })
.build(); .build();
Set<Integer> invalidated = new HashSet<>(); Set<Integer> invalidated = new HashSet<>();
for (int i = 0; i < numberOfEntries; i++) { for (int i = 0; i < numberOfEntries; i++) {
cache.put(i, Integer.toString(i)); cache.put(i, Integer.toString(i));
@ -446,12 +447,12 @@ public class CacheTests extends ESTestCase {
} }
for (int i = 0; i < numberOfThreads; i++) { for (int i = 0; i < numberOfThreads; i++) {
Thread thread = new Thread(() -> { Thread thread = new Thread(() -> {
for (int j = 0; j < numberOfEntries; j++) { for (int j = 0; j < numberOfEntries; j++) {
cache.computeIfAbsent(j, key -> { cache.computeIfAbsent(j, key -> {
assertTrue(flags.compareAndSet(key, false, true)); assertTrue(flags.compareAndSet(key, false, true));
return Integer.toString(key); return Integer.toString(key);
}); });
} }
}); });
threads.add(thread); threads.add(thread);
thread.start(); thread.start();