Author: asmuts
Date: Fri Aug 11 08:51:10 2006
New Revision: 430809
URL: http://svn.apache.org/viewvc?rev=430809&view=rev
Log:
Added a freeMemoryElements method.
Formatted a few classes.
Added some tests to the ARC memory cache implementation in the experimental
folder.
Added:
jakarta/jcs/trunk/src/experimental/org/apache/jcs/engine/memory/arc/ARCMemoryCacheUnitTest.java
jakarta/jcs/trunk/src/test-conf/TestARCCache.ccf
Modified:
jakarta/jcs/trunk/src/experimental/org/apache/jcs/engine/memory/arc/ARCMemoryCache.java
jakarta/jcs/trunk/src/java/org/apache/jcs/access/CacheAccess.java
jakarta/jcs/trunk/src/java/org/apache/jcs/access/behavior/ICacheAccess.java
jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/lateral/LateralCache.java
jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/lateral/LateralCacheNoWait.java
jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/lateral/LateralElementDescriptor.java
jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/lateral/socket/tcp/LateralTCPCacheManager.java
jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/lateral/socket/tcp/LateralTCPListener.java
jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/lateral/socket/tcp/LateralTCPSender.java
jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/lateral/socket/tcp/LateralTCPService.java
jakarta/jcs/trunk/src/java/org/apache/jcs/engine/memory/AbstractMemoryCache.java
jakarta/jcs/trunk/src/java/org/apache/jcs/engine/memory/MemoryCache.java
jakarta/jcs/trunk/src/java/org/apache/jcs/engine/memory/lru/LRUMemoryCache.java
jakarta/jcs/trunk/src/java/org/apache/jcs/engine/memory/mru/MRUMemoryCache.java
jakarta/jcs/trunk/src/java/org/apache/jcs/utils/serialization/StandardSerializer.java
jakarta/jcs/trunk/src/test-conf/TestTCPLateralCacheConcurrent.ccf
jakarta/jcs/trunk/src/test-conf/log4j.properties
jakarta/jcs/trunk/src/test/org/apache/jcs/auxiliary/lateral/socket/tcp/LateralTCPConcurrentRandomTestUtil.java
jakarta/jcs/trunk/src/test/org/apache/jcs/auxiliary/lateral/socket/tcp/LateralTCPNoDeadLockConcurrentTest.java
jakarta/jcs/trunk/src/test/org/apache/jcs/auxiliary/lateral/socket/tcp/TestTCPLateral.java
jakarta/jcs/trunk/src/test/org/apache/jcs/engine/memory/MemoryCacheMockImpl.java
Modified:
jakarta/jcs/trunk/src/experimental/org/apache/jcs/engine/memory/arc/ARCMemoryCache.java
URL:
http://svn.apache.org/viewvc/jakarta/jcs/trunk/src/experimental/org/apache/jcs/engine/memory/arc/ARCMemoryCache.java?rev=430809&r1=430808&r2=430809&view=diff
==============================================================================
---
jakarta/jcs/trunk/src/experimental/org/apache/jcs/engine/memory/arc/ARCMemoryCache.java
(original)
+++
jakarta/jcs/trunk/src/experimental/org/apache/jcs/engine/memory/arc/ARCMemoryCache.java
Fri Aug 11 08:51:10 2006
@@ -1,623 +1,797 @@
package org.apache.jcs.engine.memory.arc;
/*
- * Copyright 2001-2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License")
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Copyright 2001-2004 The Apache Software Foundation. Licensed under the
Apache
+ * License, Version 2.0 (the "License") you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
+ * or agreed to in writing, software distributed under the License is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
*/
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
-import EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-
import org.apache.jcs.engine.CacheElement;
-import org.apache.jcs.engine.control.CompositeCache;
import org.apache.jcs.engine.behavior.ICacheElement;
+import org.apache.jcs.engine.control.CompositeCache;
import org.apache.jcs.engine.memory.AbstractMemoryCache;
-import org.apache.jcs.utils.struct.DoubleLinkedList;
import org.apache.jcs.engine.memory.util.MemoryElementDescriptor;
import org.apache.jcs.engine.stats.StatElement;
import org.apache.jcs.engine.stats.Stats;
import org.apache.jcs.engine.stats.behavior.IStatElement;
import org.apache.jcs.engine.stats.behavior.IStats;
+import org.apache.jcs.utils.struct.DoubleLinkedList;
+
+import EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap;
/**
- * This is a rough implmentation of an adaptive replacement cache.
- * ARC is a hybrid LFU / LRU that adapts to user behavior.
- *
- * See the ARC method for more detail on how the algorithm works.
- *
- * @see
http://www.almaden.ibm.com/StorageSystems/autonomic_storage/ARC/index.shtml
+ * This is a rough implmentation of an adaptive replacement cache. ARC is a
+ * hybrid LFU / LRU that adapts to user behavior.
+ * <p>
+ * See the ARC method for more detail on how the algorithm works.
+ * <p>
+ * @see
http://www.almaden.ibm.com/StorageSystems/autonomic_storage/ARC/index.shtml
+ * @see http://www.almaden.ibm.com/cs/people/dmodha/ARC.pdf
*/
public class ARCMemoryCache
extends AbstractMemoryCache
{
+ private static final long serialVersionUID = 1L;
+
+ private final static Log log = LogFactory.getLog( ARCMemoryCache.class );
+
+ // private int[] loc = new int[0];
+
+ // maximum size
+ private int maxSize = 0;
+
+ private DoubleLinkedList T1 = new DoubleLinkedList();
+
+ private DoubleLinkedList T2 = new DoubleLinkedList();
+
+ private DoubleLinkedList B1 = new DoubleLinkedList();
+
+ private DoubleLinkedList B2 = new DoubleLinkedList();
+
+ /** id of list T1 */
+ protected static final int _T1_ = 1;
+
+ /** id of list T2 */
+ protected static final int _T2_ = 2;
+
+ /** id of list B1 */
+ protected static final int _B1_ = 3;
+
+ /** id of list B2 */
+ protected static final int _B2_ = 4;
+
+ // ideal size of T1
+ private int target_T1 = 0;
+
+ private ConcurrentHashMap map = new ConcurrentHashMap();
+
+ private int cnt = 0;
+
+ private int hitCnt = 0;
+
+ private int missCnt = 0;
+
+ private int putCnt = 0;
+
+ /**
+ * Default constructor.
+ */
+ public ARCMemoryCache()
+ {
+ if ( log.isInfoEnabled() )
+ {
+ log.info( "Loading Arc" );
+ }
+ }
+
+ /**
+ * Get an Array of the keys for all elements in the memory cache
+ * @return Object[]
+ */
+ public Object[] getKeyArray()
+ {
+ // need to lock to map here?
+ synchronized ( map )
+ {
+ return map.keySet().toArray();
+ }
+ }
+
+ public ICacheElement getQuiet( Serializable key )
+ throws IOException
+ {
+ return get( key );
+ }
+
+ /**
+ * For post reflection creation initialization
+ * <p>
+ * @param hub
+ */
+ public synchronized void initialize( CompositeCache hub )
+ {
+ super.initialize( hub );
+ maxSize = this.cattr.getMaxObjects(); // / 2;
+ target_T1 = maxSize / 2;
+ log.info( "initialized LRUMemoryCache for " + cacheName );
+ }
+
+ /**
+ * Looks for the item in the lists.
+ */
+ public ICacheElement get( Serializable key )
+ throws IOException
+ {
+ CacheElement ce = new CacheElement( cacheName, key, null );
+
+ ICacheElement ice = null;
+ try
+ {
+ ice = ARC( ce, true );
+ }
+ catch ( Exception e )
+ {
+ log.error( e );
+ }
+ return ice;
+ }
+
+ /**
+ * Adds an element to the cache.
+ */
+ public void update( ICacheElement ce )
+ {
+ try
+ {
+ ARC( ce, false );
+ }
+ catch ( Exception e )
+ {
+ log.error( e );
+ }
+ }
- private final static Log log =
- LogFactory.getLog(ARCMemoryCache.class);
+ /**
+ * This is the primary method for the ARC. It handles both puts and gets.
+ * <p>
+ * The ARC has 4 linked lists: T1, T2, B1, and B2. The 'T' lists are tops
+ * and the 'B' lists are bottoms. Bottom lists do not hold object, only
+ * keys.
+ * <p>
+ * The T1 list is an LRU (Least Recently Used) list. The T2 list is a near
+ * LFU (Least Frequently Used) list.
+ * <p>
+ * After items are removed from T1 and T2, their keys are stored in B1 and
+ * B2. The number of keys in B1 and B2 is restricted to the number of max
+ * items.
+ * <p>
+ * When there is a put or a get for an item whose key exists on one of the
+ * bottom lists, the maximum number of items in T1 is adjusted. If the item
+ * was found on B2 (the bottom LFU list) the maximum allowed in T1 (the top
+ * LRU list) is reduced. If the item is found in B1 list (the bottom LRU)
+ * the maximum allowed in T1 is increased.
+ * <p>
+ * The maximum allowed in T1 will not exceed the maxSize. The maximum in T1
+ * and T2 combined will not exceed the maxSize. The maximum number of
+ * elements and keys allowed in all 4 lists will not exceed twice the
+ * maximum size.
+ * <p>
+ * All the elements are stored in a map. The lists keep track of when the
+ * element was last used, or when it was deleted and from where. We first
+ * look for the item in the map, if we find it, we go looking for it in the
+ * lists.
+ * <p>
+ * @param ce
+ * ICacheElement
+ * @param isGet
+ * boolean
+ * @return ICacheElement
+ */
+ public ICacheElement ARC( ICacheElement ce, boolean isGet )
+ {
+ cnt++;
+ logStatsOccassionally( ce, isGet );
+ if ( !isGet )
+ {
+ putCnt++;
+ }
- int[] loc = new int[0];
+ ElementDescriptor temp = (ElementDescriptor) map.get( ce.getKey() );
+ boolean isHit = true;
- // maximum size
- int c = 0;
+ if ( temp != null )
+ {
+ if ( isGet )
+ {
+ hitCnt++;
+ }
- DoubleLinkedList T1 = new DoubleLinkedList();
- DoubleLinkedList T2 = new DoubleLinkedList();
- DoubleLinkedList B1 = new DoubleLinkedList();
- DoubleLinkedList B2 = new DoubleLinkedList();
-
- private static final int _T1_ = 1;
- private static final int _T2_ = 2;
- private static final int _B1_ = 3;
- private static final int _B2_ = 4;
-
- // ideal size of T1
- int target_T1 = 0;
-
- ConcurrentHashMap map = new ConcurrentHashMap();
-
- int cnt = 0;
-
- int hitCnt = 0;
- int missCnt = 0;
- int putCnt = 0;
-
- public ARCMemoryCache()
- {
- log.debug("Loading Arc");
- }
-
- public Object[] getKeyArray()
- {
- return null;
- }
-
- public ICacheElement getQuiet(Serializable key) throws IOException
- {
- return get(key);
- }
-
- /**
- * For post reflection creation initialization
- *
- *@param hub
- */
- public synchronized void initialize(CompositeCache hub)
- {
- super.initialize(hub);
- c = this.cattr.getMaxObjects(); // / 2;
- target_T1 = c / 2;
- log.info("initialized LRUMemoryCache for " + cacheName);
- }
-
- public ICacheElement get(Serializable key) throws IOException
- {
- CacheElement ce = new CacheElement(cacheName,
- (Serializable) key,
- null);
-
- ICacheElement ice = null;
- try {
- ice = ARC(ce, true);
- } catch( Exception e ) {
- log.error( e );
- }
- return ice;
- }
-
- public void update(ICacheElement ce)
- {
- try {
- ARC(ce, false);
- } catch( Exception e ) {
- log.error( e );
- }
- }
-
- /**
- * This is the primary method for the ARC. It handles both puts and gets.
- * The ARC has 4 linked lists: T1, T2, B1, and B2. The 'T' lists are tops
- * and the 'B' lists are bottoms. Bottom lists do not hold object, only
keys.
- *
- * The T1 list is an LRU (Least Recently Used) list. The T2 list is a near
- * LFU (Least Frequently Used) list.
- *
- * After items are removed from T1 and T2, their keys are stored in B1 and
B2.
- * The number of keys in B1 and B2 is restricted to the number of max items.
- *
- * When there is a put or a get for an item whose key exists on one of the
- * bottom lists, the maximum number of items in T1 is adjusted. If the item
- * was found on B2 (the bottom LFU list) the maximum allowed in T1 (the top
- * LRU list) is reduced. If the item is found in B1 list (the bottom LRU)
the
- * maximum allowed in T1 is increased.
- *
- * The maximum allowed in T1 will not exceed the maxSize. The maximum in T1
- * and T2 combined will not exceed the maxSize. The maximum number of
elements
- * and keys allowed in all 4 lists will not exceed twice the maximum size.
- *
- * @param ce ICacheElement
- * @param isGet boolean
- * @return ICacheElement
- */
- public ICacheElement ARC(ICacheElement ce, boolean isGet)
- {
-
- cnt++;
-
- if (cnt % 10000 == 0)
- //if ( true )
- {
- if (log.isInfoEnabled())
- {
- StringBuffer buf = new StringBuffer();
- buf.append("\n ce.key() = " + ce.getKey());
- buf.append("\n isGet = " + isGet);
- buf.append(getStats());
- log.info(buf.toString());
- }
- }
-
- if (!isGet)
- {
- putCnt++;
- }
-
- ElementDescriptor temp = (ElementDescriptor) map.get(ce.getKey());
- boolean isHit = true;
-
- if (temp != null)
- {
-
- if (isGet)
- {
- hitCnt++;
- }
-
- switch (temp.listNum)
- {
- case _T1_:
- if (log.isDebugEnabled())
- {
- log.debug("T1");
- }
-
- log.debug("T1 to T2, before remove = " + T1.size());
- boolean stat1 = T1.remove(temp); // need to implement our own list
- log.debug("T1 to T2, after remove = " + T1.size() + " stat = " +
stat1);
-
- temp.listNum = _T2_;
- T2.addFirst(temp);
- break;
-
- case _T2_:
- if (log.isDebugEnabled())
- {
- log.debug("T2");
- }
-
- temp.listNum = _T2_;
- T2.makeFirst(temp);
- break;
-
- case _B1_:
-
- // B1 hit: favor recency
-
- // adapt the target size
- target_T1 = Math.min(target_T1 + Math.max(B2.size() / B1.size(), 1),
- c);
- if (log.isDebugEnabled())
- {
- log.debug("B1, targetT1 = " + target_T1 );
- }
-
- if (!isGet)
- {
- if (log.isDebugEnabled())
+ // determine where the element lives.
+ switch ( temp.listNum )
+ {
+ case _T1_:
+ handleFoundInT1( temp );
+ break;
+
+ case _T2_:
+ handleFoundInT2( temp );
+ break;
+
+ case _B1_:
+ temp = handleFoundInB1( ce, isGet, temp );
+ break;
+
+ case _B2_:
+ temp = handleFoundInB2( ce, isGet, temp );
+ break;
+ }
+ }
+ else
+ {
+ /* Element is not in cache */
+ isHit = false;
+ if ( isGet )
{
- log.debug("B1 before remove = " + B1.size());
+ missCnt++;
}
- boolean stat3 = B1.remove(temp); // need to implement our own list
- if (log.isDebugEnabled())
+ if ( log.isDebugEnabled() )
{
- log.debug("B1 after remove = " + B1.size() + " stat = " + stat3);
+ log.debug( "Element is not in cache" );
}
- replace(temp);
- temp.listNum = _T2_;
+ }
+
+ //
////////////////////////////////////////////////////////////////////////////
+ // Do some size Checks if this is a put
+ if ( !isGet && !isHit )
+ {
+ if ( T1.size() + B1.size() >= maxSize )
+ {
+ /* B1 + T1 full? */
+ if ( T1.size() < maxSize )
+ {
+ /* Still room in T1? */
+ temp = (ElementDescriptor) B1.removeLast();
+ if ( temp != null )
+ {
+ map.remove( temp.key );
+ }
+ /* yes: take page off B1 */
+ // temp->pointer = replace(); /* find new place to put page
+ // */
+ replace( temp );
+ }
+ else
+ {
+ /* no: B1 must be empty */
+ temp = (ElementDescriptor) T1.removeLast(); /*
+ * take page //
+ * off // T1
+ */
+ map.remove( temp.ce.getKey() );
+ // if (temp->dirty) destage(temp); /* if dirty, evict
before
+ // overwrite */
+ replace( temp );
+ }
+ }
+ else
+ {
+ /* B1 + T1 have less than the maxSize elements */
+ if ( T1.size() + T2.size() + B1.size() + B2.size() >= maxSize )
+ {
+ /* cache full? */
+ /* Yes, cache full: */
+ if ( T1.size() + T2.size() + B1.size() + B2.size() >= 2 *
maxSize )
+ {
+ /* cache is full: */
+ /* x find and reuse B2s LRU */
+ temp = (ElementDescriptor) B2.removeLast();
+ if ( temp != null )
+ {
+ map.remove( temp.key );
+ }
+ }
+ else
+ {
+ /* cache directory not full, easy case */
+ // nop
+ }
+ replace( temp );
+ }
+ else
+ {
+ /* cache not full, easy case */
+ // nop
+ }
+ }
+ }
+
+ if ( !isGet && !isHit )
+ {
+ temp = new ElementDescriptor( ce );
temp.ce = ce;
- T2.addFirst(temp); // seen twice recently, put on T2
+ temp.listNum = _T1_;
+ T1.addFirst( temp );
+ // seen once recently, put on T1
+ this.map.put( temp.ce.getKey(), temp );
+ }
+ // end if put
+
+ if ( temp == null )
+ {
+ return null;
+ }
+ return temp.ce;
+ }
+
+ /**
+ * Move to T2 if the item was found in T1.
+ * <p>
+ * @param temp
+ */
+ protected void handleFoundInT1( ElementDescriptor temp )
+ {
+ if ( log.isDebugEnabled() )
+ {
+ log.debug( "T1" );
+ }
+ if ( log.isDebugEnabled() )
+ {
+ log.debug( "T1 to T2, before remove = " + T1.size() );
+ }
+ boolean stat1 = T1.remove( temp );
+ // need to implement our
+ // own list
+ if ( log.isDebugEnabled() )
+ {
+ log.debug( "T1 to T2, after remove = " + T1.size() + " stat = " +
stat1 );
+ }
+
+ temp.listNum = _T2_;
+ T2.addFirst( temp );
+ }
- }
- else
- {
+ /**
+ * If it was found in T2, we move it to the top of the T2 list.
+ * <p>
+ * @param temp
+ */
+ protected void handleFoundInT2( ElementDescriptor temp )
+ {
+ if ( log.isDebugEnabled() )
+ {
+ log.debug( "T2" );
+ }
+
+ temp.listNum = _T2_;
+ T2.makeFirst( temp );
+ }
+
+ /**
+ * B1 hit: favor recency
+ * <p>
+ * @param ce
+ * @param isGet
+ * @param temp
+ * @return
+ */
+ protected ElementDescriptor handleFoundInB1( ICacheElement ce, boolean
isGet, ElementDescriptor temp )
+ {
+ // B1 hit: favor recency
+
+ // adapt the target size
+ target_T1 = Math.min( target_T1 + Math.max( B2.size() / B1.size(), 1
), maxSize );
+ if ( log.isDebugEnabled() )
+ {
+ log.debug( "B1, targetT1 = " + target_T1 );
+ }
+
+ if ( !isGet )
+ {
+ if ( log.isDebugEnabled() )
+ {
+ log.debug( "B1 before remove = " + B1.size() );
+ }
+ boolean stat3 = B1.remove( temp ); // need to implement
+ // our own list
+ if ( log.isDebugEnabled() )
+ {
+ log.debug( "B1 after remove = " + B1.size() + " stat = " +
stat3 );
+ }
+ replace( temp );
+ temp.listNum = _T2_;
+ temp.ce = ce;
+ // seen twice recently, put on T2
+ T2.addFirst( temp );
+ }
+ else
+ {
// if this is just a get, then adjust the cache
// it is essentially a miss.
temp = null;
hitCnt--;
missCnt++;
- }
- break;
-
- case _B2_:
-
- // B2 hit: favor frequency
+ }
+ return temp;
+ }
- // adapt the target size
- target_T1 = Math.max(target_T1 - Math.max(B1.size() / B2.size(), 1),
- 0);
- if (log.isDebugEnabled())
- {
- log.debug("B2, targetT1 = " + target_T1 );
- }
+ /**
+ * B2 hit: favor frequency
+ * <p>
+ * @param ce
+ * @param isGet
+ * @param temp
+ * @return
+ */
+ protected ElementDescriptor handleFoundInB2( ICacheElement ce, boolean
isGet, ElementDescriptor temp )
+ {
+ // adapt the target size
+ target_T1 = Math.max( target_T1 - Math.max( B1.size() / B2.size(), 1
), 0 );
+ if ( log.isDebugEnabled() )
+ {
+ log.debug( "B2, targetT1 = " + target_T1 );
+ }
- if (!isGet)
- {
- if (log.isDebugEnabled())
+ if ( !isGet )
+ {
+ if ( log.isDebugEnabled() )
{
- log.debug("B2 before remove = " + B2.size());
+ log.debug( "B2 before remove = " + B2.size() );
}
- boolean stat4 = B2.remove(temp); // need to implement our own list
- if (log.isDebugEnabled())
+ boolean stat4 = B2.remove( temp ); // need to implement
+ // our own list
+ if ( log.isDebugEnabled() )
{
- log.debug("B2 after remove = " + B2.size() + " stat = " + stat4);
+ log.debug( "B2 after remove = " + B2.size() + " stat = " +
stat4 );
}
- replace(temp);
+ replace( temp );
temp.listNum = _T2_;
temp.ce = ce;
- T2.addFirst(temp); // seen twice recently, put on T2
+ // seen twice recently, put on T2
+ T2.addFirst( temp );
- replace(temp);
- }
- else
- {
+ replace( temp );
+ }
+ else
+ {
// if this is just a get, then adjust the cache
// it is essentially a miss.
temp = null;
hitCnt--;
missCnt++;
- }
- break;
- }
-
- // was null
- }
- else
- {
- /* page is not in cache */
-
- isHit = false;
- if (isGet)
- {
- missCnt++;
- }
-
- if (log.isDebugEnabled())
- {
- log.debug("Page is not in cache");
- }
-
- } // end if not in cache
-
-
//////////////////////////////////////////////////////////////////////////////
- // Do some size Checks if this is a put
- //if (!isGet)
- //{
- if (T1.size() + B1.size() >= c)
- {
- /* B1 + T1 full? */
- if (T1.size() < c)
- {
- /* Still room in T1? */
- temp = (ElementDescriptor) B1.removeLast();
- if ( temp != null ) {
- map.remove(temp.key);
- }
- /* yes: take page off B1 */
- //temp->pointer = replace(); /* find new place to put page */
- replace(temp);
}
- else
+ return temp;
+ }
+
+ /**
+ * Prints the stats every 10000 or so operations.
+ * <p>
+ * @param ce
+ * @param isGet
+ */
+ protected void logStatsOccassionally( ICacheElement ce, boolean isGet )
+ {
+ if ( cnt % 10000 == 0 )
+ // if ( true )
{
- /* no: B1 must be empty */
- //temp = (ElementDescriptor) T1.removeLast(); /* take page off T1 */
- //map.remove(temp.ce.getKey());
- //if (temp->dirty) destage(temp); /* if dirty, evict before
overwrite */
- replace(temp);
- }
- }
- else
- {
- /* B1 + T1 have less than c pages */
- if (T1.size() + T2.size() + B1.size() + B2.size() >= c)
- {
- /* cache full? */
- /* Yes, cache full: */
- if (T1.size() + T2.size() + B1.size() + B2.size() >= 2 * c)
- {
- /* cache is full: */
- /* x find and reuse B2s LRU */
- temp = (ElementDescriptor) B2.removeLast();
- if ( temp != null ) {
- map.remove(temp.key);
- }
- }
- else
- {
- /* cache directory not full, easy case */
- ; //nop
- }
- replace(temp);
+ if ( log.isInfoEnabled() )
+ {
+ StringBuffer buf = new StringBuffer();
+ buf.append( "\n ce.key() = " + ce.getKey() );
+ buf.append( "\n isGet = " + isGet );
+ buf.append( getStats() );
+ log.info( buf.toString() );
+ }
}
- else
+ }
+
+ /**
+ * This method doesn't so much replace as remove. It pushes the least
+ * recently used in t1 or t2 to a dummy holder. The holder keeps a dummy
+ * object that stores the key so that subsequent gets and puts can help
+ * train the cache. Items are spooled if there is a disk cache at this
+ * point.
+ * <p>
+ * @param orig
+ * ElementDescriptor
+ */
+ public void replace( ElementDescriptor orig )
+ {
+ try
{
- /* cache not full, easy case */
- ; //nop
- }
- }
+ ElementDescriptor temp;
+ if ( T1.size() >= Math.max( 1, target_T1 ) )
+ {
+ // T1s size exceeds target?
+ // yes: T1 is too big
+ temp = (ElementDescriptor) T1.getLast();
+ if ( orig == null || !orig.key.equals( temp.key ) )
+ {
+ if ( log.isDebugEnabled() )
+ {
+ log.debug( "replace -- T1 to B1" );
+ log.debug( getStats() );
+ }
+ temp = (ElementDescriptor) T1.removeLast(); // grab LRU
from
+ // T1
+ // nullify object, temp is now just a dummy container to
+ // help adjust the lru size
+ try
+ {
+ this.waterfal( temp.ce );
+ }
+ catch ( Exception e )
+ {
+ log.error( e );
+ }
+ temp.ce = null;
+ temp.listNum = _B1_; // note that fact
+ B1.addFirst( temp ); // put it on B1
+ // T1Length; B1Length++; // bookkeep
+ }
+ else
+ {
+ if ( log.isDebugEnabled() )
+ {
+ log.debug( "orig == temp, t1" );
+ }
+ }
+ }
+ else
+ // if t2 is greater than or equal to what is left in c after the
+ // target
+ if ( ( T2.size() + T1.size() ) > maxSize )
+ {
- if (!isGet && !isHit)
- {
- temp = new ElementDescriptor(ce);
- temp.ce = ce;
- temp.listNum = _T1_;
- T1.addFirst(temp); /* seen once recently, put on T1 */
- this.map.put(temp.ce.getKey(), temp);
- } // end if put
-
-
- if (temp == null)
- {
- return null;
- }
- return temp.ce;
- }
-
- /**
- * This method doesn't so much replace as remove. It pushes the least
- * recently used in t1 or t2 to a dummy holder. The holder keeps a dummy
object
- * that stores the key so that subsequent gets and puts can help train the
- * cache. Items are spooled if there is a disk cache at this point.
- *
- * @param orig ElementDescriptor
- */
- public void replace(ElementDescriptor orig)
- {
- try
- {
- ElementDescriptor temp;
- if (T1.size() >= Math.max(1, target_T1))
- { // T1s size exceeds target?
- // yes: T1 is too big
- temp = (ElementDescriptor) T1.getLast();
- if (orig == null || !orig.key.equals(temp.key))
- {
- if (log.isDebugEnabled())
- {
- log.debug("replace -- T1 to B1");
- log.debug(getStats());
- }
- temp = (ElementDescriptor) T1.removeLast(); // grab LRU from T1
- // nullify object, temp is now just a dummy container to help
- // adjust the lru size
- try
- {
- this.waterfal(temp.ce);
- }
- catch (Exception e)
- {
- log.error(e);
- }
- temp.ce = null;
- temp.listNum = _B1_; // note that fact
- B1.addFirst(temp); // put it on B1
- //T1Length; B1Length++; // bookkeep
+ // no: T1 is not too big
+ temp = (ElementDescriptor) T2.getLast();
+ if ( orig == null || !orig.key.equals( temp.key ) )
+ {
+ if ( log.isDebugEnabled() )
+ {
+ log.debug( "replace -- T2 to B2" );
+ log.debug( getStats() );
+ }
+
+ temp = (ElementDescriptor) T2.removeLast(); // grab LRU
page
+ // of T2
+ // nullify object, temp is now just a dummy container to
+ // help
+ // adjust the lru size
+ try
+ {
+ this.waterfal( temp.ce );
+ }
+ catch ( Exception e )
+ {
+ log.error( e );
+ }
+ temp.ce = null;
+ temp.listNum = _B2_; // note that fact
+ B2.addFirst( temp ); // put it on B2
+ // T2Length; B2Length++; // bookkeep
+ }
+ else
+ {
+ if ( log.isDebugEnabled() )
+ {
+ log.debug( "orig == temp, t2" );
+ }
+ }
+ }
}
- else
+ catch ( Exception e )
{
- if (log.isDebugEnabled())
- {
- log.debug("orig == temp, t1");
- }
- }
- }
- else
- // if t2 is greater than or equal to what is left in c after the target
- if ( ( T2.size() + T1.size() ) > c )
- {
-
- // no: T1 is not too big
- temp = (ElementDescriptor) T2.getLast();
- if (orig == null || !orig.key.equals(temp.key))
- {
- if (log.isDebugEnabled())
- {
- log.debug("replace -- T2 to B2");
- log.debug(getStats());
- }
-
- temp = (ElementDescriptor) T2.removeLast(); // grab LRU page of T2
- // nullify object, temp is now just a dummy container to help
- // adjust the lru size
- try
- {
- this.waterfal(temp.ce);
- }
- catch (Exception e)
- {
- log.error(e);
- }
- temp.ce = null;
- temp.listNum = _B2_; // note that fact
- B2.addFirst(temp); // put it on B2
- //T2Length; B2Length++; // bookkeep
+ log.error( e );
}
- else
+ }
+
+ /**
+ * remove the element if it is in any of the lists.
+ * @param key
+ * Serializable
+ * @return boolean
+ */
+ public boolean remove( Serializable key )
+ {
+ ElementDescriptor temp = (ElementDescriptor) map.remove( key );
+ if ( temp != null )
{
- if (log.isDebugEnabled())
- {
- log.debug("orig == temp, t2");
- }
- }
- }
- }
- catch (Exception e)
- {
- log.error(e);
- }
- }
-
- /**
- * remove
- *
- * @param key Serializable
- * @return boolean
- */
- public boolean remove(Serializable key)
- {
- ElementDescriptor temp = (ElementDescriptor) map.remove(key);
- if ( temp != null ) {
- int loc = temp.listNum;
- if (loc == _T1_)
- {
- T1.remove(temp);
- }
- else
- if (loc == _T2_)
- {
- T2.remove(temp);
- }
- else
- if (loc == _B1_)
- {
- B1.remove(temp);
- }
- else
- if (loc == _B2_)
- {
- B2.remove(temp);
- }
- }
- return true;
- }
-
- /**
- * Remove all of the elements from both the Map and the linked
- * list implementation. Overrides base class.
- */
- public synchronized void removeAll() throws IOException
- {
- map.clear();
- T1.removeAll();
- T2.removeAll();
- B1.removeAll();
- B2.removeAll();
- }
-
- /////////////////////////////////////////////////////////////////////////
- public String getStats()
- {
- return getStatistics().toString();
- }
-
-
- /*
- * (non-Javadoc)
- * @see org.apache.jcs.engine.memory.MemoryCache#getStatistics()
- */
- public IStats getStatistics()
- {
- IStats stats = new Stats();
- stats.setTypeName( "LRU Memory Cache" );
-
- ArrayList elems = new ArrayList();
-
- IStatElement se = null;
-
- se = new StatElement();
- se.setName( "T1 Size" );
- se.setData("" + T1.size());
- elems.add(se);
-
- se = new StatElement();
- se.setName( "T2 Size" );
- se.setData("" + T2.size());
- elems.add(se);
-
- se = new StatElement();
- se.setName( "B1 Size" );
- se.setData("" + B1.size());
- elems.add(se);
-
- se = new StatElement();
- se.setName( "B2 Size" );
- se.setData("" + B2.size());
- elems.add(se);
-
- se = new StatElement();
- se.setName( "Target T1 Size" );
- se.setData("" + target_T1);
- elems.add(se);
-
- se = new StatElement();
- se.setName( "Map Size" );
- se.setData("" + map.size());
- elems.add(se);
-
- se = new StatElement();
- se.setName( "Put Count" );
- se.setData("" + putCnt);
- elems.add(se);
-
- se = new StatElement();
- se.setName( "Hit Count" );
- se.setData("" + hitCnt);
- elems.add(se);
-
- se = new StatElement();
- se.setName( "Miss Count" );
- se.setData("" + missCnt);
- elems.add(se);
-
- // get an array and put them in the Stats object
- IStatElement[] ses = (IStatElement[])elems.toArray( new StatElement[0]
);
- stats.setStatElements( ses );
-
- // int rate = ((hitCnt + missCnt) * 100) / (hitCnt * 100) * 100;
- //buf.append("\n Hit Rate = " + rate + " %" );
-
- return stats;
- }
-
-/////////////////////////////////////////////////
- public class ElementDescriptor
- extends MemoryElementDescriptor
- {
- public int listNum;
-
- public Serializable key;
+ int loc = temp.listNum;
+ if ( loc == _T1_ )
+ {
+ T1.remove( temp );
+ }
+ else if ( loc == _T2_ )
+ {
+ T2.remove( temp );
+ }
+ else if ( loc == _B1_ )
+ {
+ B1.remove( temp );
+ }
+ else if ( loc == _B2_ )
+ {
+ B2.remove( temp );
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Remove all of the elements from both the Map and the linked list
+ * implementation. Overrides base class.
+ */
+ public synchronized void removeAll()
+ throws IOException
+ {
+ map.clear();
+ T1.removeAll();
+ T2.removeAll();
+ B1.removeAll();
+ B2.removeAll();
+ }
- public ElementDescriptor(ICacheElement ce)
+ // ///////////////////////////////////////////////////////////////////////
+ /**
+ * @return
+ */
+ public String getStats()
{
- super(ce);
- key = ce.getKey();
+ return getStatistics().toString();
}
- }
+ /*
+ * (non-Javadoc)
+ * @see org.apache.jcs.engine.memory.MemoryCache#getStatistics()
+ */
+ public IStats getStatistics()
+ {
+ IStats stats = new Stats();
+ stats.setTypeName( "LRU Memory Cache" );
+
+ ArrayList elems = new ArrayList();
+
+ IStatElement se = null;
+
+ se = new StatElement();
+ se.setName( "T1 Size" );
+ se.setData( "" + T1.size() );
+ elems.add( se );
+
+ se = new StatElement();
+ se.setName( "T2 Size" );
+ se.setData( "" + T2.size() );
+ elems.add( se );
+
+ se = new StatElement();
+ se.setName( "B1 Size" );
+ se.setData( "" + B1.size() );
+ elems.add( se );
+
+ se = new StatElement();
+ se.setName( "B2 Size" );
+ se.setData( "" + B2.size() );
+ elems.add( se );
+
+ se = new StatElement();
+ se.setName( "Target T1 Size" );
+ se.setData( "" + target_T1 );
+ elems.add( se );
+
+ se = new StatElement();
+ se.setName( "Map Size" );
+ se.setData( "" + map.size() );
+ elems.add( se );
+
+ se = new StatElement();
+ se.setName( "Put Count" );
+ se.setData( "" + putCnt );
+ elems.add( se );
+
+ se = new StatElement();
+ se.setName( "Hit Count" );
+ se.setData( "" + hitCnt );
+ elems.add( se );
+
+ se = new StatElement();
+ se.setName( "Miss Count" );
+ se.setData( "" + missCnt );
+ elems.add( se );
+
+ // get an array and put them in the Stats object
+ IStatElement[] ses = (IStatElement[]) elems.toArray( new
StatElement[0] );
+ stats.setStatElements( ses );
+
+ // int rate = ((hitCnt + missCnt) * 100) / (hitCnt * 100) * 100;
+ // buf.append("\n Hit Rate = " + rate + " %" );
+
+ return stats;
+ }
+
+ // ///////////////////////////////////////////////
+ /**
+ * @author Aaron Smuts
+ */
+ public class ElementDescriptor
+ extends MemoryElementDescriptor
+ {
+ private static final long serialVersionUID = -6271920830449238031L;
+
+ /** Where this is located */
+ public int listNum;
+
+ /** Its key */
+ public Serializable key;
+
+ /**
+ * Constructs a usable object
+ * @param ce
+ */
+ public ElementDescriptor( ICacheElement ce )
+ {
+ super( ce );
+ key = ce.getKey();
+ }
+ }
+
+ /**
+ * This is currently not implemented. It should remove items from t2. If
+ * there are none in t2, it should move them to t2 and then remove them.
+ * <p>
+ * (non-Javadoc)
+ * @see org.apache.jcs.engine.memory.MemoryCache#freeElements(int)
+ */
+ public int freeElements( int numberToFree )
+ throws IOException
+ {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ /**
+ * At the start this will be 1/2 the max.
+ * <p>
+ * @return Returns the target_T1.
+ */
+ protected int getTarget_T1()
+ {
+ return target_T1;
+ }
+
+ /**
+ * Returns the size of the list.
+ * @param listNumber
+ * @return -1 if the list is unknown.
+ */
+ protected int getListSize( int listNumber )
+ {
+ switch ( listNumber )
+ {
+ case _T1_:
+ return T1.size();
+
+ case _T2_:
+ return T2.size();
+
+ case _B1_:
+ return B1.size();
+
+ case _B2_:
+ return B2.size();
+ }
+ return -1;
+ }
}
Added:
jakarta/jcs/trunk/src/experimental/org/apache/jcs/engine/memory/arc/ARCMemoryCacheUnitTest.java
URL:
http://svn.apache.org/viewvc/jakarta/jcs/trunk/src/experimental/org/apache/jcs/engine/memory/arc/ARCMemoryCacheUnitTest.java?rev=430809&view=auto
==============================================================================
---
jakarta/jcs/trunk/src/experimental/org/apache/jcs/engine/memory/arc/ARCMemoryCacheUnitTest.java
(added)
+++
jakarta/jcs/trunk/src/experimental/org/apache/jcs/engine/memory/arc/ARCMemoryCacheUnitTest.java
Fri Aug 11 08:51:10 2006
@@ -0,0 +1,271 @@
+package org.apache.jcs.engine.memory.arc;
+
+import junit.framework.TestCase;
+
+import org.apache.jcs.JCS;
+import org.apache.jcs.access.exception.CacheException;
+import org.apache.jcs.engine.CacheElement;
+import org.apache.jcs.engine.behavior.ICacheElement;
+import org.apache.jcs.engine.control.CompositeCache;
+import org.apache.jcs.engine.control.CompositeCacheManager;
+
+/**
+ * Initial tests for the ARCMemoryCache
+ * <p>
+ * @author Aaron Smuts
+ */
+public class ARCMemoryCacheUnitTest
+ extends TestCase
+{
+ /**
+ * Test setup
+ */
+ public void setUp()
+ {
+ JCS.setConfigFilename( "/TestARCCache.ccf" );
+ }
+
+ /**
+ * Put a few items on, get them, and then remove them.
+ * @throws CacheException
+ */
+ public void testPutGetRemoveThroughHub()
+ throws CacheException
+ {
+ JCS cache = JCS.getInstance( "testPutGetThroughHub" );
+
+ int max = cache.getCacheAttributes().getMaxObjects();
+ int items = max * 2;
+
+ for ( int i = 0; i < items; i++ )
+ {
+ cache.put( i + ":key", "myregion" + " data " + i );
+ }
+
+ // Test that first items are not in the cache
+ for ( int i = max; i >= 0; i-- )
+ {
+ String value = (String) cache.get( i + ":key" );
+ assertNull( "Should not have value for key [" + i + ":key" + "] in
the cache.", value );
+ }
+
+ // Test that last items are in cache
+ // skip 2 for the buffer.
+ for ( int i = max + 2; i < items; i++ )
+ {
+ String value = (String) cache.get( i + ":key" );
+ assertEquals( "myregion" + " data " + i, value );
+ }
+
+ System.out.println( cache.getStats() );
+ }
+
+ /**
+ * Put half the max, get the key array, and verify that it has the correct
+ * number of items.
+ * <p>
+ * @throws Exception
+ */
+ public void testGetKeyArray()
+ throws Exception
+ {
+ CompositeCacheManager cacheMgr =
CompositeCacheManager.getUnconfiguredInstance();
+ cacheMgr.configure( "/TestARCCache.ccf" );
+ CompositeCache cache = cacheMgr.getCache( "testGetKeyArray" );
+
+ ARCMemoryCache arc = new ARCMemoryCache();
+ arc.initialize( cache );
+
+ int max = cache.getCacheAttributes().getMaxObjects();
+ int items = max / 2;
+
+ for ( int i = 0; i < items; i++ )
+ {
+ ICacheElement ice = new CacheElement( cache.getCacheName(), i +
":key", cache.getCacheName() + " data " + i );
+ ice.setElementAttributes( cache.getElementAttributes() );
+ arc.update( ice );
+ }
+
+ System.out.println( "testGetKeyArray " + arc.getStats() );
+
+ Object[] keys = arc.getKeyArray();
+ assertEquals( "Wrong number of keys.", items, keys.length );
+ assertEquals( "Target t1 should be 1/2 until dupe gets or puts.", max
/ 2, arc.getTarget_T1() );
+ }
+
+ /**
+ * Put half the max and then get the first element. It should now be in
t2.
+ * <p>
+ * @throws Exception
+ */
+ public void testHitInT1BelowMax()
+ throws Exception
+ {
+ CompositeCacheManager cacheMgr =
CompositeCacheManager.getUnconfiguredInstance();
+ cacheMgr.configure( "/TestARCCache.ccf" );
+ CompositeCache cache = cacheMgr.getCache( "testGetKeyArray" );
+
+ ARCMemoryCache arc = new ARCMemoryCache();
+ arc.initialize( cache );
+
+ int max = cache.getCacheAttributes().getMaxObjects();
+ int items = max / 2;
+
+ for ( int i = 0; i < items; i++ )
+ {
+ ICacheElement ice = new CacheElement( cache.getCacheName(), i +
":key", cache.getCacheName() + " data " + i );
+ ice.setElementAttributes( cache.getElementAttributes() );
+ arc.update( ice );
+ }
+
+ ICacheElement element = arc.get( 0 + ":key" );
+
+ System.out.println( "testHitInT1BelowMax " + arc.getStats() );
+
+ assertNotNull( "Should have the element.", element );
+ assertEquals( "Target t1 should be 1/2 until dupe gets or puts.", max
/ 2, arc.getTarget_T1() );
+
+ assertEquals( "T2 should have one item.", 1, arc.getListSize(
ARCMemoryCache._T2_ ) );
+ }
+
+ /**
+ * Put half the max and then get the first element. then get it again. ti
shoudl be in t2
+ * <p>
+ * @throws Exception
+ */
+ public void testHitInT1ThenT2BelowMax()
+ throws Exception
+ {
+ CompositeCacheManager cacheMgr =
CompositeCacheManager.getUnconfiguredInstance();
+ cacheMgr.configure( "/TestARCCache.ccf" );
+ CompositeCache cache = cacheMgr.getCache( "testGetKeyArray" );
+
+ ARCMemoryCache arc = new ARCMemoryCache();
+ arc.initialize( cache );
+
+ int max = cache.getCacheAttributes().getMaxObjects();
+ int items = max / 2;
+
+ for ( int i = 0; i < items; i++ )
+ {
+ ICacheElement ice = new CacheElement( cache.getCacheName(), i +
":key", cache.getCacheName() + " data " + i );
+ ice.setElementAttributes( cache.getElementAttributes() );
+ arc.update( ice );
+ }
+
+ ICacheElement element = arc.get( 0 + ":key" );
+
+ System.out.println( "testHitInT1ThenT2BelowMax " + arc.getStats() );
+
+ assertNotNull( "Should have the element.", element );
+ assertEquals( "Target t1 should be 1/2 until dupe gets or puts.", max
/ 2, arc.getTarget_T1() );
+
+ assertEquals( "T2 should have one item.", 1, arc.getListSize(
ARCMemoryCache._T2_ ) );
+ }
+
+ /**
+ * Put half the max and then get the first element. It should now be in
t2.
+ * <p>
+ * @throws Exception
+ */
+ public void testHitInT1AtMax()
+ throws Exception
+ {
+ CompositeCacheManager cacheMgr =
CompositeCacheManager.getUnconfiguredInstance();
+ cacheMgr.configure( "/TestARCCache.ccf" );
+ CompositeCache cache = cacheMgr.getCache( "testGetKeyArray" );
+
+ ARCMemoryCache arc = new ARCMemoryCache();
+ arc.initialize( cache );
+
+ int max = cache.getCacheAttributes().getMaxObjects();
+ int items = max;
+
+ for ( int i = 0; i < items; i++ )
+ {
+ ICacheElement ice = new CacheElement( cache.getCacheName(), i +
":key", cache.getCacheName() + " data " + i );
+ ice.setElementAttributes( cache.getElementAttributes() );
+ arc.update( ice );
+ }
+
+ ICacheElement element = arc.get( 0 + ":key" );
+
+ System.out.println( "testHitInT1AtMax " + arc.getStats() );
+
+ assertNotNull( "Should have the element.", element );
+ assertEquals( "Target t1 should be 1/2 until dupe gets or puts.", max
/ 2, arc.getTarget_T1() );
+
+ assertEquals( "T2 should have one item.", 1, arc.getListSize(
ARCMemoryCache._T2_ ) );
+ }
+
+ /**
+ * Put half the max and then get the first element. It should now be in
t2.
+ * <p>
+ * @throws Exception
+ */
+ public void SKIPtestHitInT1OverMax()
+ throws Exception
+ {
+ CompositeCacheManager cacheMgr =
CompositeCacheManager.getUnconfiguredInstance();
+ cacheMgr.configure( "/TestARCCache.ccf" );
+ CompositeCache cache = cacheMgr.getCache( "testGetKeyArray" );
+
+ ARCMemoryCache arc = new ARCMemoryCache();
+ arc.initialize( cache );
+
+ int max = cache.getCacheAttributes().getMaxObjects();
+ int items = max + 1;
+
+ for ( int i = 0; i < items; i++ )
+ {
+ ICacheElement ice = new CacheElement( cache.getCacheName(), i +
":key", cache.getCacheName() + " data " + i );
+ ice.setElementAttributes( cache.getElementAttributes() );
+ arc.update( ice );
+ }
+
+ ICacheElement element = arc.get( 0 + ":key" );
+
+ System.out.println( "testHitInT1OverMax " + arc.getStats() );
+
+ assertNull( "Should not have the element since it was the first.",
element );
+ assertEquals( "Target t1 should be 1/2 until dupe gets or puts.", max
/ 2, arc.getTarget_T1() );
+
+ assertEquals( "T2 should have one item.", 1, arc.getListSize(
ARCMemoryCache._T2_ ) );
+ }
+
+ /**
+ * Put half the max and then get the first element. It should now be in
t2.
+ * <p>
+ * @throws Exception
+ */
+ public void testPutInT1ToMax()
+ throws Exception
+ {
+ CompositeCacheManager cacheMgr =
CompositeCacheManager.getUnconfiguredInstance();
+ cacheMgr.configure( "/TestARCCache.ccf" );
+ CompositeCache cache = cacheMgr.getCache( "testGetKeyArray" );
+
+ ARCMemoryCache arc = new ARCMemoryCache();
+ arc.initialize( cache );
+
+ int max = cache.getCacheAttributes().getMaxObjects();
+ int items = max;
+
+ for ( int i = 0; i < items; i++ )
+ {
+ ICacheElement ice = new CacheElement( cache.getCacheName(), i +
":key", cache.getCacheName() + " data " + i );
+ ice.setElementAttributes( cache.getElementAttributes() );
+ arc.update( ice );
+ }
+
+ //ICacheElement element = arc.get( 0 + ":key" );
+
+ System.out.println( "testPutInT1ToMax " + arc.getStats() );
+
+ //assertNotNull( "Should have the element.", element );
+ assertEquals( "Target t1 should be 1/2 until dupe gets or puts.", max
/ 2, arc.getTarget_T1() );
+
+ assertEquals( "Wrong number of items in T1.", max, arc.getListSize(
ARCMemoryCache._T1_ ) );
+ assertEquals( "Wrong number of items in T2.", 0, arc.getListSize(
ARCMemoryCache._T2_ ) );
+ }
+}
Modified: jakarta/jcs/trunk/src/java/org/apache/jcs/access/CacheAccess.java
URL:
http://svn.apache.org/viewvc/jakarta/jcs/trunk/src/java/org/apache/jcs/access/CacheAccess.java?rev=430809&r1=430808&r2=430809&view=diff
==============================================================================
--- jakarta/jcs/trunk/src/java/org/apache/jcs/access/CacheAccess.java (original)
+++ jakarta/jcs/trunk/src/java/org/apache/jcs/access/CacheAccess.java Fri Aug
11 08:51:10 2006
@@ -567,4 +567,32 @@
{
this.cacheControl.setCacheAttributes( cattr );
}
+
+ /**
+ * This instructs the memory cache to remove the <i>numberToFree</i>
+ * according to its eviction policy. For example, the LRUMemoryCache will
+ * remove the <i>numberToFree</i> least recently used items. These will be
+ * spooled to disk if a disk auxiliary is available.
+ * <p>
+ * @param numberToFree
+ * @return the number that were removed. if you ask to free 5, but there
are
+ * only 3, you will get 3.
+ * @throws CacheException
+ */
+ public int freeMemoryElements( int numberToFree )
+ throws CacheException
+ {
+ int numFreed = -1;
+ try
+ {
+ numFreed = this.cacheControl.getMemoryCache().freeElements(
numberToFree );
+ }
+ catch ( IOException ioe )
+ {
+ String message = "Failure freeing memory elements. ";
+ log.error( message, ioe );
+ throw new CacheException( message + ioe.getMessage() );
+ }
+ return numFreed;
+ }
}
Modified:
jakarta/jcs/trunk/src/java/org/apache/jcs/access/behavior/ICacheAccess.java
URL:
http://svn.apache.org/viewvc/jakarta/jcs/trunk/src/java/org/apache/jcs/access/behavior/ICacheAccess.java?rev=430809&r1=430808&r2=430809&view=diff
==============================================================================
--- jakarta/jcs/trunk/src/java/org/apache/jcs/access/behavior/ICacheAccess.java
(original)
+++ jakarta/jcs/trunk/src/java/org/apache/jcs/access/behavior/ICacheAccess.java
Fri Aug 11 08:51:10 2006
@@ -159,4 +159,17 @@
*/
public void setCacheAttributes( ICompositeCacheAttributes cattr );
+ /**
+ * This instructs the memory cache to remove the <i>numberToFree</i>
+ * according to its eviction policy. For example, the LRUMemoryCache will
+ * remove the <i>numberToFree</i> least recently used items. These will be
+ * spooled to disk if a disk auxiliary is available.
+ * <p>
+ * @param numberToFree
+ * @return the number that were removed. if you ask to free 5, but there
are
+ * only 3, you will get 3.
+ * @throws CacheException
+ */
+ public int freeMemoryElements( int numberToFree )
+ throws CacheException;
}
Modified:
jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/lateral/LateralCache.java
URL:
http://svn.apache.org/viewvc/jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/lateral/LateralCache.java?rev=430809&r1=430808&r2=430809&view=diff
==============================================================================
---
jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/lateral/LateralCache.java
(original)
+++
jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/lateral/LateralCache.java
Fri Aug 11 08:51:10 2006
@@ -34,7 +34,6 @@
/**
* Lateral distributor. Returns null on get by default. Net search not
* implemented.
- *
*/
public class LateralCache
implements ICache
@@ -55,7 +54,7 @@
/**
* Constructor for the LateralCache object
- *
+ * <p>
* @param cattr
* @param lateral
* @param monitor
@@ -70,7 +69,7 @@
/**
* Constructor for the LateralCache object
- *
+ * <p>
* @param cattr
*/
protected LateralCache( ILateralCacheAttributes cattr )
@@ -81,7 +80,7 @@
/**
* Update lateral.
- *
+ * <p>
* @param ce
* @throws IOException
*/
@@ -92,7 +91,7 @@
{
if ( log.isDebugEnabled() )
{
- log.debug( "update: lateral = " + lateral + ", " +
"LateralCacheInfo.listenerId = "
+ log.debug( "update: lateral = [" + lateral + "], " +
"LateralCacheInfo.listenerId = "
+ LateralCacheInfo.listenerId );
}
lateral.update( ce, LateralCacheInfo.listenerId );
@@ -100,21 +99,19 @@
catch ( NullPointerException npe )
{
log.error( "Failure updating lateral. lateral = " + lateral, npe );
- handleException( npe, "Failed to put " + ce.getKey() + " to " +
ce.getCacheName() );
+ handleException( npe, "Failed to put [" + ce.getKey() + "] to " +
ce.getCacheName() );
return;
}
catch ( Exception ex )
{
- handleException( ex, "Failed to put " + ce.getKey() + " to " +
ce.getCacheName() );
+ handleException( ex, "Failed to put [" + ce.getKey() + "] to " +
ce.getCacheName() );
}
}
- // end update
-
/**
* The performace costs are too great. It is not recommended that you
enable
* lateral gets.
- *
+ * <p>
* @param key
* @return
* @throws IOException
@@ -153,7 +150,7 @@
/**
* Synchronously remove from the remote cache; if failed, replace the
remote
* handle with a zombie.
- *
+ * <p>
* @param key
* @return
* @throws IOException
@@ -165,10 +162,6 @@
try
{
- //DeleteLateralCacheMulticaster dlcm = new
- // DeleteLateralCacheMulticaster( cattr.getCacheName(),
(String)key,
- // cattr.getLateralCacheAddrs(), cattr.getLateralDeleteServlet() );
- //dlcm.multicast();
lateral.remove( cacheName, key, LateralCacheInfo.listenerId );
}
catch ( Exception ex )
@@ -181,7 +174,7 @@
/**
* Synchronously removeAll from the remote cache; if failed, replace the
* remote handle with a zombie.
- *
+ * <p>
* @throws IOException
*/
public void removeAll()
@@ -189,10 +182,6 @@
{
try
{
- //DeleteLateralCacheMulticaster dlcm = new
- // DeleteLateralCacheMulticaster( cattr.getCacheName(), "ALL",
- // cattr.getLateralCacheAddrs(), cattr.getLateralDeleteServlet() );
- //dlcm.multicast();
lateral.removeAll( cacheName, LateralCacheInfo.listenerId );
}
catch ( Exception ex )
@@ -230,7 +219,7 @@
/**
* Returns the cache status.
- *
+ * <p>
* @return The status value
*/
public int getStatus()
@@ -240,7 +229,7 @@
/**
* Returns the current cache size.
- *
+ * <p>
* @return The size value
*/
public int getSize()
@@ -250,7 +239,7 @@
/**
* Gets the cacheType attribute of the LateralCache object
- *
+ * <p>
* @return The cacheType value
*/
public int getCacheType()
@@ -260,7 +249,7 @@
/**
* Gets the cacheName attribute of the LateralCache object
- *
+ * <p>
* @return The cacheName value
*/
public String getCacheName()
@@ -270,7 +259,7 @@
/**
* Not yet sure what to do here.
- *
+ * <p>
* @param ex
* @param msg
* @throws IOException
@@ -278,7 +267,6 @@
private void handleException( Exception ex, String msg )
throws IOException
{
-
log.error( "Disabling lateral cache due to error " + msg, ex );
lateral = new ZombieLateralCacheService();
@@ -297,7 +285,7 @@
/**
* Replaces the current remote cache service handle with the given handle.
- *
+ * <p>
* @param lateral
*/
public void fixCache( ILateralCacheService lateral )
@@ -315,7 +303,7 @@
/**
* getStats
- *
+ * <p>
* @return String
*/
public String getStats()
Modified:
jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/lateral/LateralCacheNoWait.java
URL:
http://svn.apache.org/viewvc/jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/lateral/LateralCacheNoWait.java?rev=430809&r1=430808&r2=430809&view=diff
==============================================================================
---
jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/lateral/LateralCacheNoWait.java
(original)
+++
jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/lateral/LateralCacheNoWait.java
Fri Aug 11 08:51:10 2006
@@ -42,7 +42,6 @@
/**
* Used to queue up update requests to the underlying cache. These requests
will
* be processed in their order of arrival via the cache event queue processor.
- *
*/
public class LateralCacheNoWait
implements AuxiliaryCache
@@ -107,13 +106,12 @@
/**
* Synchronously reads from the lateral cache.
- *
+ * <p>
* @param key
* @return ICacheElement if found, else null
*/
public ICacheElement get( Serializable key )
{
-
if ( this.getStatus() != CacheConstants.STATUS_ERROR )
{
try
Modified:
jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/lateral/LateralElementDescriptor.java
URL:
http://svn.apache.org/viewvc/jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/lateral/LateralElementDescriptor.java?rev=430809&r1=430808&r2=430809&view=diff
==============================================================================
---
jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/lateral/LateralElementDescriptor.java
(original)
+++
jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/lateral/LateralElementDescriptor.java
Fri Aug 11 08:51:10 2006
@@ -1,19 +1,14 @@
package org.apache.jcs.auxiliary.lateral;
/*
- * Copyright 2001-2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License")
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Copyright 2001-2004 The Apache Software Foundation. Licensed under the
Apache
+ * License, Version 2.0 (the "License") you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
+ * or agreed to in writing, software distributed under the License is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
*/
import java.io.Serializable;
@@ -21,16 +16,15 @@
import org.apache.jcs.engine.behavior.ICacheElement;
/**
- * This class wraps command to other laterals.
- *
+ * This class wraps command to other laterals. It is essentially a
+ * JCS-TCP-Lateral packet. The headers specify the action the receiver should
+ * take.
*/
public class LateralElementDescriptor
implements Serializable
{
-
private static final long serialVersionUID = 5268222498076063575L;
- // command types
/** The int for updates */
public final static int UPDATE = 1;
@@ -63,7 +57,6 @@
*/
public int valHashCode = -1;
- // for update command
/** Constructor for the LateralElementDescriptor object */
public LateralElementDescriptor()
{
@@ -72,12 +65,24 @@
/**
* Constructor for the LateralElementDescriptor object
- *
- * @param ce
+ * <p>
+ * @param ce ICacheElement payload
*/
public LateralElementDescriptor( ICacheElement ce )
{
this.ce = ce;
}
-
+
+ /**
+ * @return String, all the important values that can be configured
+ */
+ public String toString()
+ {
+ StringBuffer buf = new StringBuffer();
+ buf.append( "\n LateralElementDescriptor " );
+ buf.append( "\n command = [" + this.command + "]" );
+ buf.append( "\n valHashCode = [" + this.valHashCode + "]" );
+ buf.append( "\n ICacheElement = [" + this.ce + "]" );
+ return buf.toString();
+ }
}
Modified:
jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/lateral/socket/tcp/LateralTCPCacheManager.java
URL:
http://svn.apache.org/viewvc/jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/lateral/socket/tcp/LateralTCPCacheManager.java?rev=430809&r1=430808&r2=430809&view=diff
==============================================================================
---
jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/lateral/socket/tcp/LateralTCPCacheManager.java
(original)
+++
jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/lateral/socket/tcp/LateralTCPCacheManager.java
Fri Aug 11 08:51:10 2006
@@ -84,7 +84,7 @@
/**
* Returns an instance of the LateralCacheManager.
- *
+ * <p>
* @param lca
* @param cacheMgr
* this allows the auxiliary to be passed a cache manager.
@@ -115,9 +115,9 @@
/**
* The monitor needs reference to one instance, acutally just a type.
- *
- * refactor this.
- *
+ * <p>
+ * TODO refactor this.
+ * <p>
* @param instance
*/
private static synchronized void createMonitor( ILateralCacheManager
instance )
@@ -139,7 +139,7 @@
/**
* Constructor for the LateralCacheManager object.
- *
+ * <p>
* @param lcaA
* @param cacheMgr
*/
@@ -192,7 +192,7 @@
/**
* Adds the lateral cache listener to the underlying cache-watch service.
- *
+ * <p>
* @param cacheName
* The feature to be added to the LateralCacheListener attribute
* @param listener
@@ -218,7 +218,7 @@
* <p>
* There should be one manager per server and one cache per region per
* manager.
- *
+ * <p>
* @return AuxiliaryCache
* @param cacheName
*/
Modified:
jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/lateral/socket/tcp/LateralTCPListener.java
URL:
http://svn.apache.org/viewvc/jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/lateral/socket/tcp/LateralTCPListener.java?rev=430809&r1=430808&r2=430809&view=diff
==============================================================================
---
jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/lateral/socket/tcp/LateralTCPListener.java
(original)
+++
jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/lateral/socket/tcp/LateralTCPListener.java
Fri Aug 11 08:51:10 2006
@@ -1,19 +1,14 @@
package org.apache.jcs.auxiliary.lateral.socket.tcp;
/*
- * Copyright 2001-2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License")
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Copyright 2001-2004 The Apache Software Foundation. Licensed under the
Apache
+ * License, Version 2.0 (the "License") you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
+ * or agreed to in writing, software distributed under the License is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
*/
import java.io.IOException;
@@ -40,8 +35,10 @@
import EDU.oswego.cs.dl.util.concurrent.ThreadFactory;
/**
- * Listens for connections from other TCP lateral caches and handles them.
- *
+ * Listens for connections from other TCP lateral caches and handles them. The
+ * initialization method starts a listening thread, which creates a socket
+ * server. When messages are received they are passed to a pooled executor
which
+ * then calls the appropriate handle method.
*/
public class LateralTCPListener
implements ILateralCacheListener, Serializable
@@ -59,8 +56,6 @@
/** Map of available instances, keyed by port */
protected final static HashMap instances = new HashMap();
- // ----------------------------------------------------- instance variables
-
/** The socket listener */
private ListenerThread receiver;
@@ -74,17 +69,17 @@
private int removeCnt = 0;
+ private int getCnt = 0;
+
/**
* Use the vmid by default. This can be set for testing. If we ever need to
* run more than one per vm, then we need a new technique.
*/
private long listenerId = LateralCacheInfo.listenerId;
- // -------------------------------------------------------- factory methods
-
/**
* Gets the instance attribute of the LateralCacheTCPListener class.
- *
+ * <p>
* @param ilca
* ITCPLateralCacheAttributes
* @param cacheMgr
@@ -114,12 +109,10 @@
return ins;
}
- // ------------------------------------------------------- instance methods
-
/**
* Only need one since it does work for all regions, just reference by
* multiple region names.
- *
+ * <p>
* @param ilca
*/
protected LateralTCPListener( ITCPLateralCacheAttributes ilca )
@@ -152,7 +145,7 @@
}
/**
- * let the lateral cache set a listener_id. Since there is only one
+ * Let the lateral cache set a listener_id. Since there is only one
* listerenr for all the regions and every region gets registered? the id
* shouldn't be set if it isn't zero. If it is we assume that it is a
* reconnect.
@@ -164,7 +157,7 @@
* <p>
* The service will use the value it sets in all send requests to the
* sender.
- *
+ * <p>
* @param id
* The new listenerId value
* @throws IOException
@@ -181,7 +174,7 @@
/**
* Gets the listenerId attribute of the LateralCacheTCPListener object
- *
+ * <p>
* @return The listenerId value
* @throws IOException
*/
@@ -191,9 +184,10 @@
return this.listenerId;
}
- /*
- * (non-Javadoc)
- *
+ /**
+ * Increments the put count. Gets the cache that was injected by the
lateral
+ * factory. Calls put on the cache.
+ * <p>
* @see
org.apache.jcs.engine.behavior.ICacheListener#handlePut(org.apache.jcs.engine.behavior.ICacheElement)
*/
public void handlePut( ICacheElement element )
@@ -217,9 +211,10 @@
getCache( element.getCacheName() ).localUpdate( element );
}
- /*
- * (non-Javadoc)
- *
+ /**
+ * Increments the remove count. Gets the cache that was injected by the
+ * lateral factory. Calls remove on the cache.
+ * <p>
* @see
org.apache.jcs.engine.behavior.ICacheListener#handleRemove(java.lang.String,
* java.io.Serializable)
*/
@@ -243,14 +238,15 @@
getCache( cacheName ).localRemove( key );
}
- /*
- * (non-Javadoc)
- *
+ /**
+ * Gets the cache that was injected by the lateral factory. Calls removeAll
+ * on the cache.
+ * <p>
* @see
org.apache.jcs.engine.behavior.ICacheListener#handleRemoveAll(java.lang.String)
*/
public void handleRemoveAll( String cacheName )
throws IOException
- {
+ {
if ( log.isDebugEnabled() )
{
log.debug( "handleRemoveAll> cacheName=" + cacheName );
@@ -260,6 +256,9 @@
}
/**
+ * Gets the cache that was injected by the lateral factory. Calls get on
the
+ * cache.
+ * <p>
* @param cacheName
* @param key
* @return Serializable
@@ -268,6 +267,16 @@
public Serializable handleGet( String cacheName, Serializable key )
throws IOException
{
+ getCnt++;
+ if ( log.isInfoEnabled() )
+ {
+ if ( getGetCnt() % 100 == 0 )
+ {
+ log.info( "Get Count (port " +
getTcpLateralCacheAttributes().getTcpListenerPort() + ") = "
+ + getGetCnt() );
+ }
+ }
+
if ( log.isDebugEnabled() )
{
log.debug( "handleGet> cacheName=" + cacheName + ", key = " + key
);
@@ -276,9 +285,9 @@
return getCache( cacheName ).localGet( key );
}
- /*
- * (non-Javadoc)
- *
+ /**
+ * Right now this does nothing.
+ * <p>
* @see
org.apache.jcs.engine.behavior.ICacheListener#handleDispose(java.lang.String)
*/
public void handleDispose( String cacheName )
@@ -291,7 +300,7 @@
// TODO handle active deregistration, rather than passive detection
// through error
- //getCacheManager().freeCache( cacheName, true );
+ // getCacheManager().freeCache( cacheName, true );
}
/**
@@ -299,7 +308,7 @@
* <p>
* Normally this is set by the factory. If it wasn't set the listener
* defaults to the expected singleton behavior of the cache amanger.
- *
+ * <p>
* @param name
* @return CompositeCache
*/
@@ -319,11 +328,9 @@
return getCacheManager().getCache( name );
}
- // ---------------------------------------------------------- inner classes
-
/**
* This is roughly the number of updates the lateral has received.
- *
+ * <p>
* @return Returns the putCnt.
*/
public int getPutCnt()
@@ -332,13 +339,21 @@
}
/**
+ * @return Returns the getCnt.
+ */
+ public int getGetCnt()
+ {
+ return getCnt;
+ }
+
+ /**
* @return Returns the removeCnt.
*/
public int getRemoveCnt()
{
return removeCnt;
}
-
+
/**
* @param cacheMgr
* The cacheMgr to set.
@@ -421,7 +436,8 @@
}
/**
- * A Separate thread taht runs when a command comes into the
LateralTCPReceiver.
+ * A Separate thread taht runs when a command comes into the
+ * LateralTCPReceiver.
*/
public class ConnectionHandler
implements Runnable
@@ -430,7 +446,6 @@
/**
* Construct for a given socket
- *
* @param socket
*/
public ConnectionHandler( Socket socket )
@@ -511,7 +526,7 @@
/**
* This calls the appropriate method, based on the command sent in the
* Lateral element descriptor.
- *
+ * <p>
* @param led
* @throws IOException
*/
@@ -541,19 +556,21 @@
{
if ( log.isDebugEnabled() )
{
- log.debug( "Filtering detected identical
hashCode [" + led.valHashCode + "], not issuing a remove for led " + led );
- }
+ log.debug( "Filtering detected identical
hashCode [" + led.valHashCode
+ + "], not issuing a remove for led " +
led );
+ }
return;
}
else
{
if ( log.isDebugEnabled() )
{
- log.debug( "Different hashcodes, in cache
[" + test.getVal().hashCode() + "] sent [" + led.valHashCode + "]" );
+ log.debug( "Different hashcodes, in cache
[" + test.getVal().hashCode()
+ + "] sent [" + led.valHashCode + "]" );
}
}
}
- }
+ }
}
handleRemove( cacheName, key );
}
@@ -578,16 +595,14 @@
/**
* Allows us to set the daemon status on the executor threads
- *
+ * <p>
* @author aaronsm
- *
*/
class MyThreadFactory
implements ThreadFactory
{
/*
* (non-Javadoc)
- *
* @see
EDU.oswego.cs.dl.util.concurrent.ThreadFactory#newThread(java.lang.Runnable)
*/
public Thread newThread( Runnable runner )
Modified:
jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/lateral/socket/tcp/LateralTCPSender.java
URL:
http://svn.apache.org/viewvc/jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/lateral/socket/tcp/LateralTCPSender.java?rev=430809&r1=430808&r2=430809&view=diff
==============================================================================
---
jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/lateral/socket/tcp/LateralTCPSender.java
(original)
+++
jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/lateral/socket/tcp/LateralTCPSender.java
Fri Aug 11 08:51:10 2006
@@ -29,7 +29,8 @@
/**
* This class is based on the log4j SocketAppender class. I'm using a differnet
- * repair structure, so it is significant;y different.
+ * repair structure, so it is significantly different.
+ * <p>
* @version $Id$
*/
public class LateralTCPSender
@@ -98,7 +99,7 @@
if ( h2 == null )
{
- throw new IOException( "Cannot connect to invalid address " +
h2 + ":" + po );
+ throw new IOException( "Cannot connect to invalid address [" +
h2 + ":" + po + "]" );
}
init( h2, po );
@@ -121,7 +122,10 @@
try
{
- log.debug( "Attempting connection to " + address.getHostName() );
+ if ( log.isInfoEnabled() )
+ {
+ log.info( "Attempting connection to [" + address.getHostName()
+ "]" );
+ }
// have time out socket open do this for us
socket = SocketOpener.openSocket( host, port, openTimeOut );
@@ -139,15 +143,14 @@
}
catch ( java.net.ConnectException e )
{
- log.debug( "Remote host " + address.getHostName() + " refused
connection." );
+ log.debug( "Remote host [" + address.getHostName() + "] refused
connection." );
throw e;
}
catch ( IOException e )
{
- log.debug( "Could not connect to " + address.getHostName() + ".
Exception is " + e );
+ log.debug( "Could not connect to [" + address.getHostName() + "].
Exception is " + e );
throw e;
}
-
}
/**
@@ -202,7 +205,6 @@
if ( address == null )
{
throw new IOException( "No remote host is set for
LateralTCPSender." );
- // return;
}
if ( oos != null )
@@ -271,7 +273,6 @@
{
try
{
-
try
{
// clean up input stream, nothing should be there yet.
@@ -292,6 +293,8 @@
try
{
+ // TODO make configurable
+ //socket.setSoTimeout( 2000 );
ObjectInputStream ois = new ObjectInputStream(
socket.getInputStream() );
Object obj = ois.readObject();
ice = (ICacheElement) obj;
@@ -303,7 +306,12 @@
}
catch ( IOException ioe )
{
- log.error( "Could not open ObjectInputStream to " +
socket, ioe );
+ String message = "Could not open ObjectInputStream to
" + socket;
+ if ( socket!= null )
+ {
+ message += " SoTimeout [" + socket.getSoTimeout()
+"] Connected [" + socket.isConnected() + "]";
+ }
+ log.error( message, ioe );
throw ioe;
}
catch ( Exception e )
@@ -329,10 +337,8 @@
}
}
}
- // end synchronized block
return ice;
-
}
/**
@@ -420,5 +426,4 @@
System.out.println( e.toString() );
}
}
-
}
Modified:
jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/lateral/socket/tcp/LateralTCPService.java
URL:
http://svn.apache.org/viewvc/jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/lateral/socket/tcp/LateralTCPService.java?rev=430809&r1=430808&r2=430809&view=diff
==============================================================================
---
jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/lateral/socket/tcp/LateralTCPService.java
(original)
+++
jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/lateral/socket/tcp/LateralTCPService.java
Fri Aug 11 08:51:10 2006
@@ -1,19 +1,14 @@
package org.apache.jcs.auxiliary.lateral.socket.tcp;
/*
- * Copyright 2001-2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License")
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Copyright 2001-2004 The Apache Software Foundation. Licensed under the
Apache
+ * License, Version 2.0 (the "License") you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
+ * or agreed to in writing, software distributed under the License is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
*/
import java.io.BufferedReader;
@@ -35,7 +30,7 @@
/**
* A lateral cache service implementation. Does not implement getGroupKey
- *
+ * <p>
* @version $Id$
*/
public class LateralTCPService
@@ -54,7 +49,7 @@
/**
* Constructor for the LateralTCPService object
- *
+ * <p>
* @param lca
* ITCPLateralCacheAttributes
* @exception IOException
@@ -69,7 +64,10 @@
sender = new LateralTCPSender( lca );
- log.debug( "created sender" );
+ if ( log.isInfoEnabled() )
+ {
+ log.debug( "Created sender to [" + lca.getTcpServer() + "]" );
+ }
}
catch ( IOException e )
{
@@ -82,12 +80,9 @@
}
}
- // -------------------------------------------------------- Service Methods
-
/**
* @param item
* @throws IOException
- *
*/
public void update( ICacheElement item )
throws IOException
@@ -95,16 +90,18 @@
update( item, getListenerId() );
}
- /*
- * (non-Javadoc)
- *
+ /**
+ * If put is allowed, we will issue a put. If issue put on remove
+ * is configured, we will issue a remove. Either way, we create a lateral
+ * element descriptor, which is essentially a JCS TCP packet. It describes
+ * what operation the receiver should take when it gets the packet.
+ * <p>
* @see
org.apache.jcs.auxiliary.lateral.behavior.ILateralCacheService#update(org.apache.jcs.engine.behavior.ICacheElement,
* long)
*/
public void update( ICacheElement item, long requesterId )
throws IOException
{
-
// if we don't allow put, see if we should remove on put
if ( !this.getTcpLateralCacheAttributes().isAllowPut() )
{
@@ -129,7 +126,7 @@
{
if ( log.isDebugEnabled() )
{
- log.debug( "Issuing a remvoe for a put" );
+ log.debug( "Issuing a remove for a put" );
}
// set the value to null so we don't send the item
CacheElement ce = new CacheElement( item.getCacheName(),
item.getKey(), null );
@@ -141,9 +138,9 @@
}
}
- /*
- * (non-Javadoc)
- *
+ /**
+ * Uses the default listener id and calls the next remove method.
+ * <p>
* @see
org.apache.jcs.engine.behavior.ICacheService#remove(java.lang.String,
* java.io.Serializable)
*/
@@ -153,9 +150,9 @@
remove( cacheName, key, getListenerId() );
}
- /*
- * (non-Javadoc)
- *
+ /**
+ * Wraps the key in a LateralElementDescriptor.
+ * <p>
* @see
org.apache.jcs.auxiliary.lateral.behavior.ILateralCacheService#remove(java.lang.String,
* java.io.Serializable, long)
*/
@@ -171,7 +168,6 @@
/*
* (non-Javadoc)
- *
* @see org.apache.jcs.engine.behavior.ICacheService#release()
*/
public void release()
@@ -182,7 +178,7 @@
/**
* Will close the connection.
- *
+ * <p>
* @param cache
* @throws IOException
*/
@@ -193,8 +189,8 @@
}
/**
- * The service does not get via this method, so this return null
- *
+ * The service does not get via this method, so this return null.
+ * <p>
* @param key
* @return always null.
* @throws IOException
@@ -214,7 +210,6 @@
/*
* (non-Javadoc)
- *
* @see org.apache.jcs.engine.behavior.ICacheService#get(java.lang.String,
* java.io.Serializable)
*/
@@ -240,7 +235,7 @@
/**
* Gets the set of keys of objects currently in the group throws
* UnsupportedOperationException
- *
+ * <p>
* @param cacheName
* @param group
* @return Set
@@ -256,7 +251,6 @@
/*
* (non-Javadoc)
- *
* @see
org.apache.jcs.engine.behavior.ICacheService#removeAll(java.lang.String)
*/
public void removeAll( String cacheName )
@@ -267,7 +261,6 @@
/*
* (non-Javadoc)
- *
* @see
org.apache.jcs.auxiliary.lateral.behavior.ILateralCacheService#removeAll(java.lang.String,
* long)
*/
@@ -282,7 +275,6 @@
}
/**
- *
* @param args
*/
public static void main( String args[] )
@@ -318,7 +310,6 @@
/*
* (non-Javadoc)
- *
* @see
org.apache.jcs.engine.behavior.ICacheObserver#addCacheListener(java.lang.String,
* org.apache.jcs.engine.behavior.ICacheListener)
*/
@@ -330,7 +321,6 @@
/*
* (non-Javadoc)
- *
* @see
org.apache.jcs.engine.behavior.ICacheObserver#addCacheListener(org.apache.jcs.engine.behavior.ICacheListener)
*/
public void addCacheListener( ICacheListener obj )
@@ -341,7 +331,6 @@
/*
* (non-Javadoc)
- *
* @see
org.apache.jcs.engine.behavior.ICacheObserver#removeCacheListener(java.lang.String,
* org.apache.jcs.engine.behavior.ICacheListener)
*/
@@ -353,7 +342,6 @@
/*
* (non-Javadoc)
- *
* @see
org.apache.jcs.engine.behavior.ICacheObserver#removeCacheListener(org.apache.jcs.engine.behavior.ICacheListener)
*/
public void removeCacheListener( ICacheListener obj )
|