jakarta-jcs-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From asm...@apache.org
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 GMT
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 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.
+     * <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 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.
+     * <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 ) )
+            {
+                // 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.
+     * <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 )



---------------------------------------------------------------------
To unsubscribe, e-mail: jcs-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: jcs-dev-help@jakarta.apache.org


Mime
View raw message