Prevent logging in sandboxed state

patch by Robert Stupp; reviewed by Tyler Hobbs for CASSANDRA-11033
This commit is contained in:
Robert Stupp 2016-02-19 10:28:30 +01:00
parent 6503335089
commit a76a8efcc7
26 changed files with 184 additions and 86 deletions

View File

@ -1,4 +1,5 @@
3.0.4
* Prevent logging in sandboxed state (CASSANDRA-11033)
* Disallow drop/alter operations of UDTs used by UDAs (CASSANDRA-10721)
* Add query time validation method on Index (CASSANDRA-11043)
* Avoid potential AssertionError in mixed version cluster (CASSANDRA-11128)

View File

@ -40,7 +40,7 @@ import com.google.common.io.ByteStreams;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.TypeCodec;
import org.apache.cassandra.concurrent.NamedThreadFactory;
import org.apache.cassandra.cql3.ColumnIdentifier;
import org.apache.cassandra.db.marshal.AbstractType;
@ -184,10 +184,10 @@ final class JavaBasedUDFunction extends UDFunction
super(name, argNames, argTypes, UDHelper.driverTypes(argTypes),
returnType, UDHelper.driverType(returnType), calledOnNullInput, "java", body);
// javaParamTypes is just the Java representation for argTypes resp. argDataTypes
Class<?>[] javaParamTypes = UDHelper.javaTypes(argDataTypes, calledOnNullInput);
// javaReturnType is just the Java representation for returnType resp. returnDataType
Class<?> javaReturnType = UDHelper.asJavaClass(returnDataType);
// javaParamTypes is just the Java representation for argTypes resp. argCodecs
Class<?>[] javaParamTypes = UDHelper.javaTypes(argCodecs, calledOnNullInput);
// javaReturnType is just the Java representation for returnType resp. returnCodec
Class<?> javaReturnType = UDHelper.asJavaClass(returnCodec);
// put each UDF in a separate package to prevent cross-UDF code access
String pkgName = BASE_PACKAGE + '.' + generateClassName(name, 'p');
@ -327,9 +327,9 @@ final class JavaBasedUDFunction extends UDFunction
if (nonSyntheticMethodCount != 2 || cls.getDeclaredConstructors().length != 1)
throw new InvalidRequestException("Check your source to not define additional Java methods or constructors");
MethodType methodType = MethodType.methodType(void.class)
.appendParameterTypes(DataType.class, DataType[].class);
.appendParameterTypes(TypeCodec.class, TypeCodec[].class);
MethodHandle ctor = MethodHandles.lookup().findConstructor(cls, methodType);
this.javaUDF = (JavaUDF) ctor.invokeWithArguments(returnDataType, argDataTypes);
this.javaUDF = (JavaUDF) ctor.invokeWithArguments(returnCodec, argCodecs);
}
finally
{

View File

@ -21,7 +21,7 @@ package org.apache.cassandra.cql3.functions;
import java.nio.ByteBuffer;
import java.util.List;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.TypeCodec;
/**
* Base class for all Java UDFs.
@ -31,73 +31,73 @@ import com.datastax.driver.core.DataType;
*/
public abstract class JavaUDF
{
private final DataType returnDataType;
private final DataType[] argDataTypes;
private final TypeCodec<Object> returnCodec;
private final TypeCodec<Object>[] argCodecs;
protected JavaUDF(DataType returnDataType, DataType[] argDataTypes)
protected JavaUDF(TypeCodec<Object> returnCodec, TypeCodec<Object>[] argCodecs)
{
this.returnDataType = returnDataType;
this.argDataTypes = argDataTypes;
this.returnCodec = returnCodec;
this.argCodecs = argCodecs;
}
protected abstract ByteBuffer executeImpl(int protocolVersion, List<ByteBuffer> params);
protected Object compose(int protocolVersion, int argIndex, ByteBuffer value)
{
return UDFunction.compose(argDataTypes, protocolVersion, argIndex, value);
return UDFunction.compose(argCodecs, protocolVersion, argIndex, value);
}
protected ByteBuffer decompose(int protocolVersion, Object value)
{
return UDFunction.decompose(returnDataType, protocolVersion, value);
return UDFunction.decompose(returnCodec, protocolVersion, value);
}
// do not remove - used by generated Java UDFs
protected float compose_float(int protocolVersion, int argIndex, ByteBuffer value)
{
assert value != null && value.remaining() > 0;
return (float) UDHelper.deserialize(DataType.cfloat(), protocolVersion, value);
return (float) UDHelper.deserialize(TypeCodec.cfloat(), protocolVersion, value);
}
// do not remove - used by generated Java UDFs
protected double compose_double(int protocolVersion, int argIndex, ByteBuffer value)
{
assert value != null && value.remaining() > 0;
return (double) UDHelper.deserialize(DataType.cdouble(), protocolVersion, value);
return (double) UDHelper.deserialize(TypeCodec.cdouble(), protocolVersion, value);
}
// do not remove - used by generated Java UDFs
protected byte compose_byte(int protocolVersion, int argIndex, ByteBuffer value)
{
assert value != null && value.remaining() > 0;
return (byte) UDHelper.deserialize(DataType.tinyint(), protocolVersion, value);
return (byte) UDHelper.deserialize(TypeCodec.tinyInt(), protocolVersion, value);
}
// do not remove - used by generated Java UDFs
protected short compose_short(int protocolVersion, int argIndex, ByteBuffer value)
{
assert value != null && value.remaining() > 0;
return (short) UDHelper.deserialize(DataType.smallint(), protocolVersion, value);
return (short) UDHelper.deserialize(TypeCodec.smallInt(), protocolVersion, value);
}
// do not remove - used by generated Java UDFs
protected int compose_int(int protocolVersion, int argIndex, ByteBuffer value)
{
assert value != null && value.remaining() > 0;
return (int) UDHelper.deserialize(DataType.cint(), protocolVersion, value);
return (int) UDHelper.deserialize(TypeCodec.cint(), protocolVersion, value);
}
// do not remove - used by generated Java UDFs
protected long compose_long(int protocolVersion, int argIndex, ByteBuffer value)
{
assert value != null && value.remaining() > 0;
return (long) UDHelper.deserialize(DataType.bigint(), protocolVersion, value);
return (long) UDHelper.deserialize(TypeCodec.bigint(), protocolVersion, value);
}
// do not remove - used by generated Java UDFs
protected boolean compose_boolean(int protocolVersion, int argIndex, ByteBuffer value)
{
assert value != null && value.remaining() > 0;
return (boolean) UDHelper.deserialize(DataType.cboolean(), protocolVersion, value);
return (boolean) UDHelper.deserialize(TypeCodec.cboolean(), protocolVersion, value);
}
}

View File

@ -189,7 +189,7 @@ final class ScriptBasedUDFunction extends UDFunction
if (result == null)
return null;
Class<?> javaReturnType = UDHelper.asJavaClass(returnDataType);
Class<?> javaReturnType = UDHelper.asJavaClass(returnCodec);
Class<?> resultType = result.getClass();
if (!javaReturnType.isAssignableFrom(resultType))
{

View File

@ -47,7 +47,7 @@ public final class UDFByteCodeVerifier
public static final String JAVA_UDF_NAME = JavaUDF.class.getName().replace('.', '/');
public static final String OBJECT_NAME = Object.class.getName().replace('.', '/');
public static final String CTOR_SIG = "(Lcom/datastax/driver/core/DataType;[Lcom/datastax/driver/core/DataType;)V";
public static final String CTOR_SIG = "(Lcom/datastax/driver/core/TypeCodec;[Lcom/datastax/driver/core/TypeCodec;)V";
private final Set<String> disallowedClasses = new HashSet<>();
private final Multimap<String, String> disallowedMethodCalls = HashMultimap.create();
@ -97,7 +97,7 @@ public final class UDFByteCodeVerifier
{
if (Opcodes.ACC_PUBLIC != access)
errors.add("constructor not public");
// allowed constructor - JavaUDF(DataType returnDataType, DataType[] argDataTypes)
// allowed constructor - JavaUDF(TypeCodec returnCodec, TypeCodec[] argCodecs)
return new ConstructorVisitor(errors);
}
if ("executeImpl".equals(name) && "(ILjava/util/List;)Ljava/nio/ByteBuffer;".equals(desc))

View File

@ -40,6 +40,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.TypeCodec;
import com.datastax.driver.core.UserType;
import org.apache.cassandra.config.Config;
import org.apache.cassandra.config.DatabaseDescriptor;
@ -70,8 +71,8 @@ public abstract class UDFunction extends AbstractFunction implements ScalarFunct
protected final String language;
protected final String body;
protected final DataType[] argDataTypes;
protected final DataType returnDataType;
protected final TypeCodec<Object>[] argCodecs;
protected final TypeCodec<Object> returnCodec;
protected final boolean calledOnNullInput;
//
@ -202,8 +203,8 @@ public abstract class UDFunction extends AbstractFunction implements ScalarFunct
this.argNames = argNames;
this.language = language;
this.body = body;
this.argDataTypes = argDataTypes;
this.returnDataType = returnDataType;
this.argCodecs = UDHelper.codecsFor(argDataTypes);
this.returnCodec = UDHelper.codecFor(returnDataType);
this.calledOnNullInput = calledOnNullInput;
}
@ -306,8 +307,8 @@ public abstract class UDFunction extends AbstractFunction implements ScalarFunct
{
// Get the TypeCodec stuff in Java Driver initialized.
// This is to get the classes loaded outside of the restricted sandbox's security context of a UDF.
UDHelper.codecFor(DataType.inet()).format(InetAddress.getLoopbackAddress());
UDHelper.codecFor(DataType.ascii()).format("");
TypeCodec.inet().format(InetAddress.getLoopbackAddress());
TypeCodec.ascii().format("");
}
private static final class ThreadIdAndCpuTime extends CompletableFuture<Object>
@ -478,12 +479,12 @@ public abstract class UDFunction extends AbstractFunction implements ScalarFunct
*/
protected Object compose(int protocolVersion, int argIndex, ByteBuffer value)
{
return compose(argDataTypes, protocolVersion, argIndex, value);
return compose(argCodecs, protocolVersion, argIndex, value);
}
protected static Object compose(DataType[] argDataTypes, int protocolVersion, int argIndex, ByteBuffer value)
protected static Object compose(TypeCodec<Object>[] codecs, int protocolVersion, int argIndex, ByteBuffer value)
{
return value == null ? null : UDHelper.deserialize(argDataTypes[argIndex], protocolVersion, value);
return value == null ? null : UDHelper.deserialize(codecs[argIndex], protocolVersion, value);
}
/**
@ -495,12 +496,12 @@ public abstract class UDFunction extends AbstractFunction implements ScalarFunct
*/
protected ByteBuffer decompose(int protocolVersion, Object value)
{
return decompose(returnDataType, protocolVersion, value);
return decompose(returnCodec, protocolVersion, value);
}
protected static ByteBuffer decompose(DataType dataType, int protocolVersion, Object value)
protected static ByteBuffer decompose(TypeCodec<Object> codec, int protocolVersion, Object value)
{
return value == null ? null : UDHelper.serialize(dataType, protocolVersion, value);
return value == null ? null : UDHelper.serialize(codec, protocolVersion, value);
}
@Override
@ -528,9 +529,9 @@ public abstract class UDFunction extends AbstractFunction implements ScalarFunct
{
boolean updated = false;
for (int i = 0; i < argDataTypes.length; i++)
for (int i = 0; i < argCodecs.length; i++)
{
DataType dataType = argDataTypes[i];
DataType dataType = argCodecs[i].getCqlType();
if (dataType instanceof UserType)
{
UserType userType = (UserType) dataType;
@ -542,7 +543,7 @@ public abstract class UDFunction extends AbstractFunction implements ScalarFunct
org.apache.cassandra.db.marshal.UserType ut = ksm.types.get(ByteBufferUtil.bytes(typeName)).get();
DataType newUserType = UDHelper.driverType(ut);
argDataTypes[i] = newUserType;
argCodecs[i] = UDHelper.codecFor(newUserType);
argTypes.set(i, ut);

View File

@ -56,6 +56,14 @@ public final class UDHelper
}
}
static TypeCodec<Object>[] codecsFor(DataType[] dataType)
{
TypeCodec<Object>[] codecs = new TypeCodec[dataType.length];
for (int i = 0; i < dataType.length; i++)
codecs[i] = codecFor(dataType[i]);
return codecs;
}
static TypeCodec<Object> codecFor(DataType dataType)
{
return codecRegistry.codecFor(dataType);
@ -68,7 +76,7 @@ public final class UDHelper
* @param calledOnNullInput whether to allow {@code null} as an argument value
* @return array of same size with UDF arguments
*/
public static Class<?>[] javaTypes(DataType[] dataTypes, boolean calledOnNullInput)
public static Class<?>[] javaTypes(TypeCodec<Object>[] dataTypes, boolean calledOnNullInput)
{
Class<?>[] paramTypes = new Class[dataTypes.length];
for (int i = 0; i < paramTypes.length; i++)
@ -135,23 +143,22 @@ public final class UDHelper
}
}
public static Object deserialize(DataType dataType, int protocolVersion, ByteBuffer value)
public static Object deserialize(TypeCodec<?> codec, int protocolVersion, ByteBuffer value)
{
return codecFor(dataType).deserialize(value, ProtocolVersion.fromInt(protocolVersion));
return codec.deserialize(value, ProtocolVersion.fromInt(protocolVersion));
}
public static ByteBuffer serialize(DataType dataType, int protocolVersion, Object value)
public static ByteBuffer serialize(TypeCodec<?> codec, int protocolVersion, Object value)
{
TypeCodec<Object> codec = codecFor(dataType);
if (! codec.getJavaType().getRawType().isAssignableFrom(value.getClass()))
throw new InvalidTypeException("Invalid value for CQL type " + dataType.getName().toString());
if (!codec.getJavaType().getRawType().isAssignableFrom(value.getClass()))
throw new InvalidTypeException("Invalid value for CQL type " + codec.getCqlType().getName().toString());
return codec.serialize(value, ProtocolVersion.fromInt(protocolVersion));
return ((TypeCodec)codec).serialize(value, ProtocolVersion.fromInt(protocolVersion));
}
public static Class<?> asJavaClass(DataType dataType)
public static Class<?> asJavaClass(TypeCodec<?> codec)
{
return codecFor(dataType).getJavaType().getRawType();
return codec.getJavaType().getRawType();
}
public static boolean isNullOrEmpty(AbstractType<?> type, ByteBuffer bb)

View File

@ -5,13 +5,13 @@ import java.util.List;
import org.apache.cassandra.cql3.functions.JavaUDF;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.TypeCodec;
public final class #class_name# extends JavaUDF
{
public #class_name#(DataType returnDataType, DataType[] argDataTypes)
public #class_name#(TypeCodec<Object> returnCodec, TypeCodec<Object>[] argCodecs)
{
super(returnDataType, argDataTypes);
super(returnCodec, argCodecs);
}
protected ByteBuffer executeImpl(int protocolVersion, List<ByteBuffer> params)

View File

@ -17,7 +17,7 @@
under the License.
-->
<configuration debug="false">
<configuration debug="false" scan="true">
<!-- Shutdown hook ensures that async appender flushes -->
<shutdownHook class="ch.qos.logback.core.hook.DelayingShutdownHook"/>

View File

@ -21,7 +21,7 @@ package org.apache.cassandra.cql3.validation.entities.udfverify;
import java.nio.ByteBuffer;
import java.util.List;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.TypeCodec;
import org.apache.cassandra.cql3.functions.JavaUDF;
/**
@ -29,7 +29,7 @@ import org.apache.cassandra.cql3.functions.JavaUDF;
*/
public final class CallClone extends JavaUDF
{
public CallClone(DataType returnDataType, DataType[] argDataTypes)
public CallClone(TypeCodec<Object> returnDataType, TypeCodec<Object>[] argDataTypes)
{
super(returnDataType, argDataTypes);
}

View File

@ -22,7 +22,7 @@ import java.nio.ByteBuffer;
import java.util.List;
import com.datastax.driver.core.DataType;
import org.apache.cassandra.config.DatabaseDescriptor;
import com.datastax.driver.core.TypeCodec;
import org.apache.cassandra.cql3.functions.JavaUDF;
/**
@ -30,7 +30,7 @@ import org.apache.cassandra.cql3.functions.JavaUDF;
*/
public final class CallComDatastax extends JavaUDF
{
public CallComDatastax(DataType returnDataType, DataType[] argDataTypes)
public CallComDatastax(TypeCodec<Object> returnDataType, TypeCodec<Object>[] argDataTypes)
{
super(returnDataType, argDataTypes);
}

View File

@ -21,7 +21,7 @@ package org.apache.cassandra.cql3.validation.entities.udfverify;
import java.nio.ByteBuffer;
import java.util.List;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.TypeCodec;
import org.apache.cassandra.cql3.functions.JavaUDF;
/**
@ -29,7 +29,7 @@ import org.apache.cassandra.cql3.functions.JavaUDF;
*/
public final class CallFinalize extends JavaUDF
{
public CallFinalize(DataType returnDataType, DataType[] argDataTypes)
public CallFinalize(TypeCodec<Object> returnDataType, TypeCodec<Object>[] argDataTypes)
{
super(returnDataType, argDataTypes);
}

View File

@ -21,7 +21,7 @@ package org.apache.cassandra.cql3.validation.entities.udfverify;
import java.nio.ByteBuffer;
import java.util.List;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.TypeCodec;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.cql3.functions.JavaUDF;
@ -30,7 +30,7 @@ import org.apache.cassandra.cql3.functions.JavaUDF;
*/
public final class CallOrgApache extends JavaUDF
{
public CallOrgApache(DataType returnDataType, DataType[] argDataTypes)
public CallOrgApache(TypeCodec<Object> returnDataType, TypeCodec<Object>[] argDataTypes)
{
super(returnDataType, argDataTypes);
}

View File

@ -21,7 +21,7 @@ package org.apache.cassandra.cql3.validation.entities.udfverify;
import java.nio.ByteBuffer;
import java.util.List;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.TypeCodec;
import org.apache.cassandra.cql3.functions.JavaUDF;
/**
@ -29,7 +29,7 @@ import org.apache.cassandra.cql3.functions.JavaUDF;
*/
public final class ClassWithField extends JavaUDF
{
public ClassWithField(DataType returnDataType, DataType[] argDataTypes)
public ClassWithField(TypeCodec<Object> returnDataType, TypeCodec<Object>[] argDataTypes)
{
super(returnDataType, argDataTypes);
}

View File

@ -21,7 +21,7 @@ package org.apache.cassandra.cql3.validation.entities.udfverify;
import java.nio.ByteBuffer;
import java.util.List;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.TypeCodec;
import org.apache.cassandra.cql3.functions.JavaUDF;
/**
@ -29,7 +29,7 @@ import org.apache.cassandra.cql3.functions.JavaUDF;
*/
public final class ClassWithInitializer extends JavaUDF
{
public ClassWithInitializer(DataType returnDataType, DataType[] argDataTypes)
public ClassWithInitializer(TypeCodec<Object> returnDataType, TypeCodec<Object>[] argDataTypes)
{
super(returnDataType, argDataTypes);
}

View File

@ -21,7 +21,7 @@ package org.apache.cassandra.cql3.validation.entities.udfverify;
import java.nio.ByteBuffer;
import java.util.List;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.TypeCodec;
import org.apache.cassandra.cql3.functions.JavaUDF;
/**
@ -29,7 +29,7 @@ import org.apache.cassandra.cql3.functions.JavaUDF;
*/
public final class ClassWithInitializer2 extends JavaUDF
{
public ClassWithInitializer2(DataType returnDataType, DataType[] argDataTypes)
public ClassWithInitializer2(TypeCodec<Object> returnDataType, TypeCodec<Object>[] argDataTypes)
{
super(returnDataType, argDataTypes);
}

View File

@ -21,7 +21,7 @@ package org.apache.cassandra.cql3.validation.entities.udfverify;
import java.nio.ByteBuffer;
import java.util.List;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.TypeCodec;
import org.apache.cassandra.cql3.functions.JavaUDF;
/**
@ -29,7 +29,7 @@ import org.apache.cassandra.cql3.functions.JavaUDF;
*/
public final class ClassWithInitializer3 extends JavaUDF
{
public ClassWithInitializer3(DataType returnDataType, DataType[] argDataTypes)
public ClassWithInitializer3(TypeCodec<Object> returnDataType, TypeCodec<Object>[] argDataTypes)
{
super(returnDataType, argDataTypes);
}

View File

@ -21,7 +21,7 @@ package org.apache.cassandra.cql3.validation.entities.udfverify;
import java.nio.ByteBuffer;
import java.util.List;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.TypeCodec;
import org.apache.cassandra.cql3.functions.JavaUDF;
/**
@ -29,7 +29,7 @@ import org.apache.cassandra.cql3.functions.JavaUDF;
*/
public final class ClassWithStaticInitializer extends JavaUDF
{
public ClassWithStaticInitializer(DataType returnDataType, DataType[] argDataTypes)
public ClassWithStaticInitializer(TypeCodec<Object> returnDataType, TypeCodec<Object>[] argDataTypes)
{
super(returnDataType, argDataTypes);
}

View File

@ -21,7 +21,7 @@ package org.apache.cassandra.cql3.validation.entities.udfverify;
import java.nio.ByteBuffer;
import java.util.List;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.TypeCodec;
import org.apache.cassandra.cql3.functions.JavaUDF;
/**
@ -29,7 +29,7 @@ import org.apache.cassandra.cql3.functions.JavaUDF;
*/
public final class GoodClass extends JavaUDF
{
public GoodClass(DataType returnDataType, DataType[] argDataTypes)
public GoodClass(TypeCodec<Object> returnDataType, TypeCodec<Object>[] argDataTypes)
{
super(returnDataType, argDataTypes);
}

View File

@ -21,7 +21,7 @@ package org.apache.cassandra.cql3.validation.entities.udfverify;
import java.nio.ByteBuffer;
import java.util.List;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.TypeCodec;
import org.apache.cassandra.cql3.functions.JavaUDF;
/**
@ -29,7 +29,7 @@ import org.apache.cassandra.cql3.functions.JavaUDF;
*/
public final class UseOfSynchronized extends JavaUDF
{
public UseOfSynchronized(DataType returnDataType, DataType[] argDataTypes)
public UseOfSynchronized(TypeCodec<Object> returnDataType, TypeCodec<Object>[] argDataTypes)
{
super(returnDataType, argDataTypes);
}

View File

@ -21,7 +21,7 @@ package org.apache.cassandra.cql3.validation.entities.udfverify;
import java.nio.ByteBuffer;
import java.util.List;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.TypeCodec;
import org.apache.cassandra.cql3.functions.JavaUDF;
/**
@ -29,7 +29,7 @@ import org.apache.cassandra.cql3.functions.JavaUDF;
*/
public final class UseOfSynchronizedWithNotify extends JavaUDF
{
public UseOfSynchronizedWithNotify(DataType returnDataType, DataType[] argDataTypes)
public UseOfSynchronizedWithNotify(TypeCodec<Object> returnDataType, TypeCodec<Object>[] argDataTypes)
{
super(returnDataType, argDataTypes);
}

View File

@ -21,7 +21,7 @@ package org.apache.cassandra.cql3.validation.entities.udfverify;
import java.nio.ByteBuffer;
import java.util.List;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.TypeCodec;
import org.apache.cassandra.cql3.functions.JavaUDF;
/**
@ -29,7 +29,7 @@ import org.apache.cassandra.cql3.functions.JavaUDF;
*/
public final class UseOfSynchronizedWithNotifyAll extends JavaUDF
{
public UseOfSynchronizedWithNotifyAll(DataType returnDataType, DataType[] argDataTypes)
public UseOfSynchronizedWithNotifyAll(TypeCodec<Object> returnDataType, TypeCodec<Object>[] argDataTypes)
{
super(returnDataType, argDataTypes);
}

View File

@ -21,7 +21,7 @@ package org.apache.cassandra.cql3.validation.entities.udfverify;
import java.nio.ByteBuffer;
import java.util.List;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.TypeCodec;
import org.apache.cassandra.cql3.functions.JavaUDF;
/**
@ -29,7 +29,7 @@ import org.apache.cassandra.cql3.functions.JavaUDF;
*/
public final class UseOfSynchronizedWithWait extends JavaUDF
{
public UseOfSynchronizedWithWait(DataType returnDataType, DataType[] argDataTypes)
public UseOfSynchronizedWithWait(TypeCodec<Object> returnDataType, TypeCodec<Object>[] argDataTypes)
{
super(returnDataType, argDataTypes);
}

View File

@ -21,7 +21,7 @@ package org.apache.cassandra.cql3.validation.entities.udfverify;
import java.nio.ByteBuffer;
import java.util.List;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.TypeCodec;
import org.apache.cassandra.cql3.functions.JavaUDF;
/**
@ -29,7 +29,7 @@ import org.apache.cassandra.cql3.functions.JavaUDF;
*/
public final class UseOfSynchronizedWithWaitL extends JavaUDF
{
public UseOfSynchronizedWithWaitL(DataType returnDataType, DataType[] argDataTypes)
public UseOfSynchronizedWithWaitL(TypeCodec<Object> returnDataType, TypeCodec<Object>[] argDataTypes)
{
super(returnDataType, argDataTypes);
}

View File

@ -21,7 +21,7 @@ package org.apache.cassandra.cql3.validation.entities.udfverify;
import java.nio.ByteBuffer;
import java.util.List;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.TypeCodec;
import org.apache.cassandra.cql3.functions.JavaUDF;
/**
@ -29,7 +29,7 @@ import org.apache.cassandra.cql3.functions.JavaUDF;
*/
public final class UseOfSynchronizedWithWaitLI extends JavaUDF
{
public UseOfSynchronizedWithWaitLI(DataType returnDataType, DataType[] argDataTypes)
public UseOfSynchronizedWithWaitLI(TypeCodec<Object> returnDataType, TypeCodec<Object>[] argDataTypes)
{
super(returnDataType, argDataTypes);
}

View File

@ -22,12 +22,21 @@ import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import java.util.concurrent.ThreadLocalRandom;
import org.apache.commons.lang3.time.DateUtils;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ch.qos.logback.classic.LoggerContext;
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.config.Schema;
import org.apache.cassandra.cql3.CQLTester;
import org.apache.cassandra.cql3.QueryProcessor;
@ -1731,4 +1740,84 @@ public class AggregationTest extends CQLTester
execute("INSERT INTO %s (a, b) VALUES (3, 2)");
assertRows(execute("SELECT " + a + "(b) FROM %s"), row(Arrays.asList("1", "2")));
}
@Test
public void testLogbackReload() throws Throwable
{
// see https://issues.apache.org/jira/browse/CASSANDRA-11033
// make logback's scan interval 1ms - boilerplate, but necessary for this test
configureLogbackScanPeriod(1L);
try
{
createTable("CREATE TABLE %s (" +
" year int PRIMARY KEY," +
" 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 { };");
for (int i = 0; i < 1000; i++)
{
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.setRefreshPeriod(millis);
reconfigureFilter.stop();
reconfigureFilter.start(); // start() sets the next check timestammp
done = true;
break;
}
}
assertTrue("ReconfigureOnChangeFilter not in logback's turbo-filter list - do that by adding scan=\"true\" to logback-test.xml's configuration element", done);
}
}