dlr         2003/02/11 13:11:38

  Modified:    src/java/org/apache/jcs/engine/memory/lru
                        LRUMemoryCache.java
  Log:
  * src/java/org/apache/jcs/engine/memory/lru/LRUMemoryCache.java
    update(): Clarified map.put() operation to be a bit clearer.
              Removed reference to unused MemoryElementDescriptor object.
              Added null checks to last and last.ce to avoid NPEs
              when underlying objects have bugs in their .equals() and
              .hashCode() implementations.
              Added debugging messages when items from underlying map
              cannot be found or removed when a full cache is being purged.
              Adding more debugging messages after method is complete
              to verify integrity of the cache.
  
    removeAll(): Added implementation that overrides base class. This fixes
                 issue where underlying map was being reallocated but the
                 linked list still contained data.
  
    get(): Synchronizing method to prevent possible issues.
           Adding debug code to verify cache after method completion.
  
    removeNode(): Adding debug code to display cache name in output.
  
    addLast(): Removing unnecessary return statement.
               Adding debug code to verify cache after method completion.
  
    dumpCacheSize(): Adding method to compute number of elements in the
                     linked list.
  
    verifyCache(): Adding method to verify the integrity of the cache. This
                   is done three ways; first by walking the linked list
                   and verifying that they keys exist in the map, secondly
                   by walking the list and verifying that the values exist
                   in the map, and lastly by walking the map and verifying
                   that the keys exist in the linked list. None of this
                   verification is done if the Log level is not turned up
                   to 'DEBUG' level.
  
    verifyCache(key): Adding method to ensure that an individual key exists
                      in both the linked list and the map.
  
  Submitted by: Todd Enersen <[EMAIL PROTECTED]>
  
  Revision  Changes    Path
  1.18      +183 -15   
jakarta-turbine-jcs/src/java/org/apache/jcs/engine/memory/lru/LRUMemoryCache.java
  
  Index: LRUMemoryCache.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-turbine-jcs/src/java/org/apache/jcs/engine/memory/lru/LRUMemoryCache.java,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -u -r1.17 -r1.18
  --- LRUMemoryCache.java       27 Jul 2002 06:07:12 -0000      1.17
  +++ LRUMemoryCache.java       11 Feb 2003 21:11:38 -0000      1.18
  @@ -72,7 +72,7 @@
           ce.getElementAttributes().setLastAccessTimeNow();
           addFirst( ce );
           MemoryElementDescriptor old =
  -            ( MemoryElementDescriptor ) map.put( ce.getKey(), first );
  +            ( MemoryElementDescriptor ) map.put( first.ce.getKey(), first );
   
           // If the node was the same as an existing node, remove it.
   
  @@ -107,27 +107,72 @@
               // need to pre-queue the queuing.  This would be a bit wasteful
               // and wouldn't save much time in this synchronous call.
   
  -            MemoryElementDescriptor node;
  -
               for ( int i = 0; i < chunkSizeCorrected; i++ )
               {
                   synchronized ( this )
                   {
  -                    cache.spoolToDisk( last.ce );
  -
  -                    map.remove( last.ce.getKey() );
  -
  -                    removeNode( last );
  +                    if ( last != null ) 
  +                    {
  +                        if ( last.ce != null )
  +                        {
  +                            cache.spoolToDisk( last.ce );
  +                            if ( !map.containsKey(last.ce.getKey()) )
  +                            {
  +                                log.error("update: map does not contain key: " + 
last.ce.getKey());
  +                                verifyCache();
  +                            }
  +                            if ( map.remove(last.ce.getKey()) == null )
  +                            {
  +                                log.warn("update: remove failed for key: " + 
last.ce.getKey() );
  +                                verifyCache();
  +                            }
  +                        }
  +                        else
  +                        {
  +                            throw new Error("update: last.ce is null!");
  +                        }
  +                        removeNode( last );
  +                    } 
  +                    else 
  +                    {
  +                        verifyCache();
  +                        throw new Error("update: last is null!");
  +                    }
                   }
               }
   
               if ( log.isDebugEnabled() )
               {
  -                log.debug( "After spool map size: " + size );
  +                log.debug("update: After spool map size: " + map.size());
  +            }
  +            if ( map.size() != dumpCacheSize() )
  +            {
  +                log.error("update: After spool, size mismatch: map.size() = "
  +                          + map.size() + ", linked list size = " +
  +                          dumpCacheSize());
               }
           }
       }
   
  +    /**
  +     * 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();
  +        for ( MemoryElementDescriptor me = first; me != null; ) 
  +        {
  +            if ( me.prev != null )
  +            {
  +                me.prev = null;
  +            }
  +            MemoryElementDescriptor next = me.next;
  +            me = next;
  +        }
  +        first = last = null;
  +    }
   
       /**
        *  Get an item from the cache without affecting its last access time or
  @@ -168,14 +213,15 @@
        *@return                  ICacheElement if found, else null
        *@exception  IOException
        */
  -    public ICacheElement get( Serializable key )
  +    public synchronized ICacheElement get( Serializable key )
           throws IOException
       {
           ICacheElement ce = null;
   
           if ( log.isDebugEnabled() )
           {
  -            log.debug( "getting item for key: " + key );
  +            log.debug( "getting item from cache " + cacheName + " for key " +
  +                       key );
           }
   
           MemoryElementDescriptor me = (MemoryElementDescriptor)map.get(key);
  @@ -197,6 +243,7 @@
               log.debug( cacheName + ": LRUMemoryCache miss for " + key );
           }
           
  +        verifyCache();
           return ce;
       }
   
  @@ -210,7 +257,7 @@
        *@return
        *@exception  IOException
        */
  -    public boolean remove( Serializable key )
  +    public synchronized boolean remove( Serializable key )
           throws IOException
       {
           if ( log.isDebugEnabled() )
  @@ -287,7 +334,9 @@
       public class IteratorWrapper
           implements Iterator
       {
  +        private final Log log = LogFactory.getLog( LRUMemoryCache.class );
           private final Iterator i;
  +
           private IteratorWrapper(Map m)
           {
               i = m.entrySet().iterator();
  @@ -382,7 +431,8 @@
       {
           if ( log.isDebugEnabled() )
           {
  -            log.debug( "removing node " + me.ce.getKey() );
  +            log.debug( "removing node " + me.ce.getKey() + " from cache " +
  +                       cacheName );
           }
   
           if ( me.next == null )
  @@ -443,7 +493,7 @@
               me.prev = last;
           }
           last = me;
  -        return;
  +        verifyCache(ce.getKey());
       }
   
       /**
  @@ -537,6 +587,124 @@
           {
               log.debug( "dumpCacheEntries> key="
                    + me.ce.getKey() + ", val=" + me.ce.getVal() );
  +        }
  +    }
  +
  +    private int dumpCacheSize() 
  +    {
  +        int size = 0;
  +        for ( MemoryElementDescriptor me = first; me != null;  me = me.next )
  +        {
  +            size++;
  +        }
  +        return size; 
  +    }
  +
  +    private void verifyCache() 
  +    {
  +        if ( !log.isDebugEnabled() ) 
  +            return;
  +
  +        boolean found = false;
  +        log.debug("verifycache[" + cacheName + "]: mapContains " + map.size() + " 
elements, linked list contains " 
  +                  + dumpCacheSize() + " elements" );
  +        log.debug("verifycache: checking linked list by key ");
  +        for ( MemoryElementDescriptor li = first; li != null; li = li.next ) 
  +        {
  +            Object key = li.ce.getKey();
  +            if ( !map.containsKey(key) ) 
  +            {
  +                log.error("verifycache[" + cacheName + "]: map does not contain key 
: " + li.ce.getKey());
  +                log.error("li.hashcode=" + li.ce.getKey().hashCode());
  +                log.error("key class=" + key.getClass());
  +                log.error("key hashcode=" + key.hashCode());
  +                log.error("key toString=" + key.toString());
  +                if ( key instanceof GroupAttrName ) 
  +                {
  +                    GroupAttrName name = (GroupAttrName) key;
  +                    log.error("GroupID hashcode=" + name.groupId.hashCode());
  +                    log.error("GroupID.class=" + name.groupId.getClass());
  +                    log.error("AttrName hashcode=" + name.attrName.hashCode());
  +                    log.error("AttrName.class=" + name.attrName.getClass());
  +                }
  +                dumpMap();
  +            }
  +            else if ( map.get(li.ce.getKey()) == null ) 
  +            {
  +                log.error("verifycache[" + cacheName +
  +                          "]: linked list retrieval returned null for key: " +
  +                          li.ce.getKey());
  +            }
  +        }
  +
  +        log.debug("verifycache: checking linked list by value ");
  +        for ( MemoryElementDescriptor li3 = first; li3 != null; li3 = li3.next ) 
  +        {
  +            if ( map.containsValue(li3) == false ) 
  +            {
  +                log.error("verifycache[" + cacheName + "]: map does not contain 
value : " + li3);
  +                dumpMap();
  +            } 
  +        }
  +
  +        log.debug("verifycache: checking via keysets!");
  +        for ( Iterator itr2 = map.keySet().iterator(); itr2.hasNext(); )
  +        {
  +            found = false;
  +            Serializable val = null;
  +            try
  +            {
  +                val = (Serializable) itr2.next();
  +            }
  +            catch ( NoSuchElementException nse )
  +            {
  +                log.error("verifycache: no such element exception");
  +            }                
  +
  +            for ( MemoryElementDescriptor li2 = first; li2 != null; li2 = li2.next 
) 
  +            {
  +                if ( val.equals(li2.ce.getKey()) )
  +                {
  +                    found = true;
  +                    break;
  +                }
  +            }
  +            if ( !found ) 
  +            {
  +                log.error("verifycache[" + cacheName + "]: key not found in list : 
" + val );
  +                dumpCacheEntries();
  +                if ( map.containsKey(val) ) 
  +                {
  +                    log.error("verifycache: map contains key");
  +                }
  +                else 
  +                {
  +                    log.error("verifycache: map does NOT contain key, what the 
HECK!");
  +                }
  +            }
  +        }
  +    }
  +
  +    private void verifyCache(Serializable key) 
  +    {
  +        if ( !log.isDebugEnabled() ) 
  +            return;
  +
  +        boolean found = false;
  +
  +        // go through the linked list looking for the key
  +        for ( MemoryElementDescriptor li = first; li != null; li = li.next ) 
  +        {
  +            if ( li.ce.getKey() == key ) 
  +            {
  +                found = true;
  +                log.debug("verifycache(key) key match: " + key );
  +                break;
  +            }
  +        }
  +        if ( !found ) 
  +        {
  +            log.error("verifycache(key)[" + cacheName + "], couldn't find key! : " 
+ key );
           }
       }
   }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to