Merge branch 'cassandra-2.1' into trunk

This commit is contained in:
Brandon Williams 2014-05-23 14:09:18 -05:00
commit 8b49af0b74
4 changed files with 40 additions and 26 deletions

View File

@ -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)

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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()
{