Return-Path: Delivered-To: apmail-jakarta-jcs-dev-archive@www.apache.org Received: (qmail 95246 invoked from network); 11 Aug 2006 15:51:40 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 11 Aug 2006 15:51:40 -0000 Received: (qmail 52710 invoked by uid 500); 11 Aug 2006 15:51:39 -0000 Delivered-To: apmail-jakarta-jcs-dev-archive@jakarta.apache.org Received: (qmail 52683 invoked by uid 500); 11 Aug 2006 15:51:39 -0000 Mailing-List: contact jcs-dev-help@jakarta.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: "JCS Developers List" Delivered-To: mailing list jcs-dev@jakarta.apache.org Received: (qmail 52672 invoked by uid 500); 11 Aug 2006 15:51:39 -0000 Delivered-To: apmail-jakarta-jcs-commits@jakarta.apache.org Received: (qmail 52669 invoked by uid 500); 11 Aug 2006 15:51:39 -0000 Delivered-To: apmail-jakarta-jcs-cvs@jakarta.apache.org Received: (qmail 52666 invoked by uid 99); 11 Aug 2006 15:51:39 -0000 Received: from asf.osuosl.org (HELO asf.osuosl.org) (140.211.166.49) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 11 Aug 2006 08:51:39 -0700 X-ASF-Spam-Status: No, hits=-8.6 required=10.0 tests=ALL_TRUSTED,INFO_TLD,NO_REAL_NAME X-Spam-Check-By: apache.org Received-SPF: pass (asf.osuosl.org: local policy) Received: from [140.211.166.113] (HELO eris.apache.org) (140.211.166.113) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 11 Aug 2006 08:51:36 -0700 Received: by eris.apache.org (Postfix, from userid 65534) id 11AA11A981A; Fri, 11 Aug 2006 08:51:16 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: svn commit: r430809 [1/2] - in /jakarta/jcs/trunk/src: experimental/org/apache/jcs/engine/memory/arc/ java/org/apache/jcs/access/ java/org/apache/jcs/access/behavior/ java/org/apache/jcs/auxiliary/lateral/ java/org/apache/jcs/auxiliary/lateral/socket/t... Date: Fri, 11 Aug 2006 15:51:11 -0000 To: jcs-cvs@jakarta.apache.org From: asmuts@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20060811155116.11AA11A981A@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N 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. + *

+ * See the ARC method for more detail on how the algorithm works. + *

+ * @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 + *

+ * @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. + *

+ * 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. + *

+ * 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. + *

+ * @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 B2’s 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. + *

+ * @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. + *

+ * @param temp + */ + protected void handleFoundInT2( ElementDescriptor temp ) + { + if ( log.isDebugEnabled() ) + { + log.debug( "T2" ); + } + + temp.listNum = _T2_; + T2.makeFirst( temp ); + } + + /** + * B1 hit: favor recency + *

+ * @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 + *

+ * @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. + *

+ * @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 B2’s 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. + *

+ * @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 ) ) + { + // T1’s 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)) - { // T1’s 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. + *

+ * (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. + *

+ * @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 + *

+ * @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. + *

+ * @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. + *

+ * @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 + *

+ * @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. + *

+ * @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. + *

+ * @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. + *

+ * @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 numberToFree + * according to its eviction policy. For example, the LRUMemoryCache will + * remove the numberToFree least recently used items. These will be + * spooled to disk if a disk auxiliary is available. + *

+ * @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 numberToFree + * according to its eviction policy. For example, the LRUMemoryCache will + * remove the numberToFree least recently used items. These will be + * spooled to disk if a disk auxiliary is available. + *

+ * @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 - * + *

* @param cattr * @param lateral * @param monitor @@ -70,7 +69,7 @@ /** * Constructor for the LateralCache object - * + *

* @param cattr */ protected LateralCache( ILateralCacheAttributes cattr ) @@ -81,7 +80,7 @@ /** * Update lateral. - * + *

* @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. - * + *

* @param key * @return * @throws IOException @@ -153,7 +150,7 @@ /** * Synchronously remove from the remote cache; if failed, replace the remote * handle with a zombie. - * + *

* @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. - * + *

* @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. - * + *

* @return The status value */ public int getStatus() @@ -240,7 +229,7 @@ /** * Returns the current cache size. - * + *

* @return The size value */ public int getSize() @@ -250,7 +239,7 @@ /** * Gets the cacheType attribute of the LateralCache object - * + *

* @return The cacheType value */ public int getCacheType() @@ -260,7 +249,7 @@ /** * Gets the cacheName attribute of the LateralCache object - * + *

* @return The cacheName value */ public String getCacheName() @@ -270,7 +259,7 @@ /** * Not yet sure what to do here. - * + *

* @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. - * + *

* @param lateral */ public void fixCache( ILateralCacheService lateral ) @@ -315,7 +303,7 @@ /** * getStats - * + *

* @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. - * + *

* @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 + *

+ * @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. - * + *

* @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. - * + *

+ * TODO refactor this. + *

* @param instance */ private static synchronized void createMonitor( ILateralCacheManager instance ) @@ -139,7 +139,7 @@ /** * Constructor for the LateralCacheManager object. - * + *

* @param lcaA * @param cacheMgr */ @@ -192,7 +192,7 @@ /** * Adds the lateral cache listener to the underlying cache-watch service. - * + *

* @param cacheName * The feature to be added to the LateralCacheListener attribute * @param listener @@ -218,7 +218,7 @@ *

* There should be one manager per server and one cache per region per * manager. - * + *

* @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. - * + *

* @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. - * + *

* @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 @@ *

* The service will use the value it sets in all send requests to the * sender. - * + *

* @param id * The new listenerId value * @throws IOException @@ -181,7 +174,7 @@ /** * Gets the listenerId attribute of the LateralCacheTCPListener object - * + *

* @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. + *

* @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. + *

* @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. + *

* @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. + *

* @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. + *

* @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 @@ *

* Normally this is set by the factory. If it wasn't set the listener * defaults to the expected singleton behavior of the cache amanger. - * + *

* @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. - * + *

* @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. - * + *

* @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 - * + *

* @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. + *

* @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 - * + *

* @version $Id$ */ public class LateralTCPService @@ -54,7 +49,7 @@ /** * Constructor for the LateralTCPService object - * + *

* @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. + *

* @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. + *

* @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. + *

* @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. - * + *

* @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. + *

* @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 - * + *

* @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 ) --------------------------------------------------------------------- To unsubscribe, e-mail: jcs-dev-unsubscribe@jakarta.apache.org For additional commands, e-mail: jcs-dev-help@jakarta.apache.org