extract code from DateIndexExtension to LongToDateBucket
Making it possible to reuse the code to sort timestamps into date based buckets.
This commit is contained in:
@@ -1,89 +1,28 @@
|
||||
package org.lucares.pdb.datastore.internal;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.ConcurrentNavigableMap;
|
||||
import java.util.concurrent.ConcurrentSkipListMap;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.lucares.pdb.api.DateTimeRange;
|
||||
import org.lucares.utils.LongToDateBucket;
|
||||
|
||||
public class DateIndexExtension {
|
||||
|
||||
/**
|
||||
* This date pattern defines the resolution of the date index
|
||||
*/
|
||||
private static final DateTimeFormatter DATE_PATTERN = DateTimeFormatter.ofPattern("yyyyMM");
|
||||
|
||||
// visible for test
|
||||
static final ConcurrentNavigableMap<Long, DatePrefixAndRange> DATE_PREFIX_CACHE = new ConcurrentSkipListMap<>();
|
||||
|
||||
private static final AtomicReference<DatePrefixAndRange> LAST_ACCESSED = new AtomicReference<>(null);
|
||||
private static final LongToDateBucket longToDateBucket = new LongToDateBucket("yyyyMM");
|
||||
|
||||
static Set<String> toDateIndexPrefix(final DateTimeRange dateRange) {
|
||||
final Set<String> result = new TreeSet<>();
|
||||
|
||||
OffsetDateTime current = dateRange.getStart();
|
||||
while (current.isBefore(dateRange.getEnd())) {
|
||||
|
||||
result.add(toDateIndexPrefix(current));
|
||||
current = current.plusMonths(1);
|
||||
|
||||
}
|
||||
result.add(toDateIndexPrefix(dateRange.getEnd()));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static String toDateIndexPrefix(final OffsetDateTime time) {
|
||||
return time.format(DATE_PATTERN);
|
||||
return longToDateBucket.toDateIndexPrefix(dateRange.getStart(), dateRange.getEnd());
|
||||
}
|
||||
|
||||
public static ParititionId toPartitionId(final long epochMilli) {
|
||||
String result;
|
||||
final DatePrefixAndRange lastAccessed = LAST_ACCESSED.get();
|
||||
if (lastAccessed != null && lastAccessed.getMinEpochMilli() <= epochMilli
|
||||
&& lastAccessed.getMaxEpochMilli() >= epochMilli) {
|
||||
result = lastAccessed.getDatePrefix();
|
||||
} else {
|
||||
final Entry<Long, DatePrefixAndRange> value = DATE_PREFIX_CACHE.floorEntry(epochMilli);
|
||||
|
||||
if (value == null || !value.getValue().contains(epochMilli)) {
|
||||
final DatePrefixAndRange newValue = toDatePrefixAndRange(epochMilli);
|
||||
DATE_PREFIX_CACHE.put(newValue.getMinEpochMilli(), newValue);
|
||||
result = newValue.getDatePrefix();
|
||||
LAST_ACCESSED.set(newValue);
|
||||
} else {
|
||||
result = value.getValue().getDatePrefix();
|
||||
LAST_ACCESSED.set(value.getValue());
|
||||
}
|
||||
}
|
||||
return new ParititionId(result);
|
||||
return new ParititionId(longToDateBucket.toPartitionId(epochMilli));
|
||||
}
|
||||
|
||||
public static String toDateIndexPrefix(final long epochMilli) {
|
||||
|
||||
final Entry<Long, DatePrefixAndRange> value = DATE_PREFIX_CACHE.floorEntry(epochMilli);
|
||||
|
||||
String result;
|
||||
if (value == null || !value.getValue().contains(epochMilli)) {
|
||||
final DatePrefixAndRange newValue = toDatePrefixAndRange(epochMilli);
|
||||
DATE_PREFIX_CACHE.put(newValue.getMinEpochMilli(), newValue);
|
||||
result = newValue.getDatePrefix();
|
||||
} else {
|
||||
result = value.getValue().getDatePrefix();
|
||||
}
|
||||
|
||||
return result;
|
||||
return longToDateBucket.toDateIndexPrefix(epochMilli);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -94,20 +33,12 @@ public class DateIndexExtension {
|
||||
* @return
|
||||
*/
|
||||
static List<ParititionId> toPartitionIds(final DateTimeRange dateRange) {
|
||||
final List<String> partitionIds = longToDateBucket.toPartitionIds(dateRange.getStart(), dateRange.getEnd());
|
||||
|
||||
final List<ParititionId> result = new ArrayList<>();
|
||||
|
||||
OffsetDateTime current = dateRange.getStart();
|
||||
final OffsetDateTime end = dateRange.getEnd();
|
||||
current = current.withOffsetSameInstant(ZoneOffset.UTC).withDayOfMonth(1).withHour(0).withMinute(0)
|
||||
.withSecond(0).withNano(0);
|
||||
|
||||
while (!current.isAfter(end)) {
|
||||
final String id = current.format(DATE_PATTERN);
|
||||
final ParititionId partitionId = new ParititionId(id);
|
||||
result.add(partitionId);
|
||||
current = current.plusMonths(1);
|
||||
for (final String partitionId : partitionIds) {
|
||||
result.add(new ParititionId(partitionId));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -127,70 +58,8 @@ public class DateIndexExtension {
|
||||
return result;
|
||||
}
|
||||
|
||||
public static DatePrefixAndRange toDatePrefixAndRange(final long epochMilli) {
|
||||
final OffsetDateTime date = Instant.ofEpochMilli(epochMilli).atOffset(ZoneOffset.UTC);
|
||||
final OffsetDateTime beginOfMonth = date.withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0).withNano(0);
|
||||
final OffsetDateTime endOfMonth = beginOfMonth.plusMonths(1).minusNanos(1);
|
||||
|
||||
final String datePrefix = date.format(DATE_PATTERN);
|
||||
final long minEpochMilli = beginOfMonth.toInstant().toEpochMilli();
|
||||
final long maxEpochMilli = endOfMonth.toInstant().toEpochMilli();
|
||||
|
||||
return new DatePrefixAndRange(datePrefix, minEpochMilli, maxEpochMilli);
|
||||
}
|
||||
|
||||
public static List<Long> toDateIndexEpochMillis(final DateTimeRange dateRange) {
|
||||
final List<Long> result = new ArrayList<>();
|
||||
|
||||
OffsetDateTime current = dateRange.getStart();
|
||||
final OffsetDateTime end = dateRange.getEnd();
|
||||
current = current.withOffsetSameInstant(ZoneOffset.UTC).withDayOfMonth(1).withHour(0).withMinute(0)
|
||||
.withSecond(0).withNano(0);
|
||||
|
||||
while (!current.isAfter(end)) {
|
||||
result.add(current.toInstant().toEpochMilli());
|
||||
current = current.plusMonths(1);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static ParititionId now() {
|
||||
return toPartitionId(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class DatePrefixAndRange {
|
||||
private final String datePrefix;
|
||||
private final long minEpochMilli;
|
||||
private final long maxEpochMilli;
|
||||
|
||||
public DatePrefixAndRange(final String datePrefix, final long minEpochMilli, final long maxEpochMilli) {
|
||||
super();
|
||||
this.datePrefix = datePrefix;
|
||||
this.minEpochMilli = minEpochMilli;
|
||||
this.maxEpochMilli = maxEpochMilli;
|
||||
}
|
||||
|
||||
public String getDatePrefix() {
|
||||
return datePrefix;
|
||||
}
|
||||
|
||||
public long getMinEpochMilli() {
|
||||
return minEpochMilli;
|
||||
}
|
||||
|
||||
public long getMaxEpochMilli() {
|
||||
return maxEpochMilli;
|
||||
}
|
||||
|
||||
public boolean contains(final long epochMilli) {
|
||||
return minEpochMilli <= epochMilli && epochMilli <= maxEpochMilli;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return datePrefix + " (" + minEpochMilli + " - " + maxEpochMilli + ")";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user