I just have a concurrency issue :

Exception in thread "pool-1-thread-3" java.util.ConcurrentModificationException
        at 
java.util.LinkedHashMap$LinkedHashIterator.nextEntry(LinkedHashMap.java:373)
        at java.util.LinkedHashMap$EntryIterator.next(LinkedHashMap.java:392)
        at java.util.LinkedHashMap$EntryIterator.next(LinkedHashMap.java:391)
        at 
org.apache.maven.cli.ConsoleMavenTransferListener.doProgress(ConsoleMavenTransferListener.java:57)
        at 
org.apache.maven.cli.AbstractMavenTransferListener.transferProgress(AbstractMavenTransferListener.java:106)
        at 
org.apache.maven.repository.legacy.TransferListenerAdapter.transferProgress(TransferListenerAdapter.java:128)
        at 
org.apache.maven.wagon.events.TransferEventSupport.fireTransferProgress(TransferEventSupport.java:124)
        at 
org.apache.maven.wagon.AbstractWagon.fireTransferProgress(AbstractWagon.java:505)
        at org.apache.maven.wagon.AbstractWagon.transfer(AbstractWagon.java:490)
        at 
org.apache.maven.wagon.AbstractWagon.getTransfer(AbstractWagon.java:328)
        at 
org.apache.maven.wagon.AbstractWagon.getTransfer(AbstractWagon.java:299)
        at 
org.apache.maven.wagon.AbstractWagon.getTransfer(AbstractWagon.java:276)
        at org.apache.maven.wagon.StreamWagon.getIfNewer(StreamWagon.java:97)
        at org.apache.maven.wagon.StreamWagon.get(StreamWagon.java:61)
        at 
org.apache.maven.repository.legacy.DefaultWagonManager.getRemoteFile(DefaultWagonManager.java:309)
        at 
org.apache.maven.repository.legacy.DefaultWagonManager.getArtifact(DefaultWagonManager.java:98)
        at 
org.apache.maven.repository.legacy.DefaultWagonManager.getArtifact(DefaultWagonManager.java:129)
        at 
org.apache.maven.artifact.resolver.DefaultArtifactResolver.resolve(DefaultArtifactResolver.java:251)
        at 
org.apache.maven.artifact.resolver.DefaultArtifactResolver.access$000(DefaultArtifactResolver.java:73)
        at 
org.apache.maven.artifact.resolver.DefaultArtifactResolver$ResolveTask.run(DefaultArtifactResolver.java:686)
        at 
java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
        at 
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
        at java.lang.Thread.run(Thread.java:619)

But it's on a build server with a huge number of cpu ( solaris : 8
cores * 8 cpu per core).
I'm testing a small change which looks to fix the issue.



2010/1/20 Olivier Lamy <[email protected]>:
> Nice and thanks !!
>
> --
> Olivier
>
> 2010/1/19  <[email protected]>:
>> Author: bentmann
>> Date: Tue Jan 19 22:25:12 2010
>> New Revision: 900982
>>
>> URL: http://svn.apache.org/viewvc?rev=900982&view=rev
>> Log:
>> [MNG-4432] reimplement parallel artifacts download
>>
>> Modified:
>>    
>> maven/maven-3/trunk/maven-compat/src/main/java/org/apache/maven/artifact/resolver/DefaultArtifactResolver.java
>>    
>> maven/maven-3/trunk/maven-compat/src/main/java/org/apache/maven/repository/legacy/TransferListenerAdapter.java
>>    
>> maven/maven-3/trunk/maven-embedder/src/main/java/org/apache/maven/cli/ConsoleMavenTransferListener.java
>>
>> Modified: 
>> maven/maven-3/trunk/maven-compat/src/main/java/org/apache/maven/artifact/resolver/DefaultArtifactResolver.java
>> URL: 
>> http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-compat/src/main/java/org/apache/maven/artifact/resolver/DefaultArtifactResolver.java?rev=900982&r1=900981&r2=900982&view=diff
>> ==============================================================================
>> --- 
>> maven/maven-3/trunk/maven-compat/src/main/java/org/apache/maven/artifact/resolver/DefaultArtifactResolver.java
>>  (original)
>> +++ 
>> maven/maven-3/trunk/maven-compat/src/main/java/org/apache/maven/artifact/resolver/DefaultArtifactResolver.java
>>  Tue Jan 19 22:25:12 2010
>> @@ -24,6 +24,12 @@
>>  import java.util.List;
>>  import java.util.Map;
>>  import java.util.Set;
>> +import java.util.concurrent.CountDownLatch;
>> +import java.util.concurrent.Executor;
>> +import java.util.concurrent.ExecutorService;
>> +import java.util.concurrent.LinkedBlockingQueue;
>> +import java.util.concurrent.ThreadPoolExecutor;
>> +import java.util.concurrent.TimeUnit;
>>
>>  import org.apache.maven.artifact.Artifact;
>>  import org.apache.maven.artifact.factory.ArtifactFactory;
>> @@ -97,6 +103,38 @@
>>     @Requirement
>>     private LegacySupport legacySupport;
>>
>> +    private final Executor executor;
>> +
>> +    public DefaultArtifactResolver()
>> +    {
>> +        int threads = Integer.getInteger( "maven.artifact.threads", 5 
>> ).intValue();
>> +        if ( threads <= 1 )
>> +        {
>> +            executor = new Executor()
>> +            {
>> +                public void execute( Runnable command )
>> +                {
>> +                    command.run();
>> +                }
>> +            };
>> +        }
>> +        else
>> +        {
>> +            executor =
>> +                new ThreadPoolExecutor( threads, threads, 3, 
>> TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>() );
>> +        }
>> +    }
>> +
>> +   �...@override
>> +    protected void finalize()
>> +        throws Throwable
>> +    {
>> +        if ( executor instanceof ExecutorService )
>> +        {
>> +            ( (ExecutorService) executor ).shutdown();
>> +        }
>> +    }
>> +
>>     private void injectSession( RepositoryRequest request )
>>     {
>>         MavenSession session = legacySupport.getSession();
>> @@ -558,41 +596,41 @@
>>         {
>>             return result;
>>         }
>> -
>> +
>>         if ( result.getArtifactResolutionNodes() != null )
>>         {
>> -            ArtifactResolutionRequest childRequest = new 
>> ArtifactResolutionRequest( request );
>> +            ClassLoader classLoader = 
>> Thread.currentThread().getContextClassLoader();
>> +
>> +            CountDownLatch latch = new CountDownLatch( 
>> result.getArtifactResolutionNodes().size() );
>>
>>             for ( ResolutionNode node : result.getArtifactResolutionNodes() )
>>             {
>>                 Artifact artifact = node.getArtifact();
>>
>> -                try
>> +                if ( resolutionFilter == null || resolutionFilter.include( 
>> artifact ) )
>>                 {
>> -                    if ( resolutionFilter == null || 
>> resolutionFilter.include( artifact ) )
>> -                    {
>> -                        childRequest.setRemoteRepositories( 
>> node.getRemoteRepositories() );
>> +                    ArtifactResolutionRequest childRequest = new 
>> ArtifactResolutionRequest( request );
>> +                    childRequest.setRemoteRepositories( 
>> node.getRemoteRepositories() );
>>
>> -                        resolve( artifact, childRequest, transferListener, 
>> false );
>> -                    }
>> +                    executor.execute( new ResolveTask( classLoader, latch, 
>> artifact, transferListener, childRequest,
>> +                                                       result ) );
>>                 }
>> -                catch ( ArtifactNotFoundException anfe )
>> -                {
>> -                    // These are cases where the artifact just isn't 
>> present in any of the remote repositories
>> -                    // because it wasn't deployed, or it was deployed in 
>> the wrong place.
>> -
>> -                    result.addMissingArtifact( artifact );
>> -                }
>> -                catch ( ArtifactResolutionException e )
>> +                else
>>                 {
>> -                    // This is really a wagon TransferFailedException so 
>> something went wrong after we successfully
>> -                    // retrieved the metadata.
>> -
>> -                    result.addErrorArtifactException( e );
>> +                    latch.countDown();
>>                 }
>>             }
>> +            try
>> +            {
>> +                latch.await();
>> +            }
>> +            catch ( InterruptedException e )
>> +            {
>> +                result.addErrorArtifactException( new 
>> ArtifactResolutionException( "Resolution interrupted",
>> +                                                                            
>>        rootArtifact, e ) );
>> +            }
>>         }
>> -
>> +
>>         // We want to send the root artifact back in the result but we need 
>> to do this after the other dependencies
>>         // have been resolved.
>>         if ( request.isResolveRoot() )
>> @@ -612,4 +650,67 @@
>>     {
>>         resolve( artifact, remoteRepositories, localRepository, null );
>>     }
>> +
>> +    private class ResolveTask
>> +        implements Runnable
>> +    {
>> +
>> +        private final ClassLoader classLoader;
>> +
>> +        private final CountDownLatch latch;
>> +
>> +        private final Artifact artifact;
>> +
>> +        private final TransferListener transferListener;
>> +
>> +        private final ArtifactResolutionRequest request;
>> +
>> +        private final ArtifactResolutionResult result;
>> +
>> +        public ResolveTask( ClassLoader classLoader, CountDownLatch latch, 
>> Artifact artifact, TransferListener transferListener,
>> +                            ArtifactResolutionRequest request, 
>> ArtifactResolutionResult result )
>> +        {
>> +            this.classLoader = classLoader;
>> +            this.latch = latch;
>> +            this.artifact = artifact;
>> +            this.transferListener = transferListener;
>> +            this.request = request;
>> +            this.result = result;
>> +        }
>> +
>> +        public void run()
>> +        {
>> +            try
>> +            {
>> +                Thread.currentThread().setContextClassLoader( classLoader );
>> +                resolve( artifact, request, transferListener, false );
>> +            }
>> +            catch ( ArtifactNotFoundException anfe )
>> +            {
>> +                // These are cases where the artifact just isn't present in 
>> any of the remote repositories
>> +                // because it wasn't deployed, or it was deployed in the 
>> wrong place.
>> +
>> +                synchronized ( result )
>> +                {
>> +                    result.addMissingArtifact( artifact );
>> +                }
>> +            }
>> +            catch ( ArtifactResolutionException e )
>> +            {
>> +                // This is really a wagon TransferFailedException so 
>> something went wrong after we successfully
>> +                // retrieved the metadata.
>> +
>> +                synchronized ( result )
>> +                {
>> +                    result.addErrorArtifactException( e );
>> +                }
>> +            }
>> +            finally
>> +            {
>> +                latch.countDown();
>> +            }
>> +        }
>> +
>> +    }
>> +
>>  }
>>
>> Modified: 
>> maven/maven-3/trunk/maven-compat/src/main/java/org/apache/maven/repository/legacy/TransferListenerAdapter.java
>> URL: 
>> http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-compat/src/main/java/org/apache/maven/repository/legacy/TransferListenerAdapter.java?rev=900982&r1=900981&r2=900982&view=diff
>> ==============================================================================
>> --- 
>> maven/maven-3/trunk/maven-compat/src/main/java/org/apache/maven/repository/legacy/TransferListenerAdapter.java
>>  (original)
>> +++ 
>> maven/maven-3/trunk/maven-compat/src/main/java/org/apache/maven/repository/legacy/TransferListenerAdapter.java
>>  Tue Jan 19 22:25:12 2010
>> @@ -34,11 +34,11 @@
>>     implements TransferListener
>>  {
>>
>> -    private ArtifactTransferListener listener;
>> +    private final ArtifactTransferListener listener;
>>
>> -    private Map<Resource, ArtifactTransferResource> artifacts;
>> +    private final Map<Resource, ArtifactTransferResource> artifacts;
>>
>> -    private Map<Resource, Long> transfers;
>> +    private final Map<Resource, Long> transfers;
>>
>>     public static TransferListener newAdapter( ArtifactTransferListener 
>> listener )
>>     {
>> @@ -67,22 +67,34 @@
>>     {
>>         ArtifactTransferEvent event = wrap( transferEvent );
>>
>> -        Long transferred = transfers.get( transferEvent.getResource() );
>> +        Long transferred = null;
>> +        synchronized ( transfers )
>> +        {
>> +            transferred = transfers.remove( transferEvent.getResource() );
>> +        }
>>         if ( transferred != null )
>>         {
>>             event.setTransferredBytes( transferred.longValue() );
>>         }
>>
>> -        listener.transferCompleted( event );
>> +        synchronized ( artifacts )
>> +        {
>> +            artifacts.remove( transferEvent.getResource() );
>> +        }
>>
>> -        artifacts.remove( transferEvent.getResource() );
>> -        transfers.remove( transferEvent.getResource() );
>> +        listener.transferCompleted( event );
>>     }
>>
>>     public void transferError( TransferEvent transferEvent )
>>     {
>> -        artifacts.remove( transferEvent.getResource() );
>> -        transfers.remove( transferEvent.getResource() );
>> +        synchronized ( transfers )
>> +        {
>> +            transfers.remove( transferEvent.getResource() );
>> +        }
>> +        synchronized ( artifacts )
>> +        {
>> +            artifacts.remove( transferEvent.getResource() );
>> +        }
>>     }
>>
>>     public void transferInitiated( TransferEvent transferEvent )
>> @@ -92,16 +104,20 @@
>>
>>     public void transferProgress( TransferEvent transferEvent, byte[] 
>> buffer, int length )
>>     {
>> -        Long transferred = transfers.get( transferEvent.getResource() );
>> -        if ( transferred == null )
>> -        {
>> -            transferred = Long.valueOf( length );
>> -        }
>> -        else
>> +        Long transferred;
>> +        synchronized ( transfers )
>>         {
>> -            transferred = Long.valueOf( transferred.longValue() + length );
>> +            transferred = transfers.get( transferEvent.getResource() );
>> +            if ( transferred == null )
>> +            {
>> +                transferred = Long.valueOf( length );
>> +            }
>> +            else
>> +            {
>> +                transferred = Long.valueOf( transferred.longValue() + 
>> length );
>> +            }
>> +            transfers.put( transferEvent.getResource(), transferred );
>>         }
>> -        transfers.put( transferEvent.getResource(), transferred );
>>
>>         ArtifactTransferEvent event = wrap( transferEvent );
>>         event.setDataBuffer( buffer );
>> @@ -153,15 +169,18 @@
>>         }
>>         else
>>         {
>> -            ArtifactTransferResource artifact = artifacts.get( resource );
>> -
>> -            if ( artifact == null )
>> +            synchronized ( artifacts )
>>             {
>> -                artifact = new MavenArtifact( repository.getUrl(), resource 
>> );
>> -                artifacts.put( resource, artifact );
>> -            }
>> +                ArtifactTransferResource artifact = artifacts.get( resource 
>> );
>>
>> -            return artifact;
>> +                if ( artifact == null )
>> +                {
>> +                    artifact = new MavenArtifact( repository.getUrl(), 
>> resource );
>> +                    artifacts.put( resource, artifact );
>> +                }
>> +
>> +                return artifact;
>> +            }
>>         }
>>     }
>>
>>
>> Modified: 
>> maven/maven-3/trunk/maven-embedder/src/main/java/org/apache/maven/cli/ConsoleMavenTransferListener.java
>> URL: 
>> http://svn.apache.org/viewvc/maven/maven-3/trunk/maven-embedder/src/main/java/org/apache/maven/cli/ConsoleMavenTransferListener.java?rev=900982&r1=900981&r2=900982&view=diff
>> ==============================================================================
>> --- 
>> maven/maven-3/trunk/maven-embedder/src/main/java/org/apache/maven/cli/ConsoleMavenTransferListener.java
>>  (original)
>> +++ 
>> maven/maven-3/trunk/maven-embedder/src/main/java/org/apache/maven/cli/ConsoleMavenTransferListener.java
>>  Tue Jan 19 22:25:12 2010
>> @@ -20,18 +20,27 @@
>>  */
>>
>>  import java.io.PrintStream;
>> +import java.util.Collections;
>> +import java.util.LinkedHashMap;
>> +import java.util.Map;
>>
>>  import org.apache.maven.repository.ArtifactTransferEvent;
>> +import org.apache.maven.repository.ArtifactTransferResource;
>>
>>  /**
>>  * Console download progress meter.
>> - *
>> + *
>>  * @author <a href="mailto:[email protected]";>Brett Porter</a>
>>  */
>>  class ConsoleMavenTransferListener
>>     extends AbstractMavenTransferListener
>>  {
>>
>> +    private Map<ArtifactTransferResource, Long> downloads =
>> +        Collections.synchronizedMap( new 
>> LinkedHashMap<ArtifactTransferResource, Long>() );
>> +
>> +    private int lastLength;
>> +
>>     public ConsoleMavenTransferListener( PrintStream out )
>>     {
>>         super( out );
>> @@ -40,26 +49,69 @@
>>     @Override
>>     protected void doProgress( ArtifactTransferEvent transferEvent )
>>     {
>> -        long total = transferEvent.getResource().getContentLength();
>> -        long complete = transferEvent.getTransferredBytes();
>> +        ArtifactTransferResource resource = transferEvent.getResource();
>> +        downloads.put( resource, Long.valueOf( 
>> transferEvent.getTransferredBytes() ) );
>> +
>> +        StringBuilder buffer = new StringBuilder( 64 );
>>
>> -        // TODO [BP]: Sys.out may no longer be appropriate, but will \r 
>> work with getLogger()?
>> +        for ( Map.Entry<ArtifactTransferResource, Long> entry : 
>> downloads.entrySet() )
>> +        {
>> +            long total = entry.getKey().getContentLength();
>> +            long complete = entry.getValue().longValue();
>> +
>> +            buffer.append( getStatus( complete, total ) ).append( "  " );
>> +        }
>> +
>> +        int pad = lastLength - buffer.length();
>> +        lastLength = buffer.length();
>> +        pad( buffer, pad );
>> +        buffer.append( '\r' );
>> +
>> +        out.print( buffer );
>> +    }
>> +
>> +    private String getStatus( long complete, long total )
>> +    {
>>         if ( total >= 1024 )
>>         {
>> -            out.print( toKB( complete ) + "/" + toKB( total ) + " KB " + 
>> "\r" );
>> +            return toKB( complete ) + "/" + toKB( total ) + " KB ";
>>         }
>>         else if ( total >= 0 )
>>         {
>> -            out.print( complete + "/" + total + " B " + "\r" );
>> +            return complete + "/" + total + " B ";
>>         }
>>         else if ( complete >= 1024 )
>>         {
>> -            out.print( toKB( complete ) + " KB " + "\r" );
>> +            return toKB( complete ) + " KB ";
>>         }
>>         else
>>         {
>> -            out.print( complete + " B " + "\r" );
>> +            return complete + " B ";
>>         }
>>     }
>>
>> +    private void pad( StringBuilder buffer, int spaces )
>> +    {
>> +        String block = "                                        ";
>> +        while ( spaces > 0 )
>> +        {
>> +            int n = Math.min( spaces, block.length() );
>> +            buffer.append( block, 0, n );
>> +            spaces -= n;
>> +        }
>> +    }
>> +
>> +   �...@override
>> +    public void transferCompleted( ArtifactTransferEvent transferEvent )
>> +    {
>> +        downloads.remove( transferEvent.getResource() );
>> +
>> +        StringBuilder buffer = new StringBuilder( 64 );
>> +        pad( buffer, lastLength );
>> +        buffer.append( '\r' );
>> +        out.print( buffer );
>> +
>> +        super.transferCompleted( transferEvent );
>> +    }
>> +
>>  }
>>
>>
>>
>
>
>
> --
> Olivier
>



-- 
Olivier

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to