in baremaps-openstreetmap/src/main/java/org/apache/baremaps/openstreetmap/state/StateReader.java [117:188]
public Optional<State> getStateFromTimestamp(LocalDateTime timestamp) {
var upper = getLatestState();
if (upper.isEmpty()) {
return Optional.empty();
}
if (timestamp.isAfter(upper.get().timestamp()) || upper.get().sequenceNumber() <= 0) {
return upper;
}
var lower = Optional.<State>empty();
var lowerId = 0L;
while (lower.isEmpty()) {
lower = getLatestState(lowerId);
if (lower.isPresent() && lower.get().timestamp().isAfter(timestamp)) {
if (lower.get().sequenceNumber() == 0
|| lower.get().sequenceNumber() + 1 >= upper.get().sequenceNumber()) {
return lower;
}
upper = lower;
lower = Optional.empty();
lowerId = 0L;
}
if (lower.isEmpty()) {
var newId = (lowerId + upper.get().sequenceNumber()) / 2;
if (newId <= lowerId) {
return upper;
}
lowerId = newId;
}
}
long baseSplitId;
while (true) {
if (balancedSearch) {
baseSplitId = ((lower.get().sequenceNumber() + upper.get().sequenceNumber()) / 2);
} else {
var tsInt = upper.get().timestamp().toEpochSecond(ZoneOffset.UTC)
- lower.get().timestamp().toEpochSecond(ZoneOffset.UTC);
var seqInt = upper.get().sequenceNumber() - lower.get().sequenceNumber();
var goal = timestamp.getSecond() - lower.get().timestamp().getSecond();
baseSplitId =
lower.get().sequenceNumber() + (long) Math.ceil((double) (goal * seqInt) / tsInt);
if (baseSplitId >= upper.get().sequenceNumber()) {
baseSplitId = upper.get().sequenceNumber() - 1;
}
}
var split = getLatestState(baseSplitId);
if (split.isEmpty()) {
var splitId = baseSplitId - 1;
while (split.isEmpty() && splitId > lower.get().sequenceNumber()) {
split = getLatestState(splitId);
splitId--;
}
}
if (split.isEmpty()) {
var splitId = baseSplitId + 1;
while (split.isEmpty() && splitId < upper.get().sequenceNumber()) {
split = getLatestState(splitId);
splitId++;
}
}
if (split.isEmpty()) {
return lower;
}
if (split.get().timestamp().isBefore(timestamp)) {
lower = split;
} else {
upper = split;
}
if (lower.get().sequenceNumber() + 1 >= upper.get().sequenceNumber()) {
return lower;
}
}
}