Skip to content
This repository has been archived by the owner on Aug 5, 2022. It is now read-only.

Commit

Permalink
[MNG-7511] Ensure the degreeOfConcurrency is a positive number in Mav…
Browse files Browse the repository at this point in the history
…enExecutionRequest

This closes apache#767
  • Loading branch information
kwart authored and michael-o committed Jul 18, 2022
1 parent f05397a commit 03b1faf
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ public void execute( MavenSession session )
}

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",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public void build( MavenSession session, ReactorContext reactorContext, ProjectB
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 )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
*/
import static org.hamcrest.Matchers.empty;
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.assertNotSame;
import static org.hamcrest.MatcherAssert.assertThat;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ public 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() );
Expand Down
68 changes: 54 additions & 14 deletions maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
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;
Expand Down Expand Up @@ -1421,18 +1422,11 @@ private MavenExecutionRequest populateRequest( CliRequest cliRequest, MavenExecu

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 );
}
}

Expand Down Expand Up @@ -1698,10 +1692,56 @@ private void enableOnAbsentOption( final CommandLine commandLine,
}
}

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." );
}
}
}

// ----------------------------------------------------------------------
Expand Down
45 changes: 35 additions & 10 deletions maven-embedder/src/test/java/org/apache/maven/cli/MavenCliTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -146,18 +146,43 @@ public void testDetermineProjectActivation() throws ParseException
}

@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" ) );
assertThrows( IllegalArgumentException.class,
() -> cli.calculateDegreeOfConcurrency( "0" ) );
assertThrows( IllegalArgumentException.class,
() -> cli.calculateDegreeOfConcurrency( "-1" ) );
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
Expand Down

0 comments on commit 03b1faf

Please sign in to comment.