You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by mi...@apache.org on 2022/07/18 21:35:06 UTC

[maven] branch maven-3.9.x updated: [MNG-7511] Ensure the degreeOfConcurrency is a positive number in MavenExecutionRequest

This is an automated email from the ASF dual-hosted git repository.

michaelo pushed a commit to branch maven-3.9.x
in repository https://gitbox.apache.org/repos/asf/maven.git


The following commit(s) were added to refs/heads/maven-3.9.x by this push:
     new e1e4f5bda [MNG-7511] Ensure the degreeOfConcurrency is a positive number in MavenExecutionRequest
e1e4f5bda is described below

commit e1e4f5bda02535f718785189082f4197037774f3
Author: Josef Cacek <jo...@gmail.com>
AuthorDate: Tue Jul 12 20:15:25 2022 +0200

    [MNG-7511] Ensure the degreeOfConcurrency is a positive number in MavenExecutionRequest
    
    This closes #767
---
 .../maven/lifecycle/internal/LifecycleStarter.java |  2 +-
 .../multithreaded/MultiThreadedBuilder.java        |  2 +-
 .../main/java/org/apache/maven/cli/CLIManager.java |  2 +-
 .../main/java/org/apache/maven/cli/MavenCli.java   | 68 +++++++++++++++++-----
 .../java/org/apache/maven/cli/MavenCliTest.java    | 58 ++++++++++++------
 5 files changed, 96 insertions(+), 36 deletions(-)

diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleStarter.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleStarter.java
index cee807392..9bd74328b 100644
--- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleStarter.java
+++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleStarter.java
@@ -119,7 +119,7 @@ public class LifecycleStarter
             }
 
             int degreeOfConcurrency = session.getRequest().getDegreeOfConcurrency();
-            if ( degreeOfConcurrency >= 2 )
+            if ( degreeOfConcurrency > 1 )
             {
                 logger.info( "" );
                 logger.info( String.format( "Using the %s implementation with a thread count of %d",
diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/multithreaded/MultiThreadedBuilder.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/multithreaded/MultiThreadedBuilder.java
index 1be0e42ea..c2f9c5b6a 100644
--- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/multithreaded/MultiThreadedBuilder.java
+++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/multithreaded/MultiThreadedBuilder.java
@@ -80,7 +80,7 @@ public class MultiThreadedBuilder
         throws ExecutionException, InterruptedException
     {
         int nThreads = Math.min( session.getRequest().getDegreeOfConcurrency(), session.getProjects().size() );
-        boolean parallel = nThreads >= 2;
+        boolean parallel = nThreads > 1;
         // Propagate the parallel flag to the root session and all of the cloned sessions in each project segment
         session.setParallel( parallel );
         for ( ProjectSegment segment : projectBuilds )
diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/CLIManager.java b/maven-embedder/src/main/java/org/apache/maven/cli/CLIManager.java
index 2ad542457..8a8b04d9c 100644
--- a/maven-embedder/src/main/java/org/apache/maven/cli/CLIManager.java
+++ b/maven-embedder/src/main/java/org/apache/maven/cli/CLIManager.java
@@ -141,7 +141,7 @@ public class CLIManager
         options.addOption( Option.builder( Character.toString( SHOW_VERSION ) ).longOpt( "show-version" ).desc( "Display version information WITHOUT stopping build" ).build() );
         options.addOption( Option.builder( ENCRYPT_MASTER_PASSWORD ).longOpt( "encrypt-master-password" ).hasArg().optionalArg( true ).desc( "Encrypt master security password" ).build() );
         options.addOption( Option.builder( ENCRYPT_PASSWORD ).longOpt( "encrypt-password" ).hasArg().optionalArg( true ).desc( "Encrypt server password" ).build() );
-        options.addOption( Option.builder( THREADS ).longOpt( "threads" ).hasArg().desc( "Thread count, for instance 2.0C where C is core multiplied" ).build() );
+        options.addOption( Option.builder( THREADS ).longOpt( "threads" ).hasArg().desc( "Thread count, for instance 4 (int) or 2C/2.5C (int/float) where C is core multiplied" ).build() );
         options.addOption( Option.builder( LEGACY_LOCAL_REPOSITORY ).longOpt( "legacy-local-repository" ).desc( "Use Maven 2 Legacy Local Repository behaviour, ie no use of _remote.repositories. Can also be activated by using -Dmaven.legacyLocalRepo=true" ).build() );
         options.addOption( Option.builder( BUILDER ).longOpt( "builder" ).hasArg().desc( "The id of the build strategy to use" ).build() );
         options.addOption( Option.builder( NO_TRANSFER_PROGRESS ).longOpt( "no-transfer-progress" ).desc( "Do not display transfer progress when downloading or uploading" ).build() );
diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java b/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java
index ed695ebbf..6aded69b7 100644
--- a/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java
+++ b/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java
@@ -24,6 +24,7 @@ import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.Option;
 import org.apache.commons.cli.ParseException;
 import org.apache.commons.cli.UnrecognizedOptionException;
+import org.apache.commons.lang3.math.NumberUtils;
 import org.apache.maven.BuildAbort;
 import org.apache.maven.InternalErrorException;
 import org.apache.maven.Maven;
@@ -1584,18 +1585,11 @@ public class MavenCli
 
         if ( threadConfiguration != null )
         {
-            //
-            // Default to the standard multithreaded builder
-            //
-            request.setBuilderId( "multithreaded" );
-
-            if ( threadConfiguration.contains( "C" ) )
-            {
-                request.setDegreeOfConcurrency( calculateDegreeOfConcurrencyWithCoreMultiplier( threadConfiguration ) );
-            }
-            else
+            int degreeOfConcurrency = calculateDegreeOfConcurrency( threadConfiguration );
+            if ( degreeOfConcurrency > 1 )
             {
-                request.setDegreeOfConcurrency( Integer.parseInt( threadConfiguration ) );
+                request.setBuilderId( "multithreaded" );
+                request.setDegreeOfConcurrency( degreeOfConcurrency );
             }
         }
 
@@ -1610,10 +1604,56 @@ public class MavenCli
         return request;
     }
 
-    int calculateDegreeOfConcurrencyWithCoreMultiplier( String threadConfiguration )
+    int calculateDegreeOfConcurrency( String threadConfiguration )
     {
-        int procs = Runtime.getRuntime().availableProcessors();
-        return (int) ( Float.parseFloat( threadConfiguration.replace( "C", "" ) ) * procs );
+        if ( threadConfiguration.endsWith( "C" ) )
+        {
+            threadConfiguration = threadConfiguration.substring( 0, threadConfiguration.length() - 1 );
+
+            if ( !NumberUtils.isParsable( threadConfiguration ) )
+            {
+                throw new IllegalArgumentException( "Invalid threads core multiplier value: '" + threadConfiguration
+                        + "C'. Supported are int and float values ending with C." );
+            }
+
+            float coreMultiplier = Float.parseFloat( threadConfiguration );
+
+            if ( coreMultiplier <= 0.0f )
+            {
+                throw new IllegalArgumentException( "Invalid threads core multiplier value: '" + threadConfiguration
+                        + "C'. Value must be positive." );
+            }
+
+            int procs = Runtime.getRuntime().availableProcessors();
+            int threads = (int) ( coreMultiplier * procs );
+            return threads == 0 ? 1 : threads;
+        }
+        else
+        {
+            if ( !NumberUtils.isParsable( threadConfiguration ) )
+            {
+                throw new IllegalArgumentException( "Invalid threads value: '" + threadConfiguration
+                        + "'. Supported are int values." );
+            }
+
+            try
+            {
+                int threads = Integer.parseInt( threadConfiguration );
+
+                if ( threads <= 0 )
+                {
+                    throw new IllegalArgumentException( "Invalid threads value: '" + threadConfiguration
+                            + "'. Value must be positive." );
+                }
+
+                return threads;
+            }
+            catch ( NumberFormatException e )
+            {
+                throw new IllegalArgumentException( "Invalid threads value: '" + threadConfiguration
+                        + "'. Supported are integer values." );
+            }
+        }
     }
 
     // ----------------------------------------------------------------------
diff --git a/maven-embedder/src/test/java/org/apache/maven/cli/MavenCliTest.java b/maven-embedder/src/test/java/org/apache/maven/cli/MavenCliTest.java
index 7a96bbe5e..ff197c206 100644
--- a/maven-embedder/src/test/java/org/apache/maven/cli/MavenCliTest.java
+++ b/maven-embedder/src/test/java/org/apache/maven/cli/MavenCliTest.java
@@ -21,6 +21,7 @@ package org.apache.maven.cli;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.junit.Assume.assumeTrue;
@@ -33,8 +34,6 @@ import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.PrintStream;
 import java.nio.charset.StandardCharsets;
-import java.util.Collections;
-import java.util.List;
 
 import org.apache.commons.cli.ParseException;
 import org.apache.maven.Maven;
@@ -46,11 +45,12 @@ import org.codehaus.plexus.PlexusContainer;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.function.ThrowingRunnable;
 import org.mockito.InOrder;
 
 public class MavenCliTest
 {
-    private MavenCli cli;
+    MavenCli cli;
 
     private String origBasedir;
 
@@ -76,23 +76,27 @@ public class MavenCliTest
     }
 
     @Test
-    public void testCalculateDegreeOfConcurrencyWithCoreMultiplier()
+    public void testCalculateDegreeOfConcurrency()
     {
-        int cores = Runtime.getRuntime().availableProcessors();
-        // -T2.2C
-        assertEquals( (int) ( cores * 2.2 ), cli.calculateDegreeOfConcurrencyWithCoreMultiplier( "C2.2" ) );
-        // -TC2.2
-        assertEquals( (int) ( cores * 2.2 ), cli.calculateDegreeOfConcurrencyWithCoreMultiplier( "2.2C" ) );
-
-        try
-        {
-            cli.calculateDegreeOfConcurrencyWithCoreMultiplier( "CXXX" );
-            fail( "Should have failed with a NumberFormatException" );
-        }
-        catch ( NumberFormatException e )
-        {
-            // carry on
-        }
+        assertThrows( IllegalArgumentException.class, new ConcurrencyCalculator( "0" ) );
+        assertThrows( IllegalArgumentException.class, new ConcurrencyCalculator( "-1" ) );
+        assertThrows( IllegalArgumentException.class, new ConcurrencyCalculator( "0x4" ) );
+        assertThrows( IllegalArgumentException.class, new ConcurrencyCalculator( "1.0" ) );
+        assertThrows( IllegalArgumentException.class, new ConcurrencyCalculator( "1." ) );
+        assertThrows( IllegalArgumentException.class, new ConcurrencyCalculator( "AA" ) );
+        assertThrows( IllegalArgumentException.class, new ConcurrencyCalculator( "C" ) );
+        assertThrows( IllegalArgumentException.class, new ConcurrencyCalculator( "C2.2C" ) );
+        assertThrows( IllegalArgumentException.class, new ConcurrencyCalculator( "C2.2" ) );
+        assertThrows( IllegalArgumentException.class, new ConcurrencyCalculator( "2C2" ) );
+        assertThrows( IllegalArgumentException.class, new ConcurrencyCalculator( "CXXX" ) );
+        assertThrows( IllegalArgumentException.class, new ConcurrencyCalculator( "XXXC" ) );
+
+        int cpus = Runtime.getRuntime().availableProcessors();
+        assertEquals( (int) ( cpus * 2.2 ), cli.calculateDegreeOfConcurrency( "2.2C" ) );
+        assertEquals( 1, cli.calculateDegreeOfConcurrency( "0.0001C" ) );
+        assertThrows( IllegalArgumentException.class, new ConcurrencyCalculator( "2.C" ) );
+        assertThrows( IllegalArgumentException.class, new ConcurrencyCalculator( "-2.2C" ) );
+        assertThrows( IllegalArgumentException.class, new ConcurrencyCalculator( "0C" ) );
     }
 
     @Test
@@ -371,4 +375,20 @@ public class MavenCliTest
         assertEquals( MessageUtils.stripAnsiCodes( versionOut ), versionOut );
     }
 
+    class ConcurrencyCalculator implements ThrowingRunnable
+    {
+
+        private final String value;
+
+        public ConcurrencyCalculator( String value )
+        {
+            this.value = value;
+        }
+
+        @Override
+        public void run() throws Throwable
+        {
+            cli.calculateDegreeOfConcurrency( value );
+        }
+    }
 }