mirror of
https://github.com/apache/maven-mvnd.git
synced 2025-09-26 23:45:47 +00:00
@@ -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>
|
||||||
|
@@ -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;
|
||||||
|
@@ -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;
|
||||||
|
@@ -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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
||||||
|
2
pom.xml
2
pom.xml
@@ -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>
|
||||||
|
Reference in New Issue
Block a user