From 65baf20a081f998f87afa945e559f64c41ebf6ff Mon Sep 17 00:00:00 2001 From: ludiwudi <63492745+ludwigme@users.noreply.github.com> Date: Sat, 11 Apr 2020 20:06:46 +0200 Subject: [PATCH 1/3] Redirection of redis server output. --- .../redis/embedded/AbstractRedisInstance.java | 42 +++++++++++++++---- .../redis/embedded/RedisServerBuilder.java | 30 ++++++++++++- 2 files changed, 62 insertions(+), 10 deletions(-) diff --git a/src/main/java/redis/embedded/AbstractRedisInstance.java b/src/main/java/redis/embedded/AbstractRedisInstance.java index 7dd75428..aeea0c4f 100644 --- a/src/main/java/redis/embedded/AbstractRedisInstance.java +++ b/src/main/java/redis/embedded/AbstractRedisInstance.java @@ -16,7 +16,9 @@ abstract class AbstractRedisInstance implements Redis { private Process redisProcess; private final int port; - private ExecutorService executor; + private ExecutorService executor = Executors.newSingleThreadExecutor(); + private PrintStream err = System.out; + private PrintStream out = null; protected AbstractRedisInstance(int port) { this.port = port; @@ -42,14 +44,26 @@ public synchronized void start() throws EmbeddedRedisException { private void logErrors() { final InputStream errorStream = redisProcess.getErrorStream(); - BufferedReader reader = new BufferedReader(new InputStreamReader(errorStream)); - Runnable printReaderTask = new PrintReaderRunnable(reader); - executor = Executors.newSingleThreadExecutor(); - executor.submit(printReaderTask); + copyStreamInBackground(errorStream, err); } + private void copyStreamInBackground(final InputStream copyFrom, PrintStream copyTo) { + BufferedReader reader = new BufferedReader(new InputStreamReader(copyFrom)); + Runnable printReaderTask = new PrintReaderRunnable(reader, copyTo); + executor.submit(printReaderTask); + } + + public void outTo(PrintStream out) { + this.out = out; + } + + public void errTo(PrintStream err) { + this.err = err; + } + private void awaitRedisServerReady() throws IOException { - BufferedReader reader = new BufferedReader(new InputStreamReader(redisProcess.getInputStream())); + InputStream stdoutStream = redisProcess.getInputStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(stdoutStream)); try { StringBuffer outputStringBuffer = new StringBuffer(); String outputLine; @@ -62,10 +76,18 @@ private void awaitRedisServerReady() throws IOException { else{ outputStringBuffer.append("\n"); outputStringBuffer.append(outputLine); + if(out != null) { + out.println(outputLine); + } } } while (!outputLine.matches(redisReadyPattern())); } finally { - IOUtils.closeQuietly(reader); + if(out != null) { + /* Continue reading of STDOUT in a background thread. */ + copyStreamInBackground(stdoutStream, out); + } else { + IOUtils.closeQuietly(reader); + } } } @@ -103,9 +125,11 @@ public List ports() { private static class PrintReaderRunnable implements Runnable { private final BufferedReader reader; + private final PrintStream outputStream; - private PrintReaderRunnable(BufferedReader reader) { + private PrintReaderRunnable(BufferedReader reader, PrintStream outputStream) { this.reader = reader; + this.outputStream = outputStream; } public void run() { @@ -120,7 +144,7 @@ public void readLines() { try { String line; while ((line = reader.readLine()) != null) { - System.out.println(line); + outputStream.println(line); } } catch (IOException e) { e.printStackTrace(); diff --git a/src/main/java/redis/embedded/RedisServerBuilder.java b/src/main/java/redis/embedded/RedisServerBuilder.java index 192b9fb6..a79d2c9b 100644 --- a/src/main/java/redis/embedded/RedisServerBuilder.java +++ b/src/main/java/redis/embedded/RedisServerBuilder.java @@ -6,6 +6,7 @@ import java.io.File; import java.io.IOException; +import java.io.PrintStream; import java.net.InetSocketAddress; import java.nio.charset.Charset; import java.util.ArrayList; @@ -21,6 +22,8 @@ public class RedisServerBuilder { private int port = 6379; private InetSocketAddress slaveOf; private String redisConf; + private PrintStream out; + private PrintStream err; private StringBuilder redisConfigBuilder; @@ -71,11 +74,36 @@ public RedisServerBuilder setting(String configLine) { return this; } + /** + * Redirect Redis server messages sent to STDOUT. + * Usage example: @code{builder.outTo(System.out);} + * @param out Stream to receive Redis output. + * @return {@code this} + */ + public RedisServerBuilder outTo(PrintStream out) { + this.out = out; + return this; + } + + /** + * Redirect Redis server messages sent to STDERR. + * @param err Stream to receive Redis output. + * Usage example: @code{builder.errTo(System.err);} + * @return {@code itself} + */ + public RedisServerBuilder errTo(PrintStream err) { + this.err = err; + return this; + } + public RedisServer build() { setting("bind "+bind); tryResolveConfAndExec(); List args = buildCommandArgs(); - return new RedisServer(args, port); + RedisServer server = new RedisServer(args, port); + server.outTo(out); + server.errTo(err); + return server; } public void reset() { From 1cbcf1881f0b0d84a3e15468c48ab88bcdeb17e6 Mon Sep 17 00:00:00 2001 From: ludiwudi <63492745+ludwigme@users.noreply.github.com> Date: Sun, 12 Apr 2020 14:01:03 +0200 Subject: [PATCH 2/3] Enable redirection of Redis output when building a Redis cluster --- .../redis/embedded/AbstractRedisInstance.java | 4 +-- .../redis/embedded/RedisSentinelBuilder.java | 36 +++++++++++++++++-- .../redis/embedded/RedisServerBuilder.java | 4 +-- 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/src/main/java/redis/embedded/AbstractRedisInstance.java b/src/main/java/redis/embedded/AbstractRedisInstance.java index aeea0c4f..1876734c 100644 --- a/src/main/java/redis/embedded/AbstractRedisInstance.java +++ b/src/main/java/redis/embedded/AbstractRedisInstance.java @@ -17,8 +17,8 @@ abstract class AbstractRedisInstance implements Redis { private final int port; private ExecutorService executor = Executors.newSingleThreadExecutor(); - private PrintStream err = System.out; - private PrintStream out = null; + private PrintStream out = null; //Ignore Redis output. + private PrintStream err = System.err; //Forward Redis error messages to STDERR. protected AbstractRedisInstance(int port) { this.port = port; diff --git a/src/main/java/redis/embedded/RedisSentinelBuilder.java b/src/main/java/redis/embedded/RedisSentinelBuilder.java index 49d7f8f5..0da48c9a 100644 --- a/src/main/java/redis/embedded/RedisSentinelBuilder.java +++ b/src/main/java/redis/embedded/RedisSentinelBuilder.java @@ -6,6 +6,7 @@ import java.io.File; import java.io.IOException; +import java.io.PrintStream; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; @@ -32,7 +33,9 @@ public class RedisSentinelBuilder { private String sentinelConf; private StringBuilder redisConfigBuilder; - + private PrintStream out = null; //Ignore Redis output. + private PrintStream err = System.err; //Forward Redis error messages to STDERR. + public RedisSentinelBuilder redisExecProvider(RedisExecProvider redisExecProvider) { this.redisExecProvider = redisExecProvider; return this; @@ -100,10 +103,39 @@ public RedisSentinelBuilder setting(String configLine) { return this; } + /** + * Redirect Redis server messages sent to STDOUT. + * Usage example: + * @code{ + * RedisServerBuilder serverBuilder = RedisServer.builder().outTo(System.out).errTo(System.err); + RedisSentinelBuilder sentinelBuilder = new RedisSentinelBuilder().outTo(System.out).errTo(System.err); + RedisCluster.builder().withServerBuilder(serverBuilder).withSentinelBuilder(sentinelBuilder)... } + * @param out Stream to redirect Redis output to. + * @return {@code this} + */ + public RedisSentinelBuilder outTo(PrintStream out) { + this.out = out; + return this; + } + + /** + * Redirect Redis server messages sent to STDERR. + * @param err Stream to redirect Redis output to. + * Usage example: @code{builder.errTo(System.err);} + * @return {@code itself} + */ + public RedisSentinelBuilder errTo(PrintStream err) { + this.err = err; + return this; + } + public RedisSentinel build() { tryResolveConfAndExec(); List args = buildCommandArgs(); - return new RedisSentinel(args, port); + RedisSentinel sentinel = new RedisSentinel(args, port); + sentinel.outTo(out); + sentinel.errTo(err); + return sentinel; } private void tryResolveConfAndExec() { diff --git a/src/main/java/redis/embedded/RedisServerBuilder.java b/src/main/java/redis/embedded/RedisServerBuilder.java index a79d2c9b..d0891070 100644 --- a/src/main/java/redis/embedded/RedisServerBuilder.java +++ b/src/main/java/redis/embedded/RedisServerBuilder.java @@ -22,8 +22,8 @@ public class RedisServerBuilder { private int port = 6379; private InetSocketAddress slaveOf; private String redisConf; - private PrintStream out; - private PrintStream err; + private PrintStream out = null; //Ignore Redis output. + private PrintStream err = System.err; //Forward Redis error messages to STDERR. private StringBuilder redisConfigBuilder; From 36898aa95d1dd2f427fe2e5561c16ed3948a3e0e Mon Sep 17 00:00:00 2001 From: ludiwudi <63492745+ludwigme@users.noreply.github.com> Date: Sun, 19 Apr 2020 13:41:04 +0200 Subject: [PATCH 3/3] suppress exception message when redis is closed --- src/main/java/redis/embedded/AbstractRedisInstance.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/redis/embedded/AbstractRedisInstance.java b/src/main/java/redis/embedded/AbstractRedisInstance.java index 1876734c..a67644b3 100644 --- a/src/main/java/redis/embedded/AbstractRedisInstance.java +++ b/src/main/java/redis/embedded/AbstractRedisInstance.java @@ -147,7 +147,7 @@ public void readLines() { outputStream.println(line); } } catch (IOException e) { - e.printStackTrace(); + /* reader has been closed. The connected Redis instance has possibly shut down. */ } } }