You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@maven.apache.org by GitBox <gi...@apache.org> on 2020/07/21 06:38:24 UTC

[GitHub] [maven-surefire] eolivelli commented on a change in pull request #308: [SUREFIRE-1827] The console output is not flushed

eolivelli commented on a change in pull request #308:
URL: https://github.com/apache/maven-surefire/pull/308#discussion_r457869371



##########
File path: surefire-booter/src/main/java/org/apache/maven/surefire/booter/spi/AbstractMasterProcessChannelProcessorFactory.java
##########
@@ -0,0 +1,106 @@
+package org.apache.maven.surefire.booter.spi;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.maven.surefire.api.util.internal.WritableBufferedByteChannel;
+import org.apache.maven.surefire.spi.MasterProcessChannelProcessorFactory;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.security.AccessControlException;
+import java.security.PrivilegedAction;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.atomic.AtomicLong;
+
+import static java.security.AccessController.doPrivileged;
+import static java.util.concurrent.Executors.newScheduledThreadPool;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static org.apache.maven.surefire.api.util.internal.DaemonThreadFactory.newDaemonThreadFactory;
+
+/**
+ * Default implementation of {@link MasterProcessChannelProcessorFactory}.
+ */
+public abstract class AbstractMasterProcessChannelProcessorFactory
+    implements MasterProcessChannelProcessorFactory
+{
+    private static final String STREAM_FLUSHER = "surefire-forkedjvm-stream-flusher";
+    private final ScheduledExecutorService flusher;
+
+    public AbstractMasterProcessChannelProcessorFactory()
+    {
+        flusher = newScheduledThreadPool( 1, newDaemonThreadFactory( STREAM_FLUSHER ) );
+    }
+
+    protected void schedulePeriodicFlusher( int delayInMillis, final WritableBufferedByteChannel channel  )
+    {
+        final AtomicLong bufferOverflows = new AtomicLong();
+        flusher.scheduleWithFixedDelay( new Runnable()
+        {
+            @Override
+            public void run()
+            {
+                long currentBufferOverflows = channel.countBufferOverflows();
+                // optimization: flush the Channel only if the buffer has not overflew after last period of time
+                if ( bufferOverflows.get() == currentBufferOverflows )
+                {
+                    try
+                    {
+                        channel.write( ByteBuffer.allocate( 0 ) );
+                    }
+                    catch ( Exception e )
+                    {
+                        // cannot do anything about this I/O issue
+                    }
+                }
+                else
+                {
+                    bufferOverflows.set( currentBufferOverflows );
+                }
+            }
+        }, 0L, delayInMillis, MILLISECONDS );
+    }
+
+    @Override
+    public void close() throws IOException
+    {
+        try
+        {
+            doPrivileged( new PrivilegedAction<Object>()
+                          {
+                              @Override
+                              public Object run()
+                              {
+                                  flusher.shutdown();

Review comment:
       +1

##########
File path: surefire-booter/src/main/java/org/apache/maven/surefire/booter/spi/AbstractMasterProcessChannelProcessorFactory.java
##########
@@ -0,0 +1,106 @@
+package org.apache.maven.surefire.booter.spi;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.maven.surefire.api.util.internal.WritableBufferedByteChannel;
+import org.apache.maven.surefire.spi.MasterProcessChannelProcessorFactory;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.security.AccessControlException;
+import java.security.PrivilegedAction;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.atomic.AtomicLong;
+
+import static java.security.AccessController.doPrivileged;
+import static java.util.concurrent.Executors.newScheduledThreadPool;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static org.apache.maven.surefire.api.util.internal.DaemonThreadFactory.newDaemonThreadFactory;
+
+/**
+ * Default implementation of {@link MasterProcessChannelProcessorFactory}.
+ */
+public abstract class AbstractMasterProcessChannelProcessorFactory
+    implements MasterProcessChannelProcessorFactory
+{
+    private static final String STREAM_FLUSHER = "surefire-forkedjvm-stream-flusher";
+    private final ScheduledExecutorService flusher;
+
+    public AbstractMasterProcessChannelProcessorFactory()
+    {
+        flusher = newScheduledThreadPool( 1, newDaemonThreadFactory( STREAM_FLUSHER ) );
+    }
+
+    protected void schedulePeriodicFlusher( int delayInMillis, final WritableBufferedByteChannel channel  )
+    {
+        final AtomicLong bufferOverflows = new AtomicLong();
+        flusher.scheduleWithFixedDelay( new Runnable()
+        {
+            @Override
+            public void run()
+            {
+                long currentBufferOverflows = channel.countBufferOverflows();
+                // optimization: flush the Channel only if the buffer has not overflew after last period of time
+                if ( bufferOverflows.get() == currentBufferOverflows )
+                {
+                    try
+                    {
+                        channel.write( ByteBuffer.allocate( 0 ) );

Review comment:
       we can create a constant and save this buffer allocation

##########
File path: surefire-booter/src/main/java/org/apache/maven/surefire/booter/spi/LegacyMasterProcessChannelProcessorFactory.java
##########
@@ -36,8 +36,10 @@
  * @since 3.0.0-M5
  */
 public class LegacyMasterProcessChannelProcessorFactory
-    implements MasterProcessChannelProcessorFactory
+    extends AbstractMasterProcessChannelProcessorFactory
 {
+    private static final int FLUSH_PERIOD_MILLIS = 100;

Review comment:
       I can see a use case of having in CI this value to be set to "infinite" in order to save resources.
   But adding a new knob means that we will have to maintain it.
   I am leaning toward keeping an hardcoded constant, but I don't feel so strong about it.

##########
File path: surefire-booter/src/main/java/org/apache/maven/surefire/booter/spi/AbstractMasterProcessChannelProcessorFactory.java
##########
@@ -0,0 +1,106 @@
+package org.apache.maven.surefire.booter.spi;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.maven.surefire.api.util.internal.WritableBufferedByteChannel;
+import org.apache.maven.surefire.spi.MasterProcessChannelProcessorFactory;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.security.AccessControlException;
+import java.security.PrivilegedAction;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.atomic.AtomicLong;
+
+import static java.security.AccessController.doPrivileged;
+import static java.util.concurrent.Executors.newScheduledThreadPool;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static org.apache.maven.surefire.api.util.internal.DaemonThreadFactory.newDaemonThreadFactory;
+
+/**
+ * Default implementation of {@link MasterProcessChannelProcessorFactory}.
+ */
+public abstract class AbstractMasterProcessChannelProcessorFactory
+    implements MasterProcessChannelProcessorFactory
+{
+    private static final String STREAM_FLUSHER = "surefire-forkedjvm-stream-flusher";
+    private final ScheduledExecutorService flusher;
+
+    public AbstractMasterProcessChannelProcessorFactory()
+    {
+        flusher = newScheduledThreadPool( 1, newDaemonThreadFactory( STREAM_FLUSHER ) );
+    }
+
+    protected void schedulePeriodicFlusher( int delayInMillis, final WritableBufferedByteChannel channel  )
+    {
+        final AtomicLong bufferOverflows = new AtomicLong();
+        flusher.scheduleWithFixedDelay( new Runnable()
+        {
+            @Override
+            public void run()
+            {
+                long currentBufferOverflows = channel.countBufferOverflows();
+                // optimization: flush the Channel only if the buffer has not overflew after last period of time
+                if ( bufferOverflows.get() == currentBufferOverflows )
+                {
+                    try
+                    {
+                        channel.write( ByteBuffer.allocate( 0 ) );
+                    }
+                    catch ( Exception e )
+                    {
+                        // cannot do anything about this I/O issue
+                    }
+                }
+                else
+                {
+                    bufferOverflows.set( currentBufferOverflows );
+                }
+            }
+        }, 0L, delayInMillis, MILLISECONDS );
+    }
+
+    @Override
+    public void close() throws IOException
+    {
+        try
+        {
+            doPrivileged( new PrivilegedAction<Object>()

Review comment:
       just  for curiosity, why are you using "doPrivileged" ?




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org