mirror of https://github.com/apache/cassandra
Merge branch 'cassandra-2.0' into cassandra-2.1
Conflicts: CHANGES.txt src/java/org/apache/cassandra/db/ColumnFamilyStore.java src/java/org/apache/cassandra/db/commitlog/CommitLogAllocator.java
This commit is contained in:
commit
e024a1cc2b
|
|
@ -58,6 +58,9 @@ Merged from 2.0:
|
|||
* Fix writetime/ttl functions for static columns (CASSANDRA-7081)
|
||||
* Suggest CTRL-C or semicolon after three blank lines in cqlsh (CASSANDRA-7142)
|
||||
* Fix 2ndary index queries with DESC clustering order (CASSANDRA-6950)
|
||||
* Invalid key cache entries on DROP (CASSANDRA-6525)
|
||||
* Fix flapping RecoveryManagerTest (CASSANDRA-7084)
|
||||
* Add missing iso8601 patterns for date strings (6973)
|
||||
Merged from 1.2:
|
||||
* Add Cloudstack snitch (CASSANDRA-7147)
|
||||
* Update system.peers correctly when relocating tokens (CASSANDRA-7126)
|
||||
|
|
|
|||
|
|
@ -373,6 +373,7 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean
|
|||
indexManager.invalidate();
|
||||
|
||||
CacheService.instance.invalidateRowCacheForCf(metadata.cfId);
|
||||
CacheService.instance.invalidateKeyCacheForCf(metadata.cfId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -53,43 +53,7 @@ public class DateType extends AbstractType<Date>
|
|||
if (source.isEmpty())
|
||||
return ByteBufferUtil.EMPTY_BYTE_BUFFER;
|
||||
|
||||
return ByteBufferUtil.bytes(dateStringToTimestamp(source));
|
||||
}
|
||||
|
||||
public static long dateStringToTimestamp(String source) throws MarshalException
|
||||
{
|
||||
long millis;
|
||||
|
||||
if (source.toLowerCase().equals("now"))
|
||||
{
|
||||
millis = System.currentTimeMillis();
|
||||
}
|
||||
// Milliseconds since epoch?
|
||||
else if (source.matches("^-?\\d+$"))
|
||||
{
|
||||
try
|
||||
{
|
||||
millis = Long.parseLong(source);
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
throw new MarshalException(String.format("unable to make long (for date) from: '%s'", source), e);
|
||||
}
|
||||
}
|
||||
// Last chance, attempt to parse as date-time string
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
millis = DateUtils.parseDateStrictly(source, TimestampSerializer.iso8601Patterns).getTime();
|
||||
}
|
||||
catch (ParseException e1)
|
||||
{
|
||||
throw new MarshalException(String.format("unable to coerce '%s' to a formatted date (long)", source), e1);
|
||||
}
|
||||
}
|
||||
|
||||
return millis;
|
||||
return ByteBufferUtil.bytes(TimestampSerializer.dateStringToTimestamp(source));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import org.apache.cassandra.cql3.CQL3Type;
|
|||
import org.apache.cassandra.serializers.TypeSerializer;
|
||||
import org.apache.cassandra.serializers.MarshalException;
|
||||
import org.apache.cassandra.serializers.TimeUUIDSerializer;
|
||||
import org.apache.cassandra.serializers.TimestampSerializer;
|
||||
import org.apache.cassandra.utils.ByteBufferUtil;
|
||||
import org.apache.cassandra.utils.UUIDGen;
|
||||
|
||||
|
|
@ -105,9 +106,10 @@ public class TimeUUIDType extends AbstractType<UUID>
|
|||
|
||||
if (uuid.version() != 1)
|
||||
throw new MarshalException("TimeUUID supports only version 1 UUIDs");
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
idBytes = ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes(DateType.dateStringToTimestamp(source)));
|
||||
idBytes = ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes(TimestampSerializer.dateStringToTimestamp(source)));
|
||||
}
|
||||
|
||||
return idBytes;
|
||||
|
|
|
|||
|
|
@ -18,9 +18,7 @@
|
|||
package org.apache.cassandra.db.marshal;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.text.ParseException;
|
||||
import java.util.Date;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
|
@ -29,7 +27,6 @@ import org.apache.cassandra.serializers.TypeSerializer;
|
|||
import org.apache.cassandra.serializers.MarshalException;
|
||||
import org.apache.cassandra.serializers.TimestampSerializer;
|
||||
import org.apache.cassandra.utils.ByteBufferUtil;
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
|
||||
/**
|
||||
* Type for date-time values.
|
||||
|
|
@ -44,8 +41,6 @@ public class TimestampType extends AbstractType<Date>
|
|||
|
||||
public static final TimestampType instance = new TimestampType();
|
||||
|
||||
private static final Pattern timestampPattern = Pattern.compile("^-?\\d+$");
|
||||
|
||||
private TimestampType() {} // singleton
|
||||
|
||||
public int compare(ByteBuffer o1, ByteBuffer o2)
|
||||
|
|
@ -59,43 +54,7 @@ public class TimestampType extends AbstractType<Date>
|
|||
if (source.isEmpty())
|
||||
return ByteBufferUtil.EMPTY_BYTE_BUFFER;
|
||||
|
||||
return ByteBufferUtil.bytes(dateStringToTimestamp(source));
|
||||
}
|
||||
|
||||
public static long dateStringToTimestamp(String source) throws MarshalException
|
||||
{
|
||||
long millis;
|
||||
|
||||
if (source.toLowerCase().equals("now"))
|
||||
{
|
||||
millis = System.currentTimeMillis();
|
||||
}
|
||||
// Milliseconds since epoch?
|
||||
else if (timestampPattern.matcher(source).matches())
|
||||
{
|
||||
try
|
||||
{
|
||||
millis = Long.parseLong(source);
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
throw new MarshalException(String.format("unable to make long (for date) from: '%s'", source), e);
|
||||
}
|
||||
}
|
||||
// Last chance, attempt to parse as date-time string
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
millis = DateUtils.parseDateStrictly(source, TimestampSerializer.iso8601Patterns).getTime();
|
||||
}
|
||||
catch (ParseException e1)
|
||||
{
|
||||
throw new MarshalException(String.format("unable to coerce '%s' to a formatted date (long)", source), e1);
|
||||
}
|
||||
}
|
||||
|
||||
return millis;
|
||||
return ByteBufferUtil.bytes(TimestampSerializer.dateStringToTimestamp(source));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -26,12 +26,11 @@ import org.apache.cassandra.cql3.CQL3Type;
|
|||
import org.apache.cassandra.serializers.TypeSerializer;
|
||||
import org.apache.cassandra.serializers.MarshalException;
|
||||
import org.apache.cassandra.serializers.UUIDSerializer;
|
||||
import org.apache.cassandra.serializers.TimestampSerializer;
|
||||
import org.apache.cassandra.utils.ByteBufferUtil;
|
||||
import org.apache.cassandra.utils.UUIDGen;
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
|
||||
import static org.apache.cassandra.serializers.TimestampSerializer.iso8601Patterns;
|
||||
|
||||
/**
|
||||
* Compares UUIDs using the following criteria:<br>
|
||||
* - if count of supplied bytes is less than 16, compare counts<br>
|
||||
|
|
@ -165,8 +164,6 @@ public class UUIDType extends AbstractType<UUID>
|
|||
if (source.isEmpty())
|
||||
return ByteBufferUtil.EMPTY_BYTE_BUFFER;
|
||||
|
||||
ByteBuffer idBytes = null;
|
||||
|
||||
// ffffffff-ffff-ffff-ffff-ffffffffff
|
||||
if (TimeUUIDType.regexPattern.matcher(source).matches())
|
||||
{
|
||||
|
|
@ -174,43 +171,22 @@ public class UUIDType extends AbstractType<UUID>
|
|||
try
|
||||
{
|
||||
uuid = UUID.fromString(source);
|
||||
idBytes = ByteBuffer.wrap(UUIDGen.decompose(uuid));
|
||||
return ByteBuffer.wrap(UUIDGen.decompose(uuid));
|
||||
}
|
||||
catch (IllegalArgumentException e)
|
||||
{
|
||||
throw new MarshalException(String.format("unable to make UUID from '%s'", source), e);
|
||||
}
|
||||
} else if (source.toLowerCase().equals("now"))
|
||||
{
|
||||
idBytes = ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes());
|
||||
}
|
||||
// Milliseconds since epoch?
|
||||
else if (source.matches("^\\d+$"))
|
||||
{
|
||||
try
|
||||
{
|
||||
idBytes = ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes(Long.parseLong(source)));
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
throw new MarshalException(String.format("unable to make version 1 UUID from '%s'", source), e);
|
||||
}
|
||||
}
|
||||
// Last chance, attempt to parse as date-time string
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
long timestamp = DateUtils.parseDate(source, iso8601Patterns).getTime();
|
||||
idBytes = ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes(timestamp));
|
||||
}
|
||||
catch (ParseException e1)
|
||||
{
|
||||
throw new MarshalException(String.format("unable to coerce '%s' to version 1 UUID", source), e1);
|
||||
}
|
||||
}
|
||||
|
||||
return idBytes;
|
||||
try
|
||||
{
|
||||
return ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes(TimestampSerializer.dateStringToTimestamp(source)));
|
||||
}
|
||||
catch (MarshalException e)
|
||||
{
|
||||
throw new MarshalException(String.format("unable to make version 1 UUID from '%s'", source), e);
|
||||
}
|
||||
}
|
||||
|
||||
public CQL3Type asCQL3Type()
|
||||
|
|
|
|||
|
|
@ -21,30 +21,49 @@ import org.apache.cassandra.utils.ByteBufferUtil;
|
|||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.util.Date;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
|
||||
public class TimestampSerializer implements TypeSerializer<Date>
|
||||
{
|
||||
public static final String[] iso8601Patterns = new String[] {
|
||||
private static final String[] dateStringPatterns = new String[] {
|
||||
"yyyy-MM-dd HH:mm",
|
||||
"yyyy-MM-dd HH:mm:ss",
|
||||
"yyyy-MM-dd HH:mmZ",
|
||||
"yyyy-MM-dd HH:mm:ssZ",
|
||||
"yyyy-MM-dd HH:mmX",
|
||||
"yyyy-MM-dd HH:mmXX",
|
||||
"yyyy-MM-dd HH:mmXXX",
|
||||
"yyyy-MM-dd HH:mm:ssX",
|
||||
"yyyy-MM-dd HH:mm:ssXX",
|
||||
"yyyy-MM-dd HH:mm:ssXXX",
|
||||
"yyyy-MM-dd HH:mm:ss.SSS",
|
||||
"yyyy-MM-dd HH:mm:ss.SSSZ",
|
||||
"yyyy-MM-dd HH:mm:ss.SSSX",
|
||||
"yyyy-MM-dd HH:mm:ss.SSSXX",
|
||||
"yyyy-MM-dd HH:mm:ss.SSSXXX",
|
||||
"yyyy-MM-dd'T'HH:mm",
|
||||
"yyyy-MM-dd'T'HH:mmZ",
|
||||
"yyyy-MM-dd'T'HH:mmX",
|
||||
"yyyy-MM-dd'T'HH:mmXX",
|
||||
"yyyy-MM-dd'T'HH:mmXXX",
|
||||
"yyyy-MM-dd'T'HH:mm:ss",
|
||||
"yyyy-MM-dd'T'HH:mm:ssZ",
|
||||
"yyyy-MM-dd'T'HH:mm:ssX",
|
||||
"yyyy-MM-dd'T'HH:mm:ssXX",
|
||||
"yyyy-MM-dd'T'HH:mm:ssXXX",
|
||||
"yyyy-MM-dd'T'HH:mm:ss.SSS",
|
||||
"yyyy-MM-dd'T'HH:mm:ss.SSSZ",
|
||||
"yyyy-MM-dd'T'HH:mm:ss.SSSX",
|
||||
"yyyy-MM-dd'T'HH:mm:ss.SSSXX",
|
||||
"yyyy-MM-dd'T'HH:mm:ss.SSSXXX",
|
||||
"yyyy-MM-dd",
|
||||
"yyyy-MM-ddZ"
|
||||
"yyyy-MM-ddX",
|
||||
"yyyy-MM-ddXX",
|
||||
"yyyy-MM-ddXXX"
|
||||
};
|
||||
|
||||
static final String DEFAULT_FORMAT = iso8601Patterns[3];
|
||||
private static final String DEFAULT_FORMAT = dateStringPatterns[3];
|
||||
private static final Pattern timestampPattern = Pattern.compile("^-?\\d+$");
|
||||
|
||||
static final ThreadLocal<SimpleDateFormat> FORMATTER = new ThreadLocal<SimpleDateFormat>()
|
||||
private static final ThreadLocal<SimpleDateFormat> FORMATTER = new ThreadLocal<SimpleDateFormat>()
|
||||
{
|
||||
protected SimpleDateFormat initialValue()
|
||||
{
|
||||
|
|
@ -64,6 +83,35 @@ public class TimestampSerializer implements TypeSerializer<Date>
|
|||
return value == null ? ByteBufferUtil.EMPTY_BYTE_BUFFER : ByteBufferUtil.bytes(value.getTime());
|
||||
}
|
||||
|
||||
public static long dateStringToTimestamp(String source) throws MarshalException
|
||||
{
|
||||
if (source.equalsIgnoreCase("now"))
|
||||
return System.currentTimeMillis();
|
||||
|
||||
// Milliseconds since epoch?
|
||||
if (timestampPattern.matcher(source).matches())
|
||||
{
|
||||
try
|
||||
{
|
||||
return Long.parseLong(source);
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
throw new MarshalException(String.format("unable to make long (for date) from: '%s'", source), e);
|
||||
}
|
||||
}
|
||||
|
||||
// Last chance, attempt to parse as date-time string
|
||||
try
|
||||
{
|
||||
return DateUtils.parseDateStrictly(source, dateStringPatterns).getTime();
|
||||
}
|
||||
catch (ParseException e1)
|
||||
{
|
||||
throw new MarshalException(String.format("unable to coerce '%s' to a formatted date (long)", source), e1);
|
||||
}
|
||||
}
|
||||
|
||||
public void validate(ByteBuffer bytes) throws MarshalException
|
||||
{
|
||||
if (bytes.remaining() != 8 && bytes.remaining() != 0)
|
||||
|
|
|
|||
|
|
@ -283,6 +283,17 @@ public class CacheService implements CacheServiceMBean
|
|||
keyCache.clear();
|
||||
}
|
||||
|
||||
public void invalidateKeyCacheForCf(UUID cfId)
|
||||
{
|
||||
Iterator<KeyCacheKey> keyCacheIterator = keyCache.getKeySet().iterator();
|
||||
while (keyCacheIterator.hasNext())
|
||||
{
|
||||
KeyCacheKey key = keyCacheIterator.next();
|
||||
if (key.cfId.equals(cfId))
|
||||
keyCacheIterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public void invalidateRowCache()
|
||||
{
|
||||
rowCache.clear();
|
||||
|
|
|
|||
|
|
@ -22,9 +22,11 @@ import java.io.IOException;
|
|||
import java.util.Date;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.cassandra.OrderedJUnit4ClassRunner;
|
||||
import org.apache.cassandra.Util;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.apache.cassandra.SchemaLoader;
|
||||
import org.apache.cassandra.db.commitlog.CommitLog;
|
||||
|
|
@ -34,6 +36,7 @@ import static org.apache.cassandra.Util.column;
|
|||
import static org.apache.cassandra.db.KeyspaceTest.assertColumns;
|
||||
import static org.apache.cassandra.Util.cellname;
|
||||
|
||||
@RunWith(OrderedJUnit4ClassRunner.class)
|
||||
public class RecoveryManagerTest extends SchemaLoader
|
||||
{
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -0,0 +1,77 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.cassandra.serializers;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.apache.cassandra.serializers.MarshalException;
|
||||
import org.apache.cassandra.serializers.TimestampSerializer;
|
||||
|
||||
public class TimestampSerializerTest
|
||||
{
|
||||
private String dates[] = new String[]
|
||||
{
|
||||
"2014-04-01",
|
||||
"2014-04-01+0000",
|
||||
"2014-04-01 20:30",
|
||||
"2014-04-01 20:30:35",
|
||||
"2014-04-01 20:30:35Z",
|
||||
"2014-04-01 20:30+07",
|
||||
"2014-04-01 20:30+0700",
|
||||
"2014-04-01 20:30+07:00",
|
||||
"2014-04-01 20:30:35+07",
|
||||
"2014-04-01 20:30:35+0700",
|
||||
"2014-04-01 20:30:35+07:00",
|
||||
"2014-04-01 20:30:35.898",
|
||||
"2014-04-01 20:30:35.898Z",
|
||||
"2014-04-01 20:30:35.898+07",
|
||||
"2014-04-01 20:30:35.898+0700",
|
||||
"2014-04-01 20:30:35.898+07:00",
|
||||
"2014-04-01T20:30",
|
||||
"2014-04-01T20:30:25",
|
||||
"2014-04-01T20:30:35Z",
|
||||
"2014-04-01T20:30:35+00:00",
|
||||
"2014-04-01T20:30:35+0700",
|
||||
"2014-04-01T20:30:35+07:00",
|
||||
"2014-04-01T20:30:35.898",
|
||||
"2014-04-01T20:30:35.898+00:00"
|
||||
};
|
||||
|
||||
@Test
|
||||
public void testDateStringToTimestamp()
|
||||
{
|
||||
List<String> unparsedDates = new ArrayList<>();
|
||||
for (String date: dates)
|
||||
{
|
||||
try
|
||||
{
|
||||
long millis = TimestampSerializer.dateStringToTimestamp(date);
|
||||
}
|
||||
catch (MarshalException e)
|
||||
{
|
||||
unparsedDates.add(date);
|
||||
}
|
||||
}
|
||||
assertTrue("Unable to parse: " + unparsedDates, unparsedDates.isEmpty());
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue