JBoss Cache SVN: r7636 - in core/trunk/src: main/java/org/jboss/cache/interceptors and 4 other directories.
by jbosscache-commits@lists.jboss.org
Author: manik.surtani(a)jboss.com
Date: 2009-02-04 06:19:35 -0500 (Wed, 04 Feb 2009)
New Revision: 7636
Added:
core/trunk/src/test/java/org/jboss/cache/jmx/JmxManualTest.java
Modified:
core/trunk/src/main/java/org/jboss/cache/DataContainerImpl.java
core/trunk/src/main/java/org/jboss/cache/RPCManagerImpl.java
core/trunk/src/main/java/org/jboss/cache/RegionManagerImpl.java
core/trunk/src/main/java/org/jboss/cache/interceptors/CacheMgmtInterceptor.java
core/trunk/src/main/java/org/jboss/cache/interceptors/InterceptorChain.java
core/trunk/src/main/java/org/jboss/cache/jmx/CacheJmxWrapper.java
core/trunk/src/main/java/org/jboss/cache/util/CachePrinter.java
core/trunk/src/test/java/org/jboss/cache/jmx/deprecated/CacheJmxWrapperTest.java
Log:
More JMX details
Modified: core/trunk/src/main/java/org/jboss/cache/DataContainerImpl.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/DataContainerImpl.java 2009-02-03 22:29:46 UTC (rev 7635)
+++ core/trunk/src/main/java/org/jboss/cache/DataContainerImpl.java 2009-02-04 11:19:35 UTC (rev 7636)
@@ -30,9 +30,11 @@
import org.jboss.cache.factories.annotations.NonVolatile;
import org.jboss.cache.factories.annotations.Start;
import org.jboss.cache.factories.annotations.Stop;
+import org.jboss.cache.jmx.annotations.MBean;
import org.jboss.cache.jmx.annotations.ManagedOperation;
import org.jboss.cache.lock.LockManager;
import org.jboss.cache.marshall.NodeData;
+import org.jboss.cache.util.CachePrinter;
import java.util.ArrayList;
import java.util.Collections;
@@ -48,6 +50,7 @@
* @since 2.2
*/
@NonVolatile
+@MBean(objectName = "DataContainer", description = "Core container for all cached items")
public class DataContainerImpl implements DataContainer
{
private static final Log log = LogFactory.getLog(DataContainerImpl.class);
@@ -193,7 +196,10 @@
public NodeSPI peek(Fqn fqn, boolean includeDeletedNodes, boolean includeInvalidNodes)
{
- if (trace) log.trace("peek " + fqn + ", includeDeletedNodes:" +includeDeletedNodes + ", includeInvalidNodes:" + includeInvalidNodes);
+ if (trace)
+ {
+ log.trace("peek " + fqn + ", includeDeletedNodes:" + includeDeletedNodes + ", includeInvalidNodes:" + includeInvalidNodes);
+ }
if (fqn == null || fqn.size() == 0) return getRoot();
NodeSPI n = getRoot();
int fqnSize = fqn.size();
@@ -483,7 +489,13 @@
return sb.toString();
}
+ @ManagedOperation(description = "Prints details of the data container, formatted as an HTML String")
+ public String printDetailsAsHtml()
+ {
+ return CachePrinter.formatHtml(printDetails());
+ }
+
/**
* Returns lock information.
*
Modified: core/trunk/src/main/java/org/jboss/cache/RPCManagerImpl.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/RPCManagerImpl.java 2009-02-03 22:29:46 UTC (rev 7635)
+++ core/trunk/src/main/java/org/jboss/cache/RPCManagerImpl.java 2009-02-04 11:19:35 UTC (rev 7636)
@@ -81,7 +81,7 @@
*
* @author <a href="mailto:manik AT jboss DOT org">Manik Surtani (manik AT jboss DOT org)</a>
*/
-@MBean(objectName = "RPCManager")
+@MBean(objectName = "RPCManager", description = "Manages RPC connections to remote caches")
public class RPCManagerImpl implements RPCManager
{
private Channel channel;
@@ -177,7 +177,9 @@
if (getMembers().size() > 1) messageListener.waitForState();
if (log.isDebugEnabled())
+ {
log.debug("connected, state was retrieved successfully (in " + (System.currentTimeMillis() - start) + " milliseconds)");
+ }
}
catch (StateTransferException ste)
{
@@ -271,7 +273,9 @@
ReflectionUtil.setValue(configuration, "accessible", true);
configuration.setUsingMultiplexer(true);
if (log.isDebugEnabled())
+ {
log.debug("Created Multiplexer Channel for cache cluster " + configuration.getClusterName() + " using stack " + configuration.getMultiplexerStack());
+ }
}
else
{
@@ -447,9 +451,13 @@
int modeToUse = mode;
int preferredMode;
if ((preferredMode = spi.getInvocationContext().getOptionOverrides().getGroupRequestMode()) > -1)
+ {
modeToUse = preferredMode;
+ }
if (trace)
+ {
log.trace("callRemoteMethods(): valid members are " + recipients + " methods: " + command + " Using OOB? " + useOutOfBandMessage + " modeToUse: " + modeToUse);
+ }
if (channel.flushSupported() && !flushBlockGate.await(configuration.getStateRetrievalTimeout(), TimeUnit.MILLISECONDS))
{
throw new TimeoutException("State retrieval timed out waiting for flush unblock. (timeout = " + configuration.getStateRetrievalTimeout() + " millis) ");
@@ -458,7 +466,9 @@
RspList rsps = rpcDispatcher.invokeRemoteCommands(recipients, command, modeToUse, timeout, isUsingBuddyReplication, useOutOfBandMessage, responseFilter);
if (mode == GroupRequest.GET_NONE) return Collections.emptyList();// async case
if (trace)
+ {
log.trace("(" + getLocalAddress() + "): responses for method " + command.getClass().getSimpleName() + ":\n" + rsps);
+ }
// short-circuit no-return-value calls.
if (rsps == null) return Collections.emptyList();
List<Object> retval = new ArrayList<Object>(rsps.size());
@@ -529,7 +539,9 @@
// Yes -- cache is configured LOCAL but app doesn't know it -- Brian
//throw new IllegalArgumentException("Cannot fetch partial state, targets are " + sources + " and stateId is " + stateId);
if (log.isWarnEnabled())
+ {
log.warn("Cannot fetch partial state, targets are " + sources + " and stateId is " + stateId);
+ }
return;
}
@@ -547,14 +559,18 @@
}
if (log.isDebugEnabled())
+ {
log.debug("Node " + getLocalAddress() + " fetching partial state " + stateId + " from members " + targets);
+ }
boolean successfulTransfer = false;
for (Address target : targets)
{
try
{
if (log.isDebugEnabled())
+ {
log.debug("Node " + getLocalAddress() + " fetching partial state " + stateId + " from member " + target);
+ }
messageListener.setStateSet(false);
successfulTransfer = channel.getState(target, stateId, configuration.getStateRetrievalTimeout());
if (successfulTransfer)
@@ -570,14 +586,18 @@
}
}
if (log.isDebugEnabled())
+ {
log.debug("Node " + getLocalAddress() + " fetching partial state " + stateId + " from member " + target + (successfulTransfer ? " successful" : " failed"));
+ }
if (successfulTransfer) break;
}
catch (IllegalStateException ise)
{
// thrown by the JGroups channel if state retrieval fails.
if (log.isInfoEnabled())
+ {
log.info("Channel problems fetching state. Continuing on to next provider. ", ise);
+ }
}
}
@@ -592,10 +612,10 @@
// ------------ START: Informational methods ------------
- @ManagedAttribute (description = "Local address")
+ @ManagedAttribute(description = "Local address")
public String getLocalAddressString()
{
- Address address = getLocalAddress();
+ Address address = getLocalAddress();
return address == null ? "null" : address.toString();
}
@@ -604,7 +624,7 @@
return channel != null ? channel.getLocalAddress() : null;
}
- @ManagedAttribute (description = "Cluster view")
+ @ManagedAttribute(description = "Cluster view")
public String getMembersString()
{
List l = getMembers();
@@ -615,9 +635,13 @@
{
if (isInLocalMode) return null;
if (members == null)
+ {
return Collections.emptyList();
+ }
else
+ {
return members;
+ }
}
public boolean isCoordinator()
@@ -715,7 +739,7 @@
catch (Throwable e)
{
//do not rethrow! jgroups might behave funny, resulting even in deadlock
- log.error("Error found while processing view accepted!!!", e);
+ log.error("Error found while processing view accepted!!!", e);
}
}
@@ -812,6 +836,12 @@
return statisticsEnabled;
}
+ @ManagedAttribute(description = "whether or not the RPCManager is used in this cache instance")
+ public boolean isEnabled()
+ {
+ return !isInLocalMode;
+ }
+
@ManagedAttribute
public void setStatisticsEnabled(boolean statisticsEnabled)
{
@@ -837,7 +867,9 @@
{
//if we use a shared transport do not log any warn message
if (configuration.getMultiplexerStack() != null)
+ {
return;
+ }
//bundling is not good for sync caches
Configuration.CacheMode cacheMode = configuration.getCacheMode();
if (!cacheMode.equals(Configuration.CacheMode.LOCAL) && configuration.getCacheMode().isSynchronous())
Modified: core/trunk/src/main/java/org/jboss/cache/RegionManagerImpl.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/RegionManagerImpl.java 2009-02-03 22:29:46 UTC (rev 7635)
+++ core/trunk/src/main/java/org/jboss/cache/RegionManagerImpl.java 2009-02-04 11:19:35 UTC (rev 7636)
@@ -24,7 +24,9 @@
import net.jcip.annotations.ThreadSafe;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import static org.jboss.cache.Region.Type.*;
+import static org.jboss.cache.Region.Type.ANY;
+import static org.jboss.cache.Region.Type.EVICTION;
+import static org.jboss.cache.Region.Type.MARSHALLING;
import org.jboss.cache.buddyreplication.BuddyFqnTransformer;
import org.jboss.cache.buddyreplication.BuddyManager;
import org.jboss.cache.config.Configuration;
@@ -36,6 +38,7 @@
import org.jboss.cache.factories.annotations.Inject;
import org.jboss.cache.factories.annotations.Start;
import org.jboss.cache.factories.annotations.Stop;
+import org.jboss.cache.jmx.annotations.MBean;
import org.jboss.cache.jmx.annotations.ManagedAttribute;
import org.jboss.cache.jmx.annotations.ManagedOperation;
import org.jboss.cache.lock.LockManager;
@@ -55,6 +58,7 @@
* @since 3.0.0
*/
@ThreadSafe
+@MBean(objectName = "RegionManager", description = "Manages eviction and marshalling regions")
public class RegionManagerImpl implements RegionManager
{
/**
@@ -141,7 +145,9 @@
setDefaultInactive(configuration.isInactiveOnStartup());
if (isUsingEvictions())
+ {
evictionTimerTask.init(evictionConfig.getWakeupInterval(), configuration.getRuntimeConfig().getEvictionTimerThreadFactory(), regionsRegistry);
+ }
}
@Stop
@@ -420,7 +426,9 @@
// Don't bother trying to fetch state if we are in LOCAL mode
if (members != null && !members.isEmpty())
+ {
rpcManager.fetchPartialState(members, subtreeRoot.getFqn());
+ }
}
else if (!buddyFqnTransformer.isBackupFqn(fqn))
{
@@ -431,7 +439,9 @@
{
List<Address> sources = new ArrayList<Address>(1);
if (!cache.getMembers().contains(buddy))
+ {
continue;
+ }
sources.add(buddy);
Fqn buddyRoot = buddyFqnTransformer.getBackupFqn(buddy, fqn);
subtreeRoot = cache.peek(buddyRoot, false, false);
@@ -642,7 +652,9 @@
{
if ((type == EVICTION && r.getEvictionRegionConfig() != null) ||
(type == MARSHALLING && r.isActive() && r.getClassLoader() != null))
+ {
regions.add(r);
+ }
}
}
else
@@ -673,7 +685,9 @@
// needDefault = ercs.size() == 0;
if (evictionConfig.getDefaultEvictionRegionConfig().getEvictionAlgorithmConfig() != null &&
!ercs.contains(evictionConfig.getDefaultEvictionRegionConfig())) // then the default is a real region too; not just a template for others
+ {
ercs.add(0, evictionConfig.getDefaultEvictionRegionConfig());
+ }
// create regions for the regions defined in the evictionConfig.
// scan to be sure the _default_ region isn't added twice
@@ -746,7 +760,7 @@
evictionTimerTask.stop();
}
- @ManagedAttribute(name="numRegions", description = "A count of all regions")
+ @ManagedAttribute(name = "numRegions", description = "A count of all regions")
public int getNumRegions()
{
return regionsRegistry.size();
Modified: core/trunk/src/main/java/org/jboss/cache/interceptors/CacheMgmtInterceptor.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/interceptors/CacheMgmtInterceptor.java 2009-02-03 22:29:46 UTC (rev 7635)
+++ core/trunk/src/main/java/org/jboss/cache/interceptors/CacheMgmtInterceptor.java 2009-02-04 11:19:35 UTC (rev 7636)
@@ -152,7 +152,9 @@
{
double total = hits + misses;
if (total == 0)
+ {
return 0;
+ }
return (hits / total);
}
@@ -160,7 +162,9 @@
public double getReadWriteRatio()
{
if (stores == 0)
+ {
return 0;
+ }
return (((double) (hits + misses) / (double) stores));
}
@@ -169,7 +173,9 @@
{
long total = hits + misses;
if (total == 0)
+ {
return 0;
+ }
return (hitTimes + missTimes) / total;
}
@@ -177,17 +183,19 @@
public long getAverageWriteTime()
{
if (stores == 0)
+ {
return 0;
+ }
return (storeTimes) / stores;
}
- @ManagedAttribute(description = "number of cache eviction operations")
+ @ManagedAttribute(description = "number of cache attributes")
public int getNumberOfAttributes()
{
return dataContainer.getNumberOfAttributes();
}
- @ManagedAttribute
+ @ManagedAttribute(description = "number of nodes in the cache")
public int getNumberOfNodes()
{
return dataContainer.getNumberOfNodes();
Modified: core/trunk/src/main/java/org/jboss/cache/interceptors/InterceptorChain.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/interceptors/InterceptorChain.java 2009-02-03 22:29:46 UTC (rev 7635)
+++ core/trunk/src/main/java/org/jboss/cache/interceptors/InterceptorChain.java 2009-02-04 11:19:35 UTC (rev 7636)
@@ -30,6 +30,8 @@
import org.jboss.cache.factories.annotations.Start;
import org.jboss.cache.interceptors.base.CommandInterceptor;
import org.jboss.cache.invocation.InvocationContextContainer;
+import org.jboss.cache.jmx.annotations.MBean;
+import org.jboss.cache.jmx.annotations.ManagedOperation;
import org.jboss.cache.util.CachePrinter;
import java.util.ArrayList;
@@ -45,6 +47,7 @@
* todo - if you add the same interceptor instance twice, things get really dirty.
* -- this should be treated as an missuse and an exception should be thrown
*/
+@MBean(description = "InterceptorChain")
public class InterceptorChain
{
/**
@@ -151,6 +154,25 @@
}
+ @ManagedOperation(description = "Retrieves a list of the interceptors in the chain")
+ public String getInterceptorDetails()
+ {
+ StringBuilder sb = new StringBuilder("Interceptor chain: \n");
+ int count = 0;
+ for (CommandInterceptor i : asList())
+ {
+ count++;
+ sb.append(" ").append(count).append(". ").append(i).append("\n");
+ }
+ return sb.toString();
+ }
+
+ @ManagedOperation(description = "Retrieves a list of the interceptors in the chain, formatted as HTML")
+ public String getInterceptorDetailsAsHtml()
+ {
+ return CachePrinter.formatHtml(getInterceptorDetails());
+ }
+
/**
* Returns an unmofiable list with all the interceptors in sequence.
* If first in chain is null an empty list is returned.
Modified: core/trunk/src/main/java/org/jboss/cache/jmx/CacheJmxWrapper.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/jmx/CacheJmxWrapper.java 2009-02-03 22:29:46 UTC (rev 7635)
+++ core/trunk/src/main/java/org/jboss/cache/jmx/CacheJmxWrapper.java 2009-02-04 11:19:35 UTC (rev 7636)
@@ -48,16 +48,7 @@
import org.jgroups.jmx.JChannelFactoryMBean;
import org.w3c.dom.Element;
-import javax.management.AttributeChangeNotification;
-import javax.management.ListenerNotFoundException;
-import javax.management.MBeanNotificationInfo;
-import javax.management.MBeanRegistration;
-import javax.management.MBeanServer;
-import javax.management.MalformedObjectNameException;
-import javax.management.NotificationBroadcasterSupport;
-import javax.management.NotificationFilter;
-import javax.management.NotificationListener;
-import javax.management.ObjectName;
+import javax.management.*;
import javax.transaction.TransactionManager;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
@@ -146,7 +137,7 @@
public String printConfigurationAsHtmlString()
{
Configuration cfg = getConfiguration();
- return cfg == null ? "Configuration is null" : formatHtml(cfg.toString());
+ return cfg == null ? "Configuration is null" : CachePrinter.formatHtml(cfg.toString());
}
public String printCacheDetails()
@@ -156,7 +147,7 @@
public String printCacheDetailsAsHtml()
{
- return cache == null ? "Cache is null" : formatHtml(CachePrinter.printCacheDetails(cache));
+ return cache == null ? "Cache is null" : CachePrinter.formatHtml(CachePrinter.printCacheDetails(cache));
}
public CacheStatus getCacheStatus()
@@ -217,7 +208,7 @@
public String printLockInfoAsHtml()
{
- return cache == null ? "Cache is null" : formatHtml(CachePrinter.printCacheLockingInfo(cache));
+ return cache == null ? "Cache is null" : CachePrinter.formatHtml(CachePrinter.printCacheLockingInfo(cache));
}
public boolean getRegisterJmxResource()
@@ -599,9 +590,13 @@
if (!cacheStatus.createAllowed())
{
if (cacheStatus.needToDestroyFailedCache())
+ {
destroy();
+ }
else
+ {
return;
+ }
}
try
@@ -633,12 +628,18 @@
if (!cacheStatus.startAllowed())
{
if (cacheStatus.needToDestroyFailedCache())
+ {
destroy(); // this will take us back to DESTROYED
+ }
if (cacheStatus.needCreateBeforeStart())
+ {
create();
+ }
else
+ {
return;
+ }
}
try
@@ -718,7 +719,9 @@
}
}
else
+ {
return;
+ }
}
try
@@ -730,7 +733,9 @@
unregisterJmxResources();
if (cache != null)
+ {
cache.destroy();
+ }
}
finally
{
@@ -901,22 +906,6 @@
return server;
}
- /**
- * Formats a given String for display as an HTML snippet.
- *
- * @param s string to format
- * @return formatted string
- */
- public static String formatHtml(String s)
- {
- s = s.replaceAll("\r\n", "<br/>");
- s = s.replaceAll("\r", "<br/>");
- s = s.replaceAll("\n", "<br/>");
- s = s.replaceAll("\t", " ");
- s = s.replaceAll(" ", " ");
- return s;
- }
-
public String getNotificationServiceName()
{
return notificationServiceName;
@@ -1049,14 +1038,18 @@
{
listenerCount.incrementAndGet();
if (cache != null)
+ {
cache.addCacheListener(cacheNotificationListener);
+ }
}
else
{
if (listenerCount.decrementAndGet() <= 0)
{
if (cache != null)
+ {
cache.removeCacheListener(cacheNotificationListener);
+ }
listenerCount.set(0);
}
@@ -1082,13 +1075,21 @@
sendStateChangeNotification(oldState, getState(), getClass().getSimpleName() + " failed", t);
if (t instanceof CacheException)
+ {
throw (CacheException) t;
+ }
else if (t instanceof RuntimeException)
+ {
throw (RuntimeException) t;
+ }
else if (t instanceof Error)
+ {
throw (Error) t;
+ }
else
+ {
throw new CacheException(t);
+ }
}
/**
@@ -1097,7 +1098,9 @@
private void sendStateChangeNotification(int oldState, int newState, String msg, Throwable t)
{
if (isDisableStateChangeNotifications())
+ {
return;
+ }
long now = System.currentTimeMillis();
Modified: core/trunk/src/main/java/org/jboss/cache/util/CachePrinter.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/util/CachePrinter.java 2009-02-03 22:29:46 UTC (rev 7635)
+++ core/trunk/src/main/java/org/jboss/cache/util/CachePrinter.java 2009-02-04 11:19:35 UTC (rev 7636)
@@ -93,4 +93,20 @@
}
return sb.toString();
}
+
+ /**
+ * Formats a given String for display as an HTML snippet.
+ *
+ * @param s string to format
+ * @return formatted string
+ */
+ public static String formatHtml(String s)
+ {
+ s = s.replaceAll("\r\n", "<br/>");
+ s = s.replaceAll("\r", "<br/>");
+ s = s.replaceAll("\n", "<br/>");
+ s = s.replaceAll("\t", " ");
+ s = s.replaceAll(" ", " ");
+ return s;
+ }
}
Added: core/trunk/src/test/java/org/jboss/cache/jmx/JmxManualTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/jmx/JmxManualTest.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/jmx/JmxManualTest.java 2009-02-04 11:19:35 UTC (rev 7636)
@@ -0,0 +1,76 @@
+package org.jboss.cache.jmx;
+
+import org.jboss.cache.Cache;
+import org.jboss.cache.DefaultCacheFactory;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.config.Configuration;
+import org.jboss.cache.config.EvictionConfig;
+import org.jboss.cache.config.EvictionRegionConfig;
+import org.jboss.cache.eviction.FIFOAlgorithmConfig;
+import org.testng.annotations.Test;
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+// do NOT enable this test in SVN as it will cause Hudson (or any other continuous integration test harness) to get
+
+// stuck.
+@Test(groups = "maual", enabled = false)
+public class JmxManualTest
+{
+ public void testLocal() throws IOException
+ {
+ Configuration c = new Configuration();
+ Cache cache = new DefaultCacheFactory().createCache(c);
+ cache.put("/a/b/c", "a", "b");
+ cache.put("/a/b/c", "c", "d");
+ cache.put("/a/b/d", "a", "b");
+ cache.put("/a/b/e", "c", "d");
+
+ System.in.read();
+ }
+
+ public void testLocalNoJMX() throws IOException
+ {
+ Configuration c = new Configuration();
+ c.setExposeManagementStatistics(false);
+ Cache cache = new DefaultCacheFactory().createCache(c);
+ cache.put("/a/b/c", "a", "b");
+ cache.put("/a/b/c", "c", "d");
+ cache.put("/a/b/d", "a", "b");
+ cache.put("/a/b/e", "c", "d");
+
+ System.in.read();
+ }
+
+ public void testLocalWithEviction() throws IOException
+ {
+ Configuration c = new Configuration();
+ EvictionConfig ec = new EvictionConfig();
+ ec.setWakeupInterval(250, TimeUnit.MILLISECONDS);
+ EvictionRegionConfig erc = new EvictionRegionConfig();
+ erc.setEvictionAlgorithmConfig(new FIFOAlgorithmConfig(2));
+ erc.setRegionFqn(Fqn.ROOT);
+ ec.setDefaultEvictionRegionConfig(erc);
+ c.setEvictionConfig(ec);
+ Cache cache = new DefaultCacheFactory().createCache(c);
+ cache.put("/a/b/c", "a", "b");
+ cache.put("/a/b/c", "c", "d");
+ cache.put("/a/b/d", "a", "b");
+ cache.put("/a/b/e", "c", "d");
+
+ System.in.read();
+ }
+
+ public void testLocalWithEvictionXML() throws IOException
+ {
+ Cache cache = new DefaultCacheFactory().createCache("config-samples/eviction-enabled.xml");
+ cache.put("/a/b/c", "a", "b");
+ cache.put("/a/b/c", "c", "d");
+ cache.put("/a/b/d", "a", "b");
+ cache.put("/a/b/e", "c", "d");
+
+ System.in.read();
+ }
+
+}
Modified: core/trunk/src/test/java/org/jboss/cache/jmx/deprecated/CacheJmxWrapperTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/jmx/deprecated/CacheJmxWrapperTest.java 2009-02-03 22:29:46 UTC (rev 7635)
+++ core/trunk/src/test/java/org/jboss/cache/jmx/deprecated/CacheJmxWrapperTest.java 2009-02-04 11:19:35 UTC (rev 7636)
@@ -16,7 +16,6 @@
import org.jboss.cache.notifications.event.Event;
import org.jboss.cache.transaction.DummyTransactionManagerLookup;
import org.jboss.cache.util.CachePrinter;
-import org.jboss.cache.util.TestingUtil;
import org.jgroups.Address;
import org.jgroups.stack.IpAddress;
import static org.testng.AssertJUnit.*;
@@ -71,7 +70,9 @@
finally
{
if (registered)
+ {
mBeanServer.unregisterMBean(on);
+ }
}
}
@@ -155,7 +156,7 @@
{
CacheJmxWrapperMBean<String, String> wrapper = registerWrapper();
String cfgFromJmx = wrapper.printConfigurationAsHtmlString();
- assertEquals(CacheJmxWrapper.formatHtml(cache.getConfiguration().toString()), cfgFromJmx);
+ assertEquals(CachePrinter.formatHtml(cache.getConfiguration().toString()), cfgFromJmx);
checkHtml(cfgFromJmx, false);
}
@@ -175,7 +176,7 @@
wrapper.create();
wrapper.start();
String cfgFromJmx = wrapper.printConfigurationAsHtmlString();
- assertEquals(CacheJmxWrapper.formatHtml(wrapper.getCache().getConfiguration().toString()), cfgFromJmx);
+ assertEquals(CachePrinter.formatHtml(wrapper.getCache().getConfiguration().toString()), cfgFromJmx);
checkHtml(cfgFromJmx, false);
}
@@ -396,7 +397,9 @@
private void checkHtml(String html, boolean checkBR)
{
if (checkBR)
+ {
assertTrue("Has <br", html.contains("<br"));
+ }
assertTrue("No tabs", html.indexOf('\t') == -1);
15 years, 10 months
JBoss Cache SVN: r7635 - in core/trunk/src: main/java/org/jboss/cache/interceptors and 2 other directories.
by jbosscache-commits@lists.jboss.org
Author: galder.zamarreno(a)jboss.com
Date: 2009-02-03 17:29:46 -0500 (Tue, 03 Feb 2009)
New Revision: 7635
Modified:
core/trunk/src/main/java/org/jboss/cache/config/Option.java
core/trunk/src/main/java/org/jboss/cache/interceptors/TxInterceptor.java
core/trunk/src/main/java/org/jboss/cache/notifications/NotifierImpl.java
core/trunk/src/test/java/org/jboss/cache/notifications/CacheListenerTest.java
Log:
[JBCACHE-1470] Added suppress event notification option override. Extended set of cache listener tests so that they're executed both and without suppress event notification and make sure the event notification expectations are correct in each scenario.
Modified: core/trunk/src/main/java/org/jboss/cache/config/Option.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/config/Option.java 2009-02-03 21:42:43 UTC (rev 7634)
+++ core/trunk/src/main/java/org/jboss/cache/config/Option.java 2009-02-03 22:29:46 UTC (rev 7635)
@@ -27,6 +27,7 @@
* Used to override characteristics of specific calls to the cache. The javadocs of each of the setters below detail functionality and behaviour.
*
* @author <a href="mailto:manik AT jboss DOT org">Manik Surtani (manik AT jboss DOT org)</a>
+ * @author <a href="mailto:galder.zamarreno@jboss.com">Galder Zamarreno</a>
* @since 1.3.0
*/
public class Option implements Cloneable
@@ -49,6 +50,7 @@
private int lockAcquisitionTimeout = -1;
private boolean suppressPersistence;
+ private boolean suppressEventNotification;
/**
* @since 1.4.0
@@ -270,6 +272,8 @@
", skipDataGravitation=" + skipDataGravitation +
", forceAsynchronous=" + forceAsynchronous +
", forceSynchronous=" + forceSynchronous +
+ ", suppressPersistence=" + suppressPersistence +
+ ", suppressEventNotification=" + suppressEventNotification +
'}';
}
@@ -320,6 +324,7 @@
if (forceSynchronous != option.forceSynchronous) return false;
if (lockAcquisitionTimeout != option.lockAcquisitionTimeout) return false;
if (suppressPersistence != option.suppressPersistence) return false;
+ if (suppressEventNotification != option.suppressEventNotification) return false;
return true;
}
@@ -338,6 +343,7 @@
result = 29 * result + (forceSynchronous ? 0 : 1);
result = 29 * result + (lockAcquisitionTimeout);
result = 29 * result + (suppressPersistence ? 0 : 1);
+ result = 29 * result + (suppressEventNotification ? 0 : 1);
return result;
}
@@ -357,6 +363,7 @@
this.forceSynchronous = false;
this.lockAcquisitionTimeout = -1;
this.suppressPersistence = false;
+ this.suppressEventNotification = false;
}
/**
@@ -475,4 +482,29 @@
{
this.suppressPersistence = suppressPersistence;
}
+
+ /**
+ * Get whether event notifications for this invocation will be suppresed. By
+ * default is false which means that corresponding events are sent depending
+ * on the type of invocation.
+ *
+ * @return true, if event notification will be suppressed for this invocation.
+ */
+ public boolean isSuppressEventNotification()
+ {
+ return suppressEventNotification;
+ }
+
+ /**
+ * Set whether event notifications should be suppressed for this particular
+ * cache or transaction invocation.
+ *
+ * @param suppressEventNotification <code>true</code> if event notification
+ * should be skipped; <code>false</code> if events
+ * should be notified if there're any listeners.
+ */
+ public void setSuppressEventNotification(boolean suppressEventNotification)
+ {
+ this.suppressEventNotification = suppressEventNotification;
+ }
}
Modified: core/trunk/src/main/java/org/jboss/cache/interceptors/TxInterceptor.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/interceptors/TxInterceptor.java 2009-02-03 21:42:43 UTC (rev 7634)
+++ core/trunk/src/main/java/org/jboss/cache/interceptors/TxInterceptor.java 2009-02-03 22:29:46 UTC (rev 7635)
@@ -74,6 +74,7 @@
*
* @author <a href="mailto:manik AT jboss DOT org">Manik Surtani (manik AT jboss DOT org)</a>
* @author <a href="mailto:stevew@jofti.com">Steve Woodcock (stevew(a)jofti.com)</a>
+ * @author <a href="mailto:galder.zamarreno@jboss.com">Galder Zamarreno</a>
*/
public class TxInterceptor extends BaseTransactionalContextInterceptor
{
@@ -921,6 +922,9 @@
{
// this should ideally be set in beforeCompletion(), after compacting the list.
if (modifications == null) modifications = transactionContext.getModifications();
+ Option transactionalOptions = transactionContext.getOption();
+ Option originalOptions = ctx.getOptionOverrides();
+ transactionalOptions.setSuppressEventNotification(originalOptions.isSuppressEventNotification());
ctx.setOptionOverrides(transactionContext.getOption());
}
if (tx != null) transactions.remove(tx);
@@ -1051,6 +1055,7 @@
// set any transaction wide options as current for this thread, caching original options that would then be reset
originalOptions = ctx.getOptionOverrides();
transactionalOptions = transactionContext.getOption();
+ transactionalOptions.setSuppressEventNotification(originalOptions.isSuppressEventNotification());
ctx.setOptionOverrides(transactionalOptions);
try
Modified: core/trunk/src/main/java/org/jboss/cache/notifications/NotifierImpl.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/notifications/NotifierImpl.java 2009-02-03 21:42:43 UTC (rev 7634)
+++ core/trunk/src/main/java/org/jboss/cache/notifications/NotifierImpl.java 2009-02-03 22:29:46 UTC (rev 7635)
@@ -64,6 +64,7 @@
* Helper class that handles all notifications to registered listeners.
*
* @author <a href="mailto:manik AT jboss DOT org">Manik Surtani (manik AT jboss DOT org)</a>
+ * @author <a href="mailto:galder.zamarreno@jboss.com">Galder Zamarreno</a>
*/
@NonVolatile
public class NotifierImpl implements Notifier
@@ -307,7 +308,7 @@
public void notifyNodeCreated(Fqn fqn, boolean pre, InvocationContext ctx)
{
- if (!nodeCreatedListeners.isEmpty())
+ if (!nodeCreatedListeners.isEmpty() && !ctx.getOptionOverrides().isSuppressEventNotification())
{
boolean originLocal = ctx.isOriginLocal();
Transaction tx = ctx.getTransaction();
@@ -326,7 +327,7 @@
public void notifyNodeModified(Fqn fqn, boolean pre, NodeModifiedEvent.ModificationType modificationType, Map data, InvocationContext ctx)
{
- if (!nodeModifiedListeners.isEmpty())
+ if (!nodeModifiedListeners.isEmpty() && !ctx.getOptionOverrides().isSuppressEventNotification())
{
boolean originLocal = ctx.isOriginLocal();
Map dataCopy = copy(data, useMarshalledValueMaps);
@@ -353,7 +354,7 @@
public void notifyNodeRemoved(Fqn fqn, boolean pre, Map data, InvocationContext ctx)
{
- if (!nodeRemovedListeners.isEmpty())
+ if (!nodeRemovedListeners.isEmpty() && !ctx.getOptionOverrides().isSuppressEventNotification())
{
boolean originLocal = ctx.isOriginLocal();
Map dataCopy = copy(data, useMarshalledValueMaps);
@@ -374,7 +375,7 @@
public void notifyNodeVisited(Fqn fqn, boolean pre, InvocationContext ctx)
{
- if (!nodeVisitedListeners.isEmpty())
+ if (!nodeVisitedListeners.isEmpty() && !ctx.getOptionOverrides().isSuppressEventNotification())
{
Transaction tx = ctx.getTransaction();
InvocationContext backup = resetInvocationContext(ctx);
@@ -391,7 +392,7 @@
public void notifyNodeMoved(Fqn originalFqn, Fqn newFqn, boolean pre, InvocationContext ctx)
{
- if (!nodeMovedListeners.isEmpty())
+ if (!nodeMovedListeners.isEmpty() && !ctx.getOptionOverrides().isSuppressEventNotification())
{
boolean originLocal = ctx.isOriginLocal();
Transaction tx = ctx.getTransaction();
@@ -411,7 +412,7 @@
public void notifyNodeEvicted(final Fqn fqn, final boolean pre, InvocationContext ctx)
{
- if (!nodeEvictedListeners.isEmpty())
+ if (!nodeEvictedListeners.isEmpty() && !ctx.getOptionOverrides().isSuppressEventNotification())
{
final boolean originLocal = ctx.isOriginLocal();
Transaction tx = ctx.getTransaction();
@@ -430,7 +431,7 @@
public void notifyNodeInvalidated(final Fqn fqn, final boolean pre, InvocationContext ctx)
{
- if (!nodeInvalidatedListeners.isEmpty())
+ if (!nodeInvalidatedListeners.isEmpty() && !ctx.getOptionOverrides().isSuppressEventNotification())
{
final boolean originLocal = ctx.isOriginLocal();
Transaction tx = ctx.getTransaction();
@@ -449,7 +450,7 @@
public void notifyNodeLoaded(Fqn fqn, boolean pre, Map data, InvocationContext ctx)
{
- if (!nodeLoadedListeners.isEmpty())
+ if (!nodeLoadedListeners.isEmpty() && !ctx.getOptionOverrides().isSuppressEventNotification())
{
boolean originLocal = ctx.isOriginLocal();
Map dataCopy = copy(data, useMarshalledValueMaps);
@@ -470,7 +471,7 @@
public void notifyNodeActivated(Fqn fqn, boolean pre, Map data, InvocationContext ctx)
{
- if (!nodeActivatedListeners.isEmpty())
+ if (!nodeActivatedListeners.isEmpty() && !ctx.getOptionOverrides().isSuppressEventNotification())
{
boolean originLocal = ctx.isOriginLocal();
Map dataCopy = copy(data, useMarshalledValueMaps);
@@ -491,7 +492,7 @@
public void notifyNodePassivated(Fqn fqn, boolean pre, Map data, InvocationContext ctx)
{
- if (!nodePassivatedListeners.isEmpty())
+ if (!nodePassivatedListeners.isEmpty() && !ctx.getOptionOverrides().isSuppressEventNotification())
{
Map dataCopy = copy(data, useMarshalledValueMaps);
Transaction tx = ctx.getTransaction();
@@ -567,7 +568,7 @@
public void notifyTransactionCompleted(Transaction transaction, boolean successful, InvocationContext ctx)
{
- if (!transactionCompletedListeners.isEmpty())
+ if (!transactionCompletedListeners.isEmpty() && !ctx.getOptionOverrides().isSuppressEventNotification())
{
boolean isOriginLocal = ctx.isOriginLocal();
InvocationContext backup = resetInvocationContext(ctx);
@@ -584,7 +585,7 @@
public void notifyTransactionRegistered(Transaction transaction, InvocationContext ctx)
{
- if (!transactionRegisteredListeners.isEmpty())
+ if (!transactionRegisteredListeners.isEmpty() && !ctx.getOptionOverrides().isSuppressEventNotification())
{
boolean isOriginLocal = ctx.isOriginLocal();
InvocationContext backup = resetInvocationContext(ctx);
Modified: core/trunk/src/test/java/org/jboss/cache/notifications/CacheListenerTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/notifications/CacheListenerTest.java 2009-02-03 21:42:43 UTC (rev 7634)
+++ core/trunk/src/test/java/org/jboss/cache/notifications/CacheListenerTest.java 2009-02-03 22:29:46 UTC (rev 7635)
@@ -12,6 +12,7 @@
import org.jboss.cache.Fqn;
import org.jboss.cache.Node;
import org.jboss.cache.config.Configuration;
+import org.jboss.cache.config.Option;
import org.jboss.cache.lock.IsolationLevel;
import org.jboss.cache.notifications.event.Event;
import static org.jboss.cache.notifications.event.Event.Type.*;
@@ -38,6 +39,7 @@
* exercises the new CacheListener annotation.
*
* @since 2.0.0
+ * @author <a href="mailto:galder.zamarreno@jboss.com">Galder Zamarreno</a>
*/
@Test(groups = "functional", sequential = true, testName = "notifications.CacheListenerTest")
public class CacheListenerTest
@@ -78,32 +80,53 @@
// simple tests first
- public void testCreation() throws Exception
+ public void testCreation()
{
+ creation(false);
+ eventLog.events.clear();
+ creation(true);
+ }
+
+ protected void creation(boolean supressEventNotification)
+ {
assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
+ if (supressEventNotification)
+ {
+ setSuppressEventNotification();
+ }
cache.put(fqn, "key", "value");
Map<Object, Object> data = new HashMap<Object, Object>();
data.put("key", "value");
//expected
List<Event> expected = new ArrayList<Event>();
- if (optLocking)
- expected.add(new EventImpl(false, cache, null, null, null, null, true, null, false, null, TRANSACTION_REGISTERED));
- expected.add(new EventImpl(true, cache, null, null, fqn, null, true, null, false, null, NODE_CREATED));
- expected.add(new EventImpl(false, cache, null, null, fqn, null, true, null, false, null, NODE_CREATED));
- expected.add(new EventImpl(true, cache, PUT_DATA, Collections.emptyMap(), fqn, null, true, null, false, null, NODE_MODIFIED));
- expected.add(new EventImpl(false, cache, PUT_DATA, data, fqn, null, true, null, false, null, NODE_MODIFIED));
- if (optLocking)
+ if (!supressEventNotification)
{
- expected.add(new EventImpl(false, cache, null, null, null, null, true, null, true, null, TRANSACTION_COMPLETED));
- eventLog.scrubImplicitTransactions();
+ if (optLocking)
+ expected.add(new EventImpl(false, cache, null, null, null, null, true, null, false, null, TRANSACTION_REGISTERED));
+ expected.add(new EventImpl(true, cache, null, null, fqn, null, true, null, false, null, NODE_CREATED));
+ expected.add(new EventImpl(false, cache, null, null, fqn, null, true, null, false, null, NODE_CREATED));
+ expected.add(new EventImpl(true, cache, PUT_DATA, Collections.emptyMap(), fqn, null, true, null, false, null, NODE_MODIFIED));
+ expected.add(new EventImpl(false, cache, PUT_DATA, data, fqn, null, true, null, false, null, NODE_MODIFIED));
+ if (optLocking)
+ {
+ expected.add(new EventImpl(false, cache, null, null, null, null, true, null, true, null, TRANSACTION_COMPLETED));
+ eventLog.scrubImplicitTransactions();
+ }
}
assertEquals(expected, eventLog.events);
- assertEquals("value", cache.get(fqn, "key"));
+ assertEquals("value", cache.get(fqn, "key"));
}
- public void testOnlyModification() throws Exception
+ public void testOnlyModification()
{
+ onlyModification(false);
+ eventLog.events.clear();
+ onlyModification(true);
+ }
+
+ protected void onlyModification(boolean supressEventNotification)
+ {
assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
cache.put(fqn, "key", "value");
Map<Object, Object> oldData = new HashMap<Object, Object>();
@@ -114,28 +137,42 @@
assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
// modify existing node
+ if (supressEventNotification)
+ {
+ setSuppressEventNotification();
+ }
cache.put(fqn, "key", "value2");
Map<Object, Object> newData = new HashMap<Object, Object>();
newData.put("key", "value2");
//expected
List<Event> expected = new ArrayList<Event>();
- if (optLocking)
- expected.add(new EventImpl(false, cache, null, null, null, null, true, null, false, null, TRANSACTION_REGISTERED));
- expected.add(new EventImpl(true, cache, PUT_DATA, oldData, fqn, null, true, null, false, null, NODE_MODIFIED));
- expected.add(new EventImpl(false, cache, PUT_DATA, newData, fqn, null, true, null, false, null, NODE_MODIFIED));
- if (optLocking)
+ if (!supressEventNotification)
{
- expected.add(new EventImpl(false, cache, null, null, null, null, true, null, true, null, TRANSACTION_COMPLETED));
- eventLog.scrubImplicitTransactions();
+ if (optLocking)
+ expected.add(new EventImpl(false, cache, null, null, null, null, true, null, false, null, TRANSACTION_REGISTERED));
+ expected.add(new EventImpl(true, cache, PUT_DATA, oldData, fqn, null, true, null, false, null, NODE_MODIFIED));
+ expected.add(new EventImpl(false, cache, PUT_DATA, newData, fqn, null, true, null, false, null, NODE_MODIFIED));
+ if (optLocking)
+ {
+ expected.add(new EventImpl(false, cache, null, null, null, null, true, null, true, null, TRANSACTION_COMPLETED));
+ eventLog.scrubImplicitTransactions();
+ }
}
assertEquals(expected.size(), eventLog.events.size());
assertEquals(expected, eventLog.events);
}
- public void testOnlyRemoval() throws Exception
+ public void testOnlyRemoval()
{
+ onlyRemoval(false);
+ eventLog.events.clear();
+ onlyRemoval(true);
+ }
+
+ protected void onlyRemoval(boolean supressEventNotification)
+ {
assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
cache.put(fqn, "key", "value");
Map<Object, Object> oldData = new HashMap<Object, Object>();
@@ -148,18 +185,25 @@
assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
// modify existing node
+ if (supressEventNotification)
+ {
+ setSuppressEventNotification();
+ }
cache.removeNode(fqn);
//expected
List<Event> expected = new ArrayList<Event>();
- if (optLocking)
- expected.add(new EventImpl(false, cache, null, null, null, null, true, null, false, null, TRANSACTION_REGISTERED));
- expected.add(new EventImpl(true, cache, null, oldData, fqn, null, true, null, false, null, NODE_REMOVED));
- expected.add(new EventImpl(false, cache, null, null, fqn, null, true, null, false, null, NODE_REMOVED));
- if (optLocking)
+ if (!supressEventNotification)
{
- expected.add(new EventImpl(false, cache, null, null, null, null, true, null, true, null, TRANSACTION_COMPLETED));
- eventLog.scrubImplicitTransactions();
+ if (optLocking)
+ expected.add(new EventImpl(false, cache, null, null, null, null, true, null, false, null, TRANSACTION_REGISTERED));
+ expected.add(new EventImpl(true, cache, null, oldData, fqn, null, true, null, false, null, NODE_REMOVED));
+ expected.add(new EventImpl(false, cache, null, null, fqn, null, true, null, false, null, NODE_REMOVED));
+ if (optLocking)
+ {
+ expected.add(new EventImpl(false, cache, null, null, null, null, true, null, true, null, TRANSACTION_COMPLETED));
+ eventLog.scrubImplicitTransactions();
+ }
}
assertEquals(expected, eventLog.events);
@@ -168,22 +212,42 @@
assertNull("Should be null", cache.getRoot().getChild(fqn));
}
- public void testNonexistentRemove() throws Exception
+ public void testNonexistentRemove()
{
+ nonexistentRemove(false);
+ eventLog.events.clear();
+ nonexistentRemove(true);
+ }
+
+ protected void nonexistentRemove(boolean supressEventNotification)
+ {
+ if (supressEventNotification)
+ {
+ setSuppressEventNotification();
+ }
cache.removeNode("/does/not/exist");
List<Event> expected = new ArrayList<Event>();
-
- if (optLocking)
+ if (!supressEventNotification)
{
- expected.add(new EventImpl(false, cache, null, null, null, null, true, null, false, null, TRANSACTION_REGISTERED));
- expected.add(new EventImpl(false, cache, null, null, null, null, true, null, true, null, TRANSACTION_COMPLETED));
- eventLog.scrubImplicitTransactions();
+ if (optLocking)
+ {
+ expected.add(new EventImpl(false, cache, null, null, null, null, true, null, false, null, TRANSACTION_REGISTERED));
+ expected.add(new EventImpl(false, cache, null, null, null, null, true, null, true, null, TRANSACTION_COMPLETED));
+ eventLog.scrubImplicitTransactions();
+ }
}
assertEquals(expected, eventLog.events);
}
- public void testRemoveData() throws Exception
+ public void testRemoveData()
{
+ removeData(false);
+ eventLog.events.clear();
+ removeData(true);
+ }
+
+ protected void removeData(boolean supressEventNotification)
+ {
assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
cache.put(fqn, "key", "value");
cache.put(fqn, "key2", "value2");
@@ -196,6 +260,10 @@
assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
// modify existing node
+ if (supressEventNotification)
+ {
+ setSuppressEventNotification();
+ }
cache.remove(fqn, "key2");
Map<Object, Object> removedData = new HashMap<Object, Object>();
removedData.put("key2", "value2");
@@ -203,14 +271,17 @@
//expected
List<Event> expected = new ArrayList<Event>();
- if (optLocking)
- expected.add(new EventImpl(false, cache, null, null, null, null, true, null, false, null, TRANSACTION_REGISTERED));
- expected.add(new EventImpl(true, cache, REMOVE_DATA, oldData, fqn, null, true, null, false, null, NODE_MODIFIED));
- expected.add(new EventImpl(false, cache, REMOVE_DATA, removedData, fqn, null, true, null, false, null, NODE_MODIFIED));
- if (optLocking)
+ if (!supressEventNotification)
{
- expected.add(new EventImpl(false, cache, null, null, null, null, true, null, true, null, TRANSACTION_COMPLETED));
- eventLog.scrubImplicitTransactions();
+ if (optLocking)
+ expected.add(new EventImpl(false, cache, null, null, null, null, true, null, false, null, TRANSACTION_REGISTERED));
+ expected.add(new EventImpl(true, cache, REMOVE_DATA, oldData, fqn, null, true, null, false, null, NODE_MODIFIED));
+ expected.add(new EventImpl(false, cache, REMOVE_DATA, removedData, fqn, null, true, null, false, null, NODE_MODIFIED));
+ if (optLocking)
+ {
+ expected.add(new EventImpl(false, cache, null, null, null, null, true, null, true, null, TRANSACTION_COMPLETED));
+ eventLog.scrubImplicitTransactions();
+ }
}
assertEquals(expected, eventLog.events);
@@ -218,6 +289,13 @@
public void testPutMap() throws Exception
{
+ putMap(false);
+ eventLog.events.clear();
+ putMap(true);
+ }
+
+ protected void putMap(boolean supressEventNotification)
+ {
assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
Map<Object, Object> oldData = new HashMap<Object, Object>();
oldData.put("key", "value");
@@ -228,20 +306,27 @@
assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
// modify existing node
+ if (supressEventNotification)
+ {
+ setSuppressEventNotification();
+ }
cache.put(fqn, oldData);
//expected
List<Event> expected = new ArrayList<Event>();
- if (optLocking)
- expected.add(new EventImpl(false, cache, null, null, null, null, true, null, false, null, TRANSACTION_REGISTERED));
- expected.add(new EventImpl(true, cache, null, null, fqn, null, true, null, false, null, NODE_CREATED));
- expected.add(new EventImpl(false, cache, null, null, fqn, null, true, null, false, null, NODE_CREATED));
- expected.add(new EventImpl(true, cache, PUT_MAP, Collections.emptyMap(), fqn, null, true, null, false, null, NODE_MODIFIED));
- expected.add(new EventImpl(false, cache, PUT_MAP, oldData, fqn, null, true, null, false, null, NODE_MODIFIED));
- if (optLocking)
- {
- expected.add(new EventImpl(false, cache, null, null, null, null, true, null, true, null, TRANSACTION_COMPLETED));
- eventLog.scrubImplicitTransactions();
+ if (!supressEventNotification)
+ {
+ if (optLocking)
+ expected.add(new EventImpl(false, cache, null, null, null, null, true, null, false, null, TRANSACTION_REGISTERED));
+ expected.add(new EventImpl(true, cache, null, null, fqn, null, true, null, false, null, NODE_CREATED));
+ expected.add(new EventImpl(false, cache, null, null, fqn, null, true, null, false, null, NODE_CREATED));
+ expected.add(new EventImpl(true, cache, PUT_MAP, Collections.emptyMap(), fqn, null, true, null, false, null, NODE_MODIFIED));
+ expected.add(new EventImpl(false, cache, PUT_MAP, oldData, fqn, null, true, null, false, null, NODE_MODIFIED));
+ if (optLocking)
+ {
+ expected.add(new EventImpl(false, cache, null, null, null, null, true, null, true, null, TRANSACTION_COMPLETED));
+ eventLog.scrubImplicitTransactions();
+ }
}
assertEquals(expected, eventLog.events);
@@ -249,6 +334,13 @@
public void testMove()
{
+ move(false);
+ eventLog.events.clear();
+ move(true);
+ }
+
+ protected void move(boolean supressEventNotification)
+ {
assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
Fqn newParent = Fqn.fromString("/a");
cache.put(fqn, "key", "value");
@@ -259,19 +351,26 @@
eventLog.events.clear();// clear events
assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
+ if (supressEventNotification)
+ {
+ setSuppressEventNotification();
+ }
cache.move(n1.getFqn(), n2.getFqn());
//expected
Fqn newFqn = Fqn.fromRelativeElements(newParent, fqn.getLastElement());
List<Event> expected = new ArrayList<Event>();
- if (optLocking)
- expected.add(new EventImpl(false, cache, null, null, null, null, true, null, false, null, TRANSACTION_REGISTERED));
- expected.add(new EventImpl(true, cache, null, null, fqn, null, true, newFqn, false, null, NODE_MOVED));
- expected.add(new EventImpl(false, cache, null, null, fqn, null, true, newFqn, false, null, NODE_MOVED));
- if (optLocking)
- {
- expected.add(new EventImpl(false, cache, null, null, null, null, true, null, true, null, TRANSACTION_COMPLETED));
- eventLog.scrubImplicitTransactions();
+ if (!supressEventNotification)
+ {
+ if (optLocking)
+ expected.add(new EventImpl(false, cache, null, null, null, null, true, null, false, null, TRANSACTION_REGISTERED));
+ expected.add(new EventImpl(true, cache, null, null, fqn, null, true, newFqn, false, null, NODE_MOVED));
+ expected.add(new EventImpl(false, cache, null, null, fqn, null, true, newFqn, false, null, NODE_MOVED));
+ if (optLocking)
+ {
+ expected.add(new EventImpl(false, cache, null, null, null, null, true, null, true, null, TRANSACTION_COMPLETED));
+ eventLog.scrubImplicitTransactions();
+ }
}
assertEquals(expected, eventLog.events);
@@ -281,63 +380,138 @@
public void testTxNonexistentRemove() throws Exception
{
+ txNonexistentRemove(false);
+ eventLog.events.clear();
+ txNonexistentRemove(true);
+ }
+
+ protected void txNonexistentRemove(boolean supressEventNotification) throws Exception
+ {
+ if (supressEventNotification)
+ {
+ setSuppressEventNotification();
+ }
tm.begin();
Transaction tx = tm.getTransaction();
cache.removeNode("/does/not/exist");
+ if (supressEventNotification)
+ {
+ setSuppressEventNotification();
+ }
tm.commit();
List<Event> expected = new ArrayList<Event>();
- expected.add(new EventImpl(false, cache, null, null, null, tx, true, null, false, null, TRANSACTION_REGISTERED));
- expected.add(new EventImpl(false, cache, null, null, null, tx, true, null, true, null, TRANSACTION_COMPLETED));
+ if (!supressEventNotification)
+ {
+ expected.add(new EventImpl(false, cache, null, null, null, tx, true, null, false, null, TRANSACTION_REGISTERED));
+ expected.add(new EventImpl(false, cache, null, null, null, tx, true, null, true, null, TRANSACTION_COMPLETED));
+ }
assertEquals(expected, eventLog.events);
}
-
+
public void testTxCreationCommit() throws Exception
{
+ txCreationCommit(false);
+ eventLog.events.clear();
+ txCreationCommit(true);
+ }
+
+ protected void txCreationCommit(boolean supressEventNotification) throws Exception
+ {
assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
+ if (supressEventNotification)
+ {
+ setSuppressEventNotification();
+ }
tm.begin();
Transaction tx = tm.getTransaction();
+ if (supressEventNotification)
+ {
+ setSuppressEventNotification();
+ }
cache.put(fqn, "key", "value");
//expected
Map<Object, Object> data = new HashMap<Object, Object>();
data.put("key", "value");
List<Event> expected = new ArrayList<Event>();
- expected.add(new EventImpl(false, cache, null, null, null, tx, true, null, false, null, TRANSACTION_REGISTERED));
- expected.add(new EventImpl(true, cache, null, null, fqn, tx, true, null, false, null, NODE_CREATED));
- expected.add(new EventImpl(false, cache, null, null, fqn, tx, true, null, false, null, NODE_CREATED));
- expected.add(new EventImpl(true, cache, PUT_DATA, Collections.emptyMap(), fqn, tx, true, null, false, null, NODE_MODIFIED));
- expected.add(new EventImpl(false, cache, PUT_DATA, data, fqn, tx, true, null, false, null, NODE_MODIFIED));
+ if (!supressEventNotification)
+ {
+ expected.add(new EventImpl(false, cache, null, null, null, tx, true, null, false, null, TRANSACTION_REGISTERED));
+ expected.add(new EventImpl(true, cache, null, null, fqn, tx, true, null, false, null, NODE_CREATED));
+ expected.add(new EventImpl(false, cache, null, null, fqn, tx, true, null, false, null, NODE_CREATED));
+ expected.add(new EventImpl(true, cache, PUT_DATA, Collections.emptyMap(), fqn, tx, true, null, false, null, NODE_MODIFIED));
+ expected.add(new EventImpl(false, cache, PUT_DATA, data, fqn, tx, true, null, false, null, NODE_MODIFIED));
+ }
assertEquals(expected, eventLog.events);
+ if (supressEventNotification)
+ {
+ setSuppressEventNotification();
+ }
tm.commit();
- expected.add(new EventImpl(false, cache, null, null, null, tx, true, null, true, null, TRANSACTION_COMPLETED));
+ if (!supressEventNotification)
+ {
+ expected.add(new EventImpl(false, cache, null, null, null, tx, true, null, true, null, TRANSACTION_COMPLETED));
+ }
assertEquals(expected, eventLog.events);
assertEquals("value", cache.get(fqn, "key"));
}
public void testTxCreationRollback() throws Exception
{
+ txCreationRollback(false);
+ eventLog.events.clear();
+ txCreationRollback(true);
+ }
+
+ protected void txCreationRollback(boolean supressEventNotification) throws Exception
+ {
assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
+ if (supressEventNotification)
+ {
+ setSuppressEventNotification();
+ }
tm.begin();
Transaction tx = tm.getTransaction();
+ if (supressEventNotification)
+ {
+ setSuppressEventNotification();
+ }
cache.put(fqn, "key", "value");
//expected
Map<Object, Object> data = new HashMap<Object, Object>();
data.put("key", "value");
List<Event> expected = new ArrayList<Event>();
- expected.add(new EventImpl(false, cache, null, null, null, tx, true, null, false, null, TRANSACTION_REGISTERED));
- expected.add(new EventImpl(true, cache, null, null, fqn, tx, true, null, false, null, NODE_CREATED));
- expected.add(new EventImpl(false, cache, null, null, fqn, tx, true, null, false, null, NODE_CREATED));
- expected.add(new EventImpl(true, cache, PUT_DATA, Collections.emptyMap(), fqn, tx, true, null, false, null, NODE_MODIFIED));
- expected.add(new EventImpl(false, cache, PUT_DATA, data, fqn, tx, true, null, false, null, NODE_MODIFIED));
+ if (!supressEventNotification)
+ {
+ expected.add(new EventImpl(false, cache, null, null, null, tx, true, null, false, null, TRANSACTION_REGISTERED));
+ expected.add(new EventImpl(true, cache, null, null, fqn, tx, true, null, false, null, NODE_CREATED));
+ expected.add(new EventImpl(false, cache, null, null, fqn, tx, true, null, false, null, NODE_CREATED));
+ expected.add(new EventImpl(true, cache, PUT_DATA, Collections.emptyMap(), fqn, tx, true, null, false, null, NODE_MODIFIED));
+ expected.add(new EventImpl(false, cache, PUT_DATA, data, fqn, tx, true, null, false, null, NODE_MODIFIED));
+ }
assertEquals(expected, eventLog.events);
+ if (supressEventNotification)
+ {
+ setSuppressEventNotification();
+ }
tm.rollback();
- expected.add(new EventImpl(false, cache, null, null, null, tx, true, null, false, null, TRANSACTION_COMPLETED));
- assertEquals(expected, eventLog.events);
+ if (!supressEventNotification)
+ {
+ expected.add(new EventImpl(false, cache, null, null, null, tx, true, null, false, null, TRANSACTION_COMPLETED));
+ }
+ assertEquals(expected, eventLog.events);
}
public void testTxOnlyModification() throws Exception
{
+ txOnlyModification(false);
+ eventLog.events.clear();
+ txOnlyModification(true);
+ }
+
+ protected void txOnlyModification(boolean supressEventNotification) throws Exception
+ {
assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
cache.put(fqn, "key", "value");
Map<Object, Object> oldData = new HashMap<Object, Object>();
@@ -348,26 +522,51 @@
assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
// modify existing node
+ if (supressEventNotification)
+ {
+ setSuppressEventNotification();
+ }
tm.begin();
Transaction tx = tm.getTransaction();
+ if (supressEventNotification)
+ {
+ setSuppressEventNotification();
+ }
cache.put(fqn, "key", "value2");
Map<Object, Object> newData = new HashMap<Object, Object>();
newData.put("key", "value2");
//expected
List<Event> expected = new ArrayList<Event>();
- expected.add(new EventImpl(false, cache, null, null, null, tx, true, null, false, null, TRANSACTION_REGISTERED));
- expected.add(new EventImpl(true, cache, PUT_DATA, oldData, fqn, tx, true, null, false, null, NODE_MODIFIED));
- expected.add(new EventImpl(false, cache, PUT_DATA, newData, fqn, tx, true, null, false, null, NODE_MODIFIED));
+ if (!supressEventNotification)
+ {
+ expected.add(new EventImpl(false, cache, null, null, null, tx, true, null, false, null, TRANSACTION_REGISTERED));
+ expected.add(new EventImpl(true, cache, PUT_DATA, oldData, fqn, tx, true, null, false, null, NODE_MODIFIED));
+ expected.add(new EventImpl(false, cache, PUT_DATA, newData, fqn, tx, true, null, false, null, NODE_MODIFIED));
+ }
assertEquals(expected, eventLog.events);
+ if (supressEventNotification)
+ {
+ setSuppressEventNotification();
+ }
tm.commit();
- expected.add(new EventImpl(false, cache, null, null, null, tx, true, null, true, null, TRANSACTION_COMPLETED));
+ if (!supressEventNotification)
+ {
+ expected.add(new EventImpl(false, cache, null, null, null, tx, true, null, true, null, TRANSACTION_COMPLETED));
+ }
assertEquals(expected, eventLog.events);
- }
+ }
public void testTxOnlyRemoval() throws Exception
{
+ txOnlyRemoval(false);
+ eventLog.events.clear();
+ txOnlyRemoval(true);
+ }
+
+ protected void txOnlyRemoval(boolean supressEventNotification) throws Exception
+ {
assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
cache.put(fqn, "key", "value");
Map<Object, Object> oldData = new HashMap<Object, Object>();
@@ -380,19 +579,36 @@
assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
// modify existing node
+ if (supressEventNotification)
+ {
+ setSuppressEventNotification();
+ }
tm.begin();
Transaction tx = tm.getTransaction();
+ if (supressEventNotification)
+ {
+ setSuppressEventNotification();
+ }
cache.removeNode(fqn);
//expected
List<Event> expected = new ArrayList<Event>();
+ if (!supressEventNotification)
+ {
+ expected.add(new EventImpl(false, cache, null, null, null, tx, true, null, false, null, TRANSACTION_REGISTERED));
+ expected.add(new EventImpl(true, cache, null, oldData, fqn, tx, true, null, false, null, NODE_REMOVED));
+ expected.add(new EventImpl(false, cache, null, null, fqn, tx, true, null, false, null, NODE_REMOVED));
+ }
- expected.add(new EventImpl(false, cache, null, null, null, tx, true, null, false, null, TRANSACTION_REGISTERED));
- expected.add(new EventImpl(true, cache, null, oldData, fqn, tx, true, null, false, null, NODE_REMOVED));
- expected.add(new EventImpl(false, cache, null, null, fqn, tx, true, null, false, null, NODE_REMOVED));
-
assertEquals(expected, eventLog.events);
+ if (supressEventNotification)
+ {
+ setSuppressEventNotification();
+ }
tm.commit();
- expected.add(new EventImpl(false, cache, null, null, null, tx, true, null, true, null, TRANSACTION_COMPLETED));
+ if (!supressEventNotification)
+ {
+ expected.add(new EventImpl(false, cache, null, null, null, tx, true, null, true, null, TRANSACTION_COMPLETED));
+ }
assertEquals(expected, eventLog.events);
// test that the node has in fact been removed.
assertNull("Should be null", cache.getRoot().getChild(fqn));
@@ -400,6 +616,13 @@
public void testTxRemoveData() throws Exception
{
+ txRemoveData(false);
+ eventLog.events.clear();
+ txRemoveData(true);
+ }
+
+ protected void txRemoveData(boolean supressEventNotification) throws Exception
+ {
assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
cache.put(fqn, "key", "value");
cache.put(fqn, "key2", "value2");
@@ -412,20 +635,38 @@
assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
// modify existing node
+ if (supressEventNotification)
+ {
+ setSuppressEventNotification();
+ }
tm.begin();
Transaction tx = tm.getTransaction();
+ if (supressEventNotification)
+ {
+ setSuppressEventNotification();
+ }
cache.remove(fqn, "key2");
Map<Object, Object> removedData = new HashMap<Object, Object>();
removedData.put("key2", "value2");
//expected
List<Event> expected = new ArrayList<Event>();
- expected.add(new EventImpl(false, cache, null, null, null, tx, true, null, false, null, TRANSACTION_REGISTERED));
- expected.add(new EventImpl(true, cache, REMOVE_DATA, oldData, fqn, tx, true, null, false, null, NODE_MODIFIED));
- expected.add(new EventImpl(false, cache, REMOVE_DATA, removedData, fqn, tx, true, null, false, null, NODE_MODIFIED));
+ if (!supressEventNotification)
+ {
+ expected.add(new EventImpl(false, cache, null, null, null, tx, true, null, false, null, TRANSACTION_REGISTERED));
+ expected.add(new EventImpl(true, cache, REMOVE_DATA, oldData, fqn, tx, true, null, false, null, NODE_MODIFIED));
+ expected.add(new EventImpl(false, cache, REMOVE_DATA, removedData, fqn, tx, true, null, false, null, NODE_MODIFIED));
+ }
+ if (supressEventNotification)
+ {
+ setSuppressEventNotification();
+ }
tm.commit();
- expected.add(new EventImpl(false, cache, null, null, null, tx, true, null, true, null, TRANSACTION_COMPLETED));
+ if (!supressEventNotification)
+ {
+ expected.add(new EventImpl(false, cache, null, null, null, tx, true, null, true, null, TRANSACTION_COMPLETED));
+ }
assertEquals(expected, eventLog.events);
assertEquals(expected, eventLog.events);
@@ -458,4 +699,57 @@
expected.add(new EventImpl(false, cache, null, null, null, tx, true, null, true, null, TRANSACTION_COMPLETED));
assertEquals(expected, eventLog.events);
}
+
+ protected void txMove(boolean supressEventNotification) throws Exception
+ {
+ assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
+ Fqn newParent = Fqn.fromString("/a");
+ cache.put(fqn, "key", "value");
+ cache.put(newParent, "key", "value");
+
+ Node<Object, Object> n1 = cache.getRoot().getChild(fqn);
+ Node<Object, Object> n2 = cache.getRoot().getChild(newParent);
+ eventLog.events.clear();// clear events
+ assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
+
+ if (supressEventNotification)
+ {
+ setSuppressEventNotification();
+ }
+ tm.begin();
+ Transaction tx = tm.getTransaction();
+ if (supressEventNotification)
+ {
+ setSuppressEventNotification();
+ }
+ cache.move(n1.getFqn(), n2.getFqn());
+ //expected
+ Fqn newFqn = Fqn.fromRelativeElements(newParent, fqn.getLastElement());
+ List<Event> expected = new ArrayList<Event>();
+ if (!supressEventNotification)
+ {
+ expected.add(new EventImpl(false, cache, null, null, null, tx, true, null, false, null, TRANSACTION_REGISTERED));
+ expected.add(new EventImpl(true, cache, null, null, fqn, tx, true, newFqn, false, null, NODE_MOVED));
+ expected.add(new EventImpl(false, cache, null, null, fqn, tx, true, newFqn, false, null, NODE_MOVED));
+ }
+
+ assertEquals(expected, eventLog.events);
+ if (supressEventNotification)
+ {
+ setSuppressEventNotification();
+ }
+ tm.commit();
+ if (!supressEventNotification)
+ {
+ expected.add(new EventImpl(false, cache, null, null, null, tx, true, null, true, null, TRANSACTION_COMPLETED));
+ }
+ assertEquals(expected, eventLog.events);
+ }
+
+ protected void setSuppressEventNotification()
+ {
+ Option option = new Option();
+ option.setSuppressEventNotification(true);
+ cache.getInvocationContext().setOptionOverrides(option);
+ }
}
15 years, 10 months
JBoss Cache SVN: r7634 - in core/branches/flat/src: main/java/org/horizon/eviction/algorithms and 1 other directories.
by jbosscache-commits@lists.jboss.org
Author: manik.surtani(a)jboss.com
Date: 2009-02-03 16:42:43 -0500 (Tue, 03 Feb 2009)
New Revision: 7634
Modified:
core/branches/flat/src/main/java/org/horizon/eviction/EvictionAlgorithmConfigBase.java
core/branches/flat/src/main/java/org/horizon/eviction/algorithms/BaseEvictionAlgorithm.java
core/branches/flat/src/test/java/org/horizon/eviction/algorithms/BaseAlgorithmTest.java
Log:
Eviction overhaul, phase 2
Modified: core/branches/flat/src/main/java/org/horizon/eviction/EvictionAlgorithmConfigBase.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/EvictionAlgorithmConfigBase.java 2009-02-03 21:28:24 UTC (rev 7633)
+++ core/branches/flat/src/main/java/org/horizon/eviction/EvictionAlgorithmConfigBase.java 2009-02-03 21:42:43 UTC (rev 7634)
@@ -44,12 +44,7 @@
protected int minEntries = -1;
@Dynamic
protected long minTimeToLive = -1;
- @Dynamic
- private long timeToLive = -1;
- @Dynamic
- private long maxAge = -1;
-
/**
* Can only be instantiated by a subclass.
*/
@@ -112,43 +107,6 @@
minTimeToLive = timeUnit.toMillis(time);
}
- public long getTimeToLive() {
- return timeToLive;
- }
-
- /**
- * -1 means time to live is unused, 0 means the time to live is 0 (considered for immediate eviction)
- *
- * @param timeToLive the time to live, since last modification, of any entry in the cache. Defaults to -1, meaning
- * that this is unused.
- */
- public void setTimeToLive(long timeToLive) {
- testImmutability("timeToLive");
- this.timeToLive = timeToLive;
- }
-
- public void setTimeToLive(long timeToLive, TimeUnit unit) {
- setTimeToLive(unit.toMillis(timeToLive));
- }
-
- public long getMaxAge() {
- return maxAge;
- }
-
- /**
- * -1 means max age is not considered, 0 means entries are considered for eviction immediately.
- *
- * @param maxAge the maximum age of entries in the cache, after which they will be removed.
- */
- public void setMaxAge(long maxAge) {
- testImmutability("maxAge");
- this.maxAge = maxAge;
- }
-
- public void setMaxAge(long maxAge, TimeUnit unit) {
- setMaxAge(unit.toMillis(maxAge));
- }
-
public void validate() throws ConfigurationException {
if (evictionAlgorithmClassName == null)
throw new ConfigurationException("Eviction algorithm class name cannot be null!");
@@ -161,11 +119,9 @@
EvictionAlgorithmConfigBase that = (EvictionAlgorithmConfigBase) o;
- if (maxAge != that.maxAge) return false;
if (maxEntries != that.maxEntries) return false;
if (minEntries != that.minEntries) return false;
if (minTimeToLive != that.minTimeToLive) return false;
- if (timeToLive != that.timeToLive) return false;
if (evictionAlgorithmClassName != null ? !evictionAlgorithmClassName.equals(that.evictionAlgorithmClassName) : that.evictionAlgorithmClassName != null)
return false;
@@ -178,8 +134,6 @@
result = 31 * result + maxEntries;
result = 31 * result + minEntries;
result = 31 * result + (int) (minTimeToLive ^ (minTimeToLive >>> 32));
- result = 31 * result + (int) (timeToLive ^ (timeToLive >>> 32));
- result = 31 * result + (int) (maxAge ^ (maxAge >>> 32));
return result;
}
@@ -190,8 +144,6 @@
", maxEntries=" + maxEntries +
", minEntries=" + minEntries +
", minTimeToLive=" + minTimeToLive +
- ", timeToLive=" + timeToLive +
- ", maxAge=" + maxAge +
'}';
}
@@ -199,8 +151,6 @@
maxEntries = -1;
minEntries = -1;
minTimeToLive = -1;
- timeToLive = -1;
- maxAge = -1;
}
public EvictionAlgorithmConfigBase clone() {
Modified: core/branches/flat/src/main/java/org/horizon/eviction/algorithms/BaseEvictionAlgorithm.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/algorithms/BaseEvictionAlgorithm.java 2009-02-03 21:28:24 UTC (rev 7633)
+++ core/branches/flat/src/main/java/org/horizon/eviction/algorithms/BaseEvictionAlgorithm.java 2009-02-03 21:42:43 UTC (rev 7634)
@@ -85,17 +85,6 @@
return true;
}
- // else, let's check if the entry has expired due to TTL or maxAge
- if (evictionAlgorithmConfig.getTimeToLive() > -1) {
- if (System.currentTimeMillis() > evictionAlgorithmConfig.getTimeToLive() + entry.getModifiedTimeStamp())
- return true;
- }
-
- if (evictionAlgorithmConfig.getMaxAge() > -1) {
- if (System.currentTimeMillis() > evictionAlgorithmConfig.getMaxAge() + entry.getCreationTimeStamp())
- return true;
- }
-
return false;
}
@@ -188,6 +177,9 @@
case VISIT_ENTRY_EVENT:
processVisitedEntries(event);
break;
+ case CLEAR_CACHE_EVENT:
+ processClearCacheEvent();
+ break;
case MARK_IN_USE_EVENT:
processMarkInUseNodes(event.getKey(), event.getInUseTimeout());
break;
@@ -198,7 +190,7 @@
throw new RuntimeException("Illegal Eviction Event type " + event.getEventType());
}
}
- if (trace) log.trace("processed {0} eviction events", count);
+ log.trace("processed {0} eviction events", count);
}
protected boolean evict(EntryEvictionData data) {
@@ -225,7 +217,7 @@
}
protected void processMarkInUseNodes(Object key, long inUseTimeout) throws EvictionException {
- if (trace) log.trace("Marking {0} as in use with a usage timeout of {1}", key, inUseTimeout);
+ log.trace("Marking {0} as in use with a usage timeout of {1}", key, inUseTimeout);
EntryEvictionData ne = evictionQueue.get(key);
if (ne != null) {
@@ -234,7 +226,7 @@
}
protected void processUnmarkInUseNodes(Object key) throws EvictionException {
- if (trace) log.trace("Unmarking node {0} as in use", key);
+ log.trace("Unmarking node {0} as in use", key);
EntryEvictionData ne = evictionQueue.get(key);
if (ne != null) {
@@ -244,39 +236,44 @@
protected void processAddedEntries(EvictionEvent evictedEventNode) throws EvictionException {
Object key = evictedEventNode.getKey();
- if (trace) log.trace("Adding entry {0} to eviction queue", key);
+ log.trace("Adding entry {0} to eviction queue", key);
EntryEvictionData data = evictionQueue.get(key);
if (data != null) {
data.setModifiedTimeStamp(evictedEventNode.getCreationTimestamp());
data.incrementNumberOfVisits();
- if (trace) log.trace("Queue already contains key. Processing it as visited.");
+ log.trace("Queue already contains key. Processing it as visited.");
processVisitedEntries(evictedEventNode);
} else {
data = new EntryEvictionData(1, evictedEventNode.getCreationTimestamp(), key);
data.setCreationTimeStamp(evictedEventNode.getCreationTimestamp());
evictionQueue.add(data);
- if (trace) log.trace("Added successfully to eviction queue");
+ log.trace("Added successfully to eviction queue");
}
}
protected void processRemovedEntries(EvictionEvent evictedEventNode) throws EvictionException {
Object key = evictedEventNode.getKey();
- if (trace) log.trace("Removing key {0} from eviction queue and attempting eviction", key);
+ log.trace("Removing key {0} from eviction queue and attempting eviction", key);
EntryEvictionData data = evictionQueue.get(key);
if (data != null) {
- evictionQueue.remove(data);
+ evictionQueue.remove(key);
} else {
- if (trace)
- log.trace("Can't find entry eviction data associated with key {0}. Could have been evicted earlier.",
- key);
+ log.trace("Can't find entry eviction data associated with key {0}. Could have been evicted earlier.", key);
return;
}
- if (trace) log.trace("Removed from eviction queue");
+ log.trace("Removed from eviction queue");
}
+ protected void processClearCacheEvent() throws EvictionException {
+ log.trace("Clearing eviction queue");
+ evictionQueue.clear();
+ log.trace("Cleared eviction queue");
+ }
+
+
/**
* Visit a node in cache.
* <p/>
Modified: core/branches/flat/src/test/java/org/horizon/eviction/algorithms/BaseAlgorithmTest.java
===================================================================
--- core/branches/flat/src/test/java/org/horizon/eviction/algorithms/BaseAlgorithmTest.java 2009-02-03 21:28:24 UTC (rev 7633)
+++ core/branches/flat/src/test/java/org/horizon/eviction/algorithms/BaseAlgorithmTest.java 2009-02-03 21:42:43 UTC (rev 7634)
@@ -8,12 +8,13 @@
import org.horizon.eviction.EvictionAlgorithm;
import org.horizon.eviction.EvictionAlgorithmConfigBase;
import org.horizon.eviction.EvictionEvent;
-import static org.horizon.eviction.EvictionEvent.Type.ADD_ENTRY_EVENT;
+import static org.horizon.eviction.EvictionEvent.Type.*;
import org.horizon.util.Util;
import org.testng.annotations.Test;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
@Test(groups = "unit")
public abstract class BaseAlgorithmTest {
@@ -176,85 +177,53 @@
EasyMock.verify(mockAction);
}
- public void testTimeToLive1() throws Exception {
+ public void testRemoveEvent() throws Exception {
EvictionAlgorithmConfigBase config = getNewEvictionAlgorithmConfig();
- config.setTimeToLive(-1);
+ config.setMinTimeToLive(24 * 60 * 60, TimeUnit.SECONDS); // huge - so evictions wont happen
BlockingQueue<EvictionEvent> eventQueue = new LinkedBlockingQueue<EvictionEvent>();
- eventQueue.put(new EvictionEvent("one", ADD_ENTRY_EVENT, 1));
- eventQueue.put(new EvictionEvent("two", ADD_ENTRY_EVENT, 1));
- eventQueue.put(new EvictionEvent("three", ADD_ENTRY_EVENT, 1));
- eventQueue.put(new EvictionEvent("four", ADD_ENTRY_EVENT, 1));
+ eventQueue.put(new EvictionEvent("one", ADD_ENTRY_EVENT));
+ eventQueue.put(new EvictionEvent("two", ADD_ENTRY_EVENT));
+ eventQueue.put(new EvictionEvent("three", ADD_ENTRY_EVENT));
+ eventQueue.put(new EvictionEvent("four", ADD_ENTRY_EVENT));
EvictionAlgorithm algo = createAndInit(config);
- EvictionAction mockAction = EasyMock.createMock(EvictionAction.class);
+ EvictionAction mockAction = EasyMock.createNiceMock(EvictionAction.class);
algo.setEvictionAction(mockAction);
- // Should not select any
- EasyMock.replay(mockAction);
- algo.process(eventQueue);
- EasyMock.verify(mockAction);
-
- }
-
- public void testTimeToLive2() throws Exception {
- EvictionAlgorithmConfigBase config = getNewEvictionAlgorithmConfig();
- config.setTimeToLive(0);
- BlockingQueue<EvictionEvent> eventQueue = new LinkedBlockingQueue<EvictionEvent>();
- eventQueue.put(new EvictionEvent("one", ADD_ENTRY_EVENT, 1));
- eventQueue.put(new EvictionEvent("two", ADD_ENTRY_EVENT, System.currentTimeMillis() * 2));
- eventQueue.put(new EvictionEvent("three", ADD_ENTRY_EVENT, 1));
- eventQueue.put(new EvictionEvent("four", ADD_ENTRY_EVENT, System.currentTimeMillis() * 2));
- EvictionAlgorithm algo = createAndInit(config);
- EvictionAction mockAction = EasyMock.createMock(EvictionAction.class);
- algo.setEvictionAction(mockAction);
-
- // only the first one is selected since the others are not considered since max entries has not been hit.
+ // should prune down to equal to maxEntries
EasyMock.expect(mockAction.evict(eq("one"))).andReturn(true).once();
EasyMock.replay(mockAction);
algo.process(eventQueue);
- EasyMock.verify(mockAction);
- }
- public void testMaxAge1() throws Exception {
- EvictionAlgorithmConfigBase config = getNewEvictionAlgorithmConfig();
- config.setMaxAge(-1);
- BlockingQueue<EvictionEvent> eventQueue = new LinkedBlockingQueue<EvictionEvent>();
- eventQueue.put(new EvictionEvent("one", ADD_ENTRY_EVENT, 1));
- eventQueue.put(new EvictionEvent("two", ADD_ENTRY_EVENT, 1));
- eventQueue.put(new EvictionEvent("three", ADD_ENTRY_EVENT, 1));
- eventQueue.put(new EvictionEvent("four", ADD_ENTRY_EVENT, 1));
- EvictionAlgorithm algo = createAndInit(config);
- EvictionAction mockAction = EasyMock.createMock(EvictionAction.class);
- algo.setEvictionAction(mockAction);
+ assert algo.getEvictionQueue().size() == 4;
- // Should not select any
- EasyMock.replay(mockAction);
+ eventQueue.put(new EvictionEvent("three", REMOVE_ENTRY_EVENT));
algo.process(eventQueue);
- EasyMock.verify(mockAction);
-
+ assert algo.getEvictionQueue().size() == 3;
+ assert algo.getEvictionQueue().get("three") == null;
}
- public void testMaxAge2() throws Exception {
+ public void testClearEvent() throws Exception {
EvictionAlgorithmConfigBase config = getNewEvictionAlgorithmConfig();
- config.setMaxAge(10);
+ config.setMinTimeToLive(24 * 60 * 60, TimeUnit.SECONDS); // huge - so evictions wont happen
BlockingQueue<EvictionEvent> eventQueue = new LinkedBlockingQueue<EvictionEvent>();
eventQueue.put(new EvictionEvent("one", ADD_ENTRY_EVENT));
eventQueue.put(new EvictionEvent("two", ADD_ENTRY_EVENT));
eventQueue.put(new EvictionEvent("three", ADD_ENTRY_EVENT));
eventQueue.put(new EvictionEvent("four", ADD_ENTRY_EVENT));
- Thread.sleep(10);
EvictionAlgorithm algo = createAndInit(config);
- EvictionAction mockAction = EasyMock.createMock(EvictionAction.class);
+ EvictionAction mockAction = EasyMock.createNiceMock(EvictionAction.class);
algo.setEvictionAction(mockAction);
- // all of them should have crossed max age by now
+ // should prune down to equal to maxEntries
EasyMock.expect(mockAction.evict(eq("one"))).andReturn(true).once();
- EasyMock.expect(mockAction.evict(eq("two"))).andReturn(true).once();
- EasyMock.expect(mockAction.evict(eq("three"))).andReturn(true).once();
- EasyMock.expect(mockAction.evict(eq("four"))).andReturn(true).once();
EasyMock.replay(mockAction);
algo.process(eventQueue);
- EasyMock.verify(mockAction);
- }
+ assert algo.getEvictionQueue().size() == 4;
+ eventQueue.put(new EvictionEvent("three", CLEAR_CACHE_EVENT));
+ algo.process(eventQueue);
+ assert algo.getEvictionQueue().size() == 0;
+ assert algo.getEvictionQueue().get("three") == null;
+ }
}
15 years, 10 months
JBoss Cache SVN: r7633 - in core/branches/flat/src: main/java/org/horizon/eviction/algorithms and 10 other directories.
by jbosscache-commits@lists.jboss.org
Author: manik.surtani(a)jboss.com
Date: 2009-02-03 16:28:24 -0500 (Tue, 03 Feb 2009)
New Revision: 7633
Added:
core/branches/flat/src/main/java/org/horizon/eviction/algorithms/BaseEvictionQueue.java
core/branches/flat/src/test/java/org/horizon/eviction/algorithms/BaseAlgorithmTest.java
core/branches/flat/src/test/java/org/horizon/eviction/algorithms/BaseQueueTest.java
Removed:
core/branches/flat/src/main/java/org/horizon/eviction/algorithms/BaseSortedEvictionAlgorithm.java
core/branches/flat/src/main/java/org/horizon/eviction/algorithms/SortedEvictionQueue.java
Modified:
core/branches/flat/src/main/java/org/horizon/eviction/EntryEvictionData.java
core/branches/flat/src/main/java/org/horizon/eviction/EvictionAlgorithmConfigBase.java
core/branches/flat/src/main/java/org/horizon/eviction/EvictionEvent.java
core/branches/flat/src/main/java/org/horizon/eviction/EvictionQueue.java
core/branches/flat/src/main/java/org/horizon/eviction/algorithms/BaseEvictionAlgorithm.java
core/branches/flat/src/main/java/org/horizon/eviction/algorithms/fifo/FIFOAlgorithm.java
core/branches/flat/src/main/java/org/horizon/eviction/algorithms/fifo/FIFOAlgorithmConfig.java
core/branches/flat/src/main/java/org/horizon/eviction/algorithms/fifo/FIFOQueue.java
core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lfu/LFUAlgorithm.java
core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lfu/LFUAlgorithmConfig.java
core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lfu/LFUQueue.java
core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lru/LRUAlgorithm.java
core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lru/LRUAlgorithmConfig.java
core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lru/LRUQueue.java
core/branches/flat/src/main/java/org/horizon/eviction/algorithms/mru/MRUAlgorithm.java
core/branches/flat/src/main/java/org/horizon/eviction/algorithms/mru/MRUAlgorithmConfig.java
core/branches/flat/src/main/java/org/horizon/eviction/algorithms/mru/MRUQueue.java
core/branches/flat/src/main/java/org/horizon/eviction/algorithms/nullalgo/NullEvictionQueue.java
core/branches/flat/src/test/java/org/horizon/eviction/algorithms/fifo/FifoAlgorithmTest.java
core/branches/flat/src/test/java/org/horizon/eviction/algorithms/fifo/FifoQueueTest.java
core/branches/flat/src/test/java/org/horizon/eviction/algorithms/lfu/LfuAlgorithmTest.java
core/branches/flat/src/test/java/org/horizon/eviction/algorithms/lfu/LfuQueueTest.java
core/branches/flat/src/test/java/org/horizon/eviction/algorithms/lru/LruAlgorithmTest.java
core/branches/flat/src/test/java/org/horizon/eviction/algorithms/lru/LruQueueTest.java
core/branches/flat/src/test/java/org/horizon/eviction/algorithms/mru/MruAlgorithmTest.java
core/branches/flat/src/test/java/org/horizon/eviction/algorithms/mru/MruQueueTest.java
Log:
Eviction overhaul, phase 2
Modified: core/branches/flat/src/main/java/org/horizon/eviction/EntryEvictionData.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/EntryEvictionData.java 2009-02-03 13:51:43 UTC (rev 7632)
+++ core/branches/flat/src/main/java/org/horizon/eviction/EntryEvictionData.java 2009-02-03 21:28:24 UTC (rev 7633)
@@ -110,10 +110,6 @@
this.numberOfVisits = numberOfVisits;
}
- public void incerementNumberOfNodeVisits() {
- this.numberOfVisits++;
- }
-
public Object getKey() {
return key;
}
@@ -164,4 +160,8 @@
output.append(" CurrentlyInUse: ").append(this.isCurrentlyInUse());
return output.toString();
}
+
+ public void incrementNumberOfVisits() {
+ numberOfVisits++;
+ }
}
Modified: core/branches/flat/src/main/java/org/horizon/eviction/EvictionAlgorithmConfigBase.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/EvictionAlgorithmConfigBase.java 2009-02-03 13:51:43 UTC (rev 7632)
+++ core/branches/flat/src/main/java/org/horizon/eviction/EvictionAlgorithmConfigBase.java 2009-02-03 21:28:24 UTC (rev 7633)
@@ -39,10 +39,17 @@
protected String evictionAlgorithmClassName;
@Dynamic
- protected int maxEntries = 0;
+ protected int maxEntries = -1;
@Dynamic
- protected long minTimeToLive;
+ protected int minEntries = -1;
+ @Dynamic
+ protected long minTimeToLive = -1;
+ @Dynamic
+ private long timeToLive = -1;
+ @Dynamic
+ private long maxAge = -1;
+
/**
* Can only be instantiated by a subclass.
*/
@@ -57,12 +64,34 @@
return maxEntries;
}
+ /**
+ * @param maxEntries max entries to hold in the cache. 0 denotes immediate expiry and -1 denotes unlimited entries.
+ * -1 is the default
+ */
public void setMaxEntries(int maxEntries) {
testImmutability("maxEntries");
this.maxEntries = maxEntries;
}
+ public int getMinEntries() {
+ return minEntries;
+ }
+
/**
+ * This specifies the minimum entries to prune down to when maxExtries has been hit. -1 is the default value, which
+ * means this feature is effectively unset, and eviction algorithms would be expected to evict until the cache
+ * contains no more than maxEntries. Any other value means that if a pruning process starts, it will not stop until
+ * minEntries has been reached. So, for example, minEntries of 0 would mean that the cache is emptied the moment
+ * maxEntries is exceeded.
+ *
+ * @param minEntries minEntries value
+ */
+ public void setMinEntries(int minEntries) {
+ testImmutability("minEntries");
+ this.minEntries = minEntries;
+ }
+
+ /**
* @return The minimum time to live, in milliseconds.
*/
public long getMinTimeToLive() {
@@ -70,7 +99,8 @@
}
/**
- * @param minTimeToLive time to live, in milliseconds
+ * @param minTimeToLive time to live, in milliseconds. This defaults to -1, meaning that it is excluded from
+ * calculations.
*/
public void setMinTimeToLive(long minTimeToLive) {
testImmutability("minTimeToLive");
@@ -82,42 +112,100 @@
minTimeToLive = timeUnit.toMillis(time);
}
+ public long getTimeToLive() {
+ return timeToLive;
+ }
+
+ /**
+ * -1 means time to live is unused, 0 means the time to live is 0 (considered for immediate eviction)
+ *
+ * @param timeToLive the time to live, since last modification, of any entry in the cache. Defaults to -1, meaning
+ * that this is unused.
+ */
+ public void setTimeToLive(long timeToLive) {
+ testImmutability("timeToLive");
+ this.timeToLive = timeToLive;
+ }
+
+ public void setTimeToLive(long timeToLive, TimeUnit unit) {
+ setTimeToLive(unit.toMillis(timeToLive));
+ }
+
+ public long getMaxAge() {
+ return maxAge;
+ }
+
+ /**
+ * -1 means max age is not considered, 0 means entries are considered for eviction immediately.
+ *
+ * @param maxAge the maximum age of entries in the cache, after which they will be removed.
+ */
+ public void setMaxAge(long maxAge) {
+ testImmutability("maxAge");
+ this.maxAge = maxAge;
+ }
+
+ public void setMaxAge(long maxAge, TimeUnit unit) {
+ setMaxAge(unit.toMillis(maxAge));
+ }
+
public void validate() throws ConfigurationException {
if (evictionAlgorithmClassName == null)
throw new ConfigurationException("Eviction algorithm class name cannot be null!");
}
+ @Override
public boolean equals(Object o) {
if (this == o) return true;
- if (!(o instanceof EvictionAlgorithmConfigBase)) return false;
+ if (o == null || getClass() != o.getClass()) return false;
EvictionAlgorithmConfigBase that = (EvictionAlgorithmConfigBase) o;
+ if (maxAge != that.maxAge) return false;
if (maxEntries != that.maxEntries) return false;
+ if (minEntries != that.minEntries) return false;
if (minTimeToLive != that.minTimeToLive) return false;
+ if (timeToLive != that.timeToLive) return false;
if (evictionAlgorithmClassName != null ? !evictionAlgorithmClassName.equals(that.evictionAlgorithmClassName) : that.evictionAlgorithmClassName != null)
return false;
return true;
}
+ @Override
public int hashCode() {
- int result;
- result = (evictionAlgorithmClassName != null ? evictionAlgorithmClassName.hashCode() : 0);
+ int result = evictionAlgorithmClassName != null ? evictionAlgorithmClassName.hashCode() : 0;
result = 31 * result + maxEntries;
- result = (int) (31 * result + minTimeToLive);
+ result = 31 * result + minEntries;
result = 31 * result + (int) (minTimeToLive ^ (minTimeToLive >>> 32));
+ result = 31 * result + (int) (timeToLive ^ (timeToLive >>> 32));
+ result = 31 * result + (int) (maxAge ^ (maxAge >>> 32));
return result;
}
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + "{" +
+ "evictionAlgorithmClassName='" + evictionAlgorithmClassName + '\'' +
+ ", maxEntries=" + maxEntries +
+ ", minEntries=" + minEntries +
+ ", minTimeToLive=" + minTimeToLive +
+ ", timeToLive=" + timeToLive +
+ ", maxAge=" + maxAge +
+ '}';
+ }
+
public void reset() {
- maxEntries = 0;
- minTimeToLive = 0;
+ maxEntries = -1;
+ minEntries = -1;
+ minTimeToLive = -1;
+ timeToLive = -1;
+ maxAge = -1;
}
- public EvictionAlgorithmConfig clone() {
+ public EvictionAlgorithmConfigBase clone() {
try {
- return (EvictionAlgorithmConfig) super.clone();
+ return (EvictionAlgorithmConfigBase) super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException("Should never happen", e);
}
Modified: core/branches/flat/src/main/java/org/horizon/eviction/EvictionEvent.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/EvictionEvent.java 2009-02-03 13:51:43 UTC (rev 7632)
+++ core/branches/flat/src/main/java/org/horizon/eviction/EvictionEvent.java 2009-02-03 21:28:24 UTC (rev 7633)
@@ -52,10 +52,20 @@
this.creationTimestamp = System.currentTimeMillis();
}
+ public EvictionEvent(Object key, Type type, long creationTimestamp) {
+ this.key = key;
+ this.type = type;
+ this.creationTimestamp = creationTimestamp;
+ }
+
public long getCreationTimestamp() {
return creationTimestamp;
}
+ public void setCreationTimestamp(long creationTimestamp) {
+ this.creationTimestamp = creationTimestamp;
+ }
+
public long getInUseTimeout() {
return inUseTimeout;
}
Modified: core/branches/flat/src/main/java/org/horizon/eviction/EvictionQueue.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/EvictionQueue.java 2009-02-03 13:51:43 UTC (rev 7632)
+++ core/branches/flat/src/main/java/org/horizon/eviction/EvictionQueue.java 2009-02-03 21:28:24 UTC (rev 7633)
@@ -31,17 +31,14 @@
* @since 1.0
*/
public interface EvictionQueue extends Iterable<EntryEvictionData> {
-// /**
-// * Get the first entry in the queue.
-// * <p/>
-// * If there are no entries in queue, this method will return null.
-// * <p/>
-// * The first node returned is expected to be the first node to evict.
-// *
-// * @return first NodeEntry in queue.
-// */
-// EntryEvictionData getFirstNodeEntry();
+ /**
+ * Tests whether queue is empty
+ *
+ * @return true if the queue is empty; false otherwise
+ */
+ boolean isEmpty();
+
//
/**
* Retrieve eviction entry data representing a specific key
@@ -57,17 +54,17 @@
/**
* Check if eviction entry data exists in the queue
*
- * @param entryEvictionData to check for
+ * @param key to check for
* @return true if the entry exists, false otherwise
*/
- boolean contains(EntryEvictionData entryEvictionData);
+ boolean contains(Object key);
/**
* Remove eviction entry data from the queue. A no-op if the specified object does not exist.
*
- * @param entryEvictionData to remove
+ * @param key to remove
*/
- void remove(EntryEvictionData entryEvictionData);
+ void remove(Object key);
/**
* Add entry eviction data to the queue
Modified: core/branches/flat/src/main/java/org/horizon/eviction/algorithms/BaseEvictionAlgorithm.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/algorithms/BaseEvictionAlgorithm.java 2009-02-03 13:51:43 UTC (rev 7632)
+++ core/branches/flat/src/main/java/org/horizon/eviction/algorithms/BaseEvictionAlgorithm.java 2009-02-03 21:28:24 UTC (rev 7633)
@@ -26,6 +26,7 @@
import org.horizon.eviction.EntryEvictionData;
import org.horizon.eviction.EvictionAction;
import org.horizon.eviction.EvictionAlgorithm;
+import org.horizon.eviction.EvictionAlgorithmConfigBase;
import org.horizon.eviction.EvictionEvent;
import org.horizon.eviction.EvictionEvent.Type;
import org.horizon.eviction.EvictionException;
@@ -33,6 +34,7 @@
import org.horizon.logging.Log;
import org.horizon.logging.LogFactory;
+import java.util.Iterator;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
@@ -52,7 +54,7 @@
private static final boolean trace = log.isTraceEnabled();
protected EvictionAction evictionAction;
- protected EvictionAlgorithmConfig evictionAlgorithmConfig;
+ protected EvictionAlgorithmConfigBase evictionAlgorithmConfig;
protected BlockingQueue recycleQueue;
protected EvictionQueue evictionQueue;
protected Cache cache;
@@ -66,13 +68,37 @@
protected abstract EvictionQueue setupEvictionQueue() throws EvictionException;
/**
- * This method will check whether the given node should be evicted or not.
+ * This method will check whether the given entry should be evicted or not.
*
- * @param ne NodeEntry to test eviction for.
- * @return True if the given node should be evicted. False if the given node should not be evicted.
+ * @param entry entry to consider
+ * @return true if the entry is to be evicted, false otherwise
*/
- protected abstract boolean shouldEvictNode(EntryEvictionData ne);
+ protected boolean shouldEvictEntry(EntryEvictionData entry, int originalQueueSize) {
+ // first test max and min entries
+ if (evictionAlgorithmConfig.getMaxEntries() > -1) {
+ int currentSize = evictionQueue.size();
+ // entry count eviction is enabled!
+ if (evictionAlgorithmConfig.getMaxEntries() < currentSize) return true;
+ if (evictionAlgorithmConfig.getMaxEntries() < originalQueueSize &&
+ evictionAlgorithmConfig.getMinEntries() > -1 &&
+ evictionAlgorithmConfig.getMinEntries() < currentSize)
+ return true;
+ }
+ // else, let's check if the entry has expired due to TTL or maxAge
+ if (evictionAlgorithmConfig.getTimeToLive() > -1) {
+ if (System.currentTimeMillis() > evictionAlgorithmConfig.getTimeToLive() + entry.getModifiedTimeStamp())
+ return true;
+ }
+
+ if (evictionAlgorithmConfig.getMaxAge() > -1) {
+ if (System.currentTimeMillis() > evictionAlgorithmConfig.getMaxAge() + entry.getCreationTimeStamp())
+ return true;
+ }
+
+ return false;
+ }
+
protected BaseEvictionAlgorithm() {
recycleQueue = new LinkedBlockingQueue(500000);
}
@@ -89,7 +115,7 @@
public void assignToCache(Cache<?, ?> cache, EvictionAlgorithmConfig evictionAlgorithmConfig) {
this.cache = cache;
- this.evictionAlgorithmConfig = evictionAlgorithmConfig;
+ this.evictionAlgorithmConfig = (EvictionAlgorithmConfigBase) evictionAlgorithmConfig;
}
public boolean canIgnoreEvent(Type eventType) {
@@ -108,9 +134,9 @@
public void process(BlockingQueue<EvictionEvent> eventQueue) throws EvictionException {
if (trace) log.trace("processing eviction event queue");
initialize();
- this.processQueues(eventQueue);
- this.emptyRecycleQueue();
- this.prune();
+ processQueues(eventQueue);
+ emptyRecycleQueue();
+ prune();
}
public void resetEvictionQueue() {
@@ -154,19 +180,19 @@
count++;
switch (event.getEventType()) {
case ADD_ENTRY_EVENT:
- this.processAddedNodes(event);
+ processAddedEntries(event);
break;
case REMOVE_ENTRY_EVENT:
- this.processRemovedNodes(event);
+ processRemovedEntries(event);
break;
case VISIT_ENTRY_EVENT:
- this.processVisitedNodes(event);
+ processVisitedEntries(event);
break;
case MARK_IN_USE_EVENT:
- this.processMarkInUseNodes(event.getKey(), event.getInUseTimeout());
+ processMarkInUseNodes(event.getKey(), event.getInUseTimeout());
break;
case UNMARK_IN_USE_EVENT:
- this.processUnmarkInUseNodes(event.getKey());
+ processUnmarkInUseNodes(event.getKey());
break;
default:
throw new RuntimeException("Illegal Eviction Event type " + event.getEventType());
@@ -175,9 +201,9 @@
if (trace) log.trace("processed {0} eviction events", count);
}
- protected void evict(EntryEvictionData data) {
+ protected boolean evict(EntryEvictionData data) {
if (data != null) {
- evictionQueue.remove(data);
+ log.trace("Attempting to evict {0}", data);
if (!evictionAction.evict(data.getKey())) {
try {
boolean result = recycleQueue.offer(data.getKey(), 5, TimeUnit.SECONDS);
@@ -192,6 +218,9 @@
log.debug("InterruptedException", e);
}
}
+ return true;
+ } else {
+ return false;
}
}
@@ -213,23 +242,24 @@
}
}
- protected void processAddedNodes(EvictionEvent evictedEventNode) throws EvictionException {
+ protected void processAddedEntries(EvictionEvent evictedEventNode) throws EvictionException {
Object key = evictedEventNode.getKey();
if (trace) log.trace("Adding entry {0} to eviction queue", key);
EntryEvictionData data = evictionQueue.get(key);
if (data != null) {
data.setModifiedTimeStamp(evictedEventNode.getCreationTimestamp());
- data.incerementNumberOfNodeVisits();
+ data.incrementNumberOfVisits();
if (trace) log.trace("Queue already contains key. Processing it as visited.");
- processVisitedNodes(evictedEventNode);
- return;
+ processVisitedEntries(evictedEventNode);
+ } else {
+ data = new EntryEvictionData(1, evictedEventNode.getCreationTimestamp(), key);
+ data.setCreationTimeStamp(evictedEventNode.getCreationTimestamp());
+ evictionQueue.add(data);
+ if (trace) log.trace("Added successfully to eviction queue");
}
- data = new EntryEvictionData(1, evictedEventNode.getCreationTimestamp(), key);
- evictionQueue.add(data);
- if (trace) log.trace("Added successfully to eviction queue");
}
- protected void processRemovedNodes(EvictionEvent evictedEventNode) throws EvictionException {
+ protected void processRemovedEntries(EvictionEvent evictedEventNode) throws EvictionException {
Object key = evictedEventNode.getKey();
if (trace) log.trace("Removing key {0} from eviction queue and attempting eviction", key);
@@ -258,19 +288,19 @@
*
* @throws EvictionException
*/
- protected void processVisitedNodes(EvictionEvent evictedEventNode) throws EvictionException {
- Object key = evictedEventNode.getKey();
+ protected void processVisitedEntries(EvictionEvent evictionEvent) throws EvictionException {
+ Object key = evictionEvent.getKey();
EntryEvictionData data = evictionQueue.get(key);
if (data == null) {
if (trace) log.trace("Visiting entry {0} that has not added to eviction queues before.", key);
- this.processAddedNodes(evictedEventNode);
+ this.processAddedEntries(evictionEvent);
return;
}
// note this method will visit and modify the node statistics by reference!
// if a collection is only guaranteed sort order by adding to the collection,
// this implementation will not guarantee sort order.
- data.incerementNumberOfNodeVisits();
- data.setModifiedTimeStamp(evictedEventNode.getCreationTimestamp());
+ data.incrementNumberOfVisits();
+ data.setModifiedTimeStamp(evictionEvent.getCreationTimestamp());
}
/**
@@ -312,9 +342,11 @@
}
protected void prune() throws EvictionException {
- for (EntryEvictionData data : evictionQueue) {
- if (data != null && shouldEvictNode(data)) {
- evict(data);
+ int originalQueueSize = evictionQueue.size();
+ for (Iterator<EntryEvictionData> it = evictionQueue.iterator(); it.hasNext();) {
+ EntryEvictionData data = it.next();
+ if (data != null && shouldEvictEntry(data, originalQueueSize)) {
+ if (shouldNotOverrideEviction(data) && evict(data)) it.remove();
} else {
break; // assume the rest won't need to be evicted either
}
@@ -330,13 +362,13 @@
}
/**
- * A helper for implementations that support the minimul time to live property
+ * A helper for implementations that support the minimum time to live property
*
- * @param minTTL minimum time to live, in millis, for all entries in the cache
- * @param data eviction data on the entry to consider
+ * @param data eviction data on the entry to consider
* @return true if the entry is younger than the minimum time to live, false otherwise.
*/
- protected boolean isYoungerThanMinimumTimeToLive(long minTTL, EntryEvictionData data) {
- return minTTL >= 1 && (data.getModifiedTimeStamp() + minTTL > System.currentTimeMillis());
+ protected boolean shouldNotOverrideEviction(EntryEvictionData data) {
+ long minTTL = evictionAlgorithmConfig.getMinTimeToLive();
+ return minTTL < 1 || (data.getModifiedTimeStamp() + minTTL < System.currentTimeMillis());
}
}
Added: core/branches/flat/src/main/java/org/horizon/eviction/algorithms/BaseEvictionQueue.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/algorithms/BaseEvictionQueue.java (rev 0)
+++ core/branches/flat/src/main/java/org/horizon/eviction/algorithms/BaseEvictionQueue.java 2009-02-03 21:28:24 UTC (rev 7633)
@@ -0,0 +1,9 @@
+package org.horizon.eviction.algorithms;
+
+import org.horizon.eviction.EvictionQueue;
+
+public abstract class BaseEvictionQueue implements EvictionQueue {
+ public boolean isEmpty() {
+ return size() == 0;
+ }
+}
Deleted: core/branches/flat/src/main/java/org/horizon/eviction/algorithms/BaseSortedEvictionAlgorithm.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/algorithms/BaseSortedEvictionAlgorithm.java 2009-02-03 13:51:43 UTC (rev 7632)
+++ core/branches/flat/src/main/java/org/horizon/eviction/algorithms/BaseSortedEvictionAlgorithm.java 2009-02-03 21:28:24 UTC (rev 7633)
@@ -1,92 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2000 - 2008, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.horizon.eviction.algorithms;
-
-import org.horizon.eviction.EvictionEvent;
-import org.horizon.eviction.EvictionException;
-import org.horizon.logging.Log;
-import org.horizon.logging.LogFactory;
-
-import java.util.concurrent.BlockingQueue;
-
-
-/**
- * An abstract SortedEvictionAlgorithm.
- * <p/>
- * This class supports early termination of the eviction queue processing. Because the eviction queue is sorted by first
- * to evict to last to evict, when iterating the eviction queue, the first time a node is encountered that does not
- * require eviction will terminate the loop early. This way we don't incur the full breadth of the O(n) = n operation
- * everytime we need to check for eviction (defined by eviction poll time interval).
- *
- * @author Daniel Huang - dhuang(a)jboss.org - 10/2005
- * @since 1.0
- */
-public abstract class BaseSortedEvictionAlgorithm extends BaseEvictionAlgorithm {
- private static final Log log = LogFactory.getLog(BaseSortedEvictionAlgorithm.class);
- private static final boolean trace = log.isTraceEnabled();
-
- @Override
- protected void processQueues(BlockingQueue<EvictionEvent> queue) throws EvictionException {
- boolean evictionQueueRequiresSort = false;
-
- EvictionEvent event;
- int count = 0;
- while ((event = getNextInQueue(queue)) != null) {
- count++;
- switch (event.getEventType()) {
- case ADD_ENTRY_EVENT:
- this.processAddedNodes(event);
- evictionQueueRequiresSort = true;
- break;
- case REMOVE_ENTRY_EVENT:
- this.processRemovedNodes(event);
- break;
- case VISIT_ENTRY_EVENT:
- this.processVisitedNodes(event);
- evictionQueueRequiresSort = true;
- break;
- default:
- throw new RuntimeException("Illegal Eviction Event type " + event.getEventType());
- }
- }
-
- if (evictionQueueRequiresSort) {
- if (trace) log.trace("Eviction queue requires re-sort. Re-sorting.");
- resortEvictionQueue();
- }
-
- if (trace) log.trace("processed {0} eviction events", count);
- }
-
- /**
- * This method is called to resort the queue after add or visit events have occurred.
- */
- protected void resortEvictionQueue() {
- long begin = System.currentTimeMillis();
- ((SortedEvictionQueue) evictionQueue).reSortEvictionQueue();
-
- if (trace) {
- log.trace("Took {0} millis to re-sort queue with {1} elements",
- System.currentTimeMillis() - begin, getEvictionQueue().size());
- }
- }
-}
Deleted: core/branches/flat/src/main/java/org/horizon/eviction/algorithms/SortedEvictionQueue.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/algorithms/SortedEvictionQueue.java 2009-02-03 13:51:43 UTC (rev 7632)
+++ core/branches/flat/src/main/java/org/horizon/eviction/algorithms/SortedEvictionQueue.java 2009-02-03 21:28:24 UTC (rev 7633)
@@ -1,37 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2000 - 2008, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.horizon.eviction.algorithms;
-
-import org.horizon.eviction.EvictionQueue;
-
-/**
- * Sorted Eviction Queue implementation.
- *
- * @author Daniel Huang (dhuang(a)jboss.org)
- * @since 1.0
- */
-public interface SortedEvictionQueue extends EvictionQueue {
- /**
- * Provide contract to re-sort a sorted queue.
- */
- void reSortEvictionQueue();
-}
Modified: core/branches/flat/src/main/java/org/horizon/eviction/algorithms/fifo/FIFOAlgorithm.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/algorithms/fifo/FIFOAlgorithm.java 2009-02-03 13:51:43 UTC (rev 7632)
+++ core/branches/flat/src/main/java/org/horizon/eviction/algorithms/fifo/FIFOAlgorithm.java 2009-02-03 21:28:24 UTC (rev 7633)
@@ -21,8 +21,8 @@
*/
package org.horizon.eviction.algorithms.fifo;
+import net.jcip.annotations.NotThreadSafe;
import org.horizon.config.EvictionAlgorithmConfig;
-import org.horizon.eviction.EntryEvictionData;
import org.horizon.eviction.EvictionException;
import org.horizon.eviction.EvictionQueue;
import org.horizon.eviction.algorithms.BaseEvictionAlgorithm;
@@ -30,45 +30,22 @@
import org.horizon.logging.LogFactory;
/**
- * First-in-first-out algorithm used to evict nodes.
+ * First-in-first-out algorithm used to evict cache entries
*
- * @author Daniel Huang - dhuang(a)jboss.org
- * @author Morten Kvistgaard
+ * @author Manik Surtani
* @since 1.0
*/
+@NotThreadSafe
public class FIFOAlgorithm extends BaseEvictionAlgorithm {
private static final Log log = LogFactory.getLog(FIFOAlgorithm.class);
- private static final boolean trace = log.isTraceEnabled();
- private FIFOAlgorithmConfig fifoAlgorithmConfig;
@Override
protected EvictionQueue setupEvictionQueue() throws EvictionException {
return new FIFOQueue();
}
- /**
- * For FIFO, a node should be evicted if the queue size is >= to the configured maxNodes size.
- */
- @Override
- protected boolean shouldEvictNode(EntryEvictionData data) {
- // check the minimum time to live and see if we should not evict the node. This check will
- // ensure that, if configured, nodes are kept alive for at least a minimum period of time.
- if (isYoungerThanMinimumTimeToLive(fifoAlgorithmConfig.getMinTimeToLive(), data)) return false;
-
- if (trace) log.trace("Deciding whether node in queue {0} requires eviction.", data.getKey());
-
- int size = this.getEvictionQueue().size();
- return fifoAlgorithmConfig.getMaxEntries() != 0 && size > fifoAlgorithmConfig.getMaxEntries();
- }
-
public Class<? extends EvictionAlgorithmConfig> getConfigurationClass() {
return FIFOAlgorithmConfig.class;
}
-
- @Override
- public void initialize() {
- super.initialize();
- fifoAlgorithmConfig = (FIFOAlgorithmConfig) evictionAlgorithmConfig;
- }
}
Modified: core/branches/flat/src/main/java/org/horizon/eviction/algorithms/fifo/FIFOAlgorithmConfig.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/algorithms/fifo/FIFOAlgorithmConfig.java 2009-02-03 13:51:43 UTC (rev 7632)
+++ core/branches/flat/src/main/java/org/horizon/eviction/algorithms/fifo/FIFOAlgorithmConfig.java 2009-02-03 21:28:24 UTC (rev 7633)
@@ -21,13 +21,10 @@
*/
package org.horizon.eviction.algorithms.fifo;
-import org.horizon.config.ConfigurationException;
import org.horizon.eviction.EvictionAlgorithmConfigBase;
/**
* Configuration for {@link FIFOAlgorithm}.
- * <p/>
- * Requires a "maxNodes" attribute otherwise a ConfigurationException is thrown.
*
* @author Manik Surtani
* @since 1.0
@@ -40,48 +37,9 @@
public FIFOAlgorithmConfig() {
evictionAlgorithmClassName = FIFOAlgorithm.class.getName();
- // We require that maxEntries is set
- setMaxEntries(-1);
}
- public FIFOAlgorithmConfig(int maxNodes) {
- evictionAlgorithmClassName = FIFOAlgorithm.class.getName();
- // We require that maxEntries is set
- setMaxEntries(maxNodes);
- }
-
- /**
- * Requires a positive maxNodes value or ConfigurationException is thrown.
- */
@Override
- public void validate() throws ConfigurationException {
- super.validate();
- if (getMaxEntries() < 0) {
- throw new ConfigurationException("maxEntries must be must be " +
- "configured to a value greater than or equal to 0");
- }
- }
-
- @Override
- public String toString() {
- StringBuilder ret = new StringBuilder();
- ret.append("FIFOAlgorithmConfig: maxEntries = ").append(getMaxEntries());
- return ret.toString();
- }
-
- @Override
- public boolean equals(Object obj) {
- return (obj instanceof FIFOAlgorithmConfig && super.equals(obj));
- }
-
- @Override
- public void reset() {
- super.reset();
- setMaxEntries(-1);
- evictionAlgorithmClassName = FIFOAlgorithm.class.getName();
- }
-
- @Override
public FIFOAlgorithmConfig clone() {
return (FIFOAlgorithmConfig) super.clone();
}
Modified: core/branches/flat/src/main/java/org/horizon/eviction/algorithms/fifo/FIFOQueue.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/algorithms/fifo/FIFOQueue.java 2009-02-03 13:51:43 UTC (rev 7632)
+++ core/branches/flat/src/main/java/org/horizon/eviction/algorithms/fifo/FIFOQueue.java 2009-02-03 21:28:24 UTC (rev 7633)
@@ -22,7 +22,7 @@
package org.horizon.eviction.algorithms.fifo;
import org.horizon.eviction.EntryEvictionData;
-import org.horizon.eviction.EvictionQueue;
+import org.horizon.eviction.algorithms.BaseEvictionQueue;
import java.util.Iterator;
import java.util.LinkedHashMap;
@@ -34,7 +34,7 @@
* @author Daniel Huang (dhuang(a)jboss.org)
* @since 1.0
*/
-public class FIFOQueue implements EvictionQueue {
+public class FIFOQueue extends BaseEvictionQueue {
private Map<Object, EntryEvictionData> keyMap;
protected FIFOQueue() {
@@ -47,12 +47,12 @@
return keyMap.get(key);
}
- public boolean contains(EntryEvictionData entryEvictionData) {
- return keyMap.containsKey(entryEvictionData.getKey());
+ public boolean contains(Object key) {
+ return keyMap.containsKey(key);
}
- public void remove(EntryEvictionData entryEvictionData) {
- keyMap.remove(entryEvictionData.getKey());
+ public void remove(Object key) {
+ keyMap.remove(key);
}
public void add(EntryEvictionData entryEvictionData) {
Modified: core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lfu/LFUAlgorithm.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lfu/LFUAlgorithm.java 2009-02-03 13:51:43 UTC (rev 7632)
+++ core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lfu/LFUAlgorithm.java 2009-02-03 21:28:24 UTC (rev 7633)
@@ -21,14 +21,17 @@
*/
package org.horizon.eviction.algorithms.lfu;
+import net.jcip.annotations.NotThreadSafe;
import org.horizon.config.EvictionAlgorithmConfig;
-import org.horizon.eviction.EntryEvictionData;
+import org.horizon.eviction.EvictionEvent;
import org.horizon.eviction.EvictionException;
import org.horizon.eviction.EvictionQueue;
-import org.horizon.eviction.algorithms.BaseSortedEvictionAlgorithm;
+import org.horizon.eviction.algorithms.BaseEvictionAlgorithm;
import org.horizon.logging.Log;
import org.horizon.logging.LogFactory;
+import java.util.concurrent.BlockingQueue;
+
/**
* Least Frequently Used algorithm for cache eviction. Note that this algorithm is not thread-safe.
* <p/>
@@ -43,30 +46,15 @@
* This algorithm uses a sorted eviction queue. The eviction queue is sorted in ascending order based on the number of
* times a node is visited. The more frequently a node is visited, the less likely it will be evicted.
*
- * @author Daniel Huang - dhuang(a)jboss.org 10/2005
+ * @author Manik Surtani
* @since 1.0
*/
-public class LFUAlgorithm extends BaseSortedEvictionAlgorithm {
+@NotThreadSafe
+public class LFUAlgorithm extends BaseEvictionAlgorithm {
private static final Log log = LogFactory.getLog(LFUAlgorithm.class);
private static final boolean trace = log.isTraceEnabled();
- private LFUAlgorithmConfig lfuAlgorithmConfig;
+ boolean evictionQueueRequiresSort = false;
- @Override
- protected boolean shouldEvictNode(EntryEvictionData data) {
- // check the minimum time to live and see if we should not evict the node. This check will
- // ensure that, if configured, nodes are kept alive for at least a minimum period of time.
- if (isYoungerThanMinimumTimeToLive(lfuAlgorithmConfig.getMinTimeToLive(), data)) return false;
-
- int size = this.getEvictionQueue().size();
- if (lfuAlgorithmConfig.getMaxEntries() > -1 && size > lfuAlgorithmConfig.getMaxEntries()) {
- return true;
- } else if (size > lfuAlgorithmConfig.getMinEntries()) {
- return true;
- }
-
- return false;
- }
-
/**
* Will create a LFUQueue to be used as the underlying eviction queue.
*
@@ -84,7 +72,7 @@
super.prune();
// clean up the Queue's eviction removals
- ((LFUQueue) this.evictionQueue).prune();
+ ((LFUQueue) this.evictionQueue).doBatchRemove();
}
public Class<? extends EvictionAlgorithmConfig> getConfigurationClass() {
@@ -92,8 +80,41 @@
}
@Override
- public void initialize() {
- super.initialize();
- lfuAlgorithmConfig = (LFUAlgorithmConfig) evictionAlgorithmConfig;
+ protected void processQueues(BlockingQueue<EvictionEvent> queue) throws EvictionException {
+ evictionQueueRequiresSort = false;
+ try {
+ super.processQueues(queue);
+ if (evictionQueueRequiresSort) {
+ if (trace) log.trace("Eviction queue requires re-sort. Re-sorting.");
+ resortEvictionQueue();
+ }
+ } finally {
+ evictionQueueRequiresSort = false;
+ }
}
+
+ @Override
+ protected void processAddedEntries(EvictionEvent event) {
+ evictionQueueRequiresSort = true;
+ super.processAddedEntries(event);
+ }
+
+ @Override
+ protected void processVisitedEntries(EvictionEvent event) {
+ evictionQueueRequiresSort = true;
+ super.processVisitedEntries(event);
+ }
+
+ /**
+ * This method is called to resort the queue after add or visit events have occurred.
+ */
+ protected void resortEvictionQueue() {
+ long begin = System.currentTimeMillis();
+ ((LFUQueue) evictionQueue).reSortEvictionQueue();
+
+ if (trace) {
+ log.trace("Took {0} millis to re-sort queue with {1} elements",
+ System.currentTimeMillis() - begin, getEvictionQueue().size());
+ }
+ }
}
Modified: core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lfu/LFUAlgorithmConfig.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lfu/LFUAlgorithmConfig.java 2009-02-03 13:51:43 UTC (rev 7632)
+++ core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lfu/LFUAlgorithmConfig.java 2009-02-03 21:28:24 UTC (rev 7633)
@@ -21,7 +21,6 @@
*/
package org.horizon.eviction.algorithms.lfu;
-import org.horizon.config.Dynamic;
import org.horizon.eviction.EvictionAlgorithmConfigBase;
/**
@@ -36,59 +35,12 @@
*/
private static final long serialVersionUID = 1865801530398969179L;
- @Dynamic
- private int minEntries;
-
public LFUAlgorithmConfig() {
evictionAlgorithmClassName = LFUAlgorithm.class.getName();
}
- public LFUAlgorithmConfig(int maxNodes, int minEntries) {
- this();
- setMaxEntries(maxNodes);
- setMinEntries(minEntries);
- }
-
- public int getMinEntries() {
- return minEntries;
- }
-
- public void setMinEntries(int minEntries) {
- testImmutability("minEntries");
- this.minEntries = minEntries;
- }
-
@Override
- public String toString() {
- StringBuilder ret = new StringBuilder();
- ret.append("LFUAlgorithmConfig: maxEntries = ").append(getMaxEntries()).append(" minEntries = ").append(getMinEntries());
- return ret.toString();
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj instanceof LFUAlgorithmConfig && super.equals(obj)) {
- return (this.minEntries == ((LFUAlgorithmConfig) obj).minEntries);
- }
- return false;
- }
-
- @Override
- public int hashCode() {
- int result = super.hashCode();
- result = 31 * result + minEntries;
- return result;
- }
-
- @Override
public LFUAlgorithmConfig clone() {
return (LFUAlgorithmConfig) super.clone();
}
-
- @Override
- public void reset() {
- super.reset();
- minEntries = -1;
- evictionAlgorithmClassName = LFUAlgorithm.class.getName();
- }
}
\ No newline at end of file
Modified: core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lfu/LFUQueue.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lfu/LFUQueue.java 2009-02-03 13:51:43 UTC (rev 7632)
+++ core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lfu/LFUQueue.java 2009-02-03 21:28:24 UTC (rev 7633)
@@ -22,7 +22,7 @@
package org.horizon.eviction.algorithms.lfu;
import org.horizon.eviction.EntryEvictionData;
-import org.horizon.eviction.algorithms.SortedEvictionQueue;
+import org.horizon.eviction.algorithms.BaseEvictionQueue;
import java.util.Collections;
import java.util.Comparator;
@@ -41,10 +41,10 @@
* @author Daniel Huang (dhuang(a)jboss.org)
* @since 1.0
*/
-public class LFUQueue implements SortedEvictionQueue {
- private Map<Object, EntryEvictionData> keyMap;
- private LinkedList<EntryEvictionData> evictionList;
- private Set<EntryEvictionData> removalQueue;
+public class LFUQueue extends BaseEvictionQueue {
+ Map<Object, EntryEvictionData> keyMap;
+ LinkedList<EntryEvictionData> evictionList;
+ Set<EntryEvictionData> removalQueue;
private Comparator<EntryEvictionData> comparator;
protected LFUQueue() {
@@ -58,12 +58,12 @@
return keyMap.get(key);
}
- public boolean contains(EntryEvictionData entryEvictionData) {
- return keyMap.containsKey(entryEvictionData.getKey());
+ public boolean contains(Object key) {
+ return keyMap.containsKey(key);
}
- public void remove(EntryEvictionData entryEvictionData) {
- EntryEvictionData data = keyMap.remove(entryEvictionData.getKey());
+ public void remove(Object key) {
+ EntryEvictionData data = keyMap.remove(key);
if (data != null) {
// don't remove directly from the LinkedList otherwise we will incur a O(n) = n
// performance penalty for every removal! In the prune method for LFU, we will iterate the LinkedList through ONCE
@@ -96,15 +96,36 @@
Collections.sort(evictionList, comparator);
}
- protected void prune() {
- Iterator<EntryEvictionData> it = this.iterator();
+ /**
+ * Anything removed using {@link #remove(Object)} or removing using the iterator does not actually get removed until
+ * this method is called.
+ */
+ public void doBatchRemove() {
+ Iterator<EntryEvictionData> it = evictionList.iterator();
while (it.hasNext() && removalQueue.size() > 0) {
if (removalQueue.remove(it.next())) it.remove();
}
}
public Iterator<EntryEvictionData> iterator() {
- return evictionList.iterator();
+ //return evictionList.iterator();
+ return new Iterator<EntryEvictionData>() {
+ Iterator<EntryEvictionData> delegate = evictionList.iterator();
+ EntryEvictionData current;
+
+ public boolean hasNext() {
+ return delegate.hasNext();
+ }
+
+ public EntryEvictionData next() {
+ current = delegate.next();
+ return current;
+ }
+
+ public void remove() {
+ if (current != null) LFUQueue.this.remove(current.getKey());
+ }
+ };
}
/**
Modified: core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lru/LRUAlgorithm.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lru/LRUAlgorithm.java 2009-02-03 13:51:43 UTC (rev 7632)
+++ core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lru/LRUAlgorithm.java 2009-02-03 21:28:24 UTC (rev 7633)
@@ -21,6 +21,7 @@
*/
package org.horizon.eviction.algorithms.lru;
+import net.jcip.annotations.NotThreadSafe;
import org.horizon.config.EvictionAlgorithmConfig;
import org.horizon.eviction.EntryEvictionData;
import org.horizon.eviction.EvictionException;
@@ -32,90 +33,32 @@
import java.util.Iterator;
/**
- * Least recently Used algorithm to purge old data. Note that this algorithm is not thread-safe.
+ * Least recently Used algorithm to evict cache entries
*
- * @author Ben Wang 02-2004
- * @author Daniel Huang - dhuang(a)jboss.org
+ * @author Manik Surtani
* @since 1.0
*/
+@NotThreadSafe
public class LRUAlgorithm extends BaseEvictionAlgorithm {
private static final Log log = LogFactory.getLog(LRUAlgorithm.class);
private static final boolean trace = log.isTraceEnabled();
- private LRUAlgorithmConfig lruAlgorithmConfig;
-
@Override
protected EvictionQueue setupEvictionQueue() throws EvictionException {
return new LRUQueue();
}
@Override
- protected boolean shouldEvictNode(EntryEvictionData entryEvictionData) {
- // check the minimum time to live and see if we should not evict the node. This check will
- // ensure that, if configured, nodes are kept alive for at least a minimum period of time.
- if (isYoungerThanMinimumTimeToLive(lruAlgorithmConfig.getMinTimeToLive(), entryEvictionData)) return false;
-
- // no idle or max time limit
- if (lruAlgorithmConfig.getTimeToLive() < 0 && lruAlgorithmConfig.getMaxAge() < 0) return false;
-
- long currentTime = System.currentTimeMillis();
- if (lruAlgorithmConfig.getTimeToLive() > -1) {
- long idleTime = currentTime - entryEvictionData.getModifiedTimeStamp();
- if (trace) {
- log.trace("Node " + entryEvictionData.getKey() + " has been idle for " + idleTime + "ms");
- }
- if ((idleTime >= (lruAlgorithmConfig.getTimeToLive()))) {
- if (trace) {
- log.trace("Node " + entryEvictionData.getKey() + " should be evicted because of idle time");
- log.trace("Time to live in millies is: " + (lruAlgorithmConfig.getTimeToLive()));
- log.trace("Config instance is: " + System.identityHashCode(lruAlgorithmConfig));
- }
- return true;
- }
- }
-
- if (lruAlgorithmConfig.getMaxAge() > -1) {
- long objectLifeTime = currentTime - entryEvictionData.getCreationTimeStamp();
- if (trace) {
- log.trace("Node " + entryEvictionData.getKey() + " has been alive for " + objectLifeTime + "ms");
- }
- if ((objectLifeTime >= lruAlgorithmConfig.getMaxAge())) {
- if (trace) {
- log.trace("Node " + entryEvictionData.getKey() + " should be evicted because of max age");
- }
- return true;
- }
- }
-
- if (trace) {
- log.trace("Node " + entryEvictionData.getKey() + " should not be evicted");
- }
- return false;
- }
-
- @Override
- protected void evict(EntryEvictionData data) {
- if (data != null) {
- if (!evictionAction.evict(data.getKey())) {
- try {
- recycleQueue.put(data.getKey());
- }
- catch (InterruptedException e) {
- log.debug("InterruptedException", e);
- }
- }
- }
- }
-
- @Override
protected void prune() throws EvictionException {
LRUQueue lruQueue = (LRUQueue) evictionQueue;
+ int origSize = evictionQueue.size();
+
EntryEvictionData data;
Iterator<EntryEvictionData> it = lruQueue.iterateLRUQueue();
while (it.hasNext()) {
data = it.next();
if (data.isNodeInUseAndNotTimedOut()) continue;
- if (this.shouldEvictNode(data)) {
+ if (shouldEvictEntry(data, origSize) && shouldNotOverrideEviction(data)) {
it.remove();
lruQueue.removeNodeEntryFromMaxAge(data);
this.evict(data);
@@ -128,7 +71,7 @@
while (it.hasNext()) {
data = it.next();
if (data.isNodeInUseAndNotTimedOut()) continue;
- if (this.shouldEvictNode(data)) {
+ if (shouldEvictEntry(data, origSize) && shouldNotOverrideEviction(data)) {
it.remove();
lruQueue.removeNodeEntryFromLRU(data);
this.evict(data);
@@ -137,20 +80,20 @@
}
}
- int maxNodes = ((LRUAlgorithmConfig) evictionAlgorithmConfig).getMaxEntries();
+ int maxNodes = evictionAlgorithmConfig.getMaxEntries();
if (maxNodes <= 0) {
return;
}
it = lruQueue.iterateLRUQueue();
- while (evictionQueue.size() > maxNodes) {
+ while (evictionQueue.size() > maxNodes && it.hasNext()) {
data = it.next();
if (trace) {
log.trace("Node " + data.getKey() + " will be evicted because of exceeding the maxNode limit." +
" maxNode: " + maxNodes + " but current queue size is: " + evictionQueue.size());
}
- if (!data.isNodeInUseAndNotTimedOut()) {
+ if (!data.isNodeInUseAndNotTimedOut() && shouldNotOverrideEviction(data)) {
it.remove();
lruQueue.removeNodeEntryFromMaxAge(data);
this.evict(data);
@@ -161,10 +104,4 @@
public Class<? extends EvictionAlgorithmConfig> getConfigurationClass() {
return LRUAlgorithmConfig.class;
}
-
- @Override
- public void initialize() {
- super.initialize();
- lruAlgorithmConfig = (LRUAlgorithmConfig) evictionAlgorithmConfig;
- }
}
Modified: core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lru/LRUAlgorithmConfig.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lru/LRUAlgorithmConfig.java 2009-02-03 13:51:43 UTC (rev 7632)
+++ core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lru/LRUAlgorithmConfig.java 2009-02-03 21:28:24 UTC (rev 7633)
@@ -21,12 +21,8 @@
*/
package org.horizon.eviction.algorithms.lru;
-import org.horizon.config.ConfigurationException;
-import org.horizon.config.Dynamic;
import org.horizon.eviction.EvictionAlgorithmConfigBase;
-import java.util.concurrent.TimeUnit;
-
/**
* Configuration implementation for {@link LRUAlgorithm}.
* <p/>
@@ -40,129 +36,11 @@
*/
private static final long serialVersionUID = -3426716488271559729L;
- /**
- * value expressed in millis
- */
- @Dynamic
- private long timeToLive;
-
- /**
- * value expressed in millis
- */
- @Dynamic
- private long maxAge;
-
public LRUAlgorithmConfig() {
evictionAlgorithmClassName = LRUAlgorithm.class.getName();
- // Force config of ttls
- setTimeToLive(-1);
- setMaxAge(-1);
}
- public LRUAlgorithmConfig(long timeToLive, long maxAge) {
- this();
- this.timeToLive = timeToLive;
- this.maxAge = maxAge;
- }
-
- public LRUAlgorithmConfig(long timeToLive, int maxAge, int maxNodes) {
- this(timeToLive, maxAge);
- this.maxEntries = maxNodes;
- }
-
- /**
- * @return the time to live, in milliseconds
- */
- public long getTimeToLive() {
- return timeToLive;
- }
-
- /**
- * Sets the time to live
- *
- * @param timeToLive the time to live, in milliseconds
- */
- public void setTimeToLive(long timeToLive) {
- testImmutability("timeToLive");
- this.timeToLive = timeToLive;
- }
-
- public void setTimeToLive(long timeToLive, TimeUnit timeUnit) {
- testImmutability("timeToLive");
- this.timeToLive = timeUnit.toMillis(timeToLive);
- }
-
- /**
- * @return the max age per element, in milliseconds
- */
- public long getMaxAge() {
- return maxAge;
- }
-
- /**
- * Sets the max age per element
- *
- * @param maxAge value in milliseconds
- */
- public void setMaxAge(long maxAge) {
- testImmutability("maxAge");
- this.maxAge = maxAge;
- }
-
- public void setMaxAge(long maxAge, TimeUnit timeUnit) {
- testImmutability("maxAge");
- this.maxAge = timeUnit.toMillis(maxAge);
- }
-
- /**
- * Requires a positive timeToLive value or ConfigurationException is thrown.
- */
@Override
- public void validate() throws ConfigurationException {
- super.validate();
- if (timeToLive < -1) {
- throw new ConfigurationException("timeToLive must be " +
- "configured to a value greater than or equal to 0 (or -1 for unlimited time to live) for " + getEvictionAlgorithmClassName());
- }
- }
-
- public String toString() {
- return "LRUAlgorithmConfig {" +
- "algorithmClassName=" + evictionAlgorithmClassName +
- ", timeToLive=" + timeToLive +
- ", maxAge=" + maxAge +
- '}';
- }
-
- public boolean equals(Object o) {
- if (this == o) return true;
- if (!(o instanceof LRUAlgorithmConfig)) return false;
- if (!super.equals(o)) return false;
-
- LRUAlgorithmConfig that = (LRUAlgorithmConfig) o;
-
- if (maxAge != that.maxAge) return false;
- if (timeToLive != that.timeToLive) return false;
-
- return true;
- }
-
- public int hashCode() {
- int result = super.hashCode();
- result = 31 * result + (int) (timeToLive ^ (timeToLive >>> 32));
- result = 31 * result + (int) (maxAge ^ (maxAge >>> 32));
- return result;
- }
-
- @Override
- public void reset() {
- super.reset();
- setTimeToLive(-1);
- setMaxAge(-1);
- evictionAlgorithmClassName = LRUAlgorithm.class.getName();
- }
-
- @Override
public LRUAlgorithmConfig clone() {
return (LRUAlgorithmConfig) super.clone();
}
Modified: core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lru/LRUQueue.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lru/LRUQueue.java 2009-02-03 13:51:43 UTC (rev 7632)
+++ core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lru/LRUQueue.java 2009-02-03 21:28:24 UTC (rev 7633)
@@ -22,7 +22,7 @@
package org.horizon.eviction.algorithms.lru;
import org.horizon.eviction.EntryEvictionData;
-import org.horizon.eviction.EvictionQueue;
+import org.horizon.eviction.algorithms.BaseEvictionQueue;
import java.util.Iterator;
import java.util.LinkedHashMap;
@@ -37,9 +37,9 @@
* @author Daniel Huang (dhuang(a)jboss.org)
* @since 1.0
*/
-public class LRUQueue implements EvictionQueue {
- private Map<Object, EntryEvictionData> maxAgeQueue;
- private Map<Object, EntryEvictionData> lruQueue;
+public class LRUQueue extends BaseEvictionQueue {
+ Map<Object, EntryEvictionData> maxAgeQueue;
+ Map<Object, EntryEvictionData> lruQueue;
protected LRUQueue() {
maxAgeQueue = new LinkedHashMap<Object, EntryEvictionData>();
@@ -50,13 +50,12 @@
return lruQueue.get(key);
}
- public boolean contains(EntryEvictionData entryEvictionData) {
- return this.maxAgeQueue.containsKey(entryEvictionData.getKey());
+ public boolean contains(Object key) {
+ return maxAgeQueue.containsKey(key);
}
- public void remove(EntryEvictionData entryEvictionData) {
- if (contains(entryEvictionData)) {
- Object key = entryEvictionData.getKey();
+ public void remove(Object key) {
+ if (contains(key)) {
EntryEvictionData data1 = lruQueue.remove(key);
EntryEvictionData data2 = maxAgeQueue.remove(key);
if (data1 == null || data2 == null) {
@@ -83,11 +82,11 @@
}
public Iterator<EntryEvictionData> iterator() {
- return lruQueue.values().iterator();
+ return new LRUQueueIterator(lruQueue, maxAgeQueue);
}
public Iterator<EntryEvictionData> iterateLRUQueue() {
- return lruQueue.values().iterator();
+ return new LRUQueueIterator(lruQueue, maxAgeQueue);
}
public void removeNodeEntryFromMaxAge(EntryEvictionData data) {
@@ -95,10 +94,37 @@
}
public Iterator<EntryEvictionData> iterateMaxAgeQueue() {
- return maxAgeQueue.values().iterator();
+ return new LRUQueueIterator(maxAgeQueue, lruQueue);
}
public void removeNodeEntryFromLRU(EntryEvictionData data) {
lruQueue.remove(data.getKey());
}
+
+ private class LRUQueueIterator implements Iterator<EntryEvictionData> {
+ Iterator<EntryEvictionData> delegate;
+ Map<Object, EntryEvictionData> secondaryStructure;
+ EntryEvictionData current;
+
+ private LRUQueueIterator(Map<Object, EntryEvictionData> primaryStructure, Map<Object, EntryEvictionData> secondaryStructure) {
+ delegate = primaryStructure.values().iterator();
+ this.secondaryStructure = secondaryStructure;
+ }
+
+ public boolean hasNext() {
+ return delegate.hasNext();
+ }
+
+ public EntryEvictionData next() {
+ current = delegate.next();
+ return current;
+ }
+
+ public void remove() {
+ delegate.remove();
+ if (current != null) {
+ maxAgeQueue.remove(current.getKey());
+ }
+ }
+ }
}
Modified: core/branches/flat/src/main/java/org/horizon/eviction/algorithms/mru/MRUAlgorithm.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/algorithms/mru/MRUAlgorithm.java 2009-02-03 13:51:43 UTC (rev 7632)
+++ core/branches/flat/src/main/java/org/horizon/eviction/algorithms/mru/MRUAlgorithm.java 2009-02-03 21:28:24 UTC (rev 7633)
@@ -21,8 +21,8 @@
*/
package org.horizon.eviction.algorithms.mru;
+import net.jcip.annotations.NotThreadSafe;
import org.horizon.config.EvictionAlgorithmConfig;
-import org.horizon.eviction.EntryEvictionData;
import org.horizon.eviction.EvictionEvent;
import org.horizon.eviction.EvictionException;
import org.horizon.eviction.EvictionQueue;
@@ -32,43 +32,24 @@
* Most Recently Used Algorithm.
* <p/>
* This algorithm will evict the most recently used cache entries from cache.
- * <p/>
- * Note: None of the Eviction classes are thread safe. It is assumed that an individual instance of an EvictionPolicy/
- * EvictionAlgorithm/EvictionQueue/EvictionConfiguration are only operated on by one thread at any given time.
*
- * @author Daniel Huang (dhuang(a)jboss.org)
+ * @author Manik Surtani
* @since 1.0
*/
+@NotThreadSafe
public class MRUAlgorithm extends BaseEvictionAlgorithm {
-
- MRUAlgorithmConfig mruAlgorithmConfig;
-
@Override
protected EvictionQueue setupEvictionQueue() throws EvictionException {
return new MRUQueue();
}
@Override
- protected boolean shouldEvictNode(EntryEvictionData data) {
- // check the minimum time to live and see if we should not evict the node. This check will
- // ensure that, if configured, nodes are kept alive for at least a minimum period of time.
- return !isYoungerThanMinimumTimeToLive(mruAlgorithmConfig.getMinTimeToLive(), data) &&
- evictionQueue.size() > mruAlgorithmConfig.getMaxEntries();
- }
-
- @Override
- protected void processVisitedNodes(EvictionEvent evictedEventNode) throws EvictionException {
- super.processVisitedNodes(evictedEventNode);
+ protected void processVisitedEntries(EvictionEvent evictedEventNode) throws EvictionException {
+ super.processVisitedEntries(evictedEventNode);
((MRUQueue) evictionQueue).moveToTopOfStack(evictedEventNode.getKey());
}
public Class<? extends EvictionAlgorithmConfig> getConfigurationClass() {
return MRUAlgorithmConfig.class;
}
-
- @Override
- public void initialize() {
- super.initialize();
- mruAlgorithmConfig = (MRUAlgorithmConfig) evictionAlgorithmConfig;
- }
}
Modified: core/branches/flat/src/main/java/org/horizon/eviction/algorithms/mru/MRUAlgorithmConfig.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/algorithms/mru/MRUAlgorithmConfig.java 2009-02-03 13:51:43 UTC (rev 7632)
+++ core/branches/flat/src/main/java/org/horizon/eviction/algorithms/mru/MRUAlgorithmConfig.java 2009-02-03 21:28:24 UTC (rev 7633)
@@ -21,13 +21,10 @@
*/
package org.horizon.eviction.algorithms.mru;
-import org.horizon.config.ConfigurationException;
import org.horizon.eviction.EvictionAlgorithmConfigBase;
/**
* Configuration for {@link MRUAlgorithm}.
- * <p/>
- * Requires a "maxEntries" attribute otherwise a ConfigurationException is thrown.
*
* @author Manik Surtani
* @since 1.0
@@ -40,48 +37,10 @@
public MRUAlgorithmConfig() {
evictionAlgorithmClassName = MRUAlgorithm.class.getName();
- // We require that maxEntries is set
- setMaxEntries(-1);
}
- public MRUAlgorithmConfig(int maxNodes) {
- evictionAlgorithmClassName = MRUAlgorithm.class.getName();
- setMaxEntries(maxNodes);
- }
-
- /**
- * Requires a positive maxNodes value or ConfigurationException is thrown.
- */
@Override
- public void validate() throws ConfigurationException {
- super.validate();
- if (getMaxEntries() < 0)
- throw new ConfigurationException("maxEntries not configured");
- }
-
- @Override
- public String toString() {
- StringBuilder str = new StringBuilder();
- str.append("MRUAlgorithmConfig: ").
- append(" maxEntries =").append(getMaxEntries());
- return str.toString();
- }
-
- @Override
- public boolean equals(Object obj) {
- return (obj instanceof MRUAlgorithmConfig && super.equals(obj));
- }
-
- @Override
- public void reset() {
- super.reset();
- setMaxEntries(-1);
- evictionAlgorithmClassName = MRUAlgorithm.class.getName();
- }
-
- @Override
public MRUAlgorithmConfig clone() {
return (MRUAlgorithmConfig) super.clone();
}
-
}
\ No newline at end of file
Modified: core/branches/flat/src/main/java/org/horizon/eviction/algorithms/mru/MRUQueue.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/algorithms/mru/MRUQueue.java 2009-02-03 13:51:43 UTC (rev 7632)
+++ core/branches/flat/src/main/java/org/horizon/eviction/algorithms/mru/MRUQueue.java 2009-02-03 21:28:24 UTC (rev 7633)
@@ -22,7 +22,7 @@
package org.horizon.eviction.algorithms.mru;
import org.horizon.eviction.EntryEvictionData;
-import org.horizon.eviction.EvictionQueue;
+import org.horizon.eviction.algorithms.BaseEvictionQueue;
import java.util.HashMap;
import java.util.Iterator;
@@ -39,12 +39,12 @@
* @author Daniel Huang (dhuang(a)jboss.org)
* @since 1.0
*/
-public class MRUQueue implements EvictionQueue {
+public class MRUQueue extends BaseEvictionQueue {
// we use our own Stack/Linked List implementation here because it guarantees O(n) = 1 for add, remove, get and
// we can sort it in order of MRU implicitly while still getting O(n) = 1 access time
// throughout.
Map<Object, EntryEvictionData> keyMap;
- private LinkedList<EntryEvictionData> list;
+ LinkedList<EntryEvictionData> list;
protected MRUQueue() {
keyMap = new HashMap<Object, EntryEvictionData>();
@@ -70,12 +70,12 @@
return keyMap.get(key);
}
- public boolean contains(EntryEvictionData entryEvictionData) {
- return keyMap.containsKey(entryEvictionData.getKey());
+ public boolean contains(Object key) {
+ return keyMap.containsKey(key);
}
- public void remove(EntryEvictionData entryEvictionData) {
- EntryEvictionData data = keyMap.remove(entryEvictionData.getKey());
+ public void remove(Object key) {
+ EntryEvictionData data = keyMap.remove(key);
if (data != null) list.remove(data);
}
@@ -96,7 +96,28 @@
}
public Iterator<EntryEvictionData> iterator() {
- return list.iterator();
+ return new Iterator<EntryEvictionData>() {
+ Iterator<EntryEvictionData> delegate = list.iterator();
+ EntryEvictionData current;
+
+ public boolean hasNext() {
+ return delegate.hasNext();
+ }
+
+ public EntryEvictionData next() {
+ current = delegate.next();
+ return current;
+ }
+
+ public void remove() {
+ // this will remove it from the list
+ delegate.remove();
+ // now to take care of the key map
+ if (current != null) {
+ keyMap.remove(current.getKey());
+ }
+ }
+ };
}
@Override
Modified: core/branches/flat/src/main/java/org/horizon/eviction/algorithms/nullalgo/NullEvictionQueue.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/algorithms/nullalgo/NullEvictionQueue.java 2009-02-03 13:51:43 UTC (rev 7632)
+++ core/branches/flat/src/main/java/org/horizon/eviction/algorithms/nullalgo/NullEvictionQueue.java 2009-02-03 21:28:24 UTC (rev 7633)
@@ -22,7 +22,7 @@
package org.horizon.eviction.algorithms.nullalgo;
import org.horizon.eviction.EntryEvictionData;
-import org.horizon.eviction.EvictionQueue;
+import org.horizon.eviction.algorithms.BaseEvictionQueue;
import java.util.Iterator;
import java.util.NoSuchElementException;
@@ -33,7 +33,7 @@
* @author Brian Stansberry
* @since 1.0
*/
-public class NullEvictionQueue implements EvictionQueue {
+public class NullEvictionQueue extends BaseEvictionQueue {
/**
* Singleton instance of this class.
*/
@@ -66,7 +66,7 @@
/**
* Returns <code>false</code>
*/
- public boolean contains(EntryEvictionData entryEvictionData) {
+ public boolean contains(Object key) {
return false;
}
@@ -87,7 +87,7 @@
/**
* No-op
*/
- public void remove(EntryEvictionData entryEvictionData) {
+ public void remove(Object key) {
// no-op
}
Added: core/branches/flat/src/test/java/org/horizon/eviction/algorithms/BaseAlgorithmTest.java
===================================================================
--- core/branches/flat/src/test/java/org/horizon/eviction/algorithms/BaseAlgorithmTest.java (rev 0)
+++ core/branches/flat/src/test/java/org/horizon/eviction/algorithms/BaseAlgorithmTest.java 2009-02-03 21:28:24 UTC (rev 7633)
@@ -0,0 +1,260 @@
+package org.horizon.eviction.algorithms;
+
+import org.easymock.EasyMock;
+import static org.easymock.EasyMock.*;
+import org.horizon.config.EvictionAlgorithmConfig;
+import org.horizon.eviction.EntryEvictionData;
+import org.horizon.eviction.EvictionAction;
+import org.horizon.eviction.EvictionAlgorithm;
+import org.horizon.eviction.EvictionAlgorithmConfigBase;
+import org.horizon.eviction.EvictionEvent;
+import static org.horizon.eviction.EvictionEvent.Type.ADD_ENTRY_EVENT;
+import org.horizon.util.Util;
+import org.testng.annotations.Test;
+
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+
+@Test(groups = "unit")
+public abstract class BaseAlgorithmTest {
+
+ protected abstract EvictionAlgorithmConfigBase getNewEvictionAlgorithmConfig();
+
+ protected EvictionAlgorithm createAndInit(EvictionAlgorithmConfig cfg) throws Exception {
+ EvictionAlgorithm a = (EvictionAlgorithm) Util.getInstance(cfg.getEvictionAlgorithmClassName());
+ a.assignToCache(null, cfg);
+ return a;
+ }
+
+ public void testMinTimeToLive() throws Exception {
+ EvictionAlgorithmConfigBase cfg = getNewEvictionAlgorithmConfig();
+ cfg.setMinTimeToLive(2 * 60 * 60 * 1000); // something enormous - 2 hrs
+ cfg.setMaxEntries(5);
+ EvictionAlgorithm a = createAndInit(cfg);
+ EvictionAction mockAction = EasyMock.createMock(EvictionAction.class);
+ a.setEvictionAction(mockAction);
+ BlockingQueue<EvictionEvent> eventQueue = new LinkedBlockingQueue<EvictionEvent>();
+ for (int i = 0; i < 10; i++) eventQueue.put(new EvictionEvent(i, EvictionEvent.Type.ADD_ENTRY_EVENT));
+
+ assert eventQueue.size() == 10;
+
+ // what do we expect to happen on the eviction action class?
+ // nothing at this stage.
+ replay(mockAction);
+ a.process(eventQueue);
+ verify(mockAction);
+
+ for (EntryEvictionData data : a.getEvictionQueue()) {
+ // change the creation timestamp to before 2 hrs in the past
+ // for all even keys
+ Integer key = (Integer) data.getKey();
+
+ if (key % 2 == 0) {
+ data.setCreationTimeStamp(1);
+ data.setModifiedTimeStamp(1);
+ EvictionEvent e = new EvictionEvent(key, EvictionEvent.Type.VISIT_ENTRY_EVENT);
+ e.setCreationTimestamp(1);
+ eventQueue.put(e);
+ } else {
+ eventQueue.put(new EvictionEvent(key, EvictionEvent.Type.VISIT_ENTRY_EVENT));
+ }
+ }
+
+ assert eventQueue.size() == 10;
+
+ // this time we expect all even numbered keys to get evicted.
+ reset(mockAction);
+ expect(mockAction.evict(eq(0))).andReturn(true).once();
+ expect(mockAction.evict(eq(2))).andReturn(true).once();
+ expect(mockAction.evict(eq(4))).andReturn(true).once();
+ expect(mockAction.evict(eq(6))).andReturn(true).once();
+ expect(mockAction.evict(eq(8))).andReturn(true).once();
+ replay(mockAction);
+ a.process(eventQueue);
+ verify(mockAction);
+ }
+
+ public void testNumEntries1() throws Exception {
+ EvictionAlgorithmConfigBase config = getNewEvictionAlgorithmConfig();
+ config.setMaxEntries(4);
+ config.setMinEntries(2);
+ BlockingQueue<EvictionEvent> eventQueue = new LinkedBlockingQueue<EvictionEvent>();
+ eventQueue.put(new EvictionEvent("one", ADD_ENTRY_EVENT));
+ eventQueue.put(new EvictionEvent("two", ADD_ENTRY_EVENT));
+ eventQueue.put(new EvictionEvent("three", ADD_ENTRY_EVENT));
+ eventQueue.put(new EvictionEvent("four", ADD_ENTRY_EVENT));
+ eventQueue.put(new EvictionEvent("five", ADD_ENTRY_EVENT));
+ EvictionAlgorithm algo = createAndInit(config);
+ EvictionAction mockAction = EasyMock.createMock(EvictionAction.class);
+ algo.setEvictionAction(mockAction);
+
+ // should prune down to 2 entries
+ EasyMock.expect(mockAction.evict(eq("one"))).andReturn(true).once();
+ EasyMock.expect(mockAction.evict(eq("two"))).andReturn(true).once();
+ EasyMock.expect(mockAction.evict(eq("three"))).andReturn(true).once();
+ EasyMock.replay(mockAction);
+ algo.process(eventQueue);
+ EasyMock.verify(mockAction);
+
+ }
+
+ public void testNumEntries2() throws Exception {
+ EvictionAlgorithmConfigBase config = getNewEvictionAlgorithmConfig();
+ config.setMaxEntries(0);
+ config.setMinEntries(20);
+ BlockingQueue<EvictionEvent> eventQueue = new LinkedBlockingQueue<EvictionEvent>();
+ eventQueue.put(new EvictionEvent("one", ADD_ENTRY_EVENT));
+ eventQueue.put(new EvictionEvent("two", ADD_ENTRY_EVENT));
+ EvictionAlgorithm algo = createAndInit(config);
+ EvictionAction mockAction = EasyMock.createMock(EvictionAction.class);
+ algo.setEvictionAction(mockAction);
+
+ // should prune down to 2 entries
+ EasyMock.expect(mockAction.evict(eq("one"))).andReturn(true).once();
+ EasyMock.expect(mockAction.evict(eq("two"))).andReturn(true).once();
+ EasyMock.replay(mockAction);
+ algo.process(eventQueue);
+ EasyMock.verify(mockAction);
+ }
+
+ public void testNumEntries3() throws Exception {
+ EvictionAlgorithmConfigBase config = getNewEvictionAlgorithmConfig();
+ config.setMaxEntries(3);
+ config.setMinEntries(20);
+ BlockingQueue<EvictionEvent> eventQueue = new LinkedBlockingQueue<EvictionEvent>();
+ eventQueue.put(new EvictionEvent("one", ADD_ENTRY_EVENT));
+ eventQueue.put(new EvictionEvent("two", ADD_ENTRY_EVENT));
+ eventQueue.put(new EvictionEvent("three", ADD_ENTRY_EVENT));
+ eventQueue.put(new EvictionEvent("four", ADD_ENTRY_EVENT));
+ EvictionAlgorithm algo = createAndInit(config);
+ EvictionAction mockAction = EasyMock.createMock(EvictionAction.class);
+ algo.setEvictionAction(mockAction);
+
+ // should prune down to equal to maxEntries
+ EasyMock.expect(mockAction.evict(eq("one"))).andReturn(true).once();
+ EasyMock.replay(mockAction);
+ algo.process(eventQueue);
+ EasyMock.verify(mockAction);
+ }
+
+ public void testNumEntries4() throws Exception {
+ EvictionAlgorithmConfigBase config = getNewEvictionAlgorithmConfig();
+ config.setMaxEntries(-1);
+ config.setMinEntries(2);
+ BlockingQueue<EvictionEvent> eventQueue = new LinkedBlockingQueue<EvictionEvent>();
+ eventQueue.put(new EvictionEvent("one", ADD_ENTRY_EVENT));
+ eventQueue.put(new EvictionEvent("two", ADD_ENTRY_EVENT));
+ eventQueue.put(new EvictionEvent("three", ADD_ENTRY_EVENT));
+ eventQueue.put(new EvictionEvent("four", ADD_ENTRY_EVENT));
+ EvictionAlgorithm algo = createAndInit(config);
+ EvictionAction mockAction = EasyMock.createMock(EvictionAction.class);
+ algo.setEvictionAction(mockAction);
+
+ // expecting nothing to be evicted
+ EasyMock.replay(mockAction);
+ algo.process(eventQueue);
+ EasyMock.verify(mockAction);
+ }
+
+ public void testNumEntries5() throws Exception {
+ EvictionAlgorithmConfigBase config = getNewEvictionAlgorithmConfig();
+ config.setMaxEntries(3);
+ config.setMinEntries(-1);
+ BlockingQueue<EvictionEvent> eventQueue = new LinkedBlockingQueue<EvictionEvent>();
+ eventQueue.put(new EvictionEvent("one", ADD_ENTRY_EVENT));
+ eventQueue.put(new EvictionEvent("two", ADD_ENTRY_EVENT));
+ eventQueue.put(new EvictionEvent("three", ADD_ENTRY_EVENT));
+ eventQueue.put(new EvictionEvent("four", ADD_ENTRY_EVENT));
+ EvictionAlgorithm algo = createAndInit(config);
+ EvictionAction mockAction = EasyMock.createMock(EvictionAction.class);
+ algo.setEvictionAction(mockAction);
+
+ // should prune down to equal to maxEntries
+ EasyMock.expect(mockAction.evict(eq("one"))).andReturn(true).once();
+ EasyMock.replay(mockAction);
+ algo.process(eventQueue);
+ EasyMock.verify(mockAction);
+ }
+
+ public void testTimeToLive1() throws Exception {
+ EvictionAlgorithmConfigBase config = getNewEvictionAlgorithmConfig();
+ config.setTimeToLive(-1);
+ BlockingQueue<EvictionEvent> eventQueue = new LinkedBlockingQueue<EvictionEvent>();
+ eventQueue.put(new EvictionEvent("one", ADD_ENTRY_EVENT, 1));
+ eventQueue.put(new EvictionEvent("two", ADD_ENTRY_EVENT, 1));
+ eventQueue.put(new EvictionEvent("three", ADD_ENTRY_EVENT, 1));
+ eventQueue.put(new EvictionEvent("four", ADD_ENTRY_EVENT, 1));
+ EvictionAlgorithm algo = createAndInit(config);
+ EvictionAction mockAction = EasyMock.createMock(EvictionAction.class);
+ algo.setEvictionAction(mockAction);
+
+ // Should not select any
+ EasyMock.replay(mockAction);
+ algo.process(eventQueue);
+ EasyMock.verify(mockAction);
+
+ }
+
+ public void testTimeToLive2() throws Exception {
+ EvictionAlgorithmConfigBase config = getNewEvictionAlgorithmConfig();
+ config.setTimeToLive(0);
+ BlockingQueue<EvictionEvent> eventQueue = new LinkedBlockingQueue<EvictionEvent>();
+ eventQueue.put(new EvictionEvent("one", ADD_ENTRY_EVENT, 1));
+ eventQueue.put(new EvictionEvent("two", ADD_ENTRY_EVENT, System.currentTimeMillis() * 2));
+ eventQueue.put(new EvictionEvent("three", ADD_ENTRY_EVENT, 1));
+ eventQueue.put(new EvictionEvent("four", ADD_ENTRY_EVENT, System.currentTimeMillis() * 2));
+ EvictionAlgorithm algo = createAndInit(config);
+ EvictionAction mockAction = EasyMock.createMock(EvictionAction.class);
+ algo.setEvictionAction(mockAction);
+
+ // only the first one is selected since the others are not considered since max entries has not been hit.
+ EasyMock.expect(mockAction.evict(eq("one"))).andReturn(true).once();
+ EasyMock.replay(mockAction);
+ algo.process(eventQueue);
+ EasyMock.verify(mockAction);
+ }
+
+ public void testMaxAge1() throws Exception {
+ EvictionAlgorithmConfigBase config = getNewEvictionAlgorithmConfig();
+ config.setMaxAge(-1);
+ BlockingQueue<EvictionEvent> eventQueue = new LinkedBlockingQueue<EvictionEvent>();
+ eventQueue.put(new EvictionEvent("one", ADD_ENTRY_EVENT, 1));
+ eventQueue.put(new EvictionEvent("two", ADD_ENTRY_EVENT, 1));
+ eventQueue.put(new EvictionEvent("three", ADD_ENTRY_EVENT, 1));
+ eventQueue.put(new EvictionEvent("four", ADD_ENTRY_EVENT, 1));
+ EvictionAlgorithm algo = createAndInit(config);
+ EvictionAction mockAction = EasyMock.createMock(EvictionAction.class);
+ algo.setEvictionAction(mockAction);
+
+ // Should not select any
+ EasyMock.replay(mockAction);
+ algo.process(eventQueue);
+ EasyMock.verify(mockAction);
+
+ }
+
+ public void testMaxAge2() throws Exception {
+ EvictionAlgorithmConfigBase config = getNewEvictionAlgorithmConfig();
+ config.setMaxAge(10);
+ BlockingQueue<EvictionEvent> eventQueue = new LinkedBlockingQueue<EvictionEvent>();
+ eventQueue.put(new EvictionEvent("one", ADD_ENTRY_EVENT));
+ eventQueue.put(new EvictionEvent("two", ADD_ENTRY_EVENT));
+ eventQueue.put(new EvictionEvent("three", ADD_ENTRY_EVENT));
+ eventQueue.put(new EvictionEvent("four", ADD_ENTRY_EVENT));
+ Thread.sleep(10);
+ EvictionAlgorithm algo = createAndInit(config);
+ EvictionAction mockAction = EasyMock.createMock(EvictionAction.class);
+ algo.setEvictionAction(mockAction);
+
+ // all of them should have crossed max age by now
+ EasyMock.expect(mockAction.evict(eq("one"))).andReturn(true).once();
+ EasyMock.expect(mockAction.evict(eq("two"))).andReturn(true).once();
+ EasyMock.expect(mockAction.evict(eq("three"))).andReturn(true).once();
+ EasyMock.expect(mockAction.evict(eq("four"))).andReturn(true).once();
+ EasyMock.replay(mockAction);
+ algo.process(eventQueue);
+ EasyMock.verify(mockAction);
+ }
+
+
+}
Added: core/branches/flat/src/test/java/org/horizon/eviction/algorithms/BaseQueueTest.java
===================================================================
--- core/branches/flat/src/test/java/org/horizon/eviction/algorithms/BaseQueueTest.java (rev 0)
+++ core/branches/flat/src/test/java/org/horizon/eviction/algorithms/BaseQueueTest.java 2009-02-03 21:28:24 UTC (rev 7633)
@@ -0,0 +1,50 @@
+package org.horizon.eviction.algorithms;
+
+import org.horizon.eviction.EntryEvictionData;
+import org.horizon.eviction.EvictionQueue;
+import org.testng.annotations.Test;
+
+@Test(groups = "unit")
+public abstract class BaseQueueTest {
+ protected EntryEvictionData getFirstEntry(EvictionQueue q) {
+ return q.iterator().next();
+ }
+
+ protected Object getFirstEntryKey(EvictionQueue q) {
+ return q.iterator().next().getKey();
+ }
+
+ protected void fillQueue(EvictionQueue q, int numEntries) {
+ for (int i = 0; i < numEntries; i++) q.add(new EntryEvictionData(i));
+ }
+
+ protected abstract EvictionQueue getNewEvictionQueue();
+
+ public void testSizingAndContents() {
+ EvictionQueue q = getNewEvictionQueue();
+
+ assert q.isEmpty();
+ assert q.size() == 0;
+
+ fillQueue(q, 1000);
+
+ assert !q.isEmpty();
+ assert 1000 == q.size();
+
+ assert q.contains(1);
+ assert q.contains(999);
+ assert !q.contains(1000);
+
+ for (int i = 0; i < 1000; i++) {
+ assert q.get(i).getKey().equals(i);
+ }
+
+ for (int i = 0; i < 1000; i++) {
+ assert q.size() == 1000 - i;
+ q.remove(i);
+ }
+
+ assert q.isEmpty();
+ assert q.size() == 0;
+ }
+}
Modified: core/branches/flat/src/test/java/org/horizon/eviction/algorithms/fifo/FifoAlgorithmTest.java
===================================================================
--- core/branches/flat/src/test/java/org/horizon/eviction/algorithms/fifo/FifoAlgorithmTest.java 2009-02-03 13:51:43 UTC (rev 7632)
+++ core/branches/flat/src/test/java/org/horizon/eviction/algorithms/fifo/FifoAlgorithmTest.java 2009-02-03 21:28:24 UTC (rev 7633)
@@ -1,13 +1,63 @@
package org.horizon.eviction.algorithms.fifo;
+import org.easymock.EasyMock;
+import static org.easymock.EasyMock.*;
+import org.horizon.eviction.EntryEvictionData;
+import org.horizon.eviction.EvictionAction;
+import org.horizon.eviction.EvictionEvent;
+import org.horizon.eviction.algorithms.BaseAlgorithmTest;
import org.testng.annotations.Test;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+
@Test(groups = "unit")
-public class FifoAlgorithmTest {
- public void testAlgorithm() {
- FIFOAlgorithm algo = new FIFOAlgorithm();
- algo.initialize();
- assert algo.getConfigurationClass().equals(FIFOAlgorithmConfig.class);
-// assert algo.process();
+public class FifoAlgorithmTest extends BaseAlgorithmTest {
+
+ public void testMaxEntries() throws Exception {
+ FIFOAlgorithmConfig config = new FIFOAlgorithmConfig();
+ config.setMaxEntries(5);
+
+ FIFOAlgorithm algo = (FIFOAlgorithm) createAndInit(config);
+ EvictionAction mockAction = EasyMock.createMock(EvictionAction.class);
+ algo.setEvictionAction(mockAction);
+
+ BlockingQueue<EvictionEvent> eventQueue = new LinkedBlockingQueue<EvictionEvent>();
+ for (int i = 0; i < 10; i++) eventQueue.put(new EvictionEvent(i, EvictionEvent.Type.ADD_ENTRY_EVENT));
+
+ for (int i = 0; i < 5; i++) expect(mockAction.evict(eq(i))).andReturn(true).once();
+ replay(mockAction);
+ algo.process(eventQueue);
+ verify(mockAction);
+
+ // now verify the order.
+ int index = 5;
+ for (EntryEvictionData data : algo.getEvictionQueue()) {
+ assert data.getKey().equals(index);
+ index++;
+ }
+
+ // now verify the same order still exists after visiting the entries
+ for (int i = 5; i < 10; i++) {
+ eventQueue.put(new EvictionEvent(i, EvictionEvent.Type.VISIT_ENTRY_EVENT));
+ }
+ for (int i = 5; i < 10; i++) {
+ eventQueue.put(new EvictionEvent(i, EvictionEvent.Type.VISIT_ENTRY_EVENT));
+ }
+
+ algo.process(eventQueue);
+
+ assert 5 == algo.getEvictionQueue().size();
+
+ // now verify the order.
+ index = 5;
+ for (EntryEvictionData data : algo.getEvictionQueue()) {
+ assert data.getKey().equals(index);
+ index++;
+ }
}
+
+ protected FIFOAlgorithmConfig getNewEvictionAlgorithmConfig() {
+ return new FIFOAlgorithmConfig();
+ }
}
Modified: core/branches/flat/src/test/java/org/horizon/eviction/algorithms/fifo/FifoQueueTest.java
===================================================================
--- core/branches/flat/src/test/java/org/horizon/eviction/algorithms/fifo/FifoQueueTest.java 2009-02-03 13:51:43 UTC (rev 7632)
+++ core/branches/flat/src/test/java/org/horizon/eviction/algorithms/fifo/FifoQueueTest.java 2009-02-03 21:28:24 UTC (rev 7633)
@@ -1,7 +1,50 @@
package org.horizon.eviction.algorithms.fifo;
+import org.horizon.eviction.EntryEvictionData;
+import org.horizon.eviction.EvictionQueue;
+import org.horizon.eviction.algorithms.BaseQueueTest;
import org.testng.annotations.Test;
+import java.util.Iterator;
+
@Test(groups = "unit")
-public class FifoQueueTest {
+public class FifoQueueTest extends BaseQueueTest {
+ public void testOrder() throws Exception {
+ FIFOQueue queue = new FIFOQueue();
+
+ fillQueue(queue, 5000);
+
+ assert getFirstEntryKey(queue).equals(0);
+
+ // now make sure the ordering is correct.
+ int k = 0;
+ for (Iterator<EntryEvictionData> i = queue.iterator(); i.hasNext();) {
+ EntryEvictionData data = i.next();
+ assert data.getKey().equals(k);
+ i.remove();
+ k++;
+ if (k == 2500) break;
+ }
+
+ assert getFirstEntryKey(queue).equals(2500);
+
+ assert 2500 == queue.size();
+ assert !queue.isEmpty();
+
+ k = 2500;
+
+ for (Iterator<EntryEvictionData> i = queue.iterator(); i.hasNext();) {
+ EntryEvictionData data = i.next();
+ assert data.getKey().equals(k);
+ i.remove();
+ k++;
+ }
+
+ assert 0 == queue.size();
+ assert queue.isEmpty();
+ }
+
+ protected EvictionQueue getNewEvictionQueue() {
+ return new FIFOQueue();
+ }
}
Modified: core/branches/flat/src/test/java/org/horizon/eviction/algorithms/lfu/LfuAlgorithmTest.java
===================================================================
--- core/branches/flat/src/test/java/org/horizon/eviction/algorithms/lfu/LfuAlgorithmTest.java 2009-02-03 13:51:43 UTC (rev 7632)
+++ core/branches/flat/src/test/java/org/horizon/eviction/algorithms/lfu/LfuAlgorithmTest.java 2009-02-03 21:28:24 UTC (rev 7633)
@@ -1,7 +1,60 @@
package org.horizon.eviction.algorithms.lfu;
+import org.horizon.eviction.algorithms.BaseAlgorithmTest;
import org.testng.annotations.Test;
@Test(groups = "unit")
-public class LfuAlgorithmTest {
+public class LfuAlgorithmTest extends BaseAlgorithmTest {
+// public void testMinTimeToLive() throws Exception {
+// LFUAlgorithmConfig cfg = getNewEvictionAlgorithmConfig();
+// cfg.setMinTimeToLive(2 * 60 * 60 * 1000); // something enormous - 2 hrs
+// cfg.setMaxEntries(5);
+// EvictionAlgorithm a = createAndInit(cfg);
+// EvictionAction mockAction = EasyMock.createMock(EvictionAction.class);
+// a.setEvictionAction(mockAction);
+// BlockingQueue<EvictionEvent> eventQueue = new LinkedBlockingQueue<EvictionEvent>();
+// for (int i = 0; i < 10; i++) eventQueue.put(new EvictionEvent(i, ADD_ENTRY_EVENT));
+//
+// assert eventQueue.size() == 10;
+//
+// // what do we expect to happen on the eviction action class?
+// // nothing at this stage.
+// replay(mockAction);
+// a.process(eventQueue);
+// verify(mockAction);
+//
+// for (EntryEvictionData data : a.getEvictionQueue()) {
+// // change the creation timestamp to before 2 hrs in the past
+// // for all even keys
+// Integer key = (Integer) data.getKey();
+//
+// if (key % 2 == 0) {
+// EvictionEvent e = new EvictionEvent(key, EvictionEvent.Type.VISIT_ENTRY_EVENT);
+// e.setCreationTimestamp(1);
+// data.setCreationTimeStamp(1);
+// data.setModifiedTimeStamp(1);
+// eventQueue.put(e);
+// } else {
+// eventQueue.put(new EvictionEvent(key, EvictionEvent.Type.VISIT_ENTRY_EVENT));
+// }
+// }
+//
+// assert eventQueue.size() == 10;
+//
+// // this time we expect all even numbered keys to get evicted, since they are least frequently visited
+// reset(mockAction);
+// expect(mockAction.evict(eq(0))).andReturn(true).once();
+// expect(mockAction.evict(eq(2))).andReturn(true).once();
+// expect(mockAction.evict(eq(4))).andReturn(true).once();
+// expect(mockAction.evict(eq(6))).andReturn(true).once();
+// expect(mockAction.evict(eq(8))).andReturn(true).once();
+// replay(mockAction);
+// a.process(eventQueue);
+// verify(mockAction);
+// }
+
+
+ protected LFUAlgorithmConfig getNewEvictionAlgorithmConfig() {
+ return new LFUAlgorithmConfig();
+ }
}
Modified: core/branches/flat/src/test/java/org/horizon/eviction/algorithms/lfu/LfuQueueTest.java
===================================================================
--- core/branches/flat/src/test/java/org/horizon/eviction/algorithms/lfu/LfuQueueTest.java 2009-02-03 13:51:43 UTC (rev 7632)
+++ core/branches/flat/src/test/java/org/horizon/eviction/algorithms/lfu/LfuQueueTest.java 2009-02-03 21:28:24 UTC (rev 7633)
@@ -1,7 +1,109 @@
package org.horizon.eviction.algorithms.lfu;
+import org.horizon.eviction.EntryEvictionData;
+import org.horizon.eviction.EvictionQueue;
+import org.horizon.eviction.algorithms.BaseQueueTest;
import org.testng.annotations.Test;
+import java.util.Iterator;
+
@Test(groups = "unit")
-public class LfuQueueTest {
+public class LfuQueueTest extends BaseQueueTest {
+ public void testOrder() throws Exception {
+ LFUQueue queue = (LFUQueue) getNewEvictionQueue();
+ fillQueue(queue, 500);
+ assert 500 == queue.size();
+
+ queue.reSortEvictionQueue();
+
+ assert 500 == queue.size();
+
+ int k = 0;
+ for (EntryEvictionData entry : queue) {
+ assert entry.getKey().equals(k);
+ if (k % 2 == 0) entry.incrementNumberOfVisits();
+ k++;
+ }
+
+ queue.reSortEvictionQueue();
+
+ assert getFirstEntryKey(queue).equals(1);
+
+ // now check the sort order.
+ k = 0;
+ for (EntryEvictionData entry : queue) {
+ if (k < 250)
+ assert 0 == entry.getNumberOfVisits();
+ else
+ assert 1 == entry.getNumberOfVisits();
+ k++;
+ }
+
+ k = 0;
+ for (Iterator<EntryEvictionData> it = queue.iterator(); it.hasNext() && it.next() != null;) {
+ if (k == 250) break;
+ it.remove();
+ k++;
+ }
+
+ queue.doBatchRemove();
+
+ assert 250 == queue.size();
+ assert !queue.contains(275);
+
+ for (int i = 0; i < 500; i++) {
+ if (i % 2 == 0) {
+ EntryEvictionData data = queue.get(i);
+ assert 1 == data.getNumberOfVisits();
+ if (i > 250) data.incrementNumberOfVisits();
+ }
+ }
+
+ queue.reSortEvictionQueue();
+ assert 250 == queue.size();
+
+ k = 0;
+ for (EntryEvictionData entry : queue) {
+ if (k <= 125)
+ assert 1 == entry.getNumberOfVisits();
+ else
+ assert 2 == entry.getNumberOfVisits();
+ k++;
+ }
+ }
+
+ public void testPrune() throws Exception {
+ LFUQueue queue = (LFUQueue) getNewEvictionQueue();
+ fillQueue(queue, 500);
+
+ assert 500 == queue.size();
+ assert 500 == queue.evictionList.size();
+ assert 500 == queue.keyMap.size();
+
+ int i = 0;
+ for (Iterator it = queue.iterator(); it.hasNext() && it.next() != null;) {
+ if (i % 2 == 0) it.remove();
+ i++;
+ }
+ assert 250 == queue.size();
+
+ for (EntryEvictionData data : queue.removalQueue) {
+ int currentIndex = (Integer) data.getKey();
+ assert 0 == currentIndex % 2;
+
+ assert !queue.contains(currentIndex);
+ assert queue.evictionList.contains(data);
+ }
+
+ assert 500 == queue.evictionList.size();
+
+ queue.doBatchRemove();
+
+ assert 0 == queue.removalQueue.size();
+ assert 250 == queue.evictionList.size();
+ }
+
+ protected EvictionQueue getNewEvictionQueue() {
+ return new LFUQueue();
+ }
}
Modified: core/branches/flat/src/test/java/org/horizon/eviction/algorithms/lru/LruAlgorithmTest.java
===================================================================
--- core/branches/flat/src/test/java/org/horizon/eviction/algorithms/lru/LruAlgorithmTest.java 2009-02-03 13:51:43 UTC (rev 7632)
+++ core/branches/flat/src/test/java/org/horizon/eviction/algorithms/lru/LruAlgorithmTest.java 2009-02-03 21:28:24 UTC (rev 7633)
@@ -1,7 +1,60 @@
package org.horizon.eviction.algorithms.lru;
+import org.horizon.eviction.algorithms.BaseAlgorithmTest;
import org.testng.annotations.Test;
@Test(groups = "unit")
-public class LruAlgorithmTest {
+public class LruAlgorithmTest extends BaseAlgorithmTest {
+
+ protected LRUAlgorithmConfig getNewEvictionAlgorithmConfig() {
+ return new LRUAlgorithmConfig();
+ }
+//
+// public void testMinTimeToLive() throws Exception {
+// LRUAlgorithmConfig cfg = getNewEvictionAlgorithmConfig();
+// cfg.setMinTimeToLive(2 * 60 * 60 * 1000); // something enormous - 2 hrs
+// cfg.setMaxEntries(5);
+// EvictionAlgorithm a = createAndInit(cfg);
+// EvictionAction mockAction = EasyMock.createMock(EvictionAction.class);
+// a.setEvictionAction(mockAction);
+// BlockingQueue<EvictionEvent> eventQueue = new LinkedBlockingQueue<EvictionEvent>();
+// for (int i = 0; i < 10; i++) eventQueue.put(new EvictionEvent(i, EvictionEvent.Type.ADD_ENTRY_EVENT));
+//
+// assert eventQueue.size() == 10;
+//
+// // what do we expect to happen on the eviction action class?
+// // nothing at this stage.
+// replay(mockAction);
+// a.process(eventQueue);
+// verify(mockAction);
+//
+// for (EntryEvictionData data : a.getEvictionQueue()) {
+// // change the creation timestamp to before 2 hrs in the past
+// // for all even keys
+// Integer key = (Integer) data.getKey();
+//
+// if (key % 2 == 0) {
+// data.setCreationTimeStamp(1);
+// data.setModifiedTimeStamp(1);
+// EvictionEvent e = new EvictionEvent(key, EvictionEvent.Type.VISIT_ENTRY_EVENT);
+// e.setCreationTimestamp(1);
+// eventQueue.put(e);
+// } else {
+// eventQueue.put(new EvictionEvent(key, EvictionEvent.Type.VISIT_ENTRY_EVENT));
+// }
+// }
+//
+// assert eventQueue.size() == 10;
+//
+// // this time we expect all even numbered keys to get evicted.
+// reset(mockAction);
+// expect(mockAction.evict(eq(0))).andReturn(true).once();
+// expect(mockAction.evict(eq(2))).andReturn(true).once();
+// expect(mockAction.evict(eq(4))).andReturn(true).once();
+// expect(mockAction.evict(eq(6))).andReturn(true).once();
+// expect(mockAction.evict(eq(8))).andReturn(true).once();
+// replay(mockAction);
+// a.process(eventQueue);
+// verify(mockAction);
+// }
}
Modified: core/branches/flat/src/test/java/org/horizon/eviction/algorithms/lru/LruQueueTest.java
===================================================================
--- core/branches/flat/src/test/java/org/horizon/eviction/algorithms/lru/LruQueueTest.java 2009-02-03 13:51:43 UTC (rev 7632)
+++ core/branches/flat/src/test/java/org/horizon/eviction/algorithms/lru/LruQueueTest.java 2009-02-03 21:28:24 UTC (rev 7633)
@@ -1,7 +1,139 @@
package org.horizon.eviction.algorithms.lru;
+import org.horizon.eviction.EntryEvictionData;
+import org.horizon.eviction.EvictionQueue;
+import org.horizon.eviction.algorithms.BaseQueueTest;
import org.testng.annotations.Test;
+import java.util.Iterator;
+
@Test(groups = "unit")
-public class LruQueueTest {
+public class LruQueueTest extends BaseQueueTest {
+ protected EvictionQueue getNewEvictionQueue() {
+ return new LRUQueue();
+ }
+
+ public void testOrder() throws Exception {
+ LRUQueue queue = new LRUQueue();
+ fillQueue(queue, 500);
+
+ for (int i = 0; i < 500; i++) {
+ if ((i < 100) || (i >= 300 && i < 400)) {
+ // visit the entries from 0-99 and the entries from 300 - 399
+ reorderByLRU(queue, i);
+ }
+ }
+
+ // visiting the nodes should have no affect on the maxAgeQueue.
+ Iterator<EntryEvictionData> maxAgeIt = queue.iterateMaxAgeQueue();
+ int count = 0;
+ long lastTs = 0;
+ while (maxAgeIt.hasNext()) {
+ EntryEvictionData data = maxAgeIt.next();
+ assert lastTs <= data.getCreationTimeStamp();
+ lastTs = data.getCreationTimeStamp();
+ count++;
+ }
+
+ Iterator<EntryEvictionData> lruIt = queue.iterateLRUQueue();
+ count = 0;
+ while (lruIt.hasNext()) {
+ EntryEvictionData data = lruIt.next();
+ int index = (Integer) data.getKey();
+
+ // the last 200 in the list should be the visisted LRU ones.
+ if (count >= 300 && count < 400)
+ assert count - 300 == index;
+ else if (count >= 400 && count < 500)
+ assert count - 100 == index;
+ else if (count < 200)
+ assert count + 100 == index;
+ else if (count >= 200 && count < 300)
+ assert count + 200 == index;
+
+ count++;
+ }
+
+ Object key = getFirstEntryKey(queue);
+ queue.remove(key);
+ assert 499 == queue.size();
+
+ EntryEvictionData data = queue.iterateLRUQueue().next();
+ queue.remove(data.getKey());
+ assert 498 == queue.size();
+ }
+
+ public void testEmptyingInternalCollections() {
+ LRUQueue queue = new LRUQueue();
+ fillQueue(queue, 1000);
+ assert queue.size() == 1000;
+ assert queue.maxAgeQueue.size() == 1000;
+ assert queue.lruQueue.size() == 1000;
+
+ for (Iterator<EntryEvictionData> it = queue.iterator(); it.hasNext() && it.next() != null;) it.remove();
+
+ assert queue.isEmpty();
+ assert queue.maxAgeQueue.isEmpty();
+ assert queue.lruQueue.isEmpty();
+ }
+
+ public void testGetFirstLRUNodeEntry() throws Exception {
+ LRUQueue queue = new LRUQueue();
+ fillQueue(queue, 100);
+
+ for (int i = 0; i < 100; i++) {
+ // this should move all the even numbered entries to the bottom of the lruQueue.
+ // maxAgeQueue should be unaffected.
+ if (i % 2 == 0) reorderByLRU(queue, i);
+ }
+
+ assert 100 == queue.size();
+
+ int count = 0;
+ for (Iterator<EntryEvictionData> it = queue.iterateLRUQueue(); it.hasNext();) {
+ int nodeIndex = (Integer) it.next().getKey();
+
+ if (count < 50) {
+ // the top 50 should be all odds in the lruQueue/
+ assert nodeIndex % 2 != 0;
+ } else {
+ // the bottom fifty should all be even #'s (and 0)
+ assert nodeIndex % 2 == 0;
+ }
+ it.remove();
+ count++;
+ }
+ assert queue.isEmpty();
+ }
+
+ public void testGetFirstMaxAgeNodeEntriy() throws Exception {
+ LRUQueue queue = new LRUQueue();
+ fillQueue(queue, 100);
+
+ for (int i = 0; i < 100; i++) {
+ // this should move all the even numbered NodeEntries to the bottom of the lruQueue.
+ // maxAgeQueue should be unaffected.
+ if (i % 2 == 0) {
+ reorderByLRU(queue, i);
+ }
+ }
+
+ int count = 0;
+ for (Iterator<EntryEvictionData> it = queue.iterateMaxAgeQueue(); it.hasNext();) {
+ int nodeIndex = (Integer) it.next().getKey();
+ assert count == nodeIndex;
+ it.remove();
+ count++;
+ }
+
+ assert queue.isEmpty();
+ }
+
+ private void reorderByLRU(LRUQueue queue, Object key) {
+ // leave the max age queue alone - it is like a fifo.
+
+ // the lru queue is access ordered. meaning the most recently read item is moved to the bottom of the queue.
+ // simply calling get against it visits it and will cause LinkedHashMap to move it to the bottom of the queue.
+ queue.lruQueue.get(key);
+ }
}
Modified: core/branches/flat/src/test/java/org/horizon/eviction/algorithms/mru/MruAlgorithmTest.java
===================================================================
--- core/branches/flat/src/test/java/org/horizon/eviction/algorithms/mru/MruAlgorithmTest.java 2009-02-03 13:51:43 UTC (rev 7632)
+++ core/branches/flat/src/test/java/org/horizon/eviction/algorithms/mru/MruAlgorithmTest.java 2009-02-03 21:28:24 UTC (rev 7633)
@@ -1,7 +1,73 @@
package org.horizon.eviction.algorithms.mru;
+import org.horizon.eviction.algorithms.BaseAlgorithmTest;
import org.testng.annotations.Test;
@Test(groups = "unit")
-public class MruAlgorithmTest {
+public class MruAlgorithmTest extends BaseAlgorithmTest {
+ protected MRUAlgorithmConfig getNewEvictionAlgorithmConfig() {
+ return new MRUAlgorithmConfig();
+ }
+//
+// public void testMinTimeToLive() throws Exception {
+// MRUAlgorithmConfig cfg = getNewEvictionAlgorithmConfig();
+// cfg.setMinTimeToLive(2 * 60 * 60 * 1000); // something enormous - 2 hrs
+// cfg.setMaxEntries(5);
+// EvictionAlgorithm a = createAndInit(cfg);
+// EvictionAction mockAction = EasyMock.createMock(EvictionAction.class);
+// a.setEvictionAction(mockAction);
+// BlockingQueue<EvictionEvent> eventQueue = new LinkedBlockingQueue<EvictionEvent>();
+// for (int i = 0; i < 10; i++) eventQueue.put(new EvictionEvent(i, EvictionEvent.Type.ADD_ENTRY_EVENT));
+//
+// assert eventQueue.size() == 10;
+//
+// // what do we expect to happen on the eviction action class?
+// // nothing at this stage.
+// replay(mockAction);
+// a.process(eventQueue);
+// verify(mockAction);
+//
+//
+// // the MRU queue doesn't actually work on timestamps, but instead considers the most recently accessed, and uses a stack.
+// for (EntryEvictionData data : a.getEvictionQueue()) {
+// Integer key = (Integer) data.getKey();
+//
+// if (key % 2 == 1) {
+// // so first touch all of the odd keys.
+// data.setCreationTimeStamp(1);
+// data.setModifiedTimeStamp(1);
+// EvictionEvent e = new EvictionEvent(key, EvictionEvent.Type.VISIT_ENTRY_EVENT);
+// e.setCreationTimestamp(1);
+// eventQueue.put(e);
+// }
+// }
+// // and now the event ones
+// for (EntryEvictionData data : a.getEvictionQueue()) {
+// Integer key = (Integer) data.getKey();
+//
+// if (key % 2 == 0) {
+// // so first touch all of the odd keys.
+// data.setCreationTimeStamp(1);
+// data.setModifiedTimeStamp(1);
+// EvictionEvent e = new EvictionEvent(key, EvictionEvent.Type.VISIT_ENTRY_EVENT);
+// e.setCreationTimestamp(1);
+// eventQueue.put(e);
+// }
+// }
+//
+//
+// // so that the even keys will be the most recently used.
+// assert eventQueue.size() == 10;
+//
+// // this time we expect all even numbered keys to get evicted.
+// reset(mockAction);
+// expect(mockAction.evict(eq(0))).andReturn(true).once();
+// expect(mockAction.evict(eq(2))).andReturn(true).once();
+// expect(mockAction.evict(eq(4))).andReturn(true).once();
+// expect(mockAction.evict(eq(6))).andReturn(true).once();
+// expect(mockAction.evict(eq(8))).andReturn(true).once();
+// replay(mockAction);
+// a.process(eventQueue);
+// verify(mockAction);
+// }
}
Modified: core/branches/flat/src/test/java/org/horizon/eviction/algorithms/mru/MruQueueTest.java
===================================================================
--- core/branches/flat/src/test/java/org/horizon/eviction/algorithms/mru/MruQueueTest.java 2009-02-03 13:51:43 UTC (rev 7632)
+++ core/branches/flat/src/test/java/org/horizon/eviction/algorithms/mru/MruQueueTest.java 2009-02-03 21:28:24 UTC (rev 7633)
@@ -1,7 +1,43 @@
package org.horizon.eviction.algorithms.mru;
+import org.horizon.eviction.EntryEvictionData;
+import org.horizon.eviction.EvictionQueue;
+import org.horizon.eviction.algorithms.BaseQueueTest;
import org.testng.annotations.Test;
+import java.util.Iterator;
+
@Test(groups = "unit")
-public class MruQueueTest {
+public class MruQueueTest extends BaseQueueTest {
+ protected EvictionQueue getNewEvictionQueue() {
+ return new MRUQueue();
+ }
+
+ public void testOrder() throws Exception {
+ MRUQueue queue = new MRUQueue();
+ fillQueue(queue, 100);
+ for (int i = 0; i < 100; i++) {
+ if (i % 2 == 0) {
+ EntryEvictionData data = queue.get(i);
+ data.setModifiedTimeStamp(System.currentTimeMillis());
+ queue.moveToTopOfStack(i);
+ }
+ }
+
+ int count = 0;
+ for (Iterator<EntryEvictionData> it = queue.iterator(); it.hasNext();) {
+ EntryEvictionData data = it.next();
+ if (count < 50) {
+ assert data.getModifiedTimeStamp() > 0;
+ } else {
+ assert data.getModifiedTimeStamp() == 0;
+ }
+ it.remove();
+ count++;
+ }
+
+ assert queue.isEmpty();
+ assert queue.keyMap.isEmpty();
+ assert queue.list.isEmpty();
+ }
}
15 years, 10 months
JBoss Cache SVN: r7632 - core/trunk/src/main/java/org/jboss/cache/marshall.
by jbosscache-commits@lists.jboss.org
Author: mircea.markus
Date: 2009-02-03 08:51:43 -0500 (Tue, 03 Feb 2009)
New Revision: 7632
Modified:
core/trunk/src/main/java/org/jboss/cache/marshall/CacheMarshaller200.java
Log:
changed log message
Modified: core/trunk/src/main/java/org/jboss/cache/marshall/CacheMarshaller200.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/marshall/CacheMarshaller200.java 2009-02-03 13:49:19 UTC (rev 7631)
+++ core/trunk/src/main/java/org/jboss/cache/marshall/CacheMarshaller200.java 2009-02-03 13:51:43 UTC (rev 7632)
@@ -443,7 +443,7 @@
{
if (trace)
{
- log.trace("Warning: using object serialization for " + o.getClass());
+ log.trace("Not optimum: using object serialization for " + o.getClass());
}
out.writeByte(MAGICNUMBER_SERIALIZABLE);
if (useRefs) writeReference(out, createReference(o, refMap));
15 years, 10 months
JBoss Cache SVN: r7631 - core/trunk/src/test/java/org/jboss/cache/util.
by jbosscache-commits@lists.jboss.org
Author: mircea.markus
Date: 2009-02-03 08:49:19 -0500 (Tue, 03 Feb 2009)
New Revision: 7631
Modified:
core/trunk/src/test/java/org/jboss/cache/util/SingleBuddyGravitationHelper.java
Log:
fixed replication expectation
Modified: core/trunk/src/test/java/org/jboss/cache/util/SingleBuddyGravitationHelper.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/util/SingleBuddyGravitationHelper.java 2009-02-03 13:44:19 UTC (rev 7630)
+++ core/trunk/src/test/java/org/jboss/cache/util/SingleBuddyGravitationHelper.java 2009-02-03 13:49:19 UTC (rev 7631)
@@ -194,7 +194,7 @@
private boolean newOwnerIsBuddyOfOldOwner()
{
- return (toIndex - 1 == fromIndex) || (toIndex == caches.length - 1 && fromIndex == 0);
+ return (toIndex - 1 == fromIndex) || (toIndex == 0 && fromIndex == caches.length - 1);
}
private void waitForReplication()
15 years, 10 months
JBoss Cache SVN: r7630 - in core/trunk/src/test/java/org/jboss/cache/api: mvcc/read_committed and 2 other directories.
by jbosscache-commits@lists.jboss.org
Author: mircea.markus
Date: 2009-02-03 08:44:19 -0500 (Tue, 03 Feb 2009)
New Revision: 7630
Added:
core/trunk/src/test/java/org/jboss/cache/api/NodeMoveAPIWithCLTest.java
core/trunk/src/test/java/org/jboss/cache/api/mvcc/read_committed/NodeMoveWithCLMvccTest.java
core/trunk/src/test/java/org/jboss/cache/api/mvcc/repeatable_read/NodeMoveWithCLMvccTest.java
core/trunk/src/test/java/org/jboss/cache/api/optimistic/NodeMoveAPIWithCLOptimisticTest.java
Modified:
core/trunk/src/test/java/org/jboss/cache/api/NodeMoveAPITest.java
Log:
CL tests interfered causing intermitent failures, fixed that by sepparating tests
Modified: core/trunk/src/test/java/org/jboss/cache/api/NodeMoveAPITest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/api/NodeMoveAPITest.java 2009-02-03 09:56:12 UTC (rev 7629)
+++ core/trunk/src/test/java/org/jboss/cache/api/NodeMoveAPITest.java 2009-02-03 13:44:19 UTC (rev 7630)
@@ -3,19 +3,13 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.cache.*;
-import org.jboss.cache.config.CacheLoaderConfig;
import org.jboss.cache.config.Configuration;
import org.jboss.cache.config.Configuration.NodeLockingScheme;
-import org.jboss.cache.config.parsing.XmlConfigHelper;
-import org.jboss.cache.config.parsing.element.LoadersElementParser;
-import org.jboss.cache.loader.testloaders.DummyInMemoryCacheLoader;
import org.jboss.cache.util.TestingUtil;
import static org.testng.AssertJUnit.*;
import org.testng.annotations.Test;
-import org.w3c.dom.Element;
import javax.transaction.TransactionManager;
-import java.util.Map;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
@@ -258,105 +252,6 @@
assertEquals(nodeB, nodeA.getChildren().iterator().next());
}
- public void testWithCacheloaders() throws Exception
- {
- doCacheLoaderTest(false, false);
- }
-
- public void testWithPassivation() throws Exception
- {
- doCacheLoaderTest(true, false);
- }
-
- public void testWithCacheloadersTx() throws Exception
- {
- doCacheLoaderTest(false, true);
- }
-
- public void testWithPassivationTx() throws Exception
- {
- doCacheLoaderTest(true, true);
- }
-
- protected void doCacheLoaderTest(boolean pasv, boolean useTx) throws Exception
- {
- Node<Object, Object> rootNode = cache.getRoot();
-
- cache.destroy();
- cache.getConfiguration().setCacheLoaderConfig(getSingleCacheLoaderConfig(pasv, "/", DummyInMemoryCacheLoader.class.getName(), "debug=true", false, false, false, false));
- cache.start();
-
- DummyInMemoryCacheLoader loader = (DummyInMemoryCacheLoader) cache.getCacheLoaderManager().getCacheLoader();
-
- rootNode.put("key", "value");
-
- if (!pasv)
- {
- Map m = loader.get(Fqn.ROOT);
- assertNotNull("Should not be null", m);
- assertEquals("value", m.get("key"));
- }
-
- Node<Object, Object> nodeA = rootNode.addChild(A);
- nodeA.put(k, vA);
- Node<Object, Object> nodeB = rootNode.addChild(B);
- nodeB.put(k, vB);
- Node<Object, Object> nodeC = nodeA.addChild(C);
- nodeC.put(k, vC);
- Node<Object, Object> nodeD = nodeC.addChild(D);
- nodeD.put(k, vD);
- Node<Object, Object> nodeE = nodeD.addChild(E);
- nodeE.put(k, vE);
- cache.evict(Fqn.ROOT, true);
-
- // move
- if (useTx) tm.begin();
- cache.move(nodeC.getFqn(), nodeB.getFqn());
- if (useTx) tm.commit();
-
- // after eviction, the node objects we hold are probably stale.
- nodeA = rootNode.getChild(A);
- nodeB = rootNode.getChild(B);
- nodeC = nodeB.getChild(C);
- log.info("nodeC get child B ");
- nodeD = nodeC.getChild(D);
- log.info("nodeD get child E ");
- nodeE = nodeD.getChild(E);
-
- Fqn old_C = C;
- Fqn old_D = Fqn.fromRelativeFqn(old_C, D);
- Fqn old_E = Fqn.fromRelativeFqn(old_D, E);
-
- // test data
- assertEquals(vA, nodeA.get(k));
- assertEquals(vB, nodeB.get(k));
- assertEquals(vC, nodeC.get(k));
- assertEquals(vD, nodeD.get(k));
- assertEquals(vE, nodeE.get(k));
-
- // parentage
- assertEquals(rootNode, nodeA.getParent());
- assertEquals(rootNode, nodeB.getParent());
- assertEquals(nodeB, nodeC.getParent());
- assertEquals(nodeC, nodeD.getParent());
- assertEquals(nodeD, nodeE.getParent());
-
-
- if (pasv) cache.evict(Fqn.ROOT, true);
-
- //now inspect the loader.
- assertEquals(vA, loader.get(nodeA.getFqn()).get(k));
- assertEquals(vB, loader.get(nodeB.getFqn()).get(k));
- assertEquals(vC, loader.get(nodeC.getFqn()).get(k));
- assertEquals(vD, loader.get(nodeD.getFqn()).get(k));
- assertEquals(vE, loader.get(nodeE.getFqn()).get(k));
-
- assertNull(loader.get(old_C));
- assertNull(loader.get(old_D));
- assertNull(loader.get(old_E));
-
- }
-
public void testLocksDeepMove() throws Exception
{
Node<Object, Object> rootNode = cache.getRoot();
@@ -446,7 +341,7 @@
for (int i = 0; i < N; i++)
{
- movers[i] = new Thread("Mover-" + i)
+ movers[i] = new Thread(Thread.currentThread().getName() + " -Mover-" + i)
{
public void run()
{
@@ -541,25 +436,6 @@
assert 0 == cache.getNumberOfLocksHeld();
}
- protected CacheLoaderConfig getSingleCacheLoaderConfig(boolean passivation, String preload, String cacheloaderClass, String properties, boolean async, boolean fetchPersistentState, boolean shared, boolean purgeOnStartup) throws Exception
- {
- String xml =
- " <loaders passivation=\"" + passivation + "\" shared=\"" + shared + "\">\n" +
- " <preload>\n" +
- " <node fqn=\"" + preload + "\"/>\n" +
- " </preload>\n" +
- " <loader class=\"" + cacheloaderClass + "\" async=\"" + async + "\" fetchPersistentState=\"" + fetchPersistentState + "\"\n" +
- " purgeOnStartup=\"" + purgeOnStartup + "\">\n" +
- " <properties>\n" +
- properties +
- " </properties>\n" +
- " </loader>\n" +
- " </loaders>";
- Element element = XmlConfigHelper.stringToElementInCoreNS(xml);
- LoadersElementParser elementParser = new LoadersElementParser();
- return elementParser.parseLoadersElement(element);
- }
-
protected boolean isOptimistic()
{
return false;
Added: core/trunk/src/test/java/org/jboss/cache/api/NodeMoveAPIWithCLTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/api/NodeMoveAPIWithCLTest.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/api/NodeMoveAPIWithCLTest.java 2009-02-03 13:44:19 UTC (rev 7630)
@@ -0,0 +1,172 @@
+package org.jboss.cache.api;
+
+import org.testng.annotations.Test;
+import static org.testng.AssertJUnit.assertNotNull;
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertNull;
+import org.jboss.cache.*;
+import org.jboss.cache.config.Configuration;
+import org.jboss.cache.config.CacheLoaderConfig;
+import org.jboss.cache.config.parsing.XmlConfigHelper;
+import org.jboss.cache.config.parsing.element.LoadersElementParser;
+import org.jboss.cache.loader.testloaders.DummyInMemoryCacheLoader;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.w3c.dom.Element;
+
+import javax.transaction.TransactionManager;
+import java.util.Map;
+
+/**
+ * @author Mircea.Markus(a)jboss.com
+ */
+@Test(groups = {"functional", "pessimistic"}, testName = "api.NodeMoveAPIWithCLTest")
+public class NodeMoveAPIWithCLTest extends AbstractSingleCacheTest
+{
+
+ protected final Log log = LogFactory.getLog(getClass());
+
+ protected static final Fqn A = Fqn.fromString("/a"), B = Fqn.fromString("/b"), C = Fqn.fromString("/c"), D = Fqn.fromString("/d"), E = Fqn.fromString("/e");
+ protected static final Object k = "key", vA = "valueA", vB = "valueB", vC = "valueC", vD = "valueD", vE = "valueE";
+
+ protected Configuration.NodeLockingScheme nodeLockingScheme = Configuration.NodeLockingScheme.PESSIMISTIC;
+
+ private TransactionManager tm;
+
+ protected CacheSPI createCache()
+ {
+ // start a single cache instance
+ CacheSPI<Object, Object> cache = (CacheSPI<Object, Object>) new UnitTestCacheFactory<Object, Object>().createCache("configs/local-tx.xml", false, getClass());
+ cache.getConfiguration().setNodeLockingScheme(nodeLockingScheme);
+ cache.getConfiguration().setFetchInMemoryState(false);
+ cache.getConfiguration().setEvictionConfig(null);
+ configure(cache.getConfiguration());
+ cache.start();
+ tm = cache.getTransactionManager();
+ return cache;
+ }
+
+ protected void configure(Configuration c)
+ {
+ // to be overridden
+ }
+
+
+ public void testWithCacheloaders() throws Exception
+ {
+ doCacheLoaderTest(false, false);
+ }
+
+ public void testWithPassivation() throws Exception
+ {
+ doCacheLoaderTest(true, false);
+ }
+
+ public void testWithCacheloadersTx() throws Exception
+ {
+ doCacheLoaderTest(false, true);
+ }
+
+ public void testWithPassivationTx() throws Exception
+ {
+ doCacheLoaderTest(true, true);
+ }
+
+ protected void doCacheLoaderTest(boolean pasv, boolean useTx) throws Exception
+ {
+ Node<Object, Object> rootNode = cache.getRoot();
+
+ cache.destroy();
+ cache.getConfiguration().setCacheLoaderConfig(getSingleCacheLoaderConfig(pasv, "/", DummyInMemoryCacheLoader.class.getName(), "debug=true", false, false, false, false));
+ cache.start();
+
+ DummyInMemoryCacheLoader loader = (DummyInMemoryCacheLoader) cache.getCacheLoaderManager().getCacheLoader();
+
+ rootNode.put("key", "value");
+
+ if (!pasv)
+ {
+ Map m = loader.get(Fqn.ROOT);
+ assertNotNull("Should not be null", m);
+ assertEquals("value", m.get("key"));
+ }
+
+ Node<Object, Object> nodeA = rootNode.addChild(A);
+ nodeA.put(k, vA);
+ Node<Object, Object> nodeB = rootNode.addChild(B);
+ nodeB.put(k, vB);
+ Node<Object, Object> nodeC = nodeA.addChild(C);
+ nodeC.put(k, vC);
+ Node<Object, Object> nodeD = nodeC.addChild(D);
+ nodeD.put(k, vD);
+ Node<Object, Object> nodeE = nodeD.addChild(E);
+ nodeE.put(k, vE);
+ cache.evict(Fqn.ROOT, true);
+
+ // move
+ if (useTx) tm.begin();
+ cache.move(nodeC.getFqn(), nodeB.getFqn());
+ if (useTx) tm.commit();
+
+ // after eviction, the node objects we hold are probably stale.
+ nodeA = rootNode.getChild(A);
+ nodeB = rootNode.getChild(B);
+ nodeC = nodeB.getChild(C);
+ log.info("nodeC get child B ");
+ nodeD = nodeC.getChild(D);
+ log.info("nodeD get child E ");
+ nodeE = nodeD.getChild(E);
+
+ Fqn old_C = C;
+ Fqn old_D = Fqn.fromRelativeFqn(old_C, D);
+ Fqn old_E = Fqn.fromRelativeFqn(old_D, E);
+
+ // test data
+ assertEquals(vA, nodeA.get(k));
+ assertEquals(vB, nodeB.get(k));
+ assertEquals(vC, nodeC.get(k));
+ assertEquals(vD, nodeD.get(k));
+ assertEquals(vE, nodeE.get(k));
+
+ // parentage
+ assertEquals(rootNode, nodeA.getParent());
+ assertEquals(rootNode, nodeB.getParent());
+ assertEquals(nodeB, nodeC.getParent());
+ assertEquals(nodeC, nodeD.getParent());
+ assertEquals(nodeD, nodeE.getParent());
+
+
+ if (pasv) cache.evict(Fqn.ROOT, true);
+
+ //now inspect the loader.
+ assertEquals(vA, loader.get(nodeA.getFqn()).get(k));
+ assertEquals(vB, loader.get(nodeB.getFqn()).get(k));
+ assertEquals(vC, loader.get(nodeC.getFqn()).get(k));
+ assertEquals(vD, loader.get(nodeD.getFqn()).get(k));
+ assertEquals(vE, loader.get(nodeE.getFqn()).get(k));
+
+ assertNull(loader.get(old_C));
+ assertNull(loader.get(old_D));
+ assertNull(loader.get(old_E));
+
+ }
+
+ protected CacheLoaderConfig getSingleCacheLoaderConfig(boolean passivation, String preload, String cacheloaderClass, String properties, boolean async, boolean fetchPersistentState, boolean shared, boolean purgeOnStartup) throws Exception
+ {
+ String xml =
+ " <loaders passivation=\"" + passivation + "\" shared=\"" + shared + "\">\n" +
+ " <preload>\n" +
+ " <node fqn=\"" + preload + "\"/>\n" +
+ " </preload>\n" +
+ " <loader class=\"" + cacheloaderClass + "\" async=\"" + async + "\" fetchPersistentState=\"" + fetchPersistentState + "\"\n" +
+ " purgeOnStartup=\"" + purgeOnStartup + "\">\n" +
+ " <properties>\n" +
+ properties +
+ " </properties>\n" +
+ " </loader>\n" +
+ " </loaders>";
+ Element element = XmlConfigHelper.stringToElementInCoreNS(xml);
+ LoadersElementParser elementParser = new LoadersElementParser();
+ return elementParser.parseLoadersElement(element);
+ }
+}
Added: core/trunk/src/test/java/org/jboss/cache/api/mvcc/read_committed/NodeMoveWithCLMvccTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/api/mvcc/read_committed/NodeMoveWithCLMvccTest.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/api/mvcc/read_committed/NodeMoveWithCLMvccTest.java 2009-02-03 13:44:19 UTC (rev 7630)
@@ -0,0 +1,20 @@
+package org.jboss.cache.api.mvcc.read_committed;
+
+import org.jboss.cache.config.Configuration;
+import org.jboss.cache.lock.IsolationLevel;
+import org.jboss.cache.api.NodeMoveAPIWithCLTest;
+import org.testng.annotations.Test;
+
+/**
+ * @author Mircea.Markus(a)jboss.com
+ */
+@Test(groups = {"functional", "mvcc"}, testName = "api.mvcc.read_committed.NodeMoveWithCLMvccTest")
+public class NodeMoveWithCLMvccTest extends NodeMoveAPIWithCLTest
+{
+ @Override
+ protected void configure(Configuration c)
+ {
+ c.setIsolationLevel(IsolationLevel.READ_COMMITTED);
+ }
+
+}
Added: core/trunk/src/test/java/org/jboss/cache/api/mvcc/repeatable_read/NodeMoveWithCLMvccTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/api/mvcc/repeatable_read/NodeMoveWithCLMvccTest.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/api/mvcc/repeatable_read/NodeMoveWithCLMvccTest.java 2009-02-03 13:44:19 UTC (rev 7630)
@@ -0,0 +1,20 @@
+package org.jboss.cache.api.mvcc.repeatable_read;
+
+import org.jboss.cache.config.Configuration;
+import org.jboss.cache.lock.IsolationLevel;
+import org.jboss.cache.api.NodeMoveAPIWithCLTest;
+import org.testng.annotations.Test;
+
+/**
+ * @author Mircea.Markus(a)jboss.com
+ */
+@Test(groups = {"functional", "mvcc"}, testName = "api.mvcc.repeatable_read.NodeMoveWithCLMvccTest")
+public class NodeMoveWithCLMvccTest extends NodeMoveAPIWithCLTest
+{
+ @Override
+ protected void configure(Configuration c)
+ {
+ c.setIsolationLevel(IsolationLevel.REPEATABLE_READ);
+ }
+
+}
\ No newline at end of file
Added: core/trunk/src/test/java/org/jboss/cache/api/optimistic/NodeMoveAPIWithCLOptimisticTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/api/optimistic/NodeMoveAPIWithCLOptimisticTest.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/api/optimistic/NodeMoveAPIWithCLOptimisticTest.java 2009-02-03 13:44:19 UTC (rev 7630)
@@ -0,0 +1,18 @@
+package org.jboss.cache.api.optimistic;
+
+import org.testng.annotations.Test;
+import org.jboss.cache.config.Configuration;
+import org.jboss.cache.api.NodeMoveAPIWithCLTest;
+
+/**
+ * @author Mircea.Markus(a)jboss.com
+ */
+@Test(groups = {"functional", "optimistic"}, testName = "api.optimistic.NodeMoveAPIWithCLOptimisticTest")
+public class NodeMoveAPIWithCLOptimisticTest extends NodeMoveAPIWithCLTest
+{
+ protected Configuration.NodeLockingScheme getNodeLockingScheme()
+ {
+ return Configuration.NodeLockingScheme.OPTIMISTIC;
+ }
+
+}
15 years, 10 months
JBoss Cache SVN: r7629 - core/trunk/src/test/java/org/jboss/cache/loader.
by jbosscache-commits@lists.jboss.org
Author: manik.surtani(a)jboss.com
Date: 2009-02-03 04:56:12 -0500 (Tue, 03 Feb 2009)
New Revision: 7629
Modified:
core/trunk/src/test/java/org/jboss/cache/loader/CacheLoaderTestsBase.java
Log:
Added rollback test
Modified: core/trunk/src/test/java/org/jboss/cache/loader/CacheLoaderTestsBase.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/loader/CacheLoaderTestsBase.java 2009-02-03 02:16:01 UTC (rev 7628)
+++ core/trunk/src/test/java/org/jboss/cache/loader/CacheLoaderTestsBase.java 2009-02-03 09:56:12 UTC (rev 7629)
@@ -1687,27 +1687,19 @@
{
loader.remove(Fqn.fromString("/"));
- int num = 0;
- try
- {
- ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
- MarshalledValueOutputStream os = new MarshalledValueOutputStream(baos);
- loader.loadEntireState(os);
- num = baos.size();
- }
- catch (UnsupportedOperationException ex)
- {
- return;
- }
+ cache.put(FQN, "K", "V");
+ assert loader.get(FQN).get("K").equals("V");
+ assert cache.get(FQN, "K").equals("V");
- Object txnKey = new Object();
- List<Modification> mods = createUpdates();
- loader.prepare(txnKey, mods, false);
- loader.rollback(txnKey);
- ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
- MarshalledValueOutputStream os = new MarshalledValueOutputStream(baos);
- loader.loadEntireState(os);
- assertEquals(num, baos.size());
+ // now modify K in a tx
+ cache.getTransactionManager().begin();
+ cache.put(FQN, "K", "V2");
+ assert loader.get(FQN).get("K").equals("V");
+ assert cache.get(FQN, "K").equals("V2");
+ cache.getTransactionManager().rollback();
+
+ assert loader.get(FQN).get("K").equals("V");
+ assert cache.get(FQN, "K").equals("V");
}
/**
15 years, 10 months