/** * Puts a connection to the store. * <p> * The connection's peer address is used as the key. * <p> * A connection can be successfully added to the store if any of the * following conditions is met: * <ul> * <li>The store's remaining capacity is greater than zero.</li> * <li>The store contains at least one <em>stale</em> connection, i.e. a * connection that has not been accessed for at least the store's <em> * connection expiration threshold</em> period. In such a case the least- * recently accessed stale connection gets evicted from the store to make * place for the new connection to be added.</li> * </ul> * * @return <code>true</code> if the connection could be added to the * store, <code>false</code> otherwise, e.g. because the store's * remaining capacity is zero and no stale connection can be evicted */ @Override public synchronized boolean put(final Connection connection) { if (connection != null) { return connections.put(connection.getPeerAddress(), connection); } else { return false; } }
/** * * @param capacity * @param expirationThreshold * @param noOfEntries */ private void givenACacheWithEntries(int capacity, long expirationThreshold, int noOfEntries) { cache = new LeastRecentlyUsedCache<>(capacity, expirationThreshold); for (int i = 0; i < noOfEntries; i++) { cache.put(i, String.valueOf(i)); } } }
private synchronized MessageIdTracker getTracker(final InetSocketAddress destination) { MessageIdTracker tracker = trackers.get(destination); if (tracker == null && 0 < trackers.remainingCapacity()) { // create new tracker for destination lazily int mid = null == random ? 0 : random.nextInt(MessageIdTracker.TOTAL_NO_OF_MIDS); switch (mode) { case NULL: tracker = new NullMessageIdTracker(mid); break; case MAPBASED: tracker = new MapBasedMessageIdTracker(mid, config); break; case GROUPED: default: tracker = new GroupedMessageIdTracker(mid, config); break; } trackers.put(destination, tracker); } return tracker; } }
@Test public void testStoreEvictsEldestStaleEntry() { int capacity = 10; givenACacheWithEntries(capacity, 0L, capacity); assertThat(cache.remainingCapacity(), is(0)); String eldest = cache.getEldest(); String newValue = "50"; assertTrue(cache.put(Integer.valueOf(newValue), newValue)); assertNull(cache.get(Integer.valueOf(eldest))); }
@Test public void testContinuousEviction() { int capacity = 10; givenACacheWithEntries(capacity, 0L, 0); assertThat(cache.remainingCapacity(), is(capacity)); final AtomicInteger evicted = new AtomicInteger(0); cache.addEvictionListener(new EvictionListener<String>() { @Override public void onEviction(String evictedSession) { evicted.incrementAndGet(); } }); int noOfSessions = 1000; for (int i = 0; i < noOfSessions; i++) { Integer key = i +1000; String value = String.valueOf(key); assertTrue(cache.put(key, value)); } assertThat(evicted.get(), is(noOfSessions - capacity)); assertThat(cache.remainingCapacity(), is(0)); }
@Test public void testStoreAddsNewValueIfCapacityNotReached() { int capacity = 10; givenACacheWithEntries(capacity, 0L, capacity - 1); assertThat(cache.remainingCapacity(), is(1)); String eldest = cache.getEldest(); String newValue = "50"; assertTrue(cache.put(50, newValue)); assertNotNull(cache.get(Integer.valueOf(eldest))); assertThat(cache.remainingCapacity(), is(0)); }
@Test public void testStoreFailsIfCapacityReached() { long threshold = 10; // seconds int capacity = 10; int numberOfSessions = 10; givenACacheWithEntries(capacity, threshold, numberOfSessions); assertThat(cache.remainingCapacity(), is(0)); String eldest = cache.getEldest(); String newValue = "50"; Integer key = Integer.valueOf(newValue); assertFalse(cache.put(key, newValue)); assertNull(cache.get(key)); assertNotNull(cache.get(Integer.valueOf(eldest))); }