Merge pull request #169 from gnodet/improvements

Improvements
This commit is contained in:
Guillaume Nodet
2020-10-28 15:49:22 +01:00
committed by GitHub
7 changed files with 45 additions and 34 deletions

View File

@@ -120,8 +120,6 @@
--no-fallback --no-fallback
--allow-incomplete-classpath --allow-incomplete-classpath
-H:IncludeResources=org/jboss/fuse/mvnd/.* -H:IncludeResources=org/jboss/fuse/mvnd/.*
-H:IncludeResources=org/jline/utils/.*
-H:IncludeResources=org/fusesource/jansi/jansi.properties
-H:-ParseRuntimeOptions -H:-ParseRuntimeOptions
</buildArgs> </buildArgs>
</configuration> </configuration>

View File

@@ -25,10 +25,12 @@ import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
import org.jboss.fuse.mvnd.common.DaemonConnection; import org.jboss.fuse.mvnd.common.DaemonConnection;
import org.jboss.fuse.mvnd.common.DaemonDiagnostics;
import org.jboss.fuse.mvnd.common.DaemonException; import org.jboss.fuse.mvnd.common.DaemonException;
import org.jboss.fuse.mvnd.common.DaemonException.ConnectException; import org.jboss.fuse.mvnd.common.DaemonException.ConnectException;
import org.jboss.fuse.mvnd.common.DaemonException.StaleAddressException; import org.jboss.fuse.mvnd.common.DaemonException.StaleAddressException;
import org.jboss.fuse.mvnd.common.DaemonInfo; import org.jboss.fuse.mvnd.common.DaemonInfo;
import org.jboss.fuse.mvnd.common.Layout;
import org.jboss.fuse.mvnd.common.Message; import org.jboss.fuse.mvnd.common.Message;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -52,9 +54,10 @@ public class DaemonClientConnection implements Closeable {
private final Thread receiver; private final Thread receiver;
private final AtomicBoolean running = new AtomicBoolean(true); private final AtomicBoolean running = new AtomicBoolean(true);
private final AtomicReference<Exception> exception = new AtomicReference<>(); private final AtomicReference<Exception> exception = new AtomicReference<>();
private final Layout layout;
public DaemonClientConnection(DaemonConnection connection, DaemonInfo daemon, public DaemonClientConnection(DaemonConnection connection, DaemonInfo daemon,
StaleAddressDetector staleAddressDetector, boolean newDaemon, int maxKeepAliveMs) { StaleAddressDetector staleAddressDetector, boolean newDaemon, int maxKeepAliveMs, Layout layout) {
this.connection = connection; this.connection = connection;
this.daemon = daemon; this.daemon = daemon;
this.staleAddressDetector = staleAddressDetector; this.staleAddressDetector = staleAddressDetector;
@@ -62,6 +65,7 @@ public class DaemonClientConnection implements Closeable {
this.maxKeepAliveMs = maxKeepAliveMs; this.maxKeepAliveMs = maxKeepAliveMs;
this.receiver = new Thread(this::doReceive); this.receiver = new Thread(this::doReceive);
this.receiver.start(); this.receiver.start();
this.layout = layout;
} }
public DaemonInfo getDaemon() { public DaemonInfo getDaemon() {
@@ -101,11 +105,12 @@ public class DaemonClientConnection implements Closeable {
+ "ms, daemon may have crashed. You may want to check its status using mvnd --status"); + "ms, daemon may have crashed. You may want to check its status using mvnd --status");
} }
} catch (Exception e) { } catch (Exception e) {
DaemonDiagnostics diag = new DaemonDiagnostics(daemon.getUid(), layout);
LOG.debug("Problem receiving message to the daemon. Performing 'on failure' operation..."); LOG.debug("Problem receiving message to the daemon. Performing 'on failure' operation...");
if (!hasReceived && newDaemon) { if (!hasReceived && newDaemon) {
throw new ConnectException("Could not receive a message from the daemon.", e); throw new ConnectException("Could not receive a message from the daemon.\n" + diag.describe(), e);
} else if (staleAddressDetector.maybeStaleAddress(e)) { } else if (staleAddressDetector.maybeStaleAddress(e)) {
throw new StaleAddressException("Could not receive a message from the daemon.", e); throw new StaleAddressException("Could not receive a message from the daemon.\n" + diag.describe(), e);
} }
} finally { } finally {
hasReceived = true; hasReceived = true;

View File

@@ -237,7 +237,7 @@ public class DaemonConnector {
throw new DaemonException.InterruptedException(e); throw new DaemonException.InterruptedException(e);
} }
} while (System.currentTimeMillis() - start < DEFAULT_CONNECT_TIMEOUT); } while (System.currentTimeMillis() - start < DEFAULT_CONNECT_TIMEOUT);
DaemonDiagnostics diag = new DaemonDiagnostics(daemon, layout.daemonLog(daemon)); DaemonDiagnostics diag = new DaemonDiagnostics(daemon, layout);
throw new DaemonException.ConnectException("Timeout waiting to connect to the Maven daemon.\n" + diag.describe()); throw new DaemonException.ConnectException("Timeout waiting to connect to the Maven daemon.\n" + diag.describe());
} }
@@ -272,7 +272,7 @@ public class DaemonConnector {
command = String.join(" ", args); command = String.join(" ", args);
LOGGER.debug("Starting daemon process: uid = {}, workingDir = {}, daemonArgs: {}", uid, workingDir, command); LOGGER.debug("Starting daemon process: uid = {}, workingDir = {}, daemonArgs: {}", uid, workingDir, command);
ProcessBuilder.Redirect redirect = ProcessBuilder.Redirect.appendTo(layout.daemonLog(uid + ".out").toFile()); ProcessBuilder.Redirect redirect = ProcessBuilder.Redirect.appendTo(layout.daemonOutLog(uid).toFile());
new ProcessBuilder() new ProcessBuilder()
.directory(workingDir.toFile()) .directory(workingDir.toFile())
.command(args) .command(args)
@@ -297,7 +297,7 @@ public class DaemonConnector {
try { try {
return connectToDaemon(daemonInfo, new CleanupOnStaleAddress(daemonInfo), newDaemon); return connectToDaemon(daemonInfo, new CleanupOnStaleAddress(daemonInfo), newDaemon);
} catch (DaemonException.ConnectException e) { } catch (DaemonException.ConnectException e) {
DaemonDiagnostics diag = new DaemonDiagnostics(daemon, layout.daemonLog(daemon)); DaemonDiagnostics diag = new DaemonDiagnostics(daemon, layout);
throw new DaemonException.ConnectException("Could not connect to the Maven daemon.\n" + diag.describe(), e); throw new DaemonException.ConnectException("Could not connect to the Maven daemon.\n" + diag.describe(), e);
} }
} }
@@ -311,7 +311,7 @@ public class DaemonConnector {
try { try {
int maxKeepAliveMs = layout.getKeepAliveMs() * layout.getMaxLostKeepAlive(); int maxKeepAliveMs = layout.getKeepAliveMs() * layout.getMaxLostKeepAlive();
DaemonConnection connection = connect(daemon.getAddress()); DaemonConnection connection = connect(daemon.getAddress());
return new DaemonClientConnection(connection, daemon, staleAddressDetector, newDaemon, maxKeepAliveMs); return new DaemonClientConnection(connection, daemon, staleAddressDetector, newDaemon, maxKeepAliveMs, layout);
} catch (DaemonException.ConnectException e) { } catch (DaemonException.ConnectException e) {
staleAddressDetector.maybeStaleAddress(e); staleAddressDetector.maybeStaleAddress(e);
throw e; throw e;

View File

@@ -18,6 +18,7 @@ package org.jboss.fuse.mvnd.common;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.ArrayList; import java.util.ArrayList;
@@ -34,39 +35,53 @@ public class DaemonDiagnostics {
private final static int TAIL_SIZE = 20; private final static int TAIL_SIZE = 20;
private final String uid; private final String uid;
private final Path daemonLog; private final Layout layout;
public DaemonDiagnostics(String uid, Path daemonLog) { public DaemonDiagnostics(String uid, Layout layout) {
this.uid = uid; this.uid = uid;
this.daemonLog = daemonLog; this.layout = layout;
} }
@Override @Override
public String toString() { public String toString() {
return "{" return "{"
+ "uid=" + uid + "uid=" + uid
+ ", daemonLog=" + daemonLog + ", layout=" + layout
+ '}'; + '}';
} }
private String tailDaemonLog() { public String describe() {
StringBuilder sb = new StringBuilder();
sb.append("Daemon uid: ").append(uid).append("\n");
tail(sb, "log file", layout.daemonLog(uid));
tail(sb, "output", layout.daemonOutLog(uid));
return sb.toString();
}
static void tail(StringBuilder sb, String name, Path log) {
try { try {
String tail = tail(daemonLog, TAIL_SIZE); String tail = tail(log);
return formatTail(tail); sb.append(" ").append(name).append(": ").append(log).append("\n");
sb.append("----- Last " + TAIL_SIZE + " lines from daemon ").append(name).append(" - ").append(log)
.append(" -----\n");
sb.append(tail);
sb.append("----- End of the daemon ").append(name).append(" -----\n");
} catch (NoSuchFileException e) {
sb.append(" no ").append(name).append(" at: ").append(log).append("\n");
} catch (IOException e) { } catch (IOException e) {
return "Unable to read from the daemon log file: " + daemonLog + ", because of: " + e.getCause(); sb.append(" unable to read from the daemon ").append(name).append(": ").append(log).append(", because of: ")
.append(e);
} }
} }
/** /**
* @param path to read from tail * @param path to read from tail
* @param maxLines max lines to read
* @return tail content * @return tail content
* @throws IOException when reading failed * @throws IOException when reading failed
*/ */
static String tail(Path path, int maxLines) throws IOException { static String tail(Path path) throws IOException {
try (BufferedReader r = Files.newBufferedReader(path)) { try (BufferedReader r = Files.newBufferedReader(path)) {
return String.join("\n", r.lines().collect(lastN(maxLines))); return String.join("\n", r.lines().collect(lastN(TAIL_SIZE))) + "\n";
} }
} }
@@ -83,15 +98,4 @@ public class DaemonDiagnostics {
}, ArrayList::new); }, ArrayList::new);
} }
private String formatTail(String tail) {
return "----- Last " + TAIL_SIZE + " lines from daemon log file - " + daemonLog + " -----\n"
+ tail
+ "----- End of the daemon log -----\n";
}
public String describe() {
return "Daemon uid: " + uid + "\n"
+ " log file: " + daemonLog + "\n"
+ tailDaemonLog();
}
} }

View File

@@ -56,6 +56,10 @@ public class Layout {
return mavenHome.resolve("daemon/daemon-" + daemon + ".log"); return mavenHome.resolve("daemon/daemon-" + daemon + ".log");
} }
public Path daemonOutLog(String daemon) {
return mavenHome.resolve("daemon/daemon-" + daemon + ".out.log");
}
public Path multiModuleProjectDirectory() { public Path multiModuleProjectDirectory() {
return multiModuleProjectDirectory; return multiModuleProjectDirectory;
} }

View File

@@ -190,7 +190,7 @@ public class TerminalOutput implements ClientOutput {
break; break;
} }
if (c == '+' || c == '-' || c == CTRL_L || c == CTRL_M) { if (c == '+' || c == '-' || c == CTRL_L || c == CTRL_M) {
queue.add(new Event(EventType.INPUT, null, Character.toString(c))); queue.add(new Event(EventType.INPUT, null, Character.toString((char) c)));
} }
} }
} catch (InterruptedIOException e) { } catch (InterruptedIOException e) {
@@ -257,7 +257,7 @@ public class TerminalOutput implements ClientOutput {
linesPerProject = Math.max(0, linesPerProject - 1); linesPerProject = Math.max(0, linesPerProject - 1);
break; break;
case CTRL_L: case CTRL_L:
display.update(List.of(), 0); display.update(Collections.emptyList(), 0);
break; break;
case CTRL_M: case CTRL_M:
displayDone = !displayDone; displayDone = !displayDone;

View File

@@ -40,7 +40,7 @@
<graalvm.version>20.2.0</graalvm.version> <graalvm.version>20.2.0</graalvm.version>
<groovy.version>3.0.0</groovy.version> <groovy.version>3.0.0</groovy.version>
<jakarta.inject.version>1.0</jakarta.inject.version> <jakarta.inject.version>1.0</jakarta.inject.version>
<jline.version>3.17.0</jline.version> <jline.version>3.17.1</jline.version>
<junit.jupiter.version>5.6.0</junit.jupiter.version> <junit.jupiter.version>5.6.0</junit.jupiter.version>
<logback.version>1.2.3</logback.version> <logback.version>1.2.3</logback.version>
<maven.version>3.6.3</maven.version> <maven.version>3.6.3</maven.version>