mirror of https://github.com/apache/cassandra
Upgrade logback version to 1.5.18 and slf4j dependencies to 2.0.17
Dropback of CASSANDRA-20429 to cassandra-5.0 patch by Michael Morris; reviewed by Stefan Miklosovic, Brandon Williams for CASSANDRA-21137
This commit is contained in:
parent
30a200c39f
commit
8b6195a975
|
|
@ -397,27 +397,27 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>slf4j-api</artifactId>
|
<artifactId>slf4j-api</artifactId>
|
||||||
<version>1.7.36</version>
|
<version>2.0.17</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>log4j-over-slf4j</artifactId>
|
<artifactId>log4j-over-slf4j</artifactId>
|
||||||
<version>1.7.36</version>
|
<version>2.0.17</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>jcl-over-slf4j</artifactId>
|
<artifactId>jcl-over-slf4j</artifactId>
|
||||||
<version>1.7.36</version>
|
<version>2.0.17</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>ch.qos.logback</groupId>
|
<groupId>ch.qos.logback</groupId>
|
||||||
<artifactId>logback-core</artifactId>
|
<artifactId>logback-core</artifactId>
|
||||||
<version>1.2.12</version>
|
<version>1.5.18</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>ch.qos.logback</groupId>
|
<groupId>ch.qos.logback</groupId>
|
||||||
<artifactId>logback-classic</artifactId>
|
<artifactId>logback-classic</artifactId>
|
||||||
<version>1.2.12</version>
|
<version>1.5.18</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
5.0.7
|
5.0.7
|
||||||
|
* Upgrade logback version to 1.5.18 and slf4j dependencies to 2.0.17 (CASSANDRA-21137)
|
||||||
* Automatically disable zero-copy streaming for legacy sstables with old bloom filter format (CASSANDRA-21092)
|
* Automatically disable zero-copy streaming for legacy sstables with old bloom filter format (CASSANDRA-21092)
|
||||||
* Fix CQLSSTableWriter serialization of vector of date and time (CASSANDRA-20979)
|
* Fix CQLSSTableWriter serialization of vector of date and time (CASSANDRA-20979)
|
||||||
* Correctly calculate default for FailureDetector max interval (CASSANDRA-21025)
|
* Correctly calculate default for FailureDetector max interval (CASSANDRA-21025)
|
||||||
|
|
@ -17,6 +18,7 @@ Merged from 4.0:
|
||||||
* Updated dtest-api to 0.0.18 and removed JMX-related classes that now live in the dtest-api (CASSANDRA-20884)
|
* Updated dtest-api to 0.0.18 and removed JMX-related classes that now live in the dtest-api (CASSANDRA-20884)
|
||||||
|
|
||||||
5.0.6
|
5.0.6
|
||||||
|
* Upgrade logback version to 1.5.18 and slf4j dependencies to 2.0.17 (CASSANDRA-20429)
|
||||||
* Fix range queries on early-open BTI files (CASSANDRA-20976)
|
* Fix range queries on early-open BTI files (CASSANDRA-20976)
|
||||||
* Avoid re-initializing underlying iterator in LazilyInitializedUnfilteredRowIterator after closing (CASSANDRA-20972)
|
* Avoid re-initializing underlying iterator in LazilyInitializedUnfilteredRowIterator after closing (CASSANDRA-20972)
|
||||||
* Flush SAI segment builder when current SSTable writer is switched (CASSANDRA-20752)
|
* Flush SAI segment builder when current SSTable writer is switched (CASSANDRA-20752)
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,6 @@ appender reference in the root level section below.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<configuration scan="true" scanPeriod="60 seconds">
|
<configuration scan="true" scanPeriod="60 seconds">
|
||||||
<jmxConfigurator />
|
|
||||||
|
|
||||||
<!-- No shutdown hook; we run it ourselves in StorageService after shutdown -->
|
<!-- No shutdown hook; we run it ourselves in StorageService after shutdown -->
|
||||||
|
|
||||||
<!-- SYSTEMLOG rolling file appender to system.log (INFO level) -->
|
<!-- SYSTEMLOG rolling file appender to system.log (INFO level) -->
|
||||||
|
|
@ -43,7 +41,7 @@ appender reference in the root level section below.
|
||||||
<totalSizeCap>5GB</totalSizeCap>
|
<totalSizeCap>5GB</totalSizeCap>
|
||||||
</rollingPolicy>
|
</rollingPolicy>
|
||||||
<encoder>
|
<encoder>
|
||||||
<pattern>%-5level [%thread] %date{ISO8601} %F:%L - %msg%n</pattern>
|
<pattern>%-5level [%thread] %date{"yyyy-MM-dd'T'HH:mm:ss,SSS", UTC} %F:%L - %msg%n</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
|
|
@ -60,7 +58,7 @@ appender reference in the root level section below.
|
||||||
<totalSizeCap>5GB</totalSizeCap>
|
<totalSizeCap>5GB</totalSizeCap>
|
||||||
</rollingPolicy>
|
</rollingPolicy>
|
||||||
<encoder>
|
<encoder>
|
||||||
<pattern>%-5level [%thread] %date{ISO8601} %F:%L - %msg%n</pattern>
|
<pattern>%-5level [%thread] %date{"yyyy-MM-dd'T'HH:mm:ss,SSS", UTC} %F:%L - %msg%n</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
|
|
@ -80,7 +78,7 @@ appender reference in the root level section below.
|
||||||
<level>INFO</level>
|
<level>INFO</level>
|
||||||
</filter>
|
</filter>
|
||||||
<encoder>
|
<encoder>
|
||||||
<pattern>%-5level [%thread] %date{ISO8601} %F:%L - %msg%n</pattern>
|
<pattern>%-5level [%thread] %date{"yyyy-MM-dd'T'HH:mm:ss,SSS", UTC} %F:%L - %msg%n</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
|
|
@ -98,7 +96,7 @@ appender reference in the root level section below.
|
||||||
<totalSizeCap>5GB</totalSizeCap>
|
<totalSizeCap>5GB</totalSizeCap>
|
||||||
</rollingPolicy>
|
</rollingPolicy>
|
||||||
<encoder>
|
<encoder>
|
||||||
<pattern>%-5level [%thread] %date{ISO8601} %F:%L - %msg%n</pattern>
|
<pattern>%-5level [%thread] %date{"yyyy-MM-dd'T'HH:mm:ss,SSS", UTC} %F:%L - %msg%n</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
</appender> -->
|
</appender> -->
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -76,8 +76,8 @@ the rolling policy.
|
||||||
|
|
||||||
Specify the format of the message. Part of the rolling policy.
|
Specify the format of the message. Part of the rolling policy.
|
||||||
|
|
||||||
*Example:* <maxHistory>7</maxHistory> *Example:* <encoder>
|
*Example:* <encoder>
|
||||||
<pattern>%-5level [%thread] %date\{ISO8601} %F:%L - %msg%n</pattern>
|
<pattern>%-5level [%thread] %date\{"yyyy-MM-dd'T'HH:mm:ss,SSS", UTC} %F:%L - %msg%n</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
|
|
||||||
=== Logging to Cassandra virtual table
|
=== Logging to Cassandra virtual table
|
||||||
|
|
@ -106,7 +106,6 @@ The appender to virtual table is commented out by default so logging to virtual
|
||||||
[source,XML]
|
[source,XML]
|
||||||
----
|
----
|
||||||
<configuration scan="true" scanPeriod="60 seconds">
|
<configuration scan="true" scanPeriod="60 seconds">
|
||||||
<jmxConfigurator />
|
|
||||||
|
|
||||||
<!-- No shutdown hook; we run it ourselves in StorageService after shutdown -->
|
<!-- No shutdown hook; we run it ourselves in StorageService after shutdown -->
|
||||||
|
|
||||||
|
|
@ -126,7 +125,7 @@ The appender to virtual table is commented out by default so logging to virtual
|
||||||
<totalSizeCap>5GB</totalSizeCap>
|
<totalSizeCap>5GB</totalSizeCap>
|
||||||
</rollingPolicy>
|
</rollingPolicy>
|
||||||
<encoder>
|
<encoder>
|
||||||
<pattern>%-5level [%thread] %date{ISO8601} %F:%L - %msg%n</pattern>
|
<pattern>%-5level [%thread] %date{"yyyy-MM-dd'T'HH:mm:ss,SSS", UTC} %F:%L - %msg%n</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
|
|
@ -143,7 +142,7 @@ The appender to virtual table is commented out by default so logging to virtual
|
||||||
<totalSizeCap>5GB</totalSizeCap>
|
<totalSizeCap>5GB</totalSizeCap>
|
||||||
</rollingPolicy>
|
</rollingPolicy>
|
||||||
<encoder>
|
<encoder>
|
||||||
<pattern>%-5level [%thread] %date{ISO8601} %F:%L - %msg%n</pattern>
|
<pattern>%-5level [%thread] %date{"yyyy-MM-dd'T'HH:mm:ss,SSS", UTC} %F:%L - %msg%n</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
|
|
@ -163,7 +162,7 @@ The appender to virtual table is commented out by default so logging to virtual
|
||||||
<level>INFO</level>
|
<level>INFO</level>
|
||||||
</filter>
|
</filter>
|
||||||
<encoder>
|
<encoder>
|
||||||
<pattern>%-5level [%thread] %date{ISO8601} %F:%L - %msg%n</pattern>
|
<pattern>%-5level [%thread] %date{"yyyy-MM-dd'T'HH:mm:ss,SSS", UTC} %F:%L - %msg%n</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -213,7 +213,7 @@ the audit log events to flow through separate log file instead of system.log.
|
||||||
<totalSizeCap>5GB</totalSizeCap>
|
<totalSizeCap>5GB</totalSizeCap>
|
||||||
</rollingPolicy>
|
</rollingPolicy>
|
||||||
<encoder>
|
<encoder>
|
||||||
<pattern>%-5level [%thread] %date{ISO8601} %F:%L - %msg%n</pattern>
|
<pattern>%-5level [%thread] %date{"yyyy-MM-dd'T'HH:mm:ss,SSS", UTC} %F:%L - %msg%n</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -556,7 +556,6 @@ public interface StorageServiceMBean extends NotificationEmitter
|
||||||
* If classQualifer is not empty but level is empty/null, it will set the level to null for the defined classQualifer<br>
|
* If classQualifer is not empty but level is empty/null, it will set the level to null for the defined classQualifer<br>
|
||||||
* If level cannot be parsed, then the level will be defaulted to DEBUG<br>
|
* If level cannot be parsed, then the level will be defaulted to DEBUG<br>
|
||||||
* <br>
|
* <br>
|
||||||
* The logback configuration should have {@code < jmxConfigurator />} set
|
|
||||||
*
|
*
|
||||||
* @param classQualifier The logger's classQualifer
|
* @param classQualifier The logger's classQualifer
|
||||||
* @param level The log level
|
* @param level The log level
|
||||||
|
|
|
||||||
|
|
@ -2247,7 +2247,7 @@ public class NodeProbe implements AutoCloseable
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
throw new RuntimeException("Error setting log for " + classQualifier + " on level " + level + ". Please check logback configuration and ensure to have <jmxConfigurator /> set", e);
|
throw new RuntimeException("Error setting log for " + classQualifier + " on level " + level + ". Please check logback configuration.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@
|
||||||
|
|
||||||
package org.apache.cassandra.utils.logging;
|
package org.apache.cassandra.utils.logging;
|
||||||
|
|
||||||
import java.lang.management.ManagementFactory;
|
|
||||||
import java.security.AccessControlException;
|
import java.security.AccessControlException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
@ -26,25 +25,21 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import javax.management.JMX;
|
import com.google.common.collect.Maps;
|
||||||
import javax.management.ObjectName;
|
|
||||||
|
|
||||||
import org.apache.cassandra.security.ThreadAwareSecurityManager;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
|
|
||||||
import ch.qos.logback.classic.Level;
|
import ch.qos.logback.classic.Level;
|
||||||
import ch.qos.logback.classic.Logger;
|
import ch.qos.logback.classic.Logger;
|
||||||
import ch.qos.logback.classic.LoggerContext;
|
import ch.qos.logback.classic.LoggerContext;
|
||||||
import ch.qos.logback.classic.jmx.JMXConfiguratorMBean;
|
|
||||||
import ch.qos.logback.classic.spi.ILoggingEvent;
|
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||||
import ch.qos.logback.classic.spi.TurboFilterList;
|
import ch.qos.logback.classic.spi.TurboFilterList;
|
||||||
import ch.qos.logback.classic.turbo.ReconfigureOnChangeFilter;
|
import ch.qos.logback.classic.turbo.ReconfigureOnChangeFilter;
|
||||||
import ch.qos.logback.classic.turbo.TurboFilter;
|
import ch.qos.logback.classic.turbo.TurboFilter;
|
||||||
|
import ch.qos.logback.classic.util.ContextInitializer;
|
||||||
import ch.qos.logback.core.Appender;
|
import ch.qos.logback.core.Appender;
|
||||||
import ch.qos.logback.core.hook.DelayingShutdownHook;
|
import ch.qos.logback.core.hook.DefaultShutdownHook;
|
||||||
|
import org.apache.cassandra.security.ThreadAwareSecurityManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encapsulates all logback-specific implementations in a central place.
|
* Encapsulates all logback-specific implementations in a central place.
|
||||||
|
|
@ -92,7 +87,7 @@ public class LogbackLoggingSupport implements LoggingSupport
|
||||||
@Override
|
@Override
|
||||||
public void onShutdown()
|
public void onShutdown()
|
||||||
{
|
{
|
||||||
DelayingShutdownHook logbackHook = new DelayingShutdownHook();
|
DefaultShutdownHook logbackHook = new DefaultShutdownHook();
|
||||||
logbackHook.setContext((LoggerContext) LoggerFactory.getILoggerFactory());
|
logbackHook.setContext((LoggerContext) LoggerFactory.getILoggerFactory());
|
||||||
logbackHook.run();
|
logbackHook.run();
|
||||||
}
|
}
|
||||||
|
|
@ -105,10 +100,9 @@ public class LogbackLoggingSupport implements LoggingSupport
|
||||||
// if both classQualifier and rawLevel are empty, reload from configuration
|
// if both classQualifier and rawLevel are empty, reload from configuration
|
||||||
if (StringUtils.isBlank(classQualifier) && StringUtils.isBlank(rawLevel))
|
if (StringUtils.isBlank(classQualifier) && StringUtils.isBlank(rawLevel))
|
||||||
{
|
{
|
||||||
JMXConfiguratorMBean jmxConfiguratorMBean = JMX.newMBeanProxy(ManagementFactory.getPlatformMBeanServer(),
|
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
|
||||||
new ObjectName("ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator"),
|
lc.reset();
|
||||||
JMXConfiguratorMBean.class);
|
new ContextInitializer(lc).autoConfig();
|
||||||
jmxConfiguratorMBean.reloadDefaultConfiguration();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// classQualifier is set, but blank level given
|
// classQualifier is set, but blank level given
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
<define name="instance_id" class="org.apache.cassandra.distributed.impl.InstanceIDDefiner" />
|
<define name="instance_id" class="org.apache.cassandra.distributed.impl.InstanceIDDefiner" />
|
||||||
|
|
||||||
<!-- Shutdown hook ensures that async appender flushes -->
|
<!-- Shutdown hook ensures that async appender flushes -->
|
||||||
<shutdownHook class="ch.qos.logback.core.hook.DelayingShutdownHook"/>
|
<shutdownHook class="ch.qos.logback.core.hook.DefaultShutdownHook"/>
|
||||||
|
|
||||||
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
|
||||||
|
|
@ -36,7 +36,7 @@
|
||||||
</triggeringPolicy>
|
</triggeringPolicy>
|
||||||
|
|
||||||
<encoder>
|
<encoder>
|
||||||
<pattern>%-5level [%thread] ${instance_id} %date{ISO8601} %msg%n</pattern>
|
<pattern>%-5level [%thread] ${instance_id} %date{"yyyy-MM-dd'T'HH:mm:ss,SSS", UTC} %msg%n</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
<immediateFlush>false</immediateFlush>
|
<immediateFlush>false</immediateFlush>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
@ -51,7 +51,7 @@
|
||||||
|
|
||||||
<appender name="STDOUT" target="System.out" class="ch.qos.logback.core.ConsoleAppender">
|
<appender name="STDOUT" target="System.out" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
<encoder>
|
<encoder>
|
||||||
<pattern>%-5level [%thread] ${instance_id} %date{ISO8601} %F:%L - %msg%n</pattern>
|
<pattern>%-5level [%thread] ${instance_id} %date{"yyyy-MM-dd'T'HH:mm:ss,SSS", UTC} %F:%L - %msg%n</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
<filter class="org.apache.cassandra.net.LogbackFilter"/>
|
<filter class="org.apache.cassandra.net.LogbackFilter"/>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
|
||||||
|
|
@ -22,19 +22,19 @@
|
||||||
<define name="instance_id" class="org.apache.cassandra.distributed.impl.InstanceIDDefiner" />
|
<define name="instance_id" class="org.apache.cassandra.distributed.impl.InstanceIDDefiner" />
|
||||||
|
|
||||||
<!-- Shutdown hook ensures that async appender flushes -->
|
<!-- Shutdown hook ensures that async appender flushes -->
|
||||||
<shutdownHook class="ch.qos.logback.core.hook.DelayingShutdownHook"/>
|
<shutdownHook class="ch.qos.logback.core.hook.DefaultShutdownHook"/>
|
||||||
|
|
||||||
<appender name="INSTANCEFILE" class="ch.qos.logback.core.FileAppender">
|
<appender name="INSTANCEFILE" class="ch.qos.logback.core.FileAppender">
|
||||||
<file>./build/test/logs/${cassandra.testtag}/${suitename}/${cluster_id}/${instance_id}/system.log</file>
|
<file>./build/test/logs/${cassandra.testtag}/${suitename}/${cluster_id}/${instance_id}/system.log</file>
|
||||||
<encoder>
|
<encoder>
|
||||||
<pattern>%-5level [%thread] ${instance_id} %date{ISO8601} %msg%n</pattern>
|
<pattern>%-5level [%thread] ${instance_id} %date{"yyyy-MM-dd'T'HH:mm:ss,SSS", UTC} %F:%L - %msg%n</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
<immediateFlush>true</immediateFlush>
|
<immediateFlush>true</immediateFlush>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
<appender name="INSTANCESTDERR" target="System.err" class="ch.qos.logback.core.ConsoleAppender">
|
<appender name="INSTANCESTDERR" target="System.err" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
<encoder>
|
<encoder>
|
||||||
<pattern>%-5level %date{HH:mm:ss,SSS} %msg%n</pattern>
|
<pattern>%-5level %date{"HH:mm:ss,SSS"} %msg%n</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||||
<level>WARN</level>
|
<level>WARN</level>
|
||||||
|
|
@ -43,7 +43,7 @@
|
||||||
|
|
||||||
<appender name="INSTANCESTDOUT" target="System.out" class="ch.qos.logback.core.ConsoleAppender">
|
<appender name="INSTANCESTDOUT" target="System.out" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
<encoder>
|
<encoder>
|
||||||
<pattern>%-5level [%thread] ${instance_id} %date{ISO8601} %F:%L - %msg%n</pattern>
|
<pattern>%-5level [%thread] ${instance_id} %date{"yyyy-MM-dd'T'HH:mm:ss,SSS", UTC} %F:%L - %msg%n</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||||
<level>DEBUG</level>
|
<level>DEBUG</level>
|
||||||
|
|
|
||||||
|
|
@ -21,19 +21,19 @@
|
||||||
<define name="instance_id" class="org.apache.cassandra.distributed.impl.InstanceIDDefiner" />
|
<define name="instance_id" class="org.apache.cassandra.distributed.impl.InstanceIDDefiner" />
|
||||||
|
|
||||||
<!-- Shutdown hook ensures that async appender flushes -->
|
<!-- Shutdown hook ensures that async appender flushes -->
|
||||||
<shutdownHook class="ch.qos.logback.core.hook.DelayingShutdownHook"/>
|
<shutdownHook class="ch.qos.logback.core.hook.DefaultShutdownHook"/>
|
||||||
|
|
||||||
<appender name="INSTANCEFILE" class="ch.qos.logback.core.FileAppender">
|
<appender name="INSTANCEFILE" class="ch.qos.logback.core.FileAppender">
|
||||||
<file>./build/test/logs/${cassandra.testtag}/${suitename}/${cluster_id}/${instance_id}/system.log</file>
|
<file>./build/test/logs/${cassandra.testtag}/${suitename}/${cluster_id}/${instance_id}/system.log</file>
|
||||||
<encoder>
|
<encoder>
|
||||||
<pattern>%-5level [%thread] ${instance_id} %date{ISO8601} %msg%n</pattern>
|
<pattern>%-5level [%thread] ${instance_id} %date{"yyyy-MM-dd'T'HH:mm:ss,SSS", UTC} %msg%n</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
<immediateFlush>true</immediateFlush>
|
<immediateFlush>true</immediateFlush>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
<appender name="INSTANCESTDERR" target="System.err" class="ch.qos.logback.core.ConsoleAppender">
|
<appender name="INSTANCESTDERR" target="System.err" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
<encoder>
|
<encoder>
|
||||||
<pattern>%-5level %date{HH:mm:ss,SSS} %msg%n</pattern>
|
<pattern>%-5level %date{"yyyy-MM-dd'T'HH:mm:ss,SSS", UTC} %msg%n</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||||
<level>WARN</level>
|
<level>WARN</level>
|
||||||
|
|
@ -42,7 +42,7 @@
|
||||||
|
|
||||||
<appender name="INSTANCESTDOUT" target="System.out" class="ch.qos.logback.core.ConsoleAppender">
|
<appender name="INSTANCESTDOUT" target="System.out" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
<encoder>
|
<encoder>
|
||||||
<pattern>%-5level [%thread] ${instance_id} %date{ISO8601} %F:%L - %msg%n</pattern>
|
<pattern>%-5level [%thread] ${instance_id} %date{"yyyy-MM-dd'T'HH:mm:ss,SSS", UTC} %F:%L - %msg%n</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||||
<level>DEBUG</level>
|
<level>DEBUG</level>
|
||||||
|
|
|
||||||
|
|
@ -21,19 +21,19 @@
|
||||||
<define name="instance_id" class="org.apache.cassandra.distributed.impl.InstanceIDDefiner" />
|
<define name="instance_id" class="org.apache.cassandra.distributed.impl.InstanceIDDefiner" />
|
||||||
|
|
||||||
<!-- Shutdown hook ensures that async appender flushes -->
|
<!-- Shutdown hook ensures that async appender flushes -->
|
||||||
<shutdownHook class="ch.qos.logback.core.hook.DelayingShutdownHook"/>
|
<shutdownHook class="ch.qos.logback.core.hook.DefaultShutdownHook"/>
|
||||||
|
|
||||||
<appender name="INSTANCEFILE" class="ch.qos.logback.core.FileAppender">
|
<appender name="INSTANCEFILE" class="ch.qos.logback.core.FileAppender">
|
||||||
<file>./build/test/logs/${cassandra.testtag}/${suitename}/${cluster_id}/${instance_id}/system.log</file>
|
<file>./build/test/logs/${cassandra.testtag}/${suitename}/${cluster_id}/${instance_id}/system.log</file>
|
||||||
<encoder>
|
<encoder>
|
||||||
<pattern>%-5level [%thread] ${instance_id} %date{ISO8601} %msg%n</pattern>
|
<pattern>%-5level [%thread] ${instance_id} %date{"yyyy-MM-dd'T'HH:mm:ss,SSS", UTC} %msg%n</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
<immediateFlush>true</immediateFlush>
|
<immediateFlush>true</immediateFlush>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
<appender name="INSTANCESTDERR" target="System.err" class="ch.qos.logback.core.ConsoleAppender">
|
<appender name="INSTANCESTDERR" target="System.err" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
<encoder>
|
<encoder>
|
||||||
<pattern>%-5level %date{HH:mm:ss,SSS} %msg%n</pattern>
|
<pattern>%-5level %date{"yyyy-MM-dd'T'HH:mm:ss,SSS", UTC} %msg%n</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||||
<level>WARN</level>
|
<level>WARN</level>
|
||||||
|
|
@ -42,7 +42,7 @@
|
||||||
|
|
||||||
<appender name="INSTANCESTDOUT" target="System.out" class="ch.qos.logback.core.ConsoleAppender">
|
<appender name="INSTANCESTDOUT" target="System.out" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
<encoder>
|
<encoder>
|
||||||
<pattern>%-5level [%thread] ${instance_id} %date{ISO8601} %F:%L - %msg%n</pattern>
|
<pattern>%-5level [%thread] ${instance_id} %date{"yyyy-MM-dd'T'HH:mm:ss,SSS", UTC} %F:%L - %msg%n</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||||
<level>DEBUG</level>
|
<level>DEBUG</level>
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@ appender reference in the root level section below.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<configuration scan="false" scanPeriod="60 seconds">
|
<configuration scan="false" scanPeriod="60 seconds">
|
||||||
<jmxConfigurator />
|
|
||||||
<!-- No shutdown hook; we run it ourselves in StorageService after shutdown -->
|
<!-- No shutdown hook; we run it ourselves in StorageService after shutdown -->
|
||||||
|
|
||||||
<!-- SYSTEMLOG rolling file appender to system.log (INFO level) -->
|
<!-- SYSTEMLOG rolling file appender to system.log (INFO level) -->
|
||||||
|
|
@ -42,7 +41,7 @@ appender reference in the root level section below.
|
||||||
<totalSizeCap>5GB</totalSizeCap>
|
<totalSizeCap>5GB</totalSizeCap>
|
||||||
</rollingPolicy>
|
</rollingPolicy>
|
||||||
<encoder>
|
<encoder>
|
||||||
<pattern>%-5level [%thread] %date{ISO8601} %F:%L - %msg%n</pattern>
|
<pattern>%-5level [%thread] %date{"yyyy-MM-dd'T'HH:mm:ss,SSS", UTC} %F:%L - %msg%n</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
|
|
@ -59,7 +58,7 @@ appender reference in the root level section below.
|
||||||
<totalSizeCap>5GB</totalSizeCap>
|
<totalSizeCap>5GB</totalSizeCap>
|
||||||
</rollingPolicy>
|
</rollingPolicy>
|
||||||
<encoder>
|
<encoder>
|
||||||
<pattern>%-5level [%thread] %date{ISO8601} %F:%L - %msg%n</pattern>
|
<pattern>%-5level [%thread] %date{"yyyy-MM-dd'T'HH:mm:ss,SSS", UTC} %F:%L - %msg%n</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
|
|
@ -79,7 +78,7 @@ appender reference in the root level section below.
|
||||||
<level>INFO</level>
|
<level>INFO</level>
|
||||||
</filter>
|
</filter>
|
||||||
<encoder>
|
<encoder>
|
||||||
<pattern>%-5level [%thread] %date{ISO8601} %F:%L - %msg%n</pattern>
|
<pattern>%-5level [%thread] %date{"yyyy-MM-dd'T'HH:mm:ss,SSS", UTC} %F:%L - %msg%n</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
</appender-->
|
</appender-->
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,19 +21,19 @@
|
||||||
<define name="instance_id" class="org.apache.cassandra.distributed.impl.InstanceIDDefiner" />
|
<define name="instance_id" class="org.apache.cassandra.distributed.impl.InstanceIDDefiner" />
|
||||||
|
|
||||||
<!-- Shutdown hook ensures that async appender flushes -->
|
<!-- Shutdown hook ensures that async appender flushes -->
|
||||||
<shutdownHook class="ch.qos.logback.core.hook.DelayingShutdownHook"/>
|
<shutdownHook class="ch.qos.logback.core.hook.DefaultShutdownHook"/>
|
||||||
|
|
||||||
<appender name="INSTANCEFILE" class="ch.qos.logback.core.FileAppender">
|
<appender name="INSTANCEFILE" class="ch.qos.logback.core.FileAppender">
|
||||||
<file>./build/test/logs/${cassandra.testtag}/${suitename}/${cluster_id}/${instance_id}/system.log</file>
|
<file>./build/test/logs/${cassandra.testtag}/${suitename}/${cluster_id}/${instance_id}/system.log</file>
|
||||||
<encoder>
|
<encoder>
|
||||||
<pattern>%-5level [%thread] ${instance_id} %date{ISO8601} %msg%n</pattern>
|
<pattern>%-5level [%thread] ${instance_id} %date{"yyyy-MM-dd'T'HH:mm:ss,SSS", UTC} %msg%n</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
<immediateFlush>true</immediateFlush>
|
<immediateFlush>true</immediateFlush>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
<appender name="STDOUT" target="System.out" class="ch.qos.logback.core.ConsoleAppender">
|
<appender name="STDOUT" target="System.out" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
<encoder>
|
<encoder>
|
||||||
<pattern>%-5level [%thread] ${instance_id} %date{ISO8601} %F:%L - %msg%n</pattern>
|
<pattern>%-5level [%thread] ${instance_id} %date{"yyyy-MM-dd'T'HH:mm:ss,SSS", UTC} %F:%L - %msg%n</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||||
<level>WARN</level>
|
<level>WARN</level>
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
<configuration debug="false" scan="true" scanPeriod="60 seconds">
|
<configuration debug="false" scan="true" scanPeriod="60 seconds">
|
||||||
<!-- Shutdown hook ensures that async appender flushes -->
|
<!-- Shutdown hook ensures that async appender flushes -->
|
||||||
<shutdownHook class="ch.qos.logback.core.hook.DelayingShutdownHook"/>
|
<shutdownHook class="ch.qos.logback.core.hook.DefaultShutdownHook"/>
|
||||||
|
|
||||||
<!-- Status listener is used to wrap stdout/stderr and tee to log file -->
|
<!-- Status listener is used to wrap stdout/stderr and tee to log file -->
|
||||||
<statusListener class="org.apache.cassandra.LogbackStatusListener" />
|
<statusListener class="org.apache.cassandra.LogbackStatusListener" />
|
||||||
|
|
@ -38,14 +38,14 @@
|
||||||
</triggeringPolicy>
|
</triggeringPolicy>
|
||||||
|
|
||||||
<encoder>
|
<encoder>
|
||||||
<pattern>%-5level [%thread] %date{ISO8601} %msg%n</pattern>
|
<pattern>%-5level [%thread] %date{"yyyy-MM-dd'T'HH:mm:ss,SSS", UTC} %msg%n</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
<immediateFlush>false</immediateFlush>
|
<immediateFlush>false</immediateFlush>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
<appender name="STDOUT" target="System.out" class="org.apache.cassandra.ConsoleAppender">
|
<appender name="STDOUT" target="System.out" class="org.apache.cassandra.ConsoleAppender">
|
||||||
<encoder>
|
<encoder>
|
||||||
<pattern>%-5level [%thread] %date{ISO8601} %F:%L - %msg%n</pattern>
|
<pattern>%-5level [%thread] %date{"yyyy-MM-dd'T'HH:mm:ss,SSS", UTC} %F:%L - %msg%n</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||||
<level>DEBUG</level>
|
<level>DEBUG</level>
|
||||||
|
|
|
||||||
|
|
@ -31,18 +31,8 @@ import java.util.TimeZone;
|
||||||
import java.util.concurrent.ThreadLocalRandom;
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
import org.apache.commons.lang3.time.DateUtils;
|
import org.apache.commons.lang3.time.DateUtils;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ch.qos.logback.classic.LoggerContext;
|
|
||||||
import ch.qos.logback.classic.joran.ReconfigureOnChangeTask;
|
|
||||||
import ch.qos.logback.classic.spi.TurboFilterList;
|
|
||||||
import ch.qos.logback.classic.turbo.ReconfigureOnChangeFilter;
|
|
||||||
import ch.qos.logback.classic.turbo.TurboFilter;
|
|
||||||
import org.apache.cassandra.schema.SchemaConstants;
|
|
||||||
import org.apache.cassandra.cql3.CQLTester;
|
import org.apache.cassandra.cql3.CQLTester;
|
||||||
import org.apache.cassandra.cql3.QueryProcessor;
|
import org.apache.cassandra.cql3.QueryProcessor;
|
||||||
import org.apache.cassandra.cql3.UntypedResultSet;
|
import org.apache.cassandra.cql3.UntypedResultSet;
|
||||||
|
|
@ -51,13 +41,13 @@ import org.apache.cassandra.db.marshal.AbstractType;
|
||||||
import org.apache.cassandra.db.marshal.TypeParser;
|
import org.apache.cassandra.db.marshal.TypeParser;
|
||||||
import org.apache.cassandra.exceptions.FunctionExecutionException;
|
import org.apache.cassandra.exceptions.FunctionExecutionException;
|
||||||
import org.apache.cassandra.exceptions.InvalidRequestException;
|
import org.apache.cassandra.exceptions.InvalidRequestException;
|
||||||
|
import org.apache.cassandra.schema.SchemaConstants;
|
||||||
import org.apache.cassandra.service.ClientState;
|
import org.apache.cassandra.service.ClientState;
|
||||||
import org.apache.cassandra.transport.Event.SchemaChange.Change;
|
import org.apache.cassandra.transport.Event.SchemaChange.Change;
|
||||||
import org.apache.cassandra.transport.Event.SchemaChange.Target;
|
import org.apache.cassandra.transport.Event.SchemaChange.Target;
|
||||||
import org.apache.cassandra.transport.ProtocolVersion;
|
import org.apache.cassandra.transport.ProtocolVersion;
|
||||||
import org.apache.cassandra.transport.messages.ResultMessage;
|
import org.apache.cassandra.transport.messages.ResultMessage;
|
||||||
|
|
||||||
import static ch.qos.logback.core.CoreConstants.RECONFIGURE_ON_CHANGE_TASK;
|
|
||||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
@ -1893,91 +1883,48 @@ public class AggregationTest extends CQLTester
|
||||||
{
|
{
|
||||||
// see https://issues.apache.org/jira/browse/CASSANDRA-11033
|
// see https://issues.apache.org/jira/browse/CASSANDRA-11033
|
||||||
|
|
||||||
// make logback's scan interval 1ms - boilerplate, but necessary for this test
|
createTable("CREATE TABLE %s (" +
|
||||||
configureLogbackScanPeriod(1L);
|
" year int PRIMARY KEY," +
|
||||||
try
|
" country text," +
|
||||||
|
" title text)");
|
||||||
|
|
||||||
|
String[] countries = Locale.getISOCountries();
|
||||||
|
ThreadLocalRandom rand = ThreadLocalRandom.current();
|
||||||
|
for (int i = 0; i < 10000; i++)
|
||||||
{
|
{
|
||||||
|
execute("INSERT INTO %s (year, country, title) VALUES (1980,?,?)",
|
||||||
createTable("CREATE TABLE %s (" +
|
countries[rand.nextInt(countries.length)],
|
||||||
" year int PRIMARY KEY," +
|
"title-" + i);
|
||||||
" country text," +
|
|
||||||
" title text)");
|
|
||||||
|
|
||||||
String[] countries = Locale.getISOCountries();
|
|
||||||
ThreadLocalRandom rand = ThreadLocalRandom.current();
|
|
||||||
for (int i = 0; i < 10000; i++)
|
|
||||||
{
|
|
||||||
execute("INSERT INTO %s (year, country, title) VALUES (1980,?,?)",
|
|
||||||
countries[rand.nextInt(countries.length)],
|
|
||||||
"title-" + i);
|
|
||||||
}
|
|
||||||
|
|
||||||
String albumCountByCountry = createFunction(KEYSPACE,
|
|
||||||
"map<text,bigint>,text,text",
|
|
||||||
"CREATE FUNCTION IF NOT EXISTS %s(state map<text,bigint>,country text, album_title text)\n" +
|
|
||||||
" RETURNS NULL ON NULL INPUT\n" +
|
|
||||||
" RETURNS map<text,bigint>\n" +
|
|
||||||
" LANGUAGE java\n" +
|
|
||||||
" AS $$\n" +
|
|
||||||
" if(state.containsKey(country)) {\n" +
|
|
||||||
" Long newCount = (Long)state.get(country) + 1;\n" +
|
|
||||||
" state.put(country, newCount);\n" +
|
|
||||||
" } else {\n" +
|
|
||||||
" state.put(country, 1L);\n" +
|
|
||||||
" }\n" +
|
|
||||||
" return state;\n" +
|
|
||||||
" $$;");
|
|
||||||
|
|
||||||
String releasesByCountry = createAggregate(KEYSPACE,
|
|
||||||
"text, text",
|
|
||||||
" CREATE AGGREGATE IF NOT EXISTS %s(text, text)\n" +
|
|
||||||
" SFUNC " + shortFunctionName(albumCountByCountry) + '\n' +
|
|
||||||
" STYPE map<text,bigint>\n" +
|
|
||||||
" INITCOND { };");
|
|
||||||
|
|
||||||
long tEnd = System.currentTimeMillis() + 150;
|
|
||||||
while (System.currentTimeMillis() < tEnd)
|
|
||||||
{
|
|
||||||
execute("SELECT " + releasesByCountry + "(country,title) FROM %s WHERE year=1980");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
configureLogbackScanPeriod(60000L);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void configureLogbackScanPeriod(long millis)
|
|
||||||
{
|
|
||||||
Logger l = LoggerFactory.getLogger(AggregationTest.class);
|
|
||||||
ch.qos.logback.classic.Logger logbackLogger = (ch.qos.logback.classic.Logger) l;
|
|
||||||
LoggerContext ctx = logbackLogger.getLoggerContext();
|
|
||||||
TurboFilterList turboFilterList = ctx.getTurboFilterList();
|
|
||||||
boolean done = false;
|
|
||||||
for (TurboFilter turboFilter : turboFilterList)
|
|
||||||
{
|
|
||||||
if (turboFilter instanceof ReconfigureOnChangeFilter)
|
|
||||||
{
|
|
||||||
ReconfigureOnChangeFilter reconfigureFilter = (ReconfigureOnChangeFilter) turboFilter;
|
|
||||||
reconfigureFilter.setContext(ctx);
|
|
||||||
reconfigureFilter.setRefreshPeriod(millis);
|
|
||||||
reconfigureFilter.stop();
|
|
||||||
reconfigureFilter.start(); // start() sets the next check timestammp
|
|
||||||
done = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReconfigureOnChangeTask roct = (ReconfigureOnChangeTask) ctx.getObject(RECONFIGURE_ON_CHANGE_TASK);
|
String albumCountByCountry = createFunction(KEYSPACE,
|
||||||
if (roct != null)
|
"map<text,bigint>,text,text",
|
||||||
{
|
"CREATE FUNCTION IF NOT EXISTS %s(state map<text,bigint>,country text, album_title text)\n" +
|
||||||
// New functionality in logback - they replaced ReconfigureOnChangeFilter (which runs in the logging code)
|
" RETURNS NULL ON NULL INPUT\n" +
|
||||||
// with an async ReconfigureOnChangeTask - i.e. in a thread that does not become sandboxed.
|
" RETURNS map<text,bigint>\n" +
|
||||||
// Let the test run anyway, just we cannot reconfigure it (and it is pointless to reconfigure).
|
" LANGUAGE java\n" +
|
||||||
return;
|
" AS $$\n" +
|
||||||
}
|
" if(state.containsKey(country)) {\n" +
|
||||||
|
" Long newCount = (Long)state.get(country) + 1;\n" +
|
||||||
|
" state.put(country, newCount);\n" +
|
||||||
|
" } else {\n" +
|
||||||
|
" state.put(country, 1L);\n" +
|
||||||
|
" }\n" +
|
||||||
|
" return state;\n" +
|
||||||
|
" $$;");
|
||||||
|
|
||||||
assertTrue("ReconfigureOnChangeFilter not in logback's turbo-filter list - do that by adding scan=\"true\" to logback-test.xml's configuration element", done);
|
String releasesByCountry = createAggregate(KEYSPACE,
|
||||||
|
"text, text",
|
||||||
|
" CREATE AGGREGATE IF NOT EXISTS %s(text, text)\n" +
|
||||||
|
" SFUNC " + shortFunctionName(albumCountByCountry) + '\n' +
|
||||||
|
" STYPE map<text,bigint>\n" +
|
||||||
|
" INITCOND { };");
|
||||||
|
|
||||||
|
long tEnd = System.currentTimeMillis() + 150;
|
||||||
|
while (System.currentTimeMillis() < tEnd)
|
||||||
|
{
|
||||||
|
execute("SELECT " + releasesByCountry + "(country,title) FROM %s WHERE year=1980");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue