You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by ti...@apache.org on 2020/07/09 15:34:53 UTC
[maven-surefire] 02/02: simple flush proposal
This is an automated email from the ASF dual-hosted git repository.
tibordigana pushed a commit to branch flush
in repository https://gitbox.apache.org/repos/asf/maven-surefire.git
commit f72e7cfb67f8aa50357e6a21f81e83b4c8651859
Author: tibordigana <ti...@apache.org>
AuthorDate: Wed Jul 8 15:37:07 2020 +0200
simple flush proposal
---
.../AbstractNoninterruptibleWritableChannel.java | 15 ++----
.../util/internal/WritableBufferedByteChannel.java | 1 +
.../api/util/internal/ChannelsWriterTest.java | 47 ++++++++++++++++--
...tractMasterProcessChannelProcessorFactory.java} | 55 +++++-----------------
...LegacyMasterProcessChannelProcessorFactory.java | 41 ++--------------
...refireMasterProcessChannelProcessorFactory.java | 10 ++--
6 files changed, 72 insertions(+), 97 deletions(-)
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/api/util/internal/AbstractNoninterruptibleWritableChannel.java b/surefire-api/src/main/java/org/apache/maven/surefire/api/util/internal/AbstractNoninterruptibleWritableChannel.java
index fe998f3..c2641e5 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/api/util/internal/AbstractNoninterruptibleWritableChannel.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/api/util/internal/AbstractNoninterruptibleWritableChannel.java
@@ -67,17 +67,12 @@ abstract class AbstractNoninterruptibleWritableChannel implements WritableBuffer
src.flip();
}
- int countWrittenBytes = 0;
-
- if ( src.hasRemaining() )
+ int countWrittenBytes = src.remaining();
+ writeImpl( src );
+ src.position( src.limit() );
+ if ( flush )
{
- countWrittenBytes = src.remaining();
- writeImpl( src );
- src.position( src.limit() );
- if ( flush )
- {
- flushImpl();
- }
+ flushImpl();
}
return countWrittenBytes;
}
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/api/util/internal/WritableBufferedByteChannel.java b/surefire-api/src/main/java/org/apache/maven/surefire/api/util/internal/WritableBufferedByteChannel.java
index 42c0d08..973424a 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/api/util/internal/WritableBufferedByteChannel.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/api/util/internal/WritableBufferedByteChannel.java
@@ -29,6 +29,7 @@ import java.nio.channels.WritableByteChannel;
* and the channel is flushed after the buffer has overflew.
* <br>
* The method {@link #write(ByteBuffer)} flushes every written message.
+ * You can flush the channel by {@link #write(ByteBuffer) writing} the zero length of {@link ByteBuffer}.
*/
public interface WritableBufferedByteChannel extends WritableByteChannel
{
diff --git a/surefire-api/src/test/java/org/apache/maven/surefire/api/util/internal/ChannelsWriterTest.java b/surefire-api/src/test/java/org/apache/maven/surefire/api/util/internal/ChannelsWriterTest.java
index 4befc24..24a09f3 100644
--- a/surefire-api/src/test/java/org/apache/maven/surefire/api/util/internal/ChannelsWriterTest.java
+++ b/surefire-api/src/test/java/org/apache/maven/surefire/api/util/internal/ChannelsWriterTest.java
@@ -137,6 +137,48 @@ public class ChannelsWriterTest
}
@Test
+ public void shouldFlushWhenEmptyBuffer() throws Exception
+ {
+ final boolean[] flushed = {false};
+ ByteArrayOutputStream out = new ByteArrayOutputStream()
+ {
+ @Override
+ public void flush() throws IOException
+ {
+ flushed[0] = true;
+ super.flush();
+ }
+ };
+ WritableByteChannel channel = Channels.newChannel( out );
+ ByteBuffer bb = ByteBuffer.allocate( 0 );
+ int countWritten = channel.write( bb );
+ assertThat( countWritten )
+ .isEqualTo( 0 );
+ assertThat( flushed[0] )
+ .isTrue();
+ }
+
+ @Test
+ public void shouldFlushWhenEmptyBufferOnBufferedWrites() throws Exception
+ {
+ final boolean[] flushed = {false};
+ ByteArrayOutputStream out = new ByteArrayOutputStream()
+ {
+ @Override
+ public void flush() throws IOException
+ {
+ flushed[0] = true;
+ super.flush();
+ }
+ };
+ WritableBufferedByteChannel channel = Channels.newBufferedChannel( out );
+ ByteBuffer bb = ByteBuffer.allocate( 0 );
+ channel.writeBuffered( bb );
+ assertThat( flushed[0] )
+ .isFalse();
+ }
+
+ @Test
public void bufferedChannel() throws Exception
{
ByteArrayOutputStream out = new ByteArrayOutputStream();
@@ -151,11 +193,6 @@ public class ChannelsWriterTest
assertThat( out.toByteArray() )
.isEmpty();
- channel.write( ByteBuffer.allocate( 0 ) );
-
- assertThat( out.toByteArray() )
- .isEmpty();
-
channel.write( ByteBuffer.wrap( new byte[] {4} ) );
assertThat( out.toByteArray() )
diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/spi/LegacyMasterProcessChannelProcessorFactory.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/spi/AbstractMasterProcessChannelProcessorFactory.java
similarity index 54%
copy from surefire-booter/src/main/java/org/apache/maven/surefire/booter/spi/LegacyMasterProcessChannelProcessorFactory.java
copy to surefire-booter/src/main/java/org/apache/maven/surefire/booter/spi/AbstractMasterProcessChannelProcessorFactory.java
index e7eb3db..b390bf0 100644
--- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/spi/LegacyMasterProcessChannelProcessorFactory.java
+++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/spi/AbstractMasterProcessChannelProcessorFactory.java
@@ -19,63 +19,32 @@ package org.apache.maven.surefire.booter.spi;
* under the License.
*/
-import org.apache.maven.surefire.api.booter.MasterProcessChannelDecoder;
-import org.apache.maven.surefire.api.booter.MasterProcessChannelEncoder;
-import org.apache.maven.surefire.api.util.internal.WritableBufferedByteChannel;
import org.apache.maven.surefire.spi.MasterProcessChannelProcessorFactory;
import java.io.IOException;
-import java.net.MalformedURLException;
import java.nio.ByteBuffer;
+import java.nio.channels.WritableByteChannel;
import java.util.concurrent.ScheduledExecutorService;
import static java.util.concurrent.Executors.newScheduledThreadPool;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static org.apache.maven.surefire.api.util.internal.Channels.newBufferedChannel;
import static org.apache.maven.surefire.api.util.internal.DaemonThreadFactory.newDaemonThreadFactory;
/**
- * Producer of encoder and decoder for process pipes.
- * <br>
- *
- * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
- * @since 3.0.0-M5
+ * Default implementation of {@link MasterProcessChannelProcessorFactory}.
*/
-public class LegacyMasterProcessChannelProcessorFactory
+public abstract class AbstractMasterProcessChannelProcessorFactory
implements MasterProcessChannelProcessorFactory
{
private final ScheduledExecutorService flusher;
- public LegacyMasterProcessChannelProcessorFactory()
+ public AbstractMasterProcessChannelProcessorFactory()
{
flusher = newScheduledThreadPool( 1, newDaemonThreadFactory() );
}
- @Override
- public boolean canUse( String channelConfig )
- {
- return channelConfig.startsWith( "pipe://" );
- }
-
- @Override
- public void connect( String channelConfig ) throws IOException
- {
- if ( !canUse( channelConfig ) )
- {
- throw new MalformedURLException( "Unknown chanel string " + channelConfig );
- }
- }
-
- @Override
- public MasterProcessChannelDecoder createDecoder()
- {
- return new LegacyMasterProcessChannelDecoder( newBufferedChannel( System.in ) );
- }
-
- @Override
- public MasterProcessChannelEncoder createEncoder()
+ protected void schedulePeriodicFlusher( int delayInMillis, final WritableByteChannel channel )
{
- final WritableBufferedByteChannel channel = newBufferedChannel( System.out );
flusher.scheduleWithFixedDelay( new Runnable()
{
@Override
@@ -83,21 +52,23 @@ public class LegacyMasterProcessChannelProcessorFactory
{
try
{
- channel.write( ByteBuffer.wrap( new byte[] {'\n'} ) );
+ channel.write( ByteBuffer.allocate( 0 ) );
}
- catch ( IOException e )
+ catch ( Exception e )
{
// cannot do anything about this I/O issue
}
}
- }, 0L, 100, MILLISECONDS );
-
- return new LegacyMasterProcessChannelEncoder( channel );
+ }, 0L, delayInMillis, MILLISECONDS );
}
@Override
- public void close()
+ public void close() throws IOException
{
flusher.shutdown();
+ // Do NOT call awaitTermination() due to this would unnecessarily prolong teardown time of the JVM.
+ // It is not a critical situation when the JXM exits this daemon thread because the interrupted
+ // flusher does not break any business function. All business data is already safely flushed by test events,
+ // then by sending BYE event at the exit time and finally by flushEventChannelOnExit() in ForkedBooter.
}
}
diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/spi/LegacyMasterProcessChannelProcessorFactory.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/spi/LegacyMasterProcessChannelProcessorFactory.java
index e7eb3db..bef079d 100644
--- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/spi/LegacyMasterProcessChannelProcessorFactory.java
+++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/spi/LegacyMasterProcessChannelProcessorFactory.java
@@ -22,17 +22,11 @@ package org.apache.maven.surefire.booter.spi;
import org.apache.maven.surefire.api.booter.MasterProcessChannelDecoder;
import org.apache.maven.surefire.api.booter.MasterProcessChannelEncoder;
import org.apache.maven.surefire.api.util.internal.WritableBufferedByteChannel;
-import org.apache.maven.surefire.spi.MasterProcessChannelProcessorFactory;
import java.io.IOException;
import java.net.MalformedURLException;
-import java.nio.ByteBuffer;
-import java.util.concurrent.ScheduledExecutorService;
-import static java.util.concurrent.Executors.newScheduledThreadPool;
-import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.apache.maven.surefire.api.util.internal.Channels.newBufferedChannel;
-import static org.apache.maven.surefire.api.util.internal.DaemonThreadFactory.newDaemonThreadFactory;
/**
* Producer of encoder and decoder for process pipes.
@@ -42,15 +36,8 @@ import static org.apache.maven.surefire.api.util.internal.DaemonThreadFactory.ne
* @since 3.0.0-M5
*/
public class LegacyMasterProcessChannelProcessorFactory
- implements MasterProcessChannelProcessorFactory
+ extends AbstractMasterProcessChannelProcessorFactory
{
- private final ScheduledExecutorService flusher;
-
- public LegacyMasterProcessChannelProcessorFactory()
- {
- flusher = newScheduledThreadPool( 1, newDaemonThreadFactory() );
- }
-
@Override
public boolean canUse( String channelConfig )
{
@@ -73,31 +60,11 @@ public class LegacyMasterProcessChannelProcessorFactory
}
@Override
+ @SuppressWarnings( "checkstyle:magicnumber" )
public MasterProcessChannelEncoder createEncoder()
{
- final WritableBufferedByteChannel channel = newBufferedChannel( System.out );
- flusher.scheduleWithFixedDelay( new Runnable()
- {
- @Override
- public void run()
- {
- try
- {
- channel.write( ByteBuffer.wrap( new byte[] {'\n'} ) );
- }
- catch ( IOException e )
- {
- // cannot do anything about this I/O issue
- }
- }
- }, 0L, 100, MILLISECONDS );
-
+ WritableBufferedByteChannel channel = newBufferedChannel( System.out );
+ schedulePeriodicFlusher( 200, channel );
return new LegacyMasterProcessChannelEncoder( channel );
}
-
- @Override
- public void close()
- {
- flusher.shutdown();
- }
}
diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/spi/SurefireMasterProcessChannelProcessorFactory.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/spi/SurefireMasterProcessChannelProcessorFactory.java
index 9efff25..9b4e6c1 100644
--- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/spi/SurefireMasterProcessChannelProcessorFactory.java
+++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/spi/SurefireMasterProcessChannelProcessorFactory.java
@@ -21,7 +21,7 @@ package org.apache.maven.surefire.booter.spi;
import org.apache.maven.surefire.api.booter.MasterProcessChannelDecoder;
import org.apache.maven.surefire.api.booter.MasterProcessChannelEncoder;
-import org.apache.maven.surefire.spi.MasterProcessChannelProcessorFactory;
+import org.apache.maven.surefire.api.util.internal.WritableBufferedByteChannel;
import java.io.IOException;
import java.net.InetSocketAddress;
@@ -53,7 +53,7 @@ import static org.apache.maven.surefire.api.util.internal.DaemonThreadFactory.ne
* @since 3.0.0-M5
*/
public class SurefireMasterProcessChannelProcessorFactory
- implements MasterProcessChannelProcessorFactory
+ extends AbstractMasterProcessChannelProcessorFactory
{
private volatile AsynchronousSocketChannel clientSocketChannel;
@@ -102,14 +102,18 @@ public class SurefireMasterProcessChannelProcessorFactory
}
@Override
+ @SuppressWarnings( "checkstyle:magicnumber" )
public MasterProcessChannelEncoder createEncoder()
{
- return new LegacyMasterProcessChannelEncoder( newBufferedChannel( newOutputStream( clientSocketChannel ) ) );
+ WritableBufferedByteChannel channel = newBufferedChannel( newOutputStream( clientSocketChannel ) );
+ schedulePeriodicFlusher( 200, channel );
+ return new LegacyMasterProcessChannelEncoder( channel );
}
@Override
public void close() throws IOException
{
+ super.close();
if ( clientSocketChannel != null && clientSocketChannel.isOpen() )
{
clientSocketChannel.close();