Author: epunzalan
Date: Mon Dec 12 23:52:22 2005
New Revision: 356503

URL: http://svn.apache.org/viewcvs?rev=356503&view=rev
Log:
PR: MRM-39

Added Cache class, and revised CachedRepositoryQueryLayer to use it.

Added:
    
maven/repository-manager/trunk/maven-repository-reports-standard/src/main/java/org/apache/maven/repository/reporting/Cache.java
   (with props)
    
maven/repository-manager/trunk/maven-repository-reports-standard/src/test/java/org/apache/maven/repository/reporting/CacheTest.java
   (with props)
Modified:
    
maven/repository-manager/trunk/maven-repository-reports-standard/src/main/java/org/apache/maven/repository/reporting/AbstractRepositoryQueryLayer.java
    
maven/repository-manager/trunk/maven-repository-reports-standard/src/main/java/org/apache/maven/repository/reporting/CachedRepositoryQueryLayer.java
    
maven/repository-manager/trunk/maven-repository-reports-standard/src/test/java/org/apache/maven/repository/reporting/AbstractRepositoryQueryLayerTest.java
    
maven/repository-manager/trunk/maven-repository-reports-standard/src/test/java/org/apache/maven/repository/reporting/CachedRepositoryQueryLayerTest.java

Modified: 
maven/repository-manager/trunk/maven-repository-reports-standard/src/main/java/org/apache/maven/repository/reporting/AbstractRepositoryQueryLayer.java
URL: 
http://svn.apache.org/viewcvs/maven/repository-manager/trunk/maven-repository-reports-standard/src/main/java/org/apache/maven/repository/reporting/AbstractRepositoryQueryLayer.java?rev=356503&r1=356502&r2=356503&view=diff
==============================================================================
--- 
maven/repository-manager/trunk/maven-repository-reports-standard/src/main/java/org/apache/maven/repository/reporting/AbstractRepositoryQueryLayer.java
 (original)
+++ 
maven/repository-manager/trunk/maven-repository-reports-standard/src/main/java/org/apache/maven/repository/reporting/AbstractRepositoryQueryLayer.java
 Mon Dec 12 23:52:22 2005
@@ -60,7 +60,7 @@
     protected String getSnapshotArtifactRepositoryPath( Artifact artifact, 
Snapshot snapshot )
     {
         File f = new File( repository.getBasedir(), repository.pathOf( 
artifact ) );
-        String snapshotInfo = artifact.getVersion().replaceAll( "SNAPSHOT", 
snapshot.getTimestamp() + "-" + 
+        String snapshotInfo = artifact.getVersion().replaceFirst( "SNAPSHOT", 
snapshot.getTimestamp() + "-" + 
                                                                             
snapshot.getBuildNumber() + ".pom" );
         File snapshotFile = new File( f.getParentFile(), 
artifact.getArtifactId() + "-" + snapshotInfo );
         return snapshotFile.getAbsolutePath();

Added: 
maven/repository-manager/trunk/maven-repository-reports-standard/src/main/java/org/apache/maven/repository/reporting/Cache.java
URL: 
http://svn.apache.org/viewcvs/maven/repository-manager/trunk/maven-repository-reports-standard/src/main/java/org/apache/maven/repository/reporting/Cache.java?rev=356503&view=auto
==============================================================================
--- 
maven/repository-manager/trunk/maven-repository-reports-standard/src/main/java/org/apache/maven/repository/reporting/Cache.java
 (added)
+++ 
maven/repository-manager/trunk/maven-repository-reports-standard/src/main/java/org/apache/maven/repository/reporting/Cache.java
 Mon Dec 12 23:52:22 2005
@@ -0,0 +1,190 @@
+package org.apache.maven.repository.reporting;
+
+/*
+ * Copyright 2001-2005 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.util.HashMap;
+import java.util.Map;
+
+/**
+ *
+ */
+public class Cache
+{
+    private Map cache;
+
+    private DblLinkedList mostRecent;
+    private double cacheHitRatio = 0;
+    private long cacheMaxSize = 0;
+    
+    private long cacheHits = 0;
+    private long cacheMiss = 0;
+
+    public Cache( double cacheHitRatio )
+    {
+        this( cacheHitRatio, 0 );
+    }
+
+    public Cache( double cacheHitRatio, long cacheMaxSize )
+    {
+        this.cacheHitRatio = cacheHitRatio;
+        this.cacheMaxSize = cacheMaxSize;
+        
+        cache = new HashMap();
+    }
+
+    public Object get( Object key )
+    {
+        Object retValue = null;
+        
+        if ( cache.containsKey( key ) )
+        {
+            DblLinkedList cacheEntry = (DblLinkedList) cache.get( key );
+            
+            makeMostRecent( cacheEntry );
+            
+            retValue = cacheEntry.cacheValue;
+            
+            cacheHits++;
+        }
+        else
+        {
+            cacheMiss++;
+        }
+
+        return retValue;
+    }
+
+    public void put( Object key, Object value )
+    {
+        DblLinkedList entry;
+        if ( !cache.containsKey( key ) )
+        {
+            entry = new DblLinkedList( key, value );
+            cache.put( key, entry );
+            manageCache();
+        }
+        else
+        {
+            entry = (DblLinkedList) cache.get( key );
+        }
+
+        makeMostRecent( entry );
+    }
+
+    public double getHitRate()
+    {
+        return ( cacheHits == 0 && cacheMiss == 0 ) ? 0 : ( (double) cacheHits 
) / (double) ( cacheHits + cacheMiss );
+    }
+    
+    public long size()
+    {
+        return cache.size();
+    }
+    
+    public void flush()
+    {
+        while ( cache.size() > 0 )
+            trimCache();
+        cacheHits = 0;
+        cacheMiss = 0;
+        cache = new HashMap();
+    }
+
+    private void makeMostRecent( DblLinkedList list )
+    {
+        if ( mostRecent != list )
+        {
+            removeFromLinks( list );
+
+            if ( mostRecent != null )
+            {
+                list.next = mostRecent;
+                mostRecent.prev = list;
+            }
+            mostRecent = list;
+        }
+    }
+
+    private void removeFromLinks( DblLinkedList list )
+    {
+        if ( list.prev != null )
+            list.prev.next = list.next;
+        if ( list.next != null )
+            list.next.prev = list.prev;
+        
+        list.prev = null;
+        list.next = null;
+    }
+
+    private void manageCache()
+    {
+        if ( cacheMaxSize == 0 )
+        {
+            //if desired HitRatio is reached, we can trim the cache to 
conserve memory
+            if ( cacheHitRatio <= getHitRate() )
+            {
+                trimCache();
+            }
+        }
+        else if ( cache.size() > cacheMaxSize )
+        {
+            //trim cache regardless of cacheHitRatio
+            while( cache.size() > cacheMaxSize )
+            {
+                trimCache();
+            }
+        }
+    }
+
+    private void trimCache()
+    {
+        DblLinkedList leastRecent = getLeastRecent();
+        cache.remove( leastRecent.cacheKey );
+        if ( cache.size() > 0 )
+        {
+            removeFromLinks( leastRecent );
+        }
+        else
+        {
+            mostRecent = null;
+        }
+    }
+    
+    private DblLinkedList getLeastRecent()
+    {
+        DblLinkedList trail = mostRecent;
+
+        while( trail.next != null )
+            trail = trail.next;
+
+        return trail;
+    }
+
+    private class DblLinkedList {
+        Object cacheKey;
+        Object cacheValue;
+        DblLinkedList prev;
+        DblLinkedList next;
+        
+        public DblLinkedList( Object key, Object value )
+        {
+            this.cacheKey = key;
+            this.cacheValue = value;
+        }
+    }
+}

Propchange: 
maven/repository-manager/trunk/maven-repository-reports-standard/src/main/java/org/apache/maven/repository/reporting/Cache.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
maven/repository-manager/trunk/maven-repository-reports-standard/src/main/java/org/apache/maven/repository/reporting/Cache.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Modified: 
maven/repository-manager/trunk/maven-repository-reports-standard/src/main/java/org/apache/maven/repository/reporting/CachedRepositoryQueryLayer.java
URL: 
http://svn.apache.org/viewcvs/maven/repository-manager/trunk/maven-repository-reports-standard/src/main/java/org/apache/maven/repository/reporting/CachedRepositoryQueryLayer.java?rev=356503&r1=356502&r2=356503&view=diff
==============================================================================
--- 
maven/repository-manager/trunk/maven-repository-reports-standard/src/main/java/org/apache/maven/repository/reporting/CachedRepositoryQueryLayer.java
 (original)
+++ 
maven/repository-manager/trunk/maven-repository-reports-standard/src/main/java/org/apache/maven/repository/reporting/CachedRepositoryQueryLayer.java
 Mon Dec 12 23:52:22 2005
@@ -18,17 +18,15 @@
  */
 
 import java.io.File;
-import java.io.FileReader;
 import java.util.HashMap;
-import java.util.List;
+import java.util.LinkedList;
 import java.util.Map;
 
 import org.apache.maven.artifact.Artifact;
 import org.apache.maven.artifact.repository.ArtifactRepository;
-import 
org.apache.maven.artifact.repository.metadata.ArtifactRepositoryMetadata;
 import org.apache.maven.artifact.repository.metadata.Metadata;
 import org.apache.maven.artifact.repository.metadata.Snapshot;
-import 
org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader;
+
 
 
 /**
@@ -37,44 +35,34 @@
 public class CachedRepositoryQueryLayer
     extends AbstractRepositoryQueryLayer
 {
-    //@todo caches should expire    
-    //cache for metadata
-    private Map cacheMetadata;
-
-    //cache for repository files, all types
-    //@todo ???should also cache missing files
-    private Map cacheFile;
-    
-    //@todo ???should a listener be required???
-    private long cacheHits = 0;
+    private Cache cache;
 
+    
     public CachedRepositoryQueryLayer( ArtifactRepository repository )
     {
         this.repository = repository;
         
-        cacheMetadata = new HashMap();
-        
-        cacheFile = new HashMap();
+        cache = new Cache( 0.5 );
     }
     
-    public long getCacheHits()
+    public double getCacheHitRate()
     {
-        return cacheHits;
+        return cache.getHitRate();
     }
-
+    
     public boolean containsArtifact( Artifact artifact )
     {
         boolean artifactFound = true;
         
         // @todo should check for snapshot artifacts
-        File artifactFile = new File( repository.pathOf( artifact ) );
+        String artifactPath = repository.getBasedir() + "/" + 
repository.pathOf( artifact );
 
-        if ( !checkFileCache( artifactFile ) )
+        if ( cache.get( artifactPath ) == null )
         {
             artifactFound = super.containsArtifact( artifact );
             if ( artifactFound )
             {
-                addToFileCache( artifactFile );
+                cache.put( artifactPath, artifactPath );
             }
         }
 
@@ -87,12 +75,12 @@
 
         String path = getSnapshotArtifactRepositoryPath( artifact, snapshot );
 
-        if ( !checkFileCache( path ) )
+        if ( cache.get( path ) == null )
         {
             artifactFound = super.containsArtifact( artifact, snapshot );
             if ( artifactFound )
             {
-                addToFileCache( new File( repository.getBasedir(), path ) );
+                cache.put( path, path );
             }
         }
 
@@ -100,50 +88,25 @@
     }
 
     /**
-     * Method to utilize the cache
-     */
-    private boolean checkFileCache( File file )
-    {
-        boolean existing = false;
-
-        if ( cacheFile.containsKey( file ) )
-        {
-            cacheHits++;
-            existing = true;
-        }
-
-        return existing;
-    }
-
-    private boolean checkFileCache( String repositoryPath )
-    {
-        return checkFileCache(  new File( repository.getBasedir(), 
repositoryPath ) );
-    }
-    
-    private void addToFileCache( File file )
-    {
-        cacheFile.put( file, file );
-    }
-
-    /**
      * Override method to utilize the cache
      */
     protected Metadata getMetadata( Artifact artifact )
         throws RepositoryQueryLayerException
     {
-        Metadata metadata = null;
+        Metadata metadata = (Metadata) cache.get( artifact.getId() );
         
-        if ( cacheMetadata.containsKey( artifact.getId() ) )
-        {
-            cacheHits++;
-            metadata = (Metadata) cacheMetadata.get( artifact.getId() );
-        }
-        else
+        if ( metadata == null )
         {
             metadata = super.getMetadata( artifact );
-            cacheMetadata.put( artifact.getId(), metadata );
+            cache.put( artifact.getId(), metadata );
         }
         
         return metadata;
+    }
+
+    private class DblLinkedList {
+        DblLinkedList prev;
+        Object cacheObject;
+        DblLinkedList next;
     }
 }

Modified: 
maven/repository-manager/trunk/maven-repository-reports-standard/src/test/java/org/apache/maven/repository/reporting/AbstractRepositoryQueryLayerTest.java
URL: 
http://svn.apache.org/viewcvs/maven/repository-manager/trunk/maven-repository-reports-standard/src/test/java/org/apache/maven/repository/reporting/AbstractRepositoryQueryLayerTest.java?rev=356503&r1=356502&r2=356503&view=diff
==============================================================================
--- 
maven/repository-manager/trunk/maven-repository-reports-standard/src/test/java/org/apache/maven/repository/reporting/AbstractRepositoryQueryLayerTest.java
 (original)
+++ 
maven/repository-manager/trunk/maven-repository-reports-standard/src/test/java/org/apache/maven/repository/reporting/AbstractRepositoryQueryLayerTest.java
 Mon Dec 12 23:52:22 2005
@@ -129,7 +129,6 @@
 
     protected Artifact getArtifact( String groupId, String artifactId, String 
version )
     {
-        if ( artifactFactory == null ) System.out.println("NULL");
         return artifactFactory.createBuildArtifact( groupId, artifactId, 
version, "pom" );
     }
 

Added: 
maven/repository-manager/trunk/maven-repository-reports-standard/src/test/java/org/apache/maven/repository/reporting/CacheTest.java
URL: 
http://svn.apache.org/viewcvs/maven/repository-manager/trunk/maven-repository-reports-standard/src/test/java/org/apache/maven/repository/reporting/CacheTest.java?rev=356503&view=auto
==============================================================================
--- 
maven/repository-manager/trunk/maven-repository-reports-standard/src/test/java/org/apache/maven/repository/reporting/CacheTest.java
 (added)
+++ 
maven/repository-manager/trunk/maven-repository-reports-standard/src/test/java/org/apache/maven/repository/reporting/CacheTest.java
 Mon Dec 12 23:52:22 2005
@@ -0,0 +1,105 @@
+package org.apache.maven.repository.reporting;
+
+/*
+ * Copyright 2001-2005 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 junit.framework.TestCase;
+
+/**
+ *
+ */
+public class CacheTest
+    extends TestCase
+{
+    private Cache cache;
+
+    public void testCacheManagementBasedOnHitsRatio()
+    {
+        cache = new Cache( 0.5 );
+        newCacheObjectTests();
+        
+        String key = "key";
+        String value = "value";
+        for( int ctr=1; ctr<10; ctr++ )
+        {
+            cache.put( key + ctr, value + ctr );
+        }
+        
+        while ( cache.getHitRate() < 0.75 )
+        {
+            cache.get( "key2" );
+        }
+        cache.put( "key10", "value10");
+        assertNull( "first key must be expired", cache.get( "key1" ) );
+    }
+
+    public void testCacheManagementBasedOnCacheSize()
+    {
+        cache = new Cache( 0.5, 9 );
+        newCacheObjectTests();
+        
+        String key = "key";
+        String value = "value";
+        for( int ctr=1; ctr<10; ctr++ )
+        {
+            cache.put( key + ctr, value + ctr );
+        }
+        
+        cache.put( "key10", "value10");
+        assertNull( "first key must be expired", cache.get( "key1" ) );
+        assertEquals( "check cache size to be max size", 9, cache.size() );
+    }
+
+    public void testCacheOnRedundantData()
+    {
+        cache = new Cache( 0.5, 9 );
+        newCacheObjectTests();
+        
+        String key = "key";
+        String value = "value";
+        for( int ctr=1; ctr<10; ctr++ )
+        {
+            cache.put( key + ctr, value + ctr );
+        }
+        
+        cache.put( "key1", "value1");
+        cache.put( "key10", "value10");
+        assertNull( "second key must be gone", cache.get( "key2" ) );
+        assertEquals( "check cache size to be max size", 9, cache.size() );
+    }
+
+    private void newCacheObjectTests()
+    {
+        assertEquals( (double) 0, cache.getHitRate(), 0 );
+        assertEquals( "check cache size", 0, cache.size() );
+
+        String value = "value";
+        String key = "key";
+
+        cache.put( key, value );
+        assertEquals( "check cache hit", value, cache.get( key ) );
+        assertEquals( (double) 1, cache.getHitRate(), 0 );
+        assertEquals( "check cache size", 1, cache.size() );
+        assertNull( "check cache miss", cache.get( "none" ) );
+        assertEquals( (double) 0.5, cache.getHitRate(), 0 );
+        cache.flush();
+        assertNull( "check flushed object", cache.get( "key" ) );
+        assertEquals( (double) 0, cache.getHitRate(), 0 );
+        assertEquals( "check flushed cache size", 0, cache.size() );
+        cache.flush();
+    }
+}

Propchange: 
maven/repository-manager/trunk/maven-repository-reports-standard/src/test/java/org/apache/maven/repository/reporting/CacheTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
maven/repository-manager/trunk/maven-repository-reports-standard/src/test/java/org/apache/maven/repository/reporting/CacheTest.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Modified: 
maven/repository-manager/trunk/maven-repository-reports-standard/src/test/java/org/apache/maven/repository/reporting/CachedRepositoryQueryLayerTest.java
URL: 
http://svn.apache.org/viewcvs/maven/repository-manager/trunk/maven-repository-reports-standard/src/test/java/org/apache/maven/repository/reporting/CachedRepositoryQueryLayerTest.java?rev=356503&r1=356502&r2=356503&view=diff
==============================================================================
--- 
maven/repository-manager/trunk/maven-repository-reports-standard/src/test/java/org/apache/maven/repository/reporting/CachedRepositoryQueryLayerTest.java
 (original)
+++ 
maven/repository-manager/trunk/maven-repository-reports-standard/src/test/java/org/apache/maven/repository/reporting/CachedRepositoryQueryLayerTest.java
 Mon Dec 12 23:52:22 2005
@@ -33,25 +33,25 @@
     public void testUseFileCache()
     {
         testContainsArtifactTrue();
-        assertEquals( "check cache usage", 0, queryLayer.getCacheHits() );
+        assertEquals( 0, queryLayer.getCacheHitRate(), 0 );
         testContainsArtifactTrue();
-        assertEquals( "check cache usage", 1, queryLayer.getCacheHits() );
+        assertEquals( 0.50, queryLayer.getCacheHitRate(), 0 );
     }
     
     public void testUseMetadataCache()
         throws Exception
     {
         testArtifactVersionsTrue();
-        assertEquals( "check cache usage", 0, queryLayer.getCacheHits() );
+        assertEquals( 0, queryLayer.getCacheHitRate(), 0 );
         testArtifactVersionsTrue();
-        assertEquals( "check cache usage", 1, queryLayer.getCacheHits() );
+        assertEquals( 0.50, queryLayer.getCacheHitRate(), 0 );
     }
     
     public void testUseFileCacheOnSnapshot()
     {
         testContainsSnapshotArtifactTrue();
-        assertEquals( "check cache usage", 0, queryLayer.getCacheHits() );
+        assertEquals( 0, queryLayer.getCacheHitRate(), 0 );
         testContainsSnapshotArtifactTrue();
-        assertEquals( "check cache usage", 1, queryLayer.getCacheHits() );
+        assertEquals( 0.50, queryLayer.getCacheHitRate(), 0 );
     }
 }


Reply via email to