This is an automated email from the ASF dual-hosted git repository.
benedict pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/cassandra.git
The following commit(s) were added to refs/heads/trunk by this push:
new a43b651 Unit test stdout capture is malfunctioning in 4.0
a43b651 is described below
commit a43b651f8e35dd7081b8593057f118ed0c49cfd6
Author: Benedict Elliott Smith <[email protected]>
AuthorDate: Thu Jan 10 12:32:16 2019 -0500
Unit test stdout capture is malfunctioning in 4.0
patch by Benedict; reviewed by Alex Petrov for CASSANDRA-14974
---
test/conf/logback-dtest.xml | 2 +-
test/conf/logback-test.xml | 2 +-
.../cassandra/distributed/InstanceClassLoader.java | 14 +-
.../apache/cassandra/distributed/TestCluster.java | 9 +
.../apache/cassandra/LogbackStatusListener.java | 770 ++++++++++++---------
.../config/DatabaseDescriptorRefTest.java | 18 +-
6 files changed, 465 insertions(+), 350 deletions(-)
diff --git a/test/conf/logback-dtest.xml b/test/conf/logback-dtest.xml
index b8019f6..7d3a8be 100644
--- a/test/conf/logback-dtest.xml
+++ b/test/conf/logback-dtest.xml
@@ -41,8 +41,8 @@
<encoder>
<pattern>%-5level [%thread] ${instance_id} %date{ISO8601}
%msg%n</pattern>
- <immediateFlush>false</immediateFlush>
</encoder>
+ <immediateFlush>false</immediateFlush>
</appender>
<appender name="STDOUT" target="System.out"
class="org.apache.cassandra.ConsoleAppender">
diff --git a/test/conf/logback-test.xml b/test/conf/logback-test.xml
index 4092050..3e3349f 100644
--- a/test/conf/logback-test.xml
+++ b/test/conf/logback-test.xml
@@ -39,8 +39,8 @@
<encoder>
<pattern>%-5level [%thread] %date{ISO8601} %msg%n</pattern>
- <immediateFlush>false</immediateFlush>
</encoder>
+ <immediateFlush>false</immediateFlush>
</appender>
<appender name="STDOUT" target="System.out"
class="org.apache.cassandra.ConsoleAppender">
diff --git
a/test/distributed/org/apache/cassandra/distributed/InstanceClassLoader.java
b/test/distributed/org/apache/cassandra/distributed/InstanceClassLoader.java
index 6349d5a..c86728a 100644
--- a/test/distributed/org/apache/cassandra/distributed/InstanceClassLoader.java
+++ b/test/distributed/org/apache/cassandra/distributed/InstanceClassLoader.java
@@ -37,12 +37,12 @@ public class InstanceClassLoader extends URLClassLoader
InstanceConfig.class,
Message.class,
InetAddressAndPort.class,
+ InvokableInstance.SerializableBiConsumer.class,
+ InvokableInstance.SerializableBiFunction.class,
InvokableInstance.SerializableCallable.class,
- InvokableInstance.SerializableRunnable.class,
InvokableInstance.SerializableConsumer.class,
- InvokableInstance.SerializableBiConsumer.class,
InvokableInstance.SerializableFunction.class,
- InvokableInstance.SerializableBiFunction.class,
+ InvokableInstance.SerializableRunnable.class,
InvokableInstance.SerializableTriFunction.class,
InvokableInstance.InstanceFunction.class
};
@@ -98,4 +98,12 @@ public class InstanceClassLoader extends URLClassLoader
return id -> new InstanceClassLoader(id, urls,
commonClassNames::contains, contextClassLoader);
}
+ /**
+ * @return true iff this class was loaded by an InstanceClassLoader, and
as such is used by a dtest node
+ */
+ public static boolean wasLoadedByAnInstanceClassLoader(Class<?> clazz)
+ {
+ return
clazz.getClassLoader().getClass().getName().equals(InstanceClassLoader.class.getName());
+ }
+
}
diff --git a/test/distributed/org/apache/cassandra/distributed/TestCluster.java
b/test/distributed/org/apache/cassandra/distributed/TestCluster.java
index 5056661..9f95a86 100644
--- a/test/distributed/org/apache/cassandra/distributed/TestCluster.java
+++ b/test/distributed/org/apache/cassandra/distributed/TestCluster.java
@@ -39,6 +39,10 @@ import java.util.stream.Collectors;
import com.google.common.collect.Sets;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.cassandra.concurrent.NamedThreadFactory;
import org.apache.cassandra.db.ColumnFamilyStore;
import org.apache.cassandra.db.ConsistencyLevel;
import org.apache.cassandra.db.Keyspace;
@@ -76,6 +80,11 @@ import org.apache.cassandra.utils.concurrent.SimpleCondition;
*/
public class TestCluster implements AutoCloseable
{
+ // WARNING: we have this logger not (necessarily) for logging, but
+ // to ensure we have instantiated the main classloader's LoggerFactory
(and any LogbackStatusListener)
+ // before we instantiate any for a new instance
+ private static final Logger logger =
LoggerFactory.getLogger(TestCluster.class);
+
private final File root;
private final List<Instance> instances;
private final Coordinator coordinator;
diff --git a/test/unit/org/apache/cassandra/LogbackStatusListener.java
b/test/unit/org/apache/cassandra/LogbackStatusListener.java
index 756f7eb..0ec73d9 100644
--- a/test/unit/org/apache/cassandra/LogbackStatusListener.java
+++ b/test/unit/org/apache/cassandra/LogbackStatusListener.java
@@ -21,434 +21,518 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
+import java.io.UnsupportedEncodingException;
import java.util.Locale;
+import org.slf4j.ILoggerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.spi.LoggerContextListener;
import ch.qos.logback.core.status.Status;
import ch.qos.logback.core.status.StatusListener;
+import org.apache.cassandra.distributed.InstanceClassLoader;
/*
* Listen for logback readiness and then redirect stdout/stderr to logback
*/
-public class LogbackStatusListener implements StatusListener
+public class LogbackStatusListener implements StatusListener,
LoggerContextListener
{
public static final PrintStream originalOut = System.out;
-
public static final PrintStream originalErr = System.err;
- private boolean hadError = false;
+ private volatile boolean hadPreInstallError = false;
+ private volatile boolean haveInstalled = false;
+ private volatile boolean haveRegisteredListener = false;
private PrintStream replacementOut;
-
private PrintStream replacementErr;
@Override
public void addStatusEvent(Status s)
{
- if (s.getLevel() != 0 || s.getEffectiveLevel() != 0)
- hadError = true;
+ if (!haveInstalled && (s.getLevel() != 0 || s.getEffectiveLevel() !=
0))
+ {
+ // if we encounter an error during setup, we're not sure what
state we're in, so we just don't switch
+ // we should log this fact, though, so that we know that we're not
necessarily capturing stdout
+ LoggerFactory.getLogger(LogbackStatusListener.class)
+ .warn("Encountered non-info status in logger setup;
aborting stdout capture: '" + s.getMessage() + '\'');
+ hadPreInstallError = true;
+ }
- if (!hadError && s.getMessage().equals("Registering current
configuration as safe fallback point"))
+ if (hadPreInstallError)
+ return;
+
+ if (s.getMessage().startsWith("Registering current configuration as
safe fallback point"))
{
- try
- {
- installReplacementStreams();
- }
- catch (Exception e)
- {
- throw new RuntimeException(e);
- }
+ onStart(null);
+ }
+
+ if (haveInstalled && !haveRegisteredListener)
+ {
+ // we register ourselves as a listener after the fact, because we
enable ourselves before the LoggerFactory
+ // is properly initialised, hence before it can accept any
LoggerContextListener registrations
+ tryRegisterListener();
}
if (s.getMessage().equals("Logback context being closed via shutdown
hook"))
{
- if (replacementOut != null) replacementOut.flush();
- if (replacementErr != null) replacementErr.flush();
- System.setErr(originalErr);
- System.setOut(originalOut);
+ onStop(null);
}
}
- private void installReplacementStreams() throws Exception
+ private static PrintStream wrapLogger(Logger logger, PrintStream original,
String encodingProperty, boolean error) throws Exception
{
- Logger stdoutLogger = LoggerFactory.getLogger("stdout");
- Logger stderrLogger = LoggerFactory.getLogger("stderr");
-
- replacementOut = wrapLogger(stdoutLogger, originalOut,
"sun.stdout.encoding", false);
- System.setOut(replacementOut);
- replacementErr = wrapLogger(stderrLogger, originalErr,
"sun.stderr.encoding", true);
- System.setErr(replacementErr);
+ final String encoding = System.getProperty(encodingProperty);
+ OutputStream os = new ToLoggerOutputStream(logger, encoding, error);
+ return encoding != null ? new WrappedPrintStream(os, true, encoding,
original)
+ : new WrappedPrintStream(os, true, original);
}
- private static PrintStream wrapLogger(final Logger logger, final
PrintStream original, String encodingProperty, boolean error) throws Exception
+ private static class ToLoggerOutputStream extends ByteArrayOutputStream
{
- final String encoding = System.getProperty(encodingProperty);
- OutputStream os = new OutputStream()
- {
+ final Logger logger;
+ final String encoding;
+ final boolean error;
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
-
- @Override
- public void write(int b) throws IOException
- {
- baos.write(b);
- }
-
- @Override
- public void write(byte[] b, int offset, int length)
- {
- baos.write(b, offset, length);
- }
+ private ToLoggerOutputStream(Logger logger, String encoding, boolean
error)
+ {
+ this.logger = logger;
+ this.encoding = encoding;
+ this.error = error;
+ }
- @Override
- public void write(byte[] b)
+ @Override
+ public void flush() throws IOException
+ {
+ try
{
- write(b, 0, b.length);
- }
+ //Filter out stupid PrintStream empty flushes
+ if (size() == 0) return;
- @Override
- public void flush() throws IOException
- {
- try
+ //Filter out newlines, log framework provides its own
+ if (size() == 1)
{
- //Filter out stupid PrintStream empty flushes
- if (baos.size() == 0) return;
-
- //Filter out newlines, log framework provides its own
- if (baos.size() == 1)
- {
- byte[] bytes = baos.toByteArray();
- if (bytes[0] == 0xA)
- return;
- }
-
- //Filter out Windows newline
- if (baos.size() == 2)
- {
- byte[] bytes = baos.toByteArray();
- if (bytes[0] == 0xD && bytes[1] == 0xA)
- return;
- }
-
- String statement;
- if (encoding != null)
- statement = new String(baos.toByteArray(), encoding);
- else
- statement = new String(baos.toByteArray());
-
- if (error)
- logger.error(statement);
- else
- logger.info(statement);
+ byte[] bytes = toByteArray();
+ if (bytes[0] == 0xA)
+ return;
}
- finally
+
+ //Filter out Windows newline
+ if (size() == 2)
{
- baos.reset();
+ byte[] bytes = toByteArray();
+ if (bytes[0] == 0xD && bytes[1] == 0xA)
+ return;
}
- }
- };
-
- if (encoding != null)
- return new PrintStream(os, true, encoding);
- return new PrintStream(os, true)
- {
-
- private long asyncAppenderThreadId = Long.MIN_VALUE;
-
- /*
- * Long and the short of it is that we don't want to serve logback
a fake System.out/err.
- * ConsoleAppender is replaced so it always goes to the real
System.out/err, but logback itself
- * will at times try to log to System.out/err when it has issues.
- *
- * Now here is the problem. There is a deadlock if a thread logs
to System.out, blocks on the async
- * appender queue, and the async appender thread tries to log to
System.out directly as part of some
- * internal logback issue.
- *
- * So to prevent this we have to exhaustively check before locking
in the PrintStream and forward
- * to real System.out/err if it is the async appender
- */
- private boolean isAsyncAppender()
- {
- //Set the thread id based on the name
- if (asyncAppenderThreadId == Long.MIN_VALUE)
- asyncAppenderThreadId =
Thread.currentThread().getName().equals("AsyncAppender-Worker-ASYNC") ?
Thread.currentThread().getId() : asyncAppenderThreadId;
- if (Thread.currentThread().getId() == asyncAppenderThreadId)
- original.println("Was in async appender");
- return Thread.currentThread().getId() == asyncAppenderThreadId;
- }
- @Override
- public void flush()
- {
- if (isAsyncAppender())
- original.flush();
+ String statement;
+ if (encoding != null)
+ statement = new String(toByteArray(), encoding);
else
- super.flush();
- }
+ statement = new String(toByteArray());
- @Override
- public void close()
- {
- if (isAsyncAppender())
- original.close();
+ if (error)
+ logger.error(statement);
else
- super.flush();
+ logger.info(statement);
}
-
- @Override
- public void write(int b)
+ finally
{
- if (isAsyncAppender())
- original.write(b);
- else
- super.write(b);
+ reset();
}
+ }
+ };
- @Override
- public void write(byte[] buf, int off, int len)
- {
- if (isAsyncAppender())
- original.write(buf, off, len);
- else
- super.write(buf, off, len);
- }
+ private static class WrappedPrintStream extends PrintStream
+ {
+ private long asyncAppenderThreadId = Long.MIN_VALUE;
+ private final PrintStream original;
- @Override
- public void print(boolean b)
- {
- if (isAsyncAppender())
- original.print(b);
- else
- super.print(b);
- }
+ public WrappedPrintStream(OutputStream out, boolean autoFlush,
PrintStream original)
+ {
+ super(out, autoFlush);
+ this.original = original;
+ }
- @Override
- public void print(char c)
- {
- if (isAsyncAppender())
- original.print(c);
- else
- super.print(c);
- }
+ public WrappedPrintStream(OutputStream out, boolean autoFlush, String
encoding, PrintStream original) throws UnsupportedEncodingException
+ {
+ super(out, autoFlush, encoding);
+ this.original = original;
+ }
- @Override
- public void print(int i)
- {
- if (isAsyncAppender())
- original.print(i);
- else
- super.print(i);
- }
+ /*
+ * Long and the short of it is that we don't want to serve logback a
fake System.out/err.
+ * ConsoleAppender is replaced so it always goes to the real
System.out/err, but logback itself
+ * will at times try to log to System.out/err when it has issues.
+ *
+ * Now here is the problem. There is a deadlock if a thread logs to
System.out, blocks on the async
+ * appender queue, and the async appender thread tries to log to
System.out directly as part of some
+ * internal logback issue.
+ *
+ * So to prevent this we have to exhaustively check before locking in
the PrintStream and forward
+ * to real System.out/err if it is the async appender
+ */
+ private boolean isAsyncAppender()
+ {
+ //Set the thread id based on the name
+ Thread currentThread = Thread.currentThread();
+ long currentThreadId = currentThread.getId();
+ if (asyncAppenderThreadId == Long.MIN_VALUE &&
+ currentThread.getName().equals("AsyncAppender-Worker-ASYNC") &&
+
!InstanceClassLoader.wasLoadedByAnInstanceClassLoader(currentThread.getClass()))
+ {
+ asyncAppenderThreadId = currentThreadId;
+ }
+ if (currentThreadId == asyncAppenderThreadId)
+ original.println("Was in async appender");
+ return currentThreadId == asyncAppenderThreadId;
+ }
- @Override
- public void print(long l)
- {
- if (isAsyncAppender())
- original.print(l);
- else
- super.print(l);
- }
+ @Override
+ public void flush()
+ {
+ if (isAsyncAppender())
+ original.flush();
+ else
+ super.flush();
+ }
- @Override
- public void print(float f)
- {
- if (isAsyncAppender())
- original.print(f);
- else
- super.print(f);
- }
+ @Override
+ public void close()
+ {
+ if (isAsyncAppender())
+ original.close();
+ else
+ super.flush();
+ }
- @Override
- public void print(double d)
- {
- if (isAsyncAppender())
- original.print(d);
- else
- super.print(d);
- }
+ @Override
+ public void write(int b)
+ {
+ if (isAsyncAppender())
+ original.write(b);
+ else
+ super.write(b);
+ }
- @Override
- public void print(char[] s)
- {
- if(isAsyncAppender())
- original.println(s);
- else
- super.print(s);
- }
+ @Override
+ public void write(byte[] buf, int off, int len)
+ {
+ if (isAsyncAppender())
+ original.write(buf, off, len);
+ else
+ super.write(buf, off, len);
+ }
- @Override
- public void print(String s)
- {
- if (isAsyncAppender())
- original.print(s);
- else
- super.print(s);
- }
+ @Override
+ public void print(boolean b)
+ {
+ if (isAsyncAppender())
+ original.print(b);
+ else
+ super.print(b);
+ }
- @Override
- public void print(Object obj)
- {
- if (isAsyncAppender())
- original.print(obj);
- else
- super.print(obj);
- }
+ @Override
+ public void print(char c)
+ {
+ if (isAsyncAppender())
+ original.print(c);
+ else
+ super.print(c);
+ }
- @Override
- public void println()
- {
- if (isAsyncAppender())
- original.println();
- else
- super.println();
- }
+ @Override
+ public void print(int i)
+ {
+ if (isAsyncAppender())
+ original.print(i);
+ else
+ super.print(i);
+ }
- @Override
- public void println(boolean v)
- {
- if (isAsyncAppender())
- original.println(v);
- else
- super.println(v);
- }
+ @Override
+ public void print(long l)
+ {
+ if (isAsyncAppender())
+ original.print(l);
+ else
+ super.print(l);
+ }
- @Override
- public void println(char v)
- {
- if (isAsyncAppender())
- original.println(v);
- else
- super.println(v);
- }
+ @Override
+ public void print(float f)
+ {
+ if (isAsyncAppender())
+ original.print(f);
+ else
+ super.print(f);
+ }
- @Override
- public void println(int v)
- {
- if (isAsyncAppender())
- original.println(v);
- else
- super.println(v);
- }
+ @Override
+ public void print(double d)
+ {
+ if (isAsyncAppender())
+ original.print(d);
+ else
+ super.print(d);
+ }
- @Override
- public void println(long v)
- {
- if (isAsyncAppender())
- original.println(v);
- else
- super.println(v);
- }
+ @Override
+ public void print(char[] s)
+ {
+ if(isAsyncAppender())
+ original.println(s);
+ else
+ super.print(s);
+ }
- @Override
- public void println(float v)
- {
- if (isAsyncAppender())
- original.println(v);
- else
- super.println(v);
- }
+ @Override
+ public void print(String s)
+ {
+ if (isAsyncAppender())
+ original.print(s);
+ else
+ super.print(s);
+ }
- @Override
- public void println(double v)
- {
- if (isAsyncAppender())
- original.println(v);
- else
- super.println(v);
- }
+ @Override
+ public void print(Object obj)
+ {
+ if (isAsyncAppender())
+ original.print(obj);
+ else
+ super.print(obj);
+ }
- @Override
- public void println(char[] v)
- {
- if (isAsyncAppender())
- original.println(v);
- else
- super.println(v);
- }
+ @Override
+ public void println()
+ {
+ if (isAsyncAppender())
+ original.println();
+ else
+ super.println();
+ }
- @Override
- public void println(String v)
- {
- if (isAsyncAppender())
- original.println(v);
- else
- super.println(v);
- }
+ @Override
+ public void println(boolean v)
+ {
+ if (isAsyncAppender())
+ original.println(v);
+ else
+ super.println(v);
+ }
- @Override
- public void println(Object v)
- {
- if (isAsyncAppender())
- original.println(v);
- else
- super.println(v);
- }
+ @Override
+ public void println(char v)
+ {
+ if (isAsyncAppender())
+ original.println(v);
+ else
+ super.println(v);
+ }
- @Override
- public PrintStream printf(String format, Object... args)
- {
- if (isAsyncAppender())
- return original.printf(format, args);
- else
- return super.printf(format, args);
- }
+ @Override
+ public void println(int v)
+ {
+ if (isAsyncAppender())
+ original.println(v);
+ else
+ super.println(v);
+ }
- @Override
- public PrintStream printf(Locale l, String format, Object... args)
- {
- if (isAsyncAppender())
- return original.printf(l, format, args);
- else
- return super.printf(l, format, args);
- }
+ @Override
+ public void println(long v)
+ {
+ if (isAsyncAppender())
+ original.println(v);
+ else
+ super.println(v);
+ }
- @Override
- public PrintStream format(String format, Object... args)
- {
- if (isAsyncAppender())
- return original.format(format, args);
- else
- return super.format(format, args);
- }
+ @Override
+ public void println(float v)
+ {
+ if (isAsyncAppender())
+ original.println(v);
+ else
+ super.println(v);
+ }
+
+ @Override
+ public void println(double v)
+ {
+ if (isAsyncAppender())
+ original.println(v);
+ else
+ super.println(v);
+ }
+
+ @Override
+ public void println(char[] v)
+ {
+ if (isAsyncAppender())
+ original.println(v);
+ else
+ super.println(v);
+ }
+
+ @Override
+ public void println(String v)
+ {
+ if (isAsyncAppender())
+ original.println(v);
+ else
+ super.println(v);
+ }
- @Override
- public PrintStream format(Locale l, String format, Object... args)
+ @Override
+ public void println(Object v)
+ {
+ if (isAsyncAppender())
+ original.println(v);
+ else
+ super.println(v);
+ }
+
+ @Override
+ public PrintStream printf(String format, Object... args)
+ {
+ if (isAsyncAppender())
+ return original.printf(format, args);
+ else
+ return super.printf(format, args);
+ }
+
+ @Override
+ public PrintStream printf(Locale l, String format, Object... args)
+ {
+ if (isAsyncAppender())
+ return original.printf(l, format, args);
+ else
+ return super.printf(l, format, args);
+ }
+
+ @Override
+ public PrintStream format(String format, Object... args)
+ {
+ if (isAsyncAppender())
+ return original.format(format, args);
+ else
+ return super.format(format, args);
+ }
+
+ @Override
+ public PrintStream format(Locale l, String format, Object... args)
+ {
+ if (isAsyncAppender())
+ return original.format(l, format, args);
+ else
+ return super.format(l, format, args);
+ }
+
+ @Override
+ public PrintStream append(CharSequence csq)
+ {
+ if (isAsyncAppender())
+ return original.append(csq);
+ else
+ return super.append(csq);
+ }
+
+ @Override
+ public PrintStream append(CharSequence csq, int start, int end)
+ {
+ if (isAsyncAppender())
+ return original.append(csq, start, end);
+ else
+ return super.append(csq, start, end);
+ }
+
+ @Override
+ public PrintStream append(char c)
+ {
+ if (isAsyncAppender())
+ return original.append(c);
+ else
+ return super.append(c);
+ } }
+
+ public boolean isResetResistant()
+ {
+ return false;
+ }
+
+ public synchronized void onStart(LoggerContext loggerContext)
+ {
+ if (!hadPreInstallError && !haveInstalled)
+ {
+ if
(InstanceClassLoader.wasLoadedByAnInstanceClassLoader(getClass())
+ ||
System.out.getClass().getName().contains("LogbackStatusListener"))
{
- if (isAsyncAppender())
- return original.format(l, format, args);
- else
- return super.format(l, format, args);
+ // don't operate if we're a dtest node, or if we're not the
first to swap System.out for some other reason
+ hadPreInstallError = true;
+ return;
}
+ try
+ {
+ Logger stdoutLogger = LoggerFactory.getLogger("stdout");
+ Logger stderrLogger = LoggerFactory.getLogger("stderr");
- @Override
- public PrintStream append(CharSequence csq)
+ replacementOut = wrapLogger(stdoutLogger, originalOut,
"sun.stdout.encoding", false);
+ System.setOut(replacementOut);
+ replacementErr = wrapLogger(stderrLogger, originalErr,
"sun.stderr.encoding", true);
+ System.setErr(replacementErr);
+ }
+ catch (Exception e)
{
- if (isAsyncAppender())
- return original.append(csq);
- else
- return super.append(csq);
+ throw new RuntimeException(e);
}
+ haveInstalled = true;
+ }
+ }
- @Override
- public PrintStream append(CharSequence csq, int start, int end)
+ public synchronized void onReset(LoggerContext loggerContext)
+ {
+ onStop(loggerContext);
+ }
+
+ public synchronized void onStop(LoggerContext loggerContext)
+ {
+ if (haveInstalled)
+ {
+ if (replacementOut != null) replacementOut.flush();
+ if (replacementErr != null) replacementErr.flush();
+ System.setErr(originalErr);
+ System.setOut(originalOut);
+ hadPreInstallError = false;
+ haveInstalled = false;
+ haveRegisteredListener = false;
+ if (haveRegisteredListener)
{
- if (isAsyncAppender())
- return original.append(csq, start, end);
- else
- return super.append(csq, start, end);
+
((LoggerContext)LoggerFactory.getILoggerFactory()).removeListener(this);
}
+ }
+ }
- @Override
- public PrintStream append(char c)
+ public void onLevelChange(ch.qos.logback.classic.Logger logger, Level
level)
+ {
+ }
+
+ private synchronized void tryRegisterListener()
+ {
+ if (haveInstalled && !haveRegisteredListener)
+ {
+ ILoggerFactory factory = LoggerFactory.getILoggerFactory();
+ if (factory instanceof LoggerContext)
{
- if (isAsyncAppender())
- return original.append(c);
- else
- return super.append(c);
+ ((LoggerContext) factory).addListener(this);
+ haveRegisteredListener = true;
}
- };
+ }
}
}
diff --git
a/test/unit/org/apache/cassandra/config/DatabaseDescriptorRefTest.java
b/test/unit/org/apache/cassandra/config/DatabaseDescriptorRefTest.java
index f23e909..4a11f1d 100644
--- a/test/unit/org/apache/cassandra/config/DatabaseDescriptorRefTest.java
+++ b/test/unit/org/apache/cassandra/config/DatabaseDescriptorRefTest.java
@@ -87,6 +87,20 @@ public class DatabaseDescriptorRefTest
"org.apache.cassandra.config.TransparentDataEncryptionOptions",
"org.apache.cassandra.db.ConsistencyLevel",
"org.apache.cassandra.dht.IPartitioner",
+ "org.apache.cassandra.distributed.InstanceClassLoader",
+ "org.apache.cassandra.distributed.InstanceConfig",
+ "org.apache.cassandra.distributed.InvokableInstance",
+ "org.apache.cassandra.distributed.InvokableInstance$CallableNoExcept",
+ "org.apache.cassandra.distributed.InvokableInstance$InstanceFunction",
+
"org.apache.cassandra.distributed.InvokableInstance$SerializableBiConsumer",
+
"org.apache.cassandra.distributed.InvokableInstance$SerializableBiFunction",
+ "org.apache.cassandra.distributed.InvokableInstance$SerializableCallable",
+ "org.apache.cassandra.distributed.InvokableInstance$SerializableConsumer",
+ "org.apache.cassandra.distributed.InvokableInstance$SerializableFunction",
+ "org.apache.cassandra.distributed.InvokableInstance$SerializableRunnable",
+
"org.apache.cassandra.distributed.InvokableInstance$SerializableTriFunction",
+ "org.apache.cassandra.distributed.InvokableInstance$TriFunction",
+ "org.apache.cassandra.distributed.Message",
"org.apache.cassandra.exceptions.ConfigurationException",
"org.apache.cassandra.exceptions.RequestValidationException",
"org.apache.cassandra.exceptions.CassandraException",
@@ -118,8 +132,8 @@ public class DatabaseDescriptorRefTest
"org.apache.cassandra.ConsoleAppender",
"org.apache.cassandra.ConsoleAppender$1",
"org.apache.cassandra.LogbackStatusListener",
- "org.apache.cassandra.LogbackStatusListener$1",
- "org.apache.cassandra.LogbackStatusListener$2",
+ "org.apache.cassandra.LogbackStatusListener$ToLoggerOutputStream",
+ "org.apache.cassandra.LogbackStatusListener$WrappedPrintStream",
"org.apache.cassandra.TeeingAppender",
"org.apache.cassandra.audit.IAuditLogger",
"org.apache.cassandra.audit.BinAuditLogger",
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]