Ok, I have checked in all core changes around expiry, so that you can
now specify expiry:
(a) programmatically (per entry) or declaratively (cache-wide), and
(b) absolutely (lifespan), relatively (idle time), or both.
See examples, etc on:
So tests pass, and the core structure works well. The only thing is,
folks who have implemented CacheStores (Mircea and Adrian) may want to
revisit your implementations. Like I said tests pass, even the ones I
added to BaseCacheStoreTest to test all forms of expiration, but there
are probably optimisations you can do to prevent reading and
deserializing expired state, only to have isExpired() return true and
have to throw it away.
Cheers
Manik
Begin forwarded message:
From: horizon-commits(a)lists.jboss.org
Date: 25 March 2009 15:57:08 GMT
To: horizon-commits(a)lists.jboss.org
Subject: [horizon-commits] Horizon SVN: r40 - in trunk/src/test/java/
org/horizon: expiry and 1 other directories.
Reply-To: horizon-commits(a)lists.jboss.org
Author: manik.surtani(a)jboss.com
Date: 2009-03-25 11:57:08 -0400 (Wed, 25 Mar 2009)
New Revision: 40
Modified:
trunk/src/test/java/org/horizon/container/
SimpleDataContainerTest.java
trunk/src/test/java/org/horizon/expiry/ExpiryTest.java
trunk/src/test/java/org/horizon/expiry/ReplicatedExpiryTest.java
trunk/src/test/java/org/horizon/loader/BaseCacheStoreTest.java
Log:
Expiry can now be set either as an absolute lifespan or a maxIdle time
Modified: trunk/src/test/java/org/horizon/container/
SimpleDataContainerTest.java
===================================================================
--- trunk/src/test/java/org/horizon/container/
SimpleDataContainerTest.java 2009-03-25 12:43:13 UTC (rev 39)
+++ trunk/src/test/java/org/horizon/container/
SimpleDataContainerTest.java 2009-03-25 15:57:08 UTC (rev 40)
@@ -4,6 +4,7 @@
import org.horizon.container.entries.InternalCacheEntry;
import org.horizon.container.entries.TransientCacheEntry;
import org.horizon.container.entries.MortalCacheEntry;
+import org.horizon.container.entries.ImmortalCacheEntry;
import java.util.HashSet;
import java.util.Set;
@@ -45,6 +46,40 @@
assert dc.size() == 0;
}
+ public void testUpdatingLastUsed() throws Exception {
+ long idle = 600000;
+ SimpleDataContainer dc = new SimpleDataContainer();
+ dc.put("k", "v", -1, -1);
+ InternalCacheEntry ice = dc.get("k");
+ assert ice instanceof ImmortalCacheEntry;
+ assert ice.getExpiryTime() == -1;
+ assert ice.getLastUsed() == -1;
+ assert ice.getCreated() == -1;
+ assert ice.getMaxIdle() == -1;
+ assert ice.getLifespan() == -1;
+ dc.put("k", "v", -1, idle);
+ long oldTime = System.currentTimeMillis();
+ Thread.sleep(10); // for time calc granularity
+ ice = dc.get("k");
+ assert ice instanceof TransientCacheEntry;
+ assert ice.getExpiryTime() == -1;
+ assert ice.getLastUsed() > oldTime;
+ Thread.sleep(10); // for time calc granularity
+ assert ice.getLastUsed() < System.currentTimeMillis();
+ assert ice.getMaxIdle() == idle;
+ assert ice.getCreated() == -1;
+ assert ice.getLifespan() == -1;
+
+ oldTime = System.currentTimeMillis();
+ Thread.sleep(10); // for time calc granularity
+ assert dc.containsKey("k");
+
+ // check that the last used stamp has been updated on a get
+ assert ice.getLastUsed() > oldTime;
+ Thread.sleep(10); // for time calc granularity
+ assert ice.getLastUsed() < System.currentTimeMillis();
+ }
+
public void testExpirableToImmortal() {
SimpleDataContainer dc = new SimpleDataContainer();
dc.put("k", "v", 6000000, -1);
Modified: trunk/src/test/java/org/horizon/expiry/ExpiryTest.java
===================================================================
--- trunk/src/test/java/org/horizon/expiry/ExpiryTest.java
2009-03-25 12:43:13 UTC (rev 39)
+++ trunk/src/test/java/org/horizon/expiry/ExpiryTest.java
2009-03-25 15:57:08 UTC (rev 40)
@@ -12,7 +12,7 @@
import java.util.HashMap;
import java.util.Map;
-import java.util.concurrent.TimeUnit;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
@Test(groups = "functional", testName = "expiry.ExpiryTest")
public class ExpiryTest {
@@ -29,16 +29,17 @@
TestingUtil.killCacheManagers(cm);
}
- public void testExpiryInPut() throws InterruptedException {
+ public void testLifespanExpiryInPut() throws
InterruptedException {
Cache cache = cm.getCache();
long lifespan = 1000;
- cache.put("k", "v", lifespan, TimeUnit.MILLISECONDS);
+ cache.put("k", "v", lifespan, MILLISECONDS);
DataContainer dc = cache.getAdvancedCache().getDataContainer();
InternalCacheEntry se = dc.get("k");
assert se.getKey().equals("k");
assert se.getValue().equals("v");
assert se.getLifespan() == lifespan;
+ assert se.getMaxIdle() == -1;
assert !se.isExpired();
assert cache.get("k").equals("v");
Thread.sleep(1100);
@@ -46,14 +47,32 @@
assert cache.get("k") == null;
}
- public void testExpiryInPutAll() throws InterruptedException {
+ public void testIdleExpiryInPut() throws InterruptedException {
Cache cache = cm.getCache();
+ long idleTime = 1000;
+ cache.put("k", "v", -1, MILLISECONDS, idleTime,
MILLISECONDS);
+
+ DataContainer dc = cache.getAdvancedCache().getDataContainer();
+ InternalCacheEntry se = dc.get("k");
+ assert se.getKey().equals("k");
+ assert se.getValue().equals("v");
+ assert se.getLifespan() == -1;
+ assert se.getMaxIdle() == idleTime;
+ assert !se.isExpired();
+ assert cache.get("k").equals("v");
+ Thread.sleep(1100);
+ assert se.isExpired();
+ assert cache.get("k") == null;
+ }
+
+ public void testLifespanExpiryInPutAll() throws
InterruptedException {
+ Cache cache = cm.getCache();
long startTime = System.currentTimeMillis();
long lifespan = 1000;
Map m = new HashMap();
m.put("k1", "v");
m.put("k2", "v");
- cache.putAll(m, lifespan, TimeUnit.MILLISECONDS);
+ cache.putAll(m, lifespan, MILLISECONDS);
while (System.currentTimeMillis() < startTime + lifespan) {
assert cache.get("k1").equals("v");
assert cache.get("k2").equals("v");
@@ -68,11 +87,27 @@
assert cache.get("k2") == null;
}
- public void testExpiryInPutIfAbsent() throws
InterruptedException {
+ public void testIdleExpiryInPutAll() throws InterruptedException {
Cache cache = cm.getCache();
+ long idleTime = 10000;
+ Map m = new HashMap();
+ m.put("k1", "v");
+ m.put("k2", "v");
+ cache.putAll(m, -1, MILLISECONDS, idleTime, MILLISECONDS);
+ assert cache.get("k1").equals("v");
+ assert cache.get("k2").equals("v");
+
+ Thread.sleep(idleTime + 100);
+
+ assert cache.get("k1") == null;
+ assert cache.get("k2") == null;
+ }
+
+ public void testLifespanExpiryInPutIfAbsent() throws
InterruptedException {
+ Cache cache = cm.getCache();
long startTime = System.currentTimeMillis();
long lifespan = 1000;
- assert cache.putIfAbsent("k", "v", lifespan,
TimeUnit.MILLISECONDS) == null;
+ assert cache.putIfAbsent("k", "v", lifespan, MILLISECONDS) ==
null;
while (System.currentTimeMillis() < startTime + lifespan) {
assert cache.get("k").equals("v");
Thread.sleep(50);
@@ -86,19 +121,33 @@
assert cache.get("k") == null;
cache.put("k", "v");
- assert cache.putIfAbsent("k", "v", lifespan,
TimeUnit.MILLISECONDS) != null;
+ assert cache.putIfAbsent("k", "v", lifespan, MILLISECONDS) !=
null;
}
- public void testExpiryInReplace() throws InterruptedException {
+ public void testIdleExpiryInPutIfAbsent() throws
InterruptedException {
Cache cache = cm.getCache();
+ long idleTime = 10000;
+ assert cache.putIfAbsent("k", "v", -1, MILLISECONDS,
idleTime, MILLISECONDS) == null;
+ assert cache.get("k").equals("v");
+
+ Thread.sleep(idleTime + 100);
+
+ assert cache.get("k") == null;
+
+ cache.put("k", "v");
+ assert cache.putIfAbsent("k", "v", -1, MILLISECONDS,
idleTime, MILLISECONDS) != null;
+ }
+
+ public void testLifespanExpiryInReplace() throws
InterruptedException {
+ Cache cache = cm.getCache();
long lifespan = 1000;
assert cache.get("k") == null;
- assert cache.replace("k", "v", lifespan,
TimeUnit.MILLISECONDS) == null;
+ assert cache.replace("k", "v", lifespan, MILLISECONDS) ==
null;
assert cache.get("k") == null;
cache.put("k", "v-old");
assert cache.get("k").equals("v-old");
long startTime = System.currentTimeMillis();
- assert cache.replace("k", "v", lifespan,
TimeUnit.MILLISECONDS) != null;
+ assert cache.replace("k", "v", lifespan, MILLISECONDS) !=
null;
assert cache.get("k").equals("v");
while (System.currentTimeMillis() < startTime + lifespan) {
assert cache.get("k").equals("v");
@@ -115,7 +164,7 @@
startTime = System.currentTimeMillis();
cache.put("k", "v");
- assert cache.replace("k", "v", "v2", lifespan,
TimeUnit.MILLISECONDS);
+ assert cache.replace("k", "v", "v2", lifespan,
MILLISECONDS);
while (System.currentTimeMillis() < startTime + lifespan) {
assert cache.get("k").equals("v2");
Thread.sleep(50);
@@ -128,4 +177,25 @@
}
assert cache.get("k") == null;
}
+
+ public void testIdleExpiryInReplace() throws
InterruptedException {
+ Cache cache = cm.getCache();
+ long idleTime = 10000;
+ assert cache.get("k") == null;
+ assert cache.replace("k", "v", -1, MILLISECONDS, idleTime,
MILLISECONDS) == null;
+ assert cache.get("k") == null;
+ cache.put("k", "v-old");
+ assert cache.get("k").equals("v-old");
+ assert cache.replace("k", "v", -1, MILLISECONDS, idleTime,
MILLISECONDS) != null;
+ assert cache.get("k").equals("v");
+
+ Thread.sleep(idleTime + 100);
+ assert cache.get("k") == null;
+
+ cache.put("k", "v");
+ assert cache.replace("k", "v", "v2", -1,
MILLISECONDS,
idleTime, MILLISECONDS);
+
+ Thread.sleep(idleTime + 100);
+ assert cache.get("k") == null;
+ }
}
Modified: trunk/src/test/java/org/horizon/expiry/
ReplicatedExpiryTest.java
===================================================================
--- trunk/src/test/java/org/horizon/expiry/ReplicatedExpiryTest.java
2009-03-25 12:43:13 UTC (rev 39)
+++ trunk/src/test/java/org/horizon/expiry/ReplicatedExpiryTest.java
2009-03-25 15:57:08 UTC (rev 40)
@@ -1,12 +1,16 @@
package org.horizon.expiry;
import org.horizon.Cache;
+import org.horizon.container.entries.InternalCacheEntry;
+import org.horizon.container.entries.TransientMortalCacheEntry;
+import org.horizon.container.entries.MortalCacheEntry;
+import org.horizon.container.entries.TransientCacheEntry;
import org.horizon.config.Configuration;
import org.horizon.test.MultipleCacheManagersTest;
import org.testng.annotations.Test;
import java.util.List;
-import java.util.concurrent.TimeUnit;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
@Test(groups = "functional", testName =
"expiry.ReplicatedExpiryTest")
public class ReplicatedExpiryTest extends MultipleCacheManagersTest {
@@ -20,18 +24,33 @@
c2 = caches.get(1);
}
- public void testExpiryReplicates() throws InterruptedException {
- long start = System.currentTimeMillis();
+ public void testLifespanExpiryReplicates() throws
InterruptedException {
long lifespan = 3000;
- c1.put("k", "v", lifespan, TimeUnit.MILLISECONDS);
+ c1.put("k", "v", lifespan, MILLISECONDS);
+ InternalCacheEntry ice =
c2.getAdvancedCache().getDataContainer().get("k");
- while (System.currentTimeMillis() < start + lifespan) {
- assert c1.get("k").equals("v");
- assert c2.get("k").equals("v");
- Thread.sleep(250);
- }
- Thread.sleep(1000);
- assert c1.get("k") == null;
- assert c2.get("k") == null;
+ assert ice instanceof MortalCacheEntry;
+ assert ice.getLifespan() == lifespan;
+ assert ice.getMaxIdle() == -1;
}
+
+ public void testIdleExpiryReplicates() throws
InterruptedException {
+ long idle = 3000;
+ c1.put("k", "v", -1, MILLISECONDS, idle, MILLISECONDS);
+ InternalCacheEntry ice =
c2.getAdvancedCache().getDataContainer().get("k");
+
+ assert ice instanceof TransientCacheEntry;
+ assert ice.getMaxIdle() == idle;
+ assert ice.getLifespan() == -1;
+ }
+
+ public void testBothExpiryReplicates() throws
InterruptedException {
+ long lifespan = 10000;
+ long idle = 3000;
+ c1.put("k", "v", lifespan, MILLISECONDS, idle, MILLISECONDS);
+ InternalCacheEntry ice =
c2.getAdvancedCache().getDataContainer().get("k");
+ assert ice instanceof TransientMortalCacheEntry;
+ assert ice.getLifespan() == lifespan;
+ assert ice.getMaxIdle() == idle;
+ }
}
Modified: trunk/src/test/java/org/horizon/loader/
BaseCacheStoreTest.java
===================================================================
--- trunk/src/test/java/org/horizon/loader/BaseCacheStoreTest.java
2009-03-25 12:43:13 UTC (rev 39)
+++ trunk/src/test/java/org/horizon/loader/BaseCacheStoreTest.java
2009-03-25 15:57:08 UTC (rev 40)
@@ -84,49 +84,101 @@
return new ObjectStreamMarshaller();
}
-
- public void testLoadAndStore() throws InterruptedException,
CacheLoaderException {
+ public void testLoadAndStoreImmortal() throws
InterruptedException, CacheLoaderException {
assert !cs.containsKey("k");
- InternalCacheEntry se = InternalEntryFactory.create("k", "v",
-1, -1);
+ InternalCacheEntry se = InternalEntryFactory.create("k",
"v");
cs.store(se);
assert cs.load("k").getValue().equals("v");
assert cs.load("k").getLifespan() == -1;
+ assert cs.load("k").getMaxIdle() == -1;
assert !cs.load("k").isExpired();
assert cs.containsKey("k");
+ }
- long now = System.currentTimeMillis();
+ public void testLoadAndStoreWithLifespan() throws
InterruptedException, CacheLoaderException {
+ assert !cs.containsKey("k");
+
long lifespan = 120000;
- se = InternalEntryFactory.create("k", "v", lifespan);
+ InternalCacheEntry se = InternalEntryFactory.create("k", "v",
lifespan);
cs.store(se);
assert cs.load("k").getValue().equals("v");
assert cs.load("k").getLifespan() == lifespan;
+ assert cs.load("k").getMaxIdle() == -1;
assert !cs.load("k").isExpired();
assert cs.containsKey("k");
- now = System.currentTimeMillis();
lifespan = 1;
se = InternalEntryFactory.create("k", "v", lifespan);
cs.store(se);
- Thread.sleep(100);
+ Thread.sleep(10);
assert se.isExpired();
assert cs.load("k") == null;
assert !cs.containsKey("k");
}
+ public void testLoadAndStoreWithIdle() throws
InterruptedException, CacheLoaderException {
+ assert !cs.containsKey("k");
+
+ long idle = 120000;
+ InternalCacheEntry se = InternalEntryFactory.create("k", "v",
-1, idle);
+ cs.store(se);
+
+ assert cs.load("k").getValue().equals("v");
+ assert cs.load("k").getLifespan() == -1;
+ assert cs.load("k").getMaxIdle() == idle;
+ assert !cs.load("k").isExpired();
+ assert cs.containsKey("k");
+
+ idle = 1;
+ se = InternalEntryFactory.create("k", "v", -1, idle);
+ cs.store(se);
+ Thread.sleep(10);
+ assert se.isExpired();
+ assert cs.load("k") == null;
+ assert !cs.containsKey("k");
+ }
+
+ public void testLoadAndStoreWithLifespanAndIdle() throws
InterruptedException, CacheLoaderException {
+ assert !cs.containsKey("k");
+
+ long lifespan = 200000;
+ long idle = 120000;
+ InternalCacheEntry se = InternalEntryFactory.create("k", "v",
lifespan, idle);
+ cs.store(se);
+
+ assert cs.load("k").getValue().equals("v");
+ assert cs.load("k").getLifespan() == lifespan;
+ assert cs.load("k").getMaxIdle() == idle;
+ assert !cs.load("k").isExpired();
+ assert cs.containsKey("k");
+
+ idle = 1;
+ se = InternalEntryFactory.create("k", "v", lifespan, idle);
+ cs.store(se);
+ Thread.sleep(10);
+ assert se.isExpired();
+ assert cs.load("k") == null;
+ assert !cs.containsKey("k");
+ }
+
public void testStopStartDoesntNukeValues() throws
InterruptedException, CacheLoaderException {
assert !cs.containsKey("k1");
assert !cs.containsKey("k2");
- long now = System.currentTimeMillis();
long lifespan = 1;
+ long idle = 1;
InternalCacheEntry se1 = InternalEntryFactory.create("k1",
"v1", lifespan);
InternalCacheEntry se2 = InternalEntryFactory.create("k2",
"v2");
+ InternalCacheEntry se3 = InternalEntryFactory.create("k3",
"v3", -1, idle);
+ InternalCacheEntry se4 = InternalEntryFactory.create("k4",
"v4", lifespan, idle);
cs.store(se1);
cs.store(se2);
- Thread.sleep(100);
+ cs.store(se3);
+ cs.store(se4);
+ Thread.sleep(10);
cs.stop();
cs.start();
assert se1.isExpired();
@@ -135,7 +187,12 @@
assert cs.load("k2") != null;
assert cs.containsKey("k2");
assert cs.load("k2").getValue().equals("v2");
-
+ assert se3.isExpired();
+ assert cs.load("k3") == null;
+ assert !cs.containsKey("k3");
+ assert se3.isExpired();
+ assert cs.load("k3") == null;
+ assert !cs.containsKey("k3");
}
@@ -246,11 +303,11 @@
public void
testRollbackFromADifferentThreadReusingTransactionKey() throws
CacheLoaderException, InterruptedException {
- cs.store(InternalEntryFactory.create("old", "old", -1, -1));
+ cs.store(InternalEntryFactory.create("old", "old"));
List<Modification> mods = new ArrayList<Modification>();
- mods.add(new Store(InternalEntryFactory.create("k1", "v1",
-1, -1)));
- mods.add(new Store(InternalEntryFactory.create("k2", "v2",
-1, -1)));
+ mods.add(new Store(InternalEntryFactory.create("k1", "v1")));
+ mods.add(new Store(InternalEntryFactory.create("k2", "v2")));
mods.add(new Remove("k1"));
mods.add(new Remove("old"));
final Transaction tx =
EasyMock.createNiceMock(Transaction.class);
@@ -350,13 +407,14 @@
public void testPurgeExpired() throws Exception {
long lifespan = 1000;
+ long idle = 500;
cs.store(InternalEntryFactory.create("k1", "v1", lifespan));
- cs.store(InternalEntryFactory.create("k2", "v2", lifespan));
- cs.store(InternalEntryFactory.create("k3", "v3", lifespan));
+ cs.store(InternalEntryFactory.create("k2", "v2", -1, idle));
+ cs.store(InternalEntryFactory.create("k3", "v3", lifespan,
idle));
assert cs.containsKey("k1");
assert cs.containsKey("k2");
assert cs.containsKey("k3");
- Thread.sleep(lifespan + 100);
+ Thread.sleep(lifespan + 10);
cs.purgeExpired();
assert !cs.containsKey("k1");
assert !cs.containsKey("k2");
_______________________________________________
horizon-commits mailing list
horizon-commits(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/horizon-commits