mirror of https://github.com/apache/maven.git
[MNG-7511] Ensure the degreeOfConcurrency is a positive number in MavenExecutionRequest
This closes #767
This commit is contained in:
parent
f05397a88d
commit
03b1faff7e
|
@ -134,7 +134,7 @@ public class LifecycleStarter
|
||||||
}
|
}
|
||||||
|
|
||||||
int degreeOfConcurrency = session.getRequest().getDegreeOfConcurrency();
|
int degreeOfConcurrency = session.getRequest().getDegreeOfConcurrency();
|
||||||
if ( degreeOfConcurrency >= 2 )
|
if ( degreeOfConcurrency > 1 )
|
||||||
{
|
{
|
||||||
logger.info( "" );
|
logger.info( "" );
|
||||||
logger.info( String.format( "Using the %s implementation with a thread count of %d",
|
logger.info( String.format( "Using the %s implementation with a thread count of %d",
|
||||||
|
|
|
@ -84,7 +84,7 @@ public class MultiThreadedBuilder
|
||||||
throws ExecutionException, InterruptedException
|
throws ExecutionException, InterruptedException
|
||||||
{
|
{
|
||||||
int nThreads = Math.min( session.getRequest().getDegreeOfConcurrency(), session.getProjects().size() );
|
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
|
// Propagate the parallel flag to the root session and all of the cloned sessions in each project segment
|
||||||
session.setParallel( parallel );
|
session.setParallel( parallel );
|
||||||
for ( ProjectSegment segment : projectBuilds )
|
for ( ProjectSegment segment : projectBuilds )
|
||||||
|
|
|
@ -20,6 +20,7 @@ package org.apache.maven.execution;
|
||||||
*/
|
*/
|
||||||
import static org.hamcrest.Matchers.empty;
|
import static org.hamcrest.Matchers.empty;
|
||||||
import static org.hamcrest.Matchers.is;
|
import static org.hamcrest.Matchers.is;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotSame;
|
import static org.junit.jupiter.api.Assertions.assertNotSame;
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
|
|
@ -153,7 +153,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( 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_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( 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( 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( 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() );
|
options.addOption( Option.builder( NO_TRANSFER_PROGRESS ).longOpt( "no-transfer-progress" ).desc( "Do not display transfer progress when downloading or uploading" ).build() );
|
||||||
|
|
|
@ -24,6 +24,7 @@ import org.apache.commons.cli.CommandLine;
|
||||||
import org.apache.commons.cli.Option;
|
import org.apache.commons.cli.Option;
|
||||||
import org.apache.commons.cli.ParseException;
|
import org.apache.commons.cli.ParseException;
|
||||||
import org.apache.commons.cli.UnrecognizedOptionException;
|
import org.apache.commons.cli.UnrecognizedOptionException;
|
||||||
|
import org.apache.commons.lang3.math.NumberUtils;
|
||||||
import org.apache.maven.BuildAbort;
|
import org.apache.maven.BuildAbort;
|
||||||
import org.apache.maven.InternalErrorException;
|
import org.apache.maven.InternalErrorException;
|
||||||
import org.apache.maven.Maven;
|
import org.apache.maven.Maven;
|
||||||
|
@ -1421,18 +1422,11 @@ public class MavenCli
|
||||||
|
|
||||||
if ( threadConfiguration != null )
|
if ( threadConfiguration != null )
|
||||||
{
|
{
|
||||||
//
|
int degreeOfConcurrency = calculateDegreeOfConcurrency( threadConfiguration );
|
||||||
// Default to the standard multithreaded builder
|
if ( degreeOfConcurrency > 1 )
|
||||||
//
|
|
||||||
request.setBuilderId( "multithreaded" );
|
|
||||||
|
|
||||||
if ( threadConfiguration.contains( "C" ) )
|
|
||||||
{
|
{
|
||||||
request.setDegreeOfConcurrency( calculateDegreeOfConcurrencyWithCoreMultiplier( threadConfiguration ) );
|
request.setBuilderId( "multithreaded" );
|
||||||
}
|
request.setDegreeOfConcurrency( degreeOfConcurrency );
|
||||||
else
|
|
||||||
{
|
|
||||||
request.setDegreeOfConcurrency( Integer.parseInt( threadConfiguration ) );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1698,10 +1692,56 @@ public class MavenCli
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int calculateDegreeOfConcurrencyWithCoreMultiplier( String threadConfiguration )
|
int calculateDegreeOfConcurrency( String threadConfiguration )
|
||||||
{
|
{
|
||||||
int procs = Runtime.getRuntime().availableProcessors();
|
if ( threadConfiguration.endsWith( "C" ) )
|
||||||
return (int) ( Float.parseFloat( threadConfiguration.replace( "C", "" ) ) * procs );
|
{
|
||||||
|
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." );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|
|
@ -146,18 +146,43 @@ public class MavenCliTest
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCalculateDegreeOfConcurrencyWithCoreMultiplier()
|
public void testCalculateDegreeOfConcurrency()
|
||||||
{
|
{
|
||||||
int cores = Runtime.getRuntime().availableProcessors();
|
assertThrows( IllegalArgumentException.class,
|
||||||
// -T2.2C
|
() -> cli.calculateDegreeOfConcurrency( "0" ) );
|
||||||
assertEquals( (int) ( cores * 2.2 ), cli.calculateDegreeOfConcurrencyWithCoreMultiplier( "C2.2" ) );
|
assertThrows( IllegalArgumentException.class,
|
||||||
// -TC2.2
|
() -> cli.calculateDegreeOfConcurrency( "-1" ) );
|
||||||
assertEquals( (int) ( cores * 2.2 ), cli.calculateDegreeOfConcurrencyWithCoreMultiplier( "2.2C" ) );
|
assertThrows( IllegalArgumentException.class,
|
||||||
|
() -> cli.calculateDegreeOfConcurrency( "0x4" ) );
|
||||||
|
assertThrows( IllegalArgumentException.class,
|
||||||
|
() -> cli.calculateDegreeOfConcurrency( "1.0" ) );
|
||||||
|
assertThrows( IllegalArgumentException.class,
|
||||||
|
() -> cli.calculateDegreeOfConcurrency( "1." ) );
|
||||||
|
assertThrows( IllegalArgumentException.class,
|
||||||
|
() -> cli.calculateDegreeOfConcurrency( "AA" ) );
|
||||||
|
assertThrows( IllegalArgumentException.class,
|
||||||
|
() -> cli.calculateDegreeOfConcurrency( "C" ) );
|
||||||
|
assertThrows( IllegalArgumentException.class,
|
||||||
|
() -> cli.calculateDegreeOfConcurrency( "C2.2C" ) );
|
||||||
|
assertThrows( IllegalArgumentException.class,
|
||||||
|
() -> cli.calculateDegreeOfConcurrency( "C2.2" ) );
|
||||||
|
assertThrows( IllegalArgumentException.class,
|
||||||
|
() -> cli.calculateDegreeOfConcurrency( "2C2" ) );
|
||||||
|
assertThrows( IllegalArgumentException.class,
|
||||||
|
() -> cli.calculateDegreeOfConcurrency( "CXXX" ) );
|
||||||
|
assertThrows( IllegalArgumentException.class,
|
||||||
|
() -> cli.calculateDegreeOfConcurrency( "XXXC" ) );
|
||||||
|
|
||||||
|
int cpus = Runtime.getRuntime().availableProcessors();
|
||||||
|
assertEquals( (int) ( cpus * 2.2 ), cli.calculateDegreeOfConcurrency( "2.2C" ) );
|
||||||
|
assertEquals( 1, cli.calculateDegreeOfConcurrency( "0.0001C" ) );
|
||||||
|
assertThrows( IllegalArgumentException.class,
|
||||||
|
() -> cli.calculateDegreeOfConcurrency( "2.C" ) );
|
||||||
|
assertThrows( IllegalArgumentException.class,
|
||||||
|
() -> cli.calculateDegreeOfConcurrency( "-2.2C" ) );
|
||||||
|
assertThrows( IllegalArgumentException.class,
|
||||||
|
() -> cli.calculateDegreeOfConcurrency( "0C" ) );
|
||||||
|
|
||||||
assertThrows(
|
|
||||||
NumberFormatException.class,
|
|
||||||
() -> cli.calculateDegreeOfConcurrencyWithCoreMultiplier( "CXXX" ),
|
|
||||||
"Should have failed with a NumberFormatException" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
Loading…
Reference in New Issue