mirror of https://github.com/apache/cassandra
Merge branch 'cassandra-2.1' into trunk
This commit is contained in:
commit
8b49af0b74
|
|
@ -33,6 +33,7 @@
|
|||
* Use prepared statements internally (CASSANDRA-6975)
|
||||
* Fix broken paging state with prepared statement (CASSANDRA-7120)
|
||||
* Fix IllegalArgumentException in CqlStorage (CASSANDRA-7287)
|
||||
* Allow nulls/non-existant fields in UDT (CASSANDRA-7206)
|
||||
Merged from 2.0:
|
||||
* Always reallocate buffers in HSHA (CASSANDRA-6285)
|
||||
* (Hadoop) support authentication in CqlRecordReader (CASSANDRA-7221)
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ package org.apache.cassandra.cql3;
|
|||
import java.nio.ByteBuffer;
|
||||
import java.util.*;
|
||||
|
||||
import org.apache.cassandra.db.marshal.CompositeType;
|
||||
import org.apache.cassandra.db.marshal.UserType;
|
||||
import org.apache.cassandra.db.marshal.UTF8Type;
|
||||
import org.apache.cassandra.exceptions.InvalidRequestException;
|
||||
|
|
@ -59,7 +58,10 @@ public abstract class UserTypes
|
|||
for (int i = 0; i < ut.fieldTypes.size(); i++)
|
||||
{
|
||||
ColumnIdentifier field = new ColumnIdentifier(ut.fieldNames.get(i), UTF8Type.instance);
|
||||
Term value = entries.get(field).prepare(keyspace, fieldSpecOf(receiver, i));
|
||||
Term.Raw raw = entries.get(field);
|
||||
if (raw == null)
|
||||
raw = Constants.NULL_LITERAL;
|
||||
Term value = raw.prepare(keyspace, fieldSpecOf(receiver, i));
|
||||
|
||||
if (value instanceof Term.NonTerminal)
|
||||
allTerminal = false;
|
||||
|
|
@ -81,7 +83,7 @@ public abstract class UserTypes
|
|||
ColumnIdentifier field = new ColumnIdentifier(ut.fieldNames.get(i), UTF8Type.instance);
|
||||
Term.Raw value = entries.get(field);
|
||||
if (value == null)
|
||||
throw new InvalidRequestException(String.format("Invalid user type literal for %s: missing field %s", receiver, field));
|
||||
continue;
|
||||
|
||||
ColumnSpecification fieldSpec = fieldSpecOf(receiver, i);
|
||||
if (!value.isAssignableTo(keyspace, fieldSpec))
|
||||
|
|
@ -154,13 +156,7 @@ public abstract class UserTypes
|
|||
|
||||
ByteBuffer[] buffers = new ByteBuffer[values.size()];
|
||||
for (int i = 0; i < type.fieldTypes.size(); i++)
|
||||
{
|
||||
ByteBuffer buffer = values.get(i).bindAndGet(options);
|
||||
if (buffer == null)
|
||||
throw new InvalidRequestException("null is not supported inside user type literals");
|
||||
|
||||
buffers[i] = buffer;
|
||||
}
|
||||
buffers[i] = values.get(i).bindAndGet(options);
|
||||
return buffers;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -126,9 +126,10 @@ public class UserType extends AbstractType<ByteBuffer>
|
|||
throw new MarshalException(String.format("Not enough bytes to read size of %dth field %s", i, fieldNames.get(i)));
|
||||
|
||||
int size = input.getInt();
|
||||
// We don't handle null just yet, but we should fix that soon (CASSANDRA-7206)
|
||||
|
||||
// size < 0 means null value
|
||||
if (size < 0)
|
||||
throw new MarshalException("Nulls are not yet supported inside UDT values");
|
||||
continue;
|
||||
|
||||
if (input.remaining() < size)
|
||||
throw new MarshalException(String.format("Not enough bytes to read %dth field %s", i, fieldNames.get(i)));
|
||||
|
|
@ -164,13 +165,20 @@ public class UserType extends AbstractType<ByteBuffer>
|
|||
{
|
||||
int totalLength = 0;
|
||||
for (ByteBuffer field : fields)
|
||||
totalLength += 4 + field.remaining();
|
||||
totalLength += 4 + (field == null ? 0 : field.remaining());
|
||||
|
||||
ByteBuffer result = ByteBuffer.allocate(totalLength);
|
||||
for (ByteBuffer field : fields)
|
||||
{
|
||||
result.putInt(field.remaining());
|
||||
result.put(field.duplicate());
|
||||
if (field == null)
|
||||
{
|
||||
result.putInt(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.putInt(field.remaining());
|
||||
result.put(field.duplicate());
|
||||
}
|
||||
}
|
||||
result.rewind();
|
||||
return result;
|
||||
|
|
@ -191,11 +199,15 @@ public class UserType extends AbstractType<ByteBuffer>
|
|||
|
||||
AbstractType<?> type = fieldTypes.get(i);
|
||||
int size = input.getInt();
|
||||
assert size >= 0; // We don't support nulls yet, but we will likely do with #7206 and we'll need
|
||||
// a way to represent it as a string (without it conflicting with a user value)
|
||||
if (size < 0)
|
||||
{
|
||||
sb.append("@");
|
||||
continue;
|
||||
}
|
||||
|
||||
ByteBuffer field = ByteBufferUtil.readBytes(input, size);
|
||||
// We use ':' as delimiter so escape it if it's in the generated string
|
||||
sb.append(field == null ? "null" : type.getString(value).replaceAll(":", "\\\\:"));
|
||||
// We use ':' as delimiter, and @ to represent null, so escape them in the generated string
|
||||
sb.append(type.getString(field).replaceAll(":", "\\\\:").replaceAll("@", "\\\\@"));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
|
@ -207,10 +219,13 @@ public class UserType extends AbstractType<ByteBuffer>
|
|||
ByteBuffer[] fields = new ByteBuffer[fieldStrings.size()];
|
||||
for (int i = 0; i < fieldStrings.size(); i++)
|
||||
{
|
||||
String fieldString = fieldStrings.get(i);
|
||||
// We use @ to represent nulls
|
||||
if (fieldString.equals("@"))
|
||||
continue;
|
||||
|
||||
AbstractType<?> type = fieldTypes.get(i);
|
||||
// TODO: we'll need to handle null somehow here once we support them
|
||||
String fieldString = fieldStrings.get(i).replaceAll("\\\\:", ":");
|
||||
fields[i] = type.fromString(fieldString);
|
||||
fields[i] = type.fromString(fieldString.replaceAll("\\\\:", ":").replaceAll("\\\\@", "@"));
|
||||
}
|
||||
return buildValue(fields);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ import org.apache.cassandra.service.FileCacheService;
|
|||
|
||||
public class FileCacheMetrics
|
||||
{
|
||||
private static final MetricNameFactory factory = new DefaultNameFactory("FileCache");
|
||||
|
||||
/** Total number of hits */
|
||||
public final Meter hits;
|
||||
/** Total number of requests */
|
||||
|
|
@ -39,9 +41,9 @@ public class FileCacheMetrics
|
|||
|
||||
public FileCacheMetrics()
|
||||
{
|
||||
hits = Metrics.newMeter(new MetricName(FileCacheService.class, "Hits"), "hits", TimeUnit.SECONDS);
|
||||
requests = Metrics.newMeter(new MetricName(FileCacheService.class, "Requests"), "requests", TimeUnit.SECONDS);
|
||||
hitRate = Metrics.newGauge(new MetricName(FileCacheService.class, "HitRate"), new RatioGauge()
|
||||
hits = Metrics.newMeter(factory.createMetricName("Hits"), "hits", TimeUnit.SECONDS);
|
||||
requests = Metrics.newMeter(factory.createMetricName("Requests"), "requests", TimeUnit.SECONDS);
|
||||
hitRate = Metrics.newGauge(factory.createMetricName("HitRate"), new RatioGauge()
|
||||
{
|
||||
protected double getNumerator()
|
||||
{
|
||||
|
|
@ -53,7 +55,7 @@ public class FileCacheMetrics
|
|||
return requests.count();
|
||||
}
|
||||
});
|
||||
size = Metrics.newGauge(new MetricName(FileCacheService.class, "Size"), new Gauge<Long>()
|
||||
size = Metrics.newGauge(factory.createMetricName("Size"), new Gauge<Long>()
|
||||
{
|
||||
public Long value()
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue