introduce index clustering (part 1)
In order to prevent files from getting too big and make it easier to implement retention policies, we are splitting all files into chunks. Each chunk contains the data for a time interval (1 month per default). This first changeset introduces the ClusteredPersistentMap that implements this for PersistentMap. It is used for a couple (not all) of indices.
This commit is contained in:
100
pdb-api/src/main/java/org/lucares/pdb/api/DateTimeRange.java
Normal file
100
pdb-api/src/main/java/org/lucares/pdb/api/DateTimeRange.java
Normal file
@@ -0,0 +1,100 @@
|
||||
package org.lucares.pdb.api;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.time.temporal.TemporalUnit;
|
||||
|
||||
public class DateTimeRange {
|
||||
|
||||
private final OffsetDateTime start;
|
||||
private final OffsetDateTime end;
|
||||
|
||||
public DateTimeRange(final OffsetDateTime start, final OffsetDateTime end) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
public static DateTimeRange relative(final long amount, final TemporalUnit unit) {
|
||||
return new DateTimeRange(OffsetDateTime.now().minus(amount, unit), OffsetDateTime.now());
|
||||
}
|
||||
|
||||
public static DateTimeRange relativeMillis(final long amount) {
|
||||
return relative(amount, ChronoUnit.MILLIS);
|
||||
}
|
||||
|
||||
public static DateTimeRange relativeSeconds(final long amount) {
|
||||
return relative(amount, ChronoUnit.SECONDS);
|
||||
}
|
||||
|
||||
public static DateTimeRange relativeMinutes(final long amount) {
|
||||
return relative(amount, ChronoUnit.MINUTES);
|
||||
}
|
||||
|
||||
public static DateTimeRange relativeHours(final long amount) {
|
||||
return relative(amount, ChronoUnit.HOURS);
|
||||
}
|
||||
|
||||
public static DateTimeRange relativeDays(final long amount) {
|
||||
return relative(amount, ChronoUnit.DAYS);
|
||||
}
|
||||
|
||||
public static DateTimeRange relativeMonths(final long amount) {
|
||||
return relative(amount, ChronoUnit.MONTHS);
|
||||
}
|
||||
|
||||
public static DateTimeRange relativeYears(final long amount) {
|
||||
return relative(amount, ChronoUnit.YEARS);
|
||||
}
|
||||
|
||||
public OffsetDateTime getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public long getStartEpochMilli() {
|
||||
return start.toInstant().toEpochMilli();
|
||||
}
|
||||
|
||||
public OffsetDateTime getEnd() {
|
||||
return end;
|
||||
}
|
||||
|
||||
public long getEndEpochMilli() {
|
||||
return end.toInstant().toEpochMilli();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return start + "-" + end;
|
||||
}
|
||||
|
||||
public static DateTimeRange ofDay(final OffsetDateTime day) {
|
||||
final OffsetDateTime from = day.truncatedTo(ChronoUnit.DAYS);
|
||||
final OffsetDateTime to = from.plusDays(1).minusNanos(1);
|
||||
|
||||
return new DateTimeRange(from, to);
|
||||
}
|
||||
|
||||
public Duration duration() {
|
||||
return Duration.between(start, end);
|
||||
}
|
||||
|
||||
public boolean inRange(final long epochMilli) {
|
||||
final long fromEpochMilli = start.toInstant().toEpochMilli();
|
||||
final long toEpochMilli = end.toInstant().toEpochMilli();
|
||||
|
||||
return fromEpochMilli <= epochMilli && epochMilli <= toEpochMilli;
|
||||
}
|
||||
|
||||
public boolean inRange(final OffsetDateTime date) {
|
||||
return start.compareTo(date) <= 0 && end.compareTo(date) >= 0;
|
||||
}
|
||||
|
||||
public boolean intersect(final DateTimeRange timeRange) {
|
||||
return inRange(timeRange.start) //
|
||||
|| inRange(timeRange.end) //
|
||||
|| timeRange.inRange(start)//
|
||||
|| timeRange.inRange(end);
|
||||
}
|
||||
|
||||
}
|
||||
77
pdb-api/src/main/java/org/lucares/pdb/api/Query.java
Normal file
77
pdb-api/src/main/java/org/lucares/pdb/api/Query.java
Normal file
@@ -0,0 +1,77 @@
|
||||
package org.lucares.pdb.api;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Query {
|
||||
private final String query;
|
||||
|
||||
private final DateTimeRange dateRange;
|
||||
|
||||
public Query(final String query, final DateTimeRange dateRange) {
|
||||
super();
|
||||
this.query = query;
|
||||
this.dateRange = dateRange;
|
||||
}
|
||||
|
||||
public Query relativeMillis(final String query, final long amount) {
|
||||
return new Query(query, DateTimeRange.relativeMillis(amount));
|
||||
}
|
||||
|
||||
public Query relativeSeconds(final String query, final long amount) {
|
||||
return new Query(query, DateTimeRange.relativeSeconds(amount));
|
||||
}
|
||||
|
||||
public Query relativeMinutes(final String query, final long amount) {
|
||||
return new Query(query, DateTimeRange.relativeMinutes(amount));
|
||||
}
|
||||
|
||||
public Query relativeHours(final String query, final long amount) {
|
||||
return new Query(query, DateTimeRange.relativeHours(amount));
|
||||
}
|
||||
|
||||
public Query relativeDays(final String query, final long amount) {
|
||||
return new Query(query, DateTimeRange.relativeDays(amount));
|
||||
}
|
||||
|
||||
public Query relativeMonths(final String query, final long amount) {
|
||||
return new Query(query, DateTimeRange.relativeMonths(amount));
|
||||
}
|
||||
|
||||
public static Query createQuery(final String query, final DateTimeRange dateRange) {
|
||||
return new Query(query, dateRange);
|
||||
}
|
||||
|
||||
public static Query createQuery(final Tags tags, final DateTimeRange dateRange) {
|
||||
|
||||
final List<String> terms = new ArrayList<>();
|
||||
|
||||
for (final String key : tags.getKeys()) {
|
||||
final String value = tags.getValue(key);
|
||||
|
||||
final StringBuilder term = new StringBuilder();
|
||||
term.append(key);
|
||||
term.append("=");
|
||||
term.append(value);
|
||||
term.append(" ");
|
||||
|
||||
terms.add(term.toString());
|
||||
}
|
||||
|
||||
return new Query(String.join(" and ", terms), dateRange);
|
||||
}
|
||||
|
||||
public String getQuery() {
|
||||
return query;
|
||||
}
|
||||
|
||||
public DateTimeRange getDateRange() {
|
||||
return dateRange;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "'" + query + "' [" + dateRange + "]";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package org.lucares.pdb.api;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
public class DateTimeRangeTest {
|
||||
@DataProvider
|
||||
Object[][] providerIntersect() {
|
||||
final List<Object[]> result = new ArrayList<>();
|
||||
|
||||
final OffsetDateTime a = Instant.ofEpochMilli(1000).atOffset(ZoneOffset.UTC);
|
||||
final OffsetDateTime b = Instant.ofEpochMilli(2000).atOffset(ZoneOffset.UTC);
|
||||
final OffsetDateTime c = Instant.ofEpochMilli(3000).atOffset(ZoneOffset.UTC);
|
||||
final OffsetDateTime d = Instant.ofEpochMilli(4000).atOffset(ZoneOffset.UTC);
|
||||
|
||||
result.add(new Object[] { new DateTimeRange(a, b), new DateTimeRange(c, d), false });
|
||||
result.add(new Object[] { new DateTimeRange(a, c), new DateTimeRange(b, d), true });
|
||||
result.add(new Object[] { new DateTimeRange(a, d), new DateTimeRange(b, d), true });
|
||||
result.add(new Object[] { new DateTimeRange(a, d), new DateTimeRange(b, d), true });
|
||||
result.add(new Object[] { new DateTimeRange(a, b), new DateTimeRange(b, d), true });
|
||||
|
||||
return result.toArray(new Object[result.size()][]);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "providerIntersect")
|
||||
public void testIntersect(final DateTimeRange a, final DateTimeRange b, final boolean expected) throws Exception {
|
||||
Assert.assertEquals(a.intersect(b), expected, a + " intersects " + b);
|
||||
Assert.assertEquals(b.intersect(a), expected, a + " intersects " + b);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user