Skip to content

Commit

Permalink
Merge branch 'release/v1.5.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
rocboronat committed Dec 31, 2015
2 parents 84513f9 + 9dad805 commit d27cad7
Show file tree
Hide file tree
Showing 16 changed files with 81 additions and 99 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ cache.remove("key"); // and remove it if you want.
cache.get("unExistingKey"); // If something doesn't exists, it returns null
cache.get("tooOldKey"); // The same if a key is too old

cache.set("AnInteger", new Integer(42)); // You can save all kind of Objects...
cache.set("ACollection", new ArrayList()); // ...whatever you want

cache.removeAll(); // You can also clean it,
cache.size(); // and ask it how many elements it has

QNCache<String> stringCache = new QNCacheBuilder().createQNCache(); //You can also make it typesafe
stringCache.set("key", 42); //so this line does not compile :)
```

Let's talk about the memory
Expand All @@ -41,7 +41,7 @@ By default, the cache stores a reference to all stored instances, doesn't matter
```java
QNCache cache = new QNCacheBuilder().setAutoReleaseInSeconds(1).createQNCache(); //frees the memory every second
QNCache cache = new QNCacheBuilder().setAutoReleaseInSeconds(60).createQNCache(); //frees the memory every minute
QNCache cache = new QNCacheBuilder().setAutoReleaseInSeconds(60 * 60).createQNCache(); //frees the memory every hour
QNCache cache = new QNCacheBuilder().setAutoReleaseInSeconds(60*60).createQNCache(); //frees the memory every hour
QNCache cache = new QNCacheBuilder().createQNCache(); //never frees the memory
```

Expand Down
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
group 'com.fewlaps.quitnowcache'
version '1.4'
version '1.5.0'

apply plugin: 'java'
apply plugin: 'com.novoda.bintray-release'
Expand Down Expand Up @@ -34,7 +34,7 @@ publish {
userOrg = 'fewlaps'
groupId = 'com.fewlaps.quitnowcache'
artifactId = 'quitnow-cache'
publishVersion = '1.4'
publishVersion = '1.5.0'
desc = 'A memcached-like Java cache, focused on portability'
website = 'https://github.com/Fewlaps/quitnow-cache'
}
Expand Down
37 changes: 18 additions & 19 deletions src/main/java/com/fewlaps/quitnowcache/QNCache.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class QNCache {
public class QNCache<T> {

public static final long KEEPALIVE_FOREVER = 0;

Expand All @@ -25,7 +25,7 @@ public QNCache(boolean caseSensitiveKeys, Integer autoReleaseInSeconds, Long def
this.defaultKeepaliveInMillis = defaultKeepaliveInMillis;
}

cache = new ConcurrentHashMap();
cache = new ConcurrentHashMap<String, QNCacheBean<T>>();

startAutoReleaseServiceIfNeeded();
}
Expand Down Expand Up @@ -63,46 +63,46 @@ protected void setDateProvider(DateProvider dateProvider) {
this.dateProvider = dateProvider;
}

private ConcurrentHashMap<String, QNCacheBean> cache;
private ConcurrentHashMap<String, QNCacheBean<T>> cache;

public void set(String key, Object value) {
public void set(String key, T value) {
if (defaultKeepaliveInMillis != null) {
set(key, value, defaultKeepaliveInMillis);
} else {
set(key, value, KEEPALIVE_FOREVER);
}
}

public void set(String key, Object value, long keepAliveInMillis) {
public void set(String key, T value, long keepAliveInMillis) {
key = getEffectiveKey(key);

if (keepAliveInMillis >= 0) {
cache.put(key, new QNCacheBean(value, now(), keepAliveInMillis));
cache.put(key, new QNCacheBean<T>(value, now(), keepAliveInMillis));
}
}

/**
* Gets an element from the cache.
*/
public <T> T get(String key) {
public T get(String key) {
key = getEffectiveKey(key);

QNCacheBean retrievedValue = cache.get(key);
QNCacheBean<T> retrievedValue = cache.get(key);
if (retrievedValue == null || !retrievedValue.isAlive(now())) {
return null;
} else {
return (T) retrievedValue.getValue();
return retrievedValue.getValue();
}
}

/**
* Gets an element from the cache. If the element exists but it's dead,
* it will be removed of the cache, to free memory
*/
Object getAndRemoveIfDead(String key) {
T getAndRemoveIfDead(String key) {
key = getEffectiveKey(key);

QNCacheBean retrievedValue = cache.get(key);
QNCacheBean<T> retrievedValue = cache.get(key);
if (retrievedValue == null) {
return null;
} else if (retrievedValue.isAlive(now())) {
Expand Down Expand Up @@ -130,10 +130,11 @@ public void removeAll() {
* Removes the dead elements of the cache, to free memory
*/
void removeTooOldValues() {
Iterator it = cache.entrySet().iterator();
Iterator<Map.Entry<String, QNCacheBean<T>>> it = cache.entrySet().iterator();

while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next();
QNCacheBean bean = (QNCacheBean) pair.getValue();
Map.Entry<String, QNCacheBean<T>> entry = it.next();
QNCacheBean<T> bean = entry.getValue();
if (!bean.isAlive(now())) {
it.remove();
}
Expand All @@ -152,11 +153,9 @@ public int size() {
*/
int sizeCountingOnlyAliveElements() {
int size = 0;
Iterator it = cache.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next();
QNCacheBean bean = (QNCacheBean) pair.getValue();
if (bean.isAlive(now())) {

for(QNCacheBean<T> cacheValue: cache.values()) {
if (cacheValue.isAlive(now())) {
size++;
}
}
Expand Down
8 changes: 4 additions & 4 deletions src/main/java/com/fewlaps/quitnowcache/QNCacheBean.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
/**
* This class is not public 'cause we'll hide the implementation of the QNCache itself
*/
class QNCacheBean {
class QNCacheBean<T> {

private long creationDate;
private long keepAliveInMillis;
private Object value;
private T value;

public QNCacheBean(Object value, long creationDate, long keepAliveInMillis) {
public QNCacheBean(T value, long creationDate, long keepAliveInMillis) {
this.creationDate = creationDate;
this.keepAliveInMillis = keepAliveInMillis;
this.value = value;
Expand All @@ -23,7 +23,7 @@ public boolean isAlive(long now) {
}
}

public Object getValue() {
public T getValue() {
return value;
}
}
4 changes: 2 additions & 2 deletions src/main/java/com/fewlaps/quitnowcache/QNCacheBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public QNCacheBuilder setDefaultKeepaliveInMillis(long defaultKeepaliveInMillis)
return this;
}

public QNCache createQNCache() {
return new QNCache(caseSensitiveKeys, autoReleaseInSeconds, defaultKeepaliveInMillis);
public <T> QNCache<T> createQNCache() {
return new QNCache<T>(caseSensitiveKeys, autoReleaseInSeconds, defaultKeepaliveInMillis);
}
}
18 changes: 9 additions & 9 deletions src/test/java/com/fewlaps/quitnowcache/BuilderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ public class BuilderTest {

@Test
public void testDefaultBuilder() {
QNCache cache = new QNCacheBuilder().createQNCache();
QNCache<Object> cache = new QNCacheBuilder().createQNCache();

assertTrue(cache.isCaseSensitiveKeys());
assertNull(cache.getAutoReleaseInSeconds());
Expand All @@ -17,56 +17,56 @@ public void testDefaultBuilder() {

@Test
public void testSettingTrueCaseSensitiveKeysBuilder() {
QNCache cache = new QNCacheBuilder().setCaseSensitiveKeys(true).createQNCache();
QNCache<Object> cache = new QNCacheBuilder().setCaseSensitiveKeys(true).createQNCache();

assertTrue(cache.isCaseSensitiveKeys());
}

@Test
public void testSettingFalseCaseSensitiveKeysBuilder() {
QNCache cache = new QNCacheBuilder().setCaseSensitiveKeys(false).createQNCache();
QNCache<Object> cache = new QNCacheBuilder().setCaseSensitiveKeys(false).createQNCache();

assertFalse(cache.isCaseSensitiveKeys());
}

@Test
public void testSettingMinusOneAutoReleaseSecondsBuilder() {
QNCache cache = new QNCacheBuilder().setAutoReleaseInSeconds(-1).createQNCache();
QNCache<Object> cache = new QNCacheBuilder().setAutoReleaseInSeconds(-1).createQNCache();

assertNull(cache.getAutoReleaseInSeconds());
}

@Test
public void testSetting10AutoReleaseSecondsBuilder() {
QNCache cache = new QNCacheBuilder().setAutoReleaseInSeconds(10).createQNCache();
QNCache<Object> cache = new QNCacheBuilder().setAutoReleaseInSeconds(10).createQNCache();

assertEquals(Integer.valueOf(10), cache.getAutoReleaseInSeconds());
}

@Test
public void testSettingDefaultKeepaliveBuilder_with10() {
QNCache cache = new QNCacheBuilder().setDefaultKeepaliveInMillis(10).createQNCache();
QNCache<Object> cache = new QNCacheBuilder().setDefaultKeepaliveInMillis(10).createQNCache();

assertEquals(Long.valueOf(10), cache.getDefaultKeepaliveInMillis());
}

@Test
public void testSettingDefaultKeepaliveBuilder_withZero() {
QNCache cache = new QNCacheBuilder().setDefaultKeepaliveInMillis(0).createQNCache();
QNCache<Object> cache = new QNCacheBuilder().setDefaultKeepaliveInMillis(0).createQNCache();

assertNull(cache.getDefaultKeepaliveInMillis());
}

@Test
public void testSettingDefaultKeepaliveBuilder_withMinusTen() {
QNCache cache = new QNCacheBuilder().setDefaultKeepaliveInMillis(-10).createQNCache();
QNCache<Object> cache = new QNCacheBuilder().setDefaultKeepaliveInMillis(-10).createQNCache();

assertNull(cache.getDefaultKeepaliveInMillis());
}

@Test
public void testQNCacheDefaultKeepaliveIsForever() {
QNCache cache = new QNCacheBuilder().setDefaultKeepaliveInMillis(QNCache.KEEPALIVE_FOREVER).createQNCache();
QNCache<Object> cache = new QNCacheBuilder().setDefaultKeepaliveInMillis(QNCache.KEEPALIVE_FOREVER).createQNCache();

assertNull(cache.getDefaultKeepaliveInMillis());
}
Expand Down
10 changes: 5 additions & 5 deletions src/test/java/com/fewlaps/quitnowcache/CacheBeanTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,31 @@ public class CacheBeanTest extends BaseTest {

@Test
public void aJustCreatedBeanWithMaxKeepaliveIsAliveRightNow() {
QNCacheBean bean = new QNCacheBean(A_VALUE, now(), FOREVER);
QNCacheBean<Object> bean = new QNCacheBean<Object>(A_VALUE, now(), FOREVER);
assertTrue(bean.isAlive(now()));
}

@Test
public void aJustCreatedBeanWithMaxKeepaliveIsAliveAfterThreeDays() {
QNCacheBean bean = new QNCacheBean(A_VALUE, now(), FOREVER);
QNCacheBean<Object> bean = new QNCacheBean<Object>(A_VALUE, now(), FOREVER);
assertTrue(bean.isAlive(threeDaysFromNow()));
}

@Test
public void aJustCreatedBeanWithOneSecondOfKeepaliveIsAliveRightNow() {
QNCacheBean bean = new QNCacheBean(A_VALUE, now(), ONE_SECOND);
QNCacheBean<Object> bean = new QNCacheBean<Object>(A_VALUE, now(), ONE_SECOND);
assertTrue(bean.isAlive(now()));
}

@Test
public void aJustCreatedBeanWithTwoHoursOfKeepaliveIsAliveAfterASecond() {
QNCacheBean bean = new QNCacheBean(A_VALUE, now(), TWO_HOURS);
QNCacheBean<Object> bean = new QNCacheBean<Object>(A_VALUE, now(), TWO_HOURS);
assertTrue(bean.isAlive(oneSecondFromNow()));
}

@Test
public void aJustCreatedBeanWithOneSecondOfKeepaliveIsNotAliveAfterTwoSeconds() {
QNCacheBean bean = new QNCacheBean(A_VALUE, now(), ONE_SECOND);
QNCacheBean<Object> bean = new QNCacheBean<Object>(A_VALUE, now(), ONE_SECOND);
assertFalse(bean.isAlive(twoHoursFromNow()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,23 @@ public class CaseSensitiveKeyTest extends BaseTest {

@Test
public void shouldReturnTheSameIfIgnoringCaseSensitive() {
QNCache cache = new QNCacheBuilder().setCaseSensitiveKeys(false).createQNCache();
QNCache<String> cache = new QNCacheBuilder().setCaseSensitiveKeys(false).createQNCache();
cache.set(A_KEY.toLowerCase(), A_VALUE, FOREVER);

assertEquals(A_VALUE, cache.get(A_KEY.toUpperCase()));
}

@Test
public void shouldReturnNullIfUsingCaseSensitive() {
QNCache cache = new QNCacheBuilder().setCaseSensitiveKeys(true).createQNCache();
QNCache<String> cache = new QNCacheBuilder().setCaseSensitiveKeys(true).createQNCache();
cache.set(A_KEY.toLowerCase(), A_VALUE, FOREVER);

assertNull(cache.get(A_KEY.toUpperCase()));
}

@Test
public void shouldReturnNullIfUsingDefaultBuilder() {
QNCache cache = new QNCacheBuilder().createQNCache();
QNCache<String> cache = new QNCacheBuilder().createQNCache();
cache.set(A_KEY.toLowerCase(), A_VALUE, FOREVER);

assertNull(cache.get(A_KEY.toUpperCase()));
Expand Down
34 changes: 2 additions & 32 deletions src/test/java/com/fewlaps/quitnowcache/CastTest.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
package com.fewlaps.quitnowcache;

import com.fewlaps.quitnowcache.bean.ObjectTestOne;
import com.fewlaps.quitnowcache.bean.ObjectTestTwo;

import org.junit.Before;
import org.junit.Test;

import static org.hamcrest.core.IsInstanceOf.instanceOf;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;

public class CastTest extends BaseTest {
QNCache cache;
QNCache<ObjectTestOne> cache;

@Before
public void init() {
Expand All @@ -24,21 +23,6 @@ public void saveObjectAndReturnSameInstance() {
assertThat(cache.get(A_KEY), instanceOf(ObjectTestOne.class));
}

@Test
public void shouldThrowExceptionOnCastReturnObject() {
cache.set(A_KEY, new ObjectTestOne());

Exception e = null;

try {
ObjectTestTwo o = (ObjectTestTwo) cache.get(A_KEY);
} catch (ClassCastException cle) {
e = cle;
}

assertNotNull(e);
}

@Test
public void shouldCastObject() {
cache.set(A_KEY, new ObjectTestOne());
Expand All @@ -48,18 +32,4 @@ public void shouldCastObject() {
assertThat(objectTestOne, instanceOf(ObjectTestOne.class));
}

@Test
public void shouldThrowExceptionOnCastWithGenericReturnObject() {
cache.set(A_KEY, new ObjectTestOne());

Exception e = null;

try {
ObjectTestTwo o = cache.get(A_KEY);
} catch (ClassCastException cle) {
e = cle;
}

assertNotNull(e);
}
}
Loading

0 comments on commit d27cad7

Please sign in to comment.