Remove joda time dependency.

Patch by Boris Tsikin, reviewed by brandonwilliams for CASSANDRA-15257
This commit is contained in:
Boris Tsirkin 2019-08-03 23:39:45 +02:00 committed by Brandon Williams
parent 9a280516ca
commit 2dbae87c78
9 changed files with 100 additions and 128 deletions

View File

@ -1,4 +1,5 @@
4.0-alpha3
* Remove joda time dependency (CASSANDRA-15257)
* Exclude purgeable tombstones from repaired data tracking (CASSANDRA-15462)
* Exclude legacy counter shards from repaired data tracking (CASSANDRA-15461)
* Make it easier to add trace headers to messages (CASSANDRA-15499)

View File

@ -576,7 +576,6 @@
<dependency groupId="org.fusesource" artifactId="sigar" version="1.6.4">
<exclusion groupId="log4j" artifactId="log4j"/>
</dependency>
<dependency groupId="joda-time" artifactId="joda-time" version="2.4" />
<dependency groupId="com.carrotsearch" artifactId="hppc" version="0.5.4" />
<dependency groupId="de.jflex" artifactId="jflex" version="1.6.0" />
<dependency groupId="com.github.rholder" artifactId="snowball-stemmer" version="1.3.0.581.1" />
@ -709,7 +708,6 @@
<parent groupId="org.apache.cassandra"
artifactId="cassandra-parent"
version="${version}"/>
<dependency groupId="joda-time" artifactId="joda-time"/>
</artifact:pom>
<!-- now the pom's for artifacts being deployed to Maven Central -->
@ -775,7 +773,6 @@
<dependency groupId="net.openhft" artifactId="chronicle-bytes" version="${chronicle-bytes.version}"/>
<dependency groupId="net.openhft" artifactId="chronicle-wire" version="${chronicle-wire.version}"/>
<dependency groupId="net.openhft" artifactId="chronicle-threads" version="${chronicle-threads.version}"/>
<dependency groupId="joda-time" artifactId="joda-time"/>
<dependency groupId="org.fusesource" artifactId="sigar"/>
<dependency groupId="org.eclipse.jdt.core.compiler" artifactId="ecj"/>
<dependency groupId="org.caffinitas.ohc" artifactId="ohc-core"/>

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -18,22 +18,26 @@
package org.apache.cassandra.serializers;
import java.nio.ByteBuffer;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.apache.cassandra.utils.ByteBufferUtil;
import static java.time.ZoneOffset.UTC;
import static java.time.format.ResolverStyle.STRICT;
// For byte-order comparability, we shift by Integer.MIN_VALUE and treat the data as an unsigned integer ranging from
// min date to max date w/epoch sitting in the center @ 2^31
public class SimpleDateSerializer implements TypeSerializer<Integer>
{
private static final DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd").withZone(DateTimeZone.UTC);
private static final DateTimeFormatter formatter =
DateTimeFormatter.ISO_LOCAL_DATE.withZone(UTC).withResolverStyle(STRICT);
private static final long minSupportedDateMillis = TimeUnit.DAYS.toMillis(Integer.MIN_VALUE);
private static final long maxSupportedDateMillis = TimeUnit.DAYS.toMillis(Integer.MAX_VALUE);
private static final long maxSupportedDays = (long)Math.pow(2,32) - 1;
@ -57,53 +61,57 @@ public class SimpleDateSerializer implements TypeSerializer<Integer>
// Raw day value in unsigned int form, epoch @ 2^31
if (rawPattern.matcher(source).matches())
{
try
{
long result = Long.parseLong(source);
if (result < 0 || result > maxSupportedDays)
throw new NumberFormatException("Input out of bounds: " + source);
// Shift > epoch days into negative portion of Integer result for byte order comparability
if (result >= Integer.MAX_VALUE)
result -= byteOrderShift;
return (int) result;
}
catch (NumberFormatException e)
{
throw new MarshalException(String.format("Unable to make unsigned int (for date) from: '%s'", source), e);
}
return parseRaw(source);
}
// Attempt to parse as date string
try
{
DateTime parsed = formatter.parseDateTime(source);
long millis = parsed.getMillis();
LocalDate parsed = formatter.parse(source, LocalDate::from);
long millis = parsed.atStartOfDay(UTC).toInstant().toEpochMilli();
if (millis < minSupportedDateMillis)
throw new MarshalException(String.format("Input date %s is less than min supported date %s", source, new LocalDate(minSupportedDateMillis).toString()));
throw new MarshalException(String.format("Input date %s is less than min supported date %s", source,
ZonedDateTime.ofInstant(Instant.ofEpochMilli(minSupportedDateMillis), UTC).toString()));
if (millis > maxSupportedDateMillis)
throw new MarshalException(String.format("Input date %s is greater than max supported date %s", source, new LocalDate(maxSupportedDateMillis).toString()));
throw new MarshalException(String.format("Input date %s is greater than max supported date %s", source,
ZonedDateTime.ofInstant(Instant.ofEpochMilli(maxSupportedDateMillis), UTC).toString()));
return timeInMillisToDay(millis);
}
catch (IllegalArgumentException e1)
catch (DateTimeParseException| ArithmeticException e1)
{
throw new MarshalException(String.format("Unable to coerce '%s' to a formatted date (long)", source), e1);
}
}
private static int parseRaw(String source) {
try
{
long result = Long.parseLong(source);
if (result < 0 || result > maxSupportedDays)
throw new NumberFormatException("Input out of bounds: " + source);
// Shift > epoch days into negative portion of Integer result for byte order comparability
if (result >= Integer.MAX_VALUE)
result -= byteOrderShift;
return (int) result;
}
catch (NumberFormatException | DateTimeParseException e)
{
throw new MarshalException(String.format("Unable to make unsigned int (for date) from: '%s'", source), e);
}
}
public static int timeInMillisToDay(long millis)
{
Integer result = (int) TimeUnit.MILLISECONDS.toDays(millis);
result -= Integer.MIN_VALUE;
return result;
return (int) (Duration.ofMillis(millis).toDays() - Integer.MIN_VALUE);
}
public static long dayToTimeInMillis(int days)
{
return TimeUnit.DAYS.toMillis(days - Integer.MIN_VALUE);
return Duration.ofDays(days + Integer.MIN_VALUE).toMillis();
}
public void validate(ByteBuffer bytes) throws MarshalException
@ -117,7 +125,7 @@ public class SimpleDateSerializer implements TypeSerializer<Integer>
if (value == null)
return "";
return formatter.print(new LocalDate(dayToTimeInMillis(value), DateTimeZone.UTC));
return Instant.ofEpochMilli(dayToTimeInMillis(value)).atZone(UTC).format(formatter);
}
public Class<Integer> getType()

View File

@ -21,6 +21,7 @@ import static org.apache.cassandra.tools.Util.BLUE;
import static org.apache.cassandra.tools.Util.CYAN;
import static org.apache.cassandra.tools.Util.RESET;
import static org.apache.cassandra.tools.Util.WHITE;
import static org.apache.commons.lang3.time.DurationFormatUtils.formatDurationWords;
import java.io.DataInputStream;
import java.io.File;
@ -70,10 +71,9 @@ import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
import org.joda.time.Duration;
import org.joda.time.format.PeriodFormat;
import com.google.common.collect.MinMaxPriorityQueue;
import org.apache.commons.lang3.time.DurationFormatUtils;
/**
* Shows the contents of sstable metadata
@ -143,7 +143,7 @@ public class SSTableMetadataViewer
{
return "never";
}
return PeriodFormat.getDefault().print(new Duration(unit.toMillis(duration)).toPeriod());
return formatDurationWords(unit.toMillis(duration), true, true);
}
public static String toByteString(long bytes)

View File

@ -19,14 +19,17 @@ package org.apache.cassandra.cql3.functions;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import org.apache.cassandra.cql3.CQLTester;
import org.apache.cassandra.serializers.SimpleDateSerializer;
import org.apache.cassandra.utils.UUIDGen;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;
import org.junit.Test;
public class CastFctsTest extends CQLTester
@ -217,25 +220,23 @@ public class CastFctsTest extends CQLTester
{
createTable("CREATE TABLE %s (a timeuuid primary key, b timestamp, c date, d time)");
DateTime dateTime = DateTimeFormat.forPattern("yyyy-MM-dd hh:mm:ss")
.withZone(DateTimeZone.UTC)
.parseDateTime("2015-05-21 11:03:02");
final String yearMonthDay = "2015-05-21";
final LocalDate localDate = LocalDate.of(2015, 5, 21);
ZonedDateTime date = localDate.atStartOfDay(ZoneOffset.UTC);
DateTime date = DateTimeFormat.forPattern("yyyy-MM-dd")
.withZone(DateTimeZone.UTC)
.parseDateTime("2015-05-21");
ZonedDateTime dateTime = ZonedDateTime.of(localDate, LocalTime.of(11,3,2), ZoneOffset.UTC);
long timeInMillis = dateTime.getMillis();
long timeInMillis = dateTime.toInstant().toEpochMilli();
execute("INSERT INTO %s (a, b, c, d) VALUES (?, '2015-05-21 11:03:02+00', '2015-05-21', '11:03:02')",
execute("INSERT INTO %s (a, b, c, d) VALUES (?, '" + yearMonthDay + " 11:03:02+00', '2015-05-21', '11:03:02')",
UUIDGen.getTimeUUID(timeInMillis));
assertRows(execute("SELECT CAST(a AS timestamp), " +
"CAST(b AS timestamp), " +
"CAST(c AS timestamp) FROM %s"),
row(new Date(dateTime.getMillis()), new Date(dateTime.getMillis()), new Date(date.getMillis())));
row(Date.from(dateTime.toInstant()), Date.from(dateTime.toInstant()), Date.from(date.toInstant())));
int timeInMillisToDay = SimpleDateSerializer.timeInMillisToDay(date.getMillis());
int timeInMillisToDay = SimpleDateSerializer.timeInMillisToDay(date.toInstant().toEpochMilli());
assertRows(execute("SELECT CAST(a AS date), " +
"CAST(b AS date), " +
"CAST(c AS date) FROM %s"),
@ -244,7 +245,7 @@ public class CastFctsTest extends CQLTester
assertRows(execute("SELECT CAST(b AS text), " +
"CAST(c AS text), " +
"CAST(d AS text) FROM %s"),
row("2015-05-21T11:03:02.000Z", "2015-05-21", "11:03:02.000000000"));
row(yearMonthDay + "T11:03:02.000Z", yearMonthDay, "11:03:02.000000000"));
}
@Test

View File

@ -18,7 +18,10 @@
package org.apache.cassandra.cql3.functions;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import org.junit.Test;
@ -30,9 +33,6 @@ import org.apache.cassandra.db.marshal.TimestampType;
import org.apache.cassandra.transport.ProtocolVersion;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.UUIDGen;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;
import static org.apache.cassandra.cql3.functions.TimeFcts.*;
import static org.junit.Assert.assertEquals;
@ -40,15 +40,21 @@ import static org.junit.Assert.assertNull;
public class TimeFctsTest
{
private static final LocalDate LOCAL_DATE = LocalDate.of(2019, 8, 3);
private static final ZonedDateTime DATE = LOCAL_DATE.atStartOfDay(ZoneOffset.UTC);
private static final LocalTime LOCAL_TIME = LocalTime.of(11, 3, 2);
private static final ZonedDateTime DATE_TIME =
ZonedDateTime.of(LOCAL_DATE, LOCAL_TIME, ZoneOffset.UTC);
private static final String DATE_STRING = DATE.format(DateTimeFormatter.ISO_LOCAL_DATE);
private static final String DATE_TIME_STRING =
DATE_STRING + " " + LOCAL_TIME.format(DateTimeFormatter.ISO_LOCAL_TIME);
@Test
public void testMinTimeUuid()
{
DateTime dateTime = DateTimeFormat.forPattern("yyyy-MM-dd hh:mm:ss")
.withZone(DateTimeZone.UTC)
.parseDateTime("2015-05-21 11:03:02");
long timeInMillis = dateTime.getMillis();
ByteBuffer input = TimestampType.instance.fromString("2015-05-21 11:03:02+00");
long timeInMillis = DATE_TIME.toInstant().toEpochMilli();
ByteBuffer input = TimestampType.instance.fromString(DATE_TIME_STRING + "+00");
ByteBuffer output = executeFunction(TimeFcts.minTimeuuidFct, input);
assertEquals(UUIDGen.minTimeUUID(timeInMillis), TimeUUIDType.instance.compose(output));
}
@ -56,12 +62,8 @@ public class TimeFctsTest
@Test
public void testMaxTimeUuid()
{
DateTime dateTime = DateTimeFormat.forPattern("yyyy-MM-dd hh:mm:ss")
.withZone(DateTimeZone.UTC)
.parseDateTime("2015-05-21 11:03:02");
long timeInMillis = dateTime.getMillis();
ByteBuffer input = TimestampType.instance.fromString("2015-05-21 11:03:02+00");
long timeInMillis = DATE_TIME.toInstant().toEpochMilli();
ByteBuffer input = TimestampType.instance.fromString(DATE_TIME_STRING + "+00");
ByteBuffer output = executeFunction(TimeFcts.maxTimeuuidFct, input);
assertEquals(UUIDGen.maxTimeUUID(timeInMillis), TimeUUIDType.instance.compose(output));
}
@ -69,37 +71,26 @@ public class TimeFctsTest
@Test
public void testDateOf()
{
DateTime dateTime = DateTimeFormat.forPattern("yyyy-MM-dd hh:mm:ss")
.withZone(DateTimeZone.UTC)
.parseDateTime("2015-05-21 11:03:02");
long timeInMillis = dateTime.getMillis();
long timeInMillis = DATE_TIME.toInstant().toEpochMilli();
ByteBuffer input = ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes(timeInMillis, 0));
ByteBuffer output = executeFunction(TimeFcts.dateOfFct, input);
assertEquals(dateTime.toDate(), TimestampType.instance.compose(output));
assertEquals(Date.from(DATE_TIME.toInstant()), TimestampType.instance.compose(output));
}
@Test
public void testTimeUuidToTimestamp()
{
DateTime dateTime = DateTimeFormat.forPattern("yyyy-MM-dd hh:mm:ss")
.withZone(DateTimeZone.UTC)
.parseDateTime("2015-05-21 11:03:02");
long timeInMillis = dateTime.getMillis();
long timeInMillis = DATE_TIME.toInstant().toEpochMilli();
ByteBuffer input = ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes(timeInMillis, 0));
ByteBuffer output = executeFunction(toTimestamp(TimeUUIDType.instance), input);
assertEquals(dateTime.toDate(), TimestampType.instance.compose(output));
assertEquals(Date.from(DATE_TIME.toInstant()), TimestampType.instance.compose(output));
}
@Test
public void testUnixTimestampOfFct()
{
DateTime dateTime = DateTimeFormat.forPattern("yyyy-MM-dd hh:mm:ss")
.withZone(DateTimeZone.UTC)
.parseDateTime("2015-05-21 11:03:02");
long timeInMillis = dateTime.getMillis();
long timeInMillis = DATE_TIME.toInstant().toEpochMilli();
ByteBuffer input = ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes(timeInMillis, 0));
ByteBuffer output = executeFunction(TimeFcts.unixTimestampOfFct, input);
assertEquals(timeInMillis, LongType.instance.compose(output).longValue());
@ -108,11 +99,7 @@ public class TimeFctsTest
@Test
public void testTimeUuidToUnixTimestamp()
{
DateTime dateTime = DateTimeFormat.forPattern("yyyy-MM-dd hh:mm:ss")
.withZone(DateTimeZone.UTC)
.parseDateTime("2015-05-21 11:03:02");
long timeInMillis = dateTime.getMillis();
long timeInMillis = DATE_TIME.toInstant().toEpochMilli();
ByteBuffer input = ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes(timeInMillis, 0));
ByteBuffer output = executeFunction(toUnixTimestamp(TimeUUIDType.instance), input);
assertEquals(timeInMillis, LongType.instance.compose(output).longValue());
@ -121,18 +108,11 @@ public class TimeFctsTest
@Test
public void testTimeUuidToDate()
{
DateTime dateTime = DateTimeFormat.forPattern("yyyy-MM-dd hh:mm:ss")
.withZone(DateTimeZone.UTC)
.parseDateTime("2015-05-21 11:03:02");
long timeInMillis = dateTime.getMillis();
long timeInMillis = DATE_TIME.toInstant().toEpochMilli();
ByteBuffer input = ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes(timeInMillis, 0));
ByteBuffer output = executeFunction(toDate(TimeUUIDType.instance), input);
long expectedTime = DateTimeFormat.forPattern("yyyy-MM-dd")
.withZone(DateTimeZone.UTC)
.parseDateTime("2015-05-21")
.getMillis();
long expectedTime = DATE.toInstant().toEpochMilli();
assertEquals(expectedTime, SimpleDateType.instance.toTimeInMillis(output));
}
@ -140,37 +120,25 @@ public class TimeFctsTest
@Test
public void testDateToTimestamp()
{
DateTime dateTime = DateTimeFormat.forPattern("yyyy-MM-dd")
.withZone(DateTimeZone.UTC)
.parseDateTime("2015-05-21");
ByteBuffer input = SimpleDateType.instance.fromString("2015-05-21");
ByteBuffer input = SimpleDateType.instance.fromString(DATE_STRING);
ByteBuffer output = executeFunction(toTimestamp(SimpleDateType.instance), input);
assertEquals(dateTime.toDate(), TimestampType.instance.compose(output));
assertEquals(Date.from(DATE.toInstant()), TimestampType.instance.compose(output));
}
@Test
public void testDateToUnixTimestamp()
{
DateTime dateTime = DateTimeFormat.forPattern("yyyy-MM-dd")
.withZone(DateTimeZone.UTC)
.parseDateTime("2015-05-21");
ByteBuffer input = SimpleDateType.instance.fromString("2015-05-21");
ByteBuffer input = SimpleDateType.instance.fromString(DATE_STRING);
ByteBuffer output = executeFunction(toUnixTimestamp(SimpleDateType.instance), input);
assertEquals(dateTime.getMillis(), LongType.instance.compose(output).longValue());
assertEquals(DATE.toInstant().toEpochMilli(), LongType.instance.compose(output).longValue());
}
@Test
public void testTimestampToDate()
{
DateTime dateTime = DateTimeFormat.forPattern("yyyy-MM-dd")
.withZone(DateTimeZone.UTC)
.parseDateTime("2015-05-21");
ByteBuffer input = TimestampType.instance.fromString("2015-05-21 11:03:02+00");
ByteBuffer input = TimestampType.instance.fromString(DATE_TIME_STRING + "+00");
ByteBuffer output = executeFunction(toDate(TimestampType.instance), input);
assertEquals(dateTime.getMillis(), SimpleDateType.instance.toTimeInMillis(output));
assertEquals(DATE.toInstant().toEpochMilli(), SimpleDateType.instance.toTimeInMillis(output));
}
@Test
@ -183,13 +151,9 @@ public class TimeFctsTest
@Test
public void testTimestampToUnixTimestamp()
{
DateTime dateTime = DateTimeFormat.forPattern("yyyy-MM-dd hh:mm:ss")
.withZone(DateTimeZone.UTC)
.parseDateTime("2015-05-21 11:03:02");
ByteBuffer input = TimestampType.instance.decompose(dateTime.toDate());
ByteBuffer input = TimestampType.instance.decompose(Date.from(DATE_TIME.toInstant()));
ByteBuffer output = executeFunction(toUnixTimestamp(TimestampType.instance), input);
assertEquals(dateTime.getMillis(), LongType.instance.compose(output).longValue());
assertEquals(DATE_TIME.toInstant().toEpochMilli(), LongType.instance.compose(output).longValue());
}
@Test
@ -201,7 +165,7 @@ public class TimeFctsTest
private static ByteBuffer executeFunction(Function function, ByteBuffer input)
{
List<ByteBuffer> params = Arrays.asList(input);
List<ByteBuffer> params = Collections.singletonList(input);
return ((ScalarFunction) function).execute(ProtocolVersion.CURRENT, params);
}
}

View File

@ -24,11 +24,12 @@ import org.junit.Test;
import java.nio.ByteBuffer;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.temporal.ChronoUnit;
import java.util.*;
public class SimpleDateSerializerTest
{
private static final long millisPerDay = 1000 * 60 * 60 * 24;
private static final long millisPerDay = ChronoUnit.DAYS.getDuration().toMillis();
private String dates[] = new String[]
{
@ -38,7 +39,7 @@ public class SimpleDateSerializerTest
"-0001-01-02",
"-5877521-01-02",
"2014-01-01",
"5881580-01-10",
"+5881580-01-10", // See java.time.format.SignStyle.EXCEEDS_PAD
"1920-12-01",
"1582-10-19"
};