MNG-5677 hooks to allow fine-grained cache management

Also fixed broken cache #flush() and missing #dispose() in
couple of places.

Signed-off-by: Igor Fedorenko <igor@ifedorenko.com>
This commit is contained in:
Igor Fedorenko 2014-08-08 22:28:02 +04:00
parent 8980f67b9b
commit 693f8f6604
11 changed files with 127 additions and 48 deletions

View File

@ -21,14 +21,16 @@
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.maven.project.ExtensionDescriptor;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.classworlds.realm.ClassRealm;
import org.codehaus.plexus.classworlds.realm.NoSuchRealmException;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Disposable;
import org.eclipse.aether.artifact.Artifact;
/**
@ -36,10 +38,11 @@
*/
@Component( role = ExtensionRealmCache.class )
public class DefaultExtensionRealmCache
implements ExtensionRealmCache
implements ExtensionRealmCache, Disposable
{
private static class CacheKey
protected static class CacheKey
implements Key
{
private final List<File> files;
@ -97,28 +100,36 @@ public boolean equals( Object o )
&& sizes.equals( other.sizes );
}
@Override
public String toString()
{
return files.toString();
}
}
private final Map<CacheKey, CacheRecord> cache = new HashMap<CacheKey, CacheRecord>();
protected final Map<Key, CacheRecord> cache = new ConcurrentHashMap<Key, CacheRecord>();
public CacheRecord get( List<? extends Artifact> extensionArtifacts )
@Override
public Key createKey( List<? extends Artifact> extensionArtifacts )
{
return cache.get( new CacheKey( extensionArtifacts ) );
return new CacheKey( extensionArtifacts );
}
public CacheRecord put( List<? extends Artifact> extensionArtifacts, ClassRealm extensionRealm,
ExtensionDescriptor extensionDescriptor )
public CacheRecord get( Key key )
{
return cache.get( key );
}
public CacheRecord put( Key key, ClassRealm extensionRealm, ExtensionDescriptor extensionDescriptor )
{
if ( extensionRealm == null )
{
throw new NullPointerException();
}
CacheKey key = new CacheKey( extensionArtifacts );
if ( cache.containsKey( key ) )
{
throw new IllegalStateException( "Duplicate extension realm for extension " + extensionArtifacts );
throw new IllegalStateException( "Duplicate extension realm for extension " + key );
}
CacheRecord record = new CacheRecord( extensionRealm, extensionDescriptor );
@ -130,12 +141,29 @@ public CacheRecord put( List<? extends Artifact> extensionArtifacts, ClassRealm
public void flush()
{
for ( CacheRecord record : cache.values() )
{
ClassRealm realm = record.realm;
try
{
realm.getWorld().disposeRealm( realm.getId() );
}
catch ( NoSuchRealmException e )
{
// ignore
}
}
cache.clear();
}
public void register( MavenProject project, CacheRecord record )
public void register( MavenProject project, Key key, CacheRecord record )
{
// default cache does not track extension usage
}
public void dispose()
{
flush();
}
}

View File

@ -21,9 +21,9 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.maven.model.Plugin;
import org.apache.maven.project.MavenProject;
@ -44,7 +44,7 @@ public class DefaultPluginArtifactsCache
implements PluginArtifactsCache
{
private static class CacheKey
protected static class CacheKey
implements Key
{
@ -133,7 +133,7 @@ private static <T> boolean eq( T s1, T s2 )
}
protected final Map<Key, CacheRecord> cache = new HashMap<Key, CacheRecord>();
protected final Map<Key, CacheRecord> cache = new ConcurrentHashMap<Key, CacheRecord>();
public Key createKey( Plugin plugin, DependencyFilter extensionFilter, List<RemoteRepository> repositories,
RepositorySystemSession session )
@ -210,7 +210,7 @@ protected static boolean pluginEquals( Plugin a, Plugin b )
return CacheUtils.pluginEquals( a, b );
}
public void register( MavenProject project, CacheRecord record )
public void register( MavenProject project, Key cacheKey, CacheRecord record )
{
// default cache does not track record usage
}

View File

@ -206,7 +206,7 @@ protected static boolean pluginEquals( Plugin a, Plugin b )
return CacheUtils.pluginEquals( a, b );
}
public void register( MavenProject project, CacheRecord record )
public void register( MavenProject project, Key key, CacheRecord record )
{
// default cache does not track plugin usage
}

View File

@ -36,6 +36,13 @@
*/
public interface ExtensionRealmCache
{
/**
* A cache key.
*/
interface Key
{
// marker interface for cache keys
}
static class CacheRecord
{
@ -52,10 +59,11 @@ public CacheRecord( ClassRealm realm, ExtensionDescriptor descriptor )
}
CacheRecord get( List<? extends Artifact> extensionArtifacts );
Key createKey( List<? extends Artifact> extensionArtifacts );
CacheRecord put( List<? extends Artifact> extensionArtifacts, ClassRealm extensionRealm,
ExtensionDescriptor extensionDescriptor );
CacheRecord get( Key key );
CacheRecord put( Key key, ClassRealm extensionRealm, ExtensionDescriptor extensionDescriptor );
void flush();
@ -67,6 +75,6 @@ CacheRecord put( List<? extends Artifact> extensionArtifacts, ClassRealm extensi
* @param project The project that employs the plugin realm, must not be {@code null}.
* @param record The cache record being used for the project, must not be {@code null}.
*/
void register( MavenProject project, CacheRecord record );
void register( MavenProject project, Key key, CacheRecord record );
}

View File

@ -86,6 +86,6 @@ Key createKey( Plugin plugin, DependencyFilter extensionFilter, List<RemoteRepos
* @param project The project that employs the plugin realm, must not be {@code null}.
* @param record The cache record being used for the project, must not be {@code null}.
*/
void register( MavenProject project, CacheRecord record );
void register( MavenProject project, Key cacheKey, CacheRecord record );
}

View File

@ -80,6 +80,6 @@ Key createKey( Plugin plugin, ClassLoader parentRealm, Map<String, ClassLoader>
* @param project The project that employs the plugin realm, must not be {@code null}.
* @param record The cache record being used for the project, must not be {@code null}.
*/
void register( MavenProject project, CacheRecord record );
void register( MavenProject project, Key key, CacheRecord record );
}

View File

@ -330,7 +330,7 @@ public synchronized void setupPluginRealm( PluginDescriptor pluginDescriptor, Ma
pluginRealmCache.put( cacheKey, pluginDescriptor.getClassRealm(), pluginDescriptor.getArtifacts() );
}
pluginRealmCache.register( project, cacheRecord );
pluginRealmCache.register( project, cacheKey, cacheRecord );
}
private void createPluginRealm( PluginDescriptor pluginDescriptor, MavenSession session, ClassLoader parent,

View File

@ -143,6 +143,7 @@ private ProjectBuildingResult build( File pomFile, ModelSource modelSource, Inte
ModelBuildingRequest request = getModelBuildingRequest( config );
project = new MavenProject();
project.setFile( pomFile );
DefaultModelBuildingListener listener =
new DefaultModelBuildingListener( project, projectBuildingHelper, projectBuildingRequest );

View File

@ -244,18 +244,20 @@ public synchronized ProjectRealmCache.CacheRecord createProjectRealm( MavenProje
{
pluginArtifactsCache.put( cacheKey, e );
pluginArtifactsCache.register( project, recordArtifacts );
pluginArtifactsCache.register( project, cacheKey, recordArtifacts );
throw e;
}
}
pluginArtifactsCache.register( project, recordArtifacts );
pluginArtifactsCache.register( project, cacheKey, recordArtifacts );
ClassRealm extensionRealm;
ExtensionDescriptor extensionDescriptor = null;
final ExtensionRealmCache.Key extensionKey = extensionRealmCache.createKey( artifacts );
ExtensionRealmCache.CacheRecord recordRealm = extensionRealmCache.get( artifacts );
ExtensionRealmCache.CacheRecord recordRealm = extensionRealmCache.get( extensionKey );
if ( recordRealm != null )
{
@ -295,10 +297,10 @@ public synchronized ProjectRealmCache.CacheRecord createProjectRealm( MavenProje
}
}
recordRealm = extensionRealmCache.put( artifacts, extensionRealm, extensionDescriptor );
recordRealm = extensionRealmCache.put( extensionKey, extensionRealm, extensionDescriptor );
}
extensionRealmCache.register( project, recordRealm );
extensionRealmCache.register( project, extensionKey, recordRealm );
extensionRealms.add( extensionRealm );
if ( extensionDescriptor != null )
@ -324,7 +326,9 @@ public synchronized ProjectRealmCache.CacheRecord createProjectRealm( MavenProje
logger.debug( "Extension realms for project " + model.getId() + ": " + extensionRealms );
}
ProjectRealmCache.CacheRecord record = projectRealmCache.get( extensionRealms );
ProjectRealmCache.Key projectRealmKey = projectRealmCache.createKey( extensionRealms );
ProjectRealmCache.CacheRecord record = projectRealmCache.get( projectRealmKey );
if ( record == null )
{
@ -365,10 +369,10 @@ public synchronized ProjectRealmCache.CacheRecord createProjectRealm( MavenProje
extensionArtifactFilter = new ExclusionsDependencyFilter( exclusions );
}
record = projectRealmCache.put( extensionRealms, projectRealm, extensionArtifactFilter );
record = projectRealmCache.put( projectRealmKey, projectRealm, extensionArtifactFilter );
}
projectRealmCache.register( project, record );
projectRealmCache.register( project, projectRealmKey, record );
return record;
}

View File

@ -20,12 +20,14 @@
*/
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.codehaus.plexus.classworlds.realm.ClassRealm;
import org.codehaus.plexus.classworlds.realm.NoSuchRealmException;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Disposable;
import org.eclipse.aether.graph.DependencyFilter;
/**
@ -33,10 +35,11 @@
*/
@Component( role = ProjectRealmCache.class )
public class DefaultProjectRealmCache
implements ProjectRealmCache
implements ProjectRealmCache, Disposable
{
private static class CacheKey
protected static class CacheKey
implements Key
{
private final List<? extends ClassRealm> extensionRealms;
@ -74,28 +77,36 @@ public boolean equals( Object o )
return extensionRealms.equals( other.extensionRealms );
}
@Override
public String toString()
{
return extensionRealms.toString();
}
}
private final Map<CacheKey, CacheRecord> cache = new HashMap<CacheKey, CacheRecord>();
protected final Map<Key, CacheRecord> cache = new ConcurrentHashMap<Key, CacheRecord>();
public CacheRecord get( List<? extends ClassRealm> extensionRealms )
@Override
public Key createKey( List<? extends ClassRealm> extensionRealms )
{
return cache.get( new CacheKey( extensionRealms ) );
return new CacheKey( extensionRealms );
}
public CacheRecord put( List<? extends ClassRealm> extensionRealms, ClassRealm projectRealm,
DependencyFilter extensionArtifactFilter )
public CacheRecord get( Key key )
{
return cache.get( key );
}
public CacheRecord put( Key key, ClassRealm projectRealm, DependencyFilter extensionArtifactFilter )
{
if ( projectRealm == null )
{
throw new NullPointerException();
}
CacheKey key = new CacheKey( extensionRealms );
if ( cache.containsKey( key ) )
{
throw new IllegalStateException( "Duplicate project realm for extensions " + extensionRealms );
throw new IllegalStateException( "Duplicate project realm for extensions " + key );
}
CacheRecord record = new CacheRecord( projectRealm, extensionArtifactFilter );
@ -107,12 +118,30 @@ public CacheRecord put( List<? extends ClassRealm> extensionRealms, ClassRealm p
public void flush()
{
for ( CacheRecord record : cache.values() )
{
ClassRealm realm = record.realm;
try
{
realm.getWorld().disposeRealm( realm.getId() );
}
catch ( NoSuchRealmException e )
{
// ignore
}
}
cache.clear();
}
public void register( MavenProject project, CacheRecord record )
public void register( MavenProject project, Key key, CacheRecord record )
{
// default cache does not track record usage
}
@Override
public void dispose()
{
flush();
}
}

View File

@ -35,6 +35,14 @@
public interface ProjectRealmCache
{
/**
* A cache key.
*/
interface Key
{
// marker interface for cache keys
}
static class CacheRecord
{
@ -50,10 +58,11 @@ public CacheRecord( ClassRealm realm, DependencyFilter extensionArtifactFilter )
}
CacheRecord get( List<? extends ClassRealm> extensionRealms );
Key createKey( List<? extends ClassRealm> extensionRealms );
CacheRecord put( List<? extends ClassRealm> extensionRealms, ClassRealm projectRealm,
DependencyFilter extensionArtifactFilter );
CacheRecord get( Key key );
CacheRecord put( Key key, ClassRealm projectRealm, DependencyFilter extensionArtifactFilter );
void flush();
@ -65,6 +74,6 @@ CacheRecord put( List<? extends ClassRealm> extensionRealms, ClassRealm projectR
* @param project The project that employs the plugin realm, must not be {@code null}.
* @param record The cache record being used for the project, must not be {@code null}.
*/
void register( MavenProject project, CacheRecord record );
void register( MavenProject project, Key key, CacheRecord record );
}