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.
*<p>
* <p>
* 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
* accept reduced write performance in exchange for easy-to-understand code. Cache statistics for hits, misses and
* 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 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
@ -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
* here if write throughput is a concern.
* <ol>
* <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>
* <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>LRU list mutations could be inserted into a blocking queue that a single thread is reading from
* and applying to the LRU list.</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>
* </ol>
*
* <p>
* 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()}.
*
@ -124,7 +124,9 @@ public class Cache<K, V> {
}
// the state of an entry in the LRU list
enum State {NEW, EXISTING, DELETED}
enum State {
NEW, EXISTING, DELETED
}
static class Entry<K, V> {
final K key;
@ -144,7 +146,7 @@ public class Cache<K, V> {
/**
* A cache segment.
*
* <p>
* A CacheSegment is backed by a HashMap and is protected by a read/write lock.
*
* @param <K> the type of the keys
@ -184,9 +186,9 @@ public class Cache<K, V> {
/**
* 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 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
*/
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
* 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
* @return the current (existing or computed) value associated with the specified key, or null if the computed
* 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
* 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
*/
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.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.AtomicLong;
import java.util.concurrent.atomic.AtomicReferenceArray;
import static org.hamcrest.Matchers.not;
public class CacheTests extends ESTestCase {
private int numberOfEntries;
@ -71,7 +72,7 @@ public class CacheTests extends ESTestCase {
}
assertEquals(hits, cache.stats().getHits());
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());
}
@ -319,11 +320,11 @@ public class CacheTests extends ESTestCase {
Set<Integer> notifications = new HashSet<>();
Cache<Integer, String> cache =
CacheBuilder.<Integer, String>builder()
.removalListener(notification -> {
assertEquals(RemovalNotification.RemovalReason.INVALIDATED, notification.getRemovalReason());
notifications.add(notification.getKey());
})
.build();
.removalListener(notification -> {
assertEquals(RemovalNotification.RemovalReason.INVALIDATED, notification.getRemovalReason());
notifications.add(notification.getKey());
})
.build();
for (int i = 0; i < numberOfEntries; i++) {
cache.put(i, Integer.toString(i));
}
@ -353,11 +354,11 @@ public class CacheTests extends ESTestCase {
Set<Integer> notifications = new HashSet<>();
Cache<Integer, String> cache =
CacheBuilder.<Integer, String>builder()
.removalListener(notification -> {
assertEquals(RemovalNotification.RemovalReason.INVALIDATED, notification.getRemovalReason());
notifications.add(notification.getKey());
})
.build();
.removalListener(notification -> {
assertEquals(RemovalNotification.RemovalReason.INVALIDATED, notification.getRemovalReason());
notifications.add(notification.getKey());
})
.build();
Set<Integer> invalidated = new HashSet<>();
for (int i = 0; i < numberOfEntries; i++) {
cache.put(i, Integer.toString(i));
@ -446,12 +447,12 @@ public class CacheTests extends ESTestCase {
}
for (int i = 0; i < numberOfThreads; i++) {
Thread thread = new Thread(() -> {
for (int j = 0; j < numberOfEntries; j++) {
cache.computeIfAbsent(j, key -> {
assertTrue(flags.compareAndSet(key, false, true));
return Integer.toString(key);
});
}
for (int j = 0; j < numberOfEntries; j++) {
cache.computeIfAbsent(j, key -> {
assertTrue(flags.compareAndSet(key, false, true));
return Integer.toString(key);
});
}
});
threads.add(thread);
thread.start();