Skip to content

Commit 8411182

Browse files
Simplify range calculations in searchable snapshots (#96154)
We had the same complicated logic for calculating the write range in two places and then once more in stateless. We can just do a proper method that computes the complete write range and also do away with all the complexity of the default range calculations in the other use cases of the computeRange method by inlining the relevant logic. -> much clearer why the math is the way it is and some code saved IMO.
1 parent 63c8a68 commit 8411182

File tree

5 files changed

+27
-53
lines changed

5 files changed

+27
-53
lines changed

x-pack/plugin/blob-cache/src/main/java/org/elasticsearch/blobcache/BlobCacheUtils.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,11 @@ public static void ensureSeek(long pos, IndexInput input) throws IOException {
4444
}
4545
}
4646

47-
public static ByteRange computeRange(long rangeSize, long position, long length) {
48-
long start = (position / rangeSize) * rangeSize;
49-
long end = Math.min(start + rangeSize, length);
50-
return ByteRange.of(start, end);
47+
public static ByteRange computeRange(long rangeSize, long position, long size, long blobLength) {
48+
return ByteRange.of(
49+
(position / rangeSize) * rangeSize,
50+
Math.min((((position + size - 1) / rangeSize) + 1) * rangeSize, blobLength)
51+
);
5152
}
5253

5354
public static void ensureSlice(String sliceName, long sliceOffset, long sliceLength, IndexInput input) {

x-pack/plugin/blob-cache/src/main/java/org/elasticsearch/blobcache/common/ByteRange.java

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77

88
package org.elasticsearch.blobcache.common;
99

10-
import org.elasticsearch.core.Nullable;
11-
1210
public final class ByteRange implements Comparable<ByteRange> {
1311

1412
public static final ByteRange EMPTY = new ByteRange(0L, 0L);
@@ -28,24 +26,6 @@ private ByteRange(long start, long end) {
2826
assert end >= start : "End must be greater or equal to start but saw [" + start + "][" + start + "]";
2927
}
3028

31-
/**
32-
* Computes the smallest range that contains both this instance as well as the given {@code other} range.
33-
*
34-
* @param other other range or {@code null} in which case this instance is returned
35-
*/
36-
public ByteRange minEnvelope(@Nullable ByteRange other) {
37-
if (other == null) {
38-
return this;
39-
}
40-
if (other.isSubRangeOf(this)) {
41-
return this;
42-
}
43-
if (this.isSubRangeOf(other)) {
44-
return other;
45-
}
46-
return of(Math.min(start, other.start), Math.max(end, other.end));
47-
}
48-
4929
public long start() {
5030
return start;
5131
}

x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/xpack/searchablesnapshots/store/input/CachedBlobContainerIndexInput.java

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import org.apache.logging.log4j.LogManager;
1111
import org.apache.logging.log4j.Logger;
1212
import org.apache.lucene.store.IOContext;
13+
import org.elasticsearch.blobcache.BlobCacheUtils;
1314
import org.elasticsearch.blobcache.common.ByteRange;
1415
import org.elasticsearch.index.snapshots.blobstore.BlobStoreIndexShardSnapshot.FileInfo;
1516
import org.elasticsearch.xpack.searchablesnapshots.cache.common.CacheFile;
@@ -98,13 +99,6 @@ private CachedBlobContainerIndexInput(
9899
);
99100
}
100101

101-
@Override
102-
protected long getDefaultRangeSize() {
103-
return (context != CACHE_WARMING_CONTEXT) ? (directory.isRecoveryFinalized() ? defaultRangeSize : recoveryRangeSize)
104-
: fileInfo.numberOfParts() == 1 ? Long.MAX_VALUE
105-
: fileInfo.partSize().getBytes();
106-
}
107-
108102
@Override
109103
protected void readWithoutBlobCache(ByteBuffer b) throws Exception {
110104
ensureContext(ctx -> ctx != CACHE_WARMING_CONTEXT);
@@ -113,11 +107,12 @@ protected void readWithoutBlobCache(ByteBuffer b) throws Exception {
113107

114108
final CacheFile cacheFile = cacheFileReference.get();
115109

116-
final ByteRange startRangeToWrite = computeRange(position);
117-
final ByteRange endRangeToWrite = computeRange(position + length - 1);
118-
assert startRangeToWrite.end() <= endRangeToWrite.end() : startRangeToWrite + " vs " + endRangeToWrite;
119-
final ByteRange rangeToWrite = startRangeToWrite.minEnvelope(endRangeToWrite);
120-
110+
final ByteRange rangeToWrite = BlobCacheUtils.computeRange(
111+
directory.isRecoveryFinalized() ? defaultRangeSize : recoveryRangeSize,
112+
position,
113+
length,
114+
fileInfo.length()
115+
);
121116
final ByteRange rangeToRead = ByteRange.of(position, position + length);
122117
assert rangeToRead.isSubRangeOf(rangeToWrite) : rangeToRead + " vs " + rangeToWrite;
123118
assert rangeToRead.length() == b.remaining() : b.remaining() + " vs " + rangeToRead;
@@ -144,7 +139,14 @@ public long prefetchPart(final int part, Supplier<Boolean> isCancelled) throws I
144139
if (isCancelled.get()) {
145140
return -1L;
146141
}
147-
final ByteRange partRange = computeRange(IntStream.range(0, part).mapToLong(fileInfo::partBytes).sum());
142+
final ByteRange partRange;
143+
if (fileInfo.numberOfParts() == 1) {
144+
partRange = ByteRange.of(0, fileInfo.length());
145+
} else {
146+
long rangeSize = fileInfo.partSize().getBytes();
147+
long rangeStart = (IntStream.range(0, part).mapToLong(fileInfo::partBytes).sum() / rangeSize) * rangeSize;
148+
partRange = ByteRange.of(rangeStart, Math.min(rangeStart + rangeSize, fileInfo.length()));
149+
}
148150
assert assertRangeIsAlignedWithPart(partRange);
149151

150152
try {

x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/xpack/searchablesnapshots/store/input/FrozenIndexInput.java

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import org.apache.logging.log4j.LogManager;
1111
import org.apache.logging.log4j.Logger;
1212
import org.apache.lucene.store.IOContext;
13+
import org.elasticsearch.blobcache.BlobCacheUtils;
1314
import org.elasticsearch.blobcache.common.ByteBufferReference;
1415
import org.elasticsearch.blobcache.common.ByteRange;
1516
import org.elasticsearch.blobcache.shared.SharedBlobCacheService;
@@ -93,11 +94,6 @@ private FrozenIndexInput(
9394
this.cacheFile = cacheFile;
9495
}
9596

96-
@Override
97-
protected long getDefaultRangeSize() {
98-
return directory.isRecoveryFinalized() ? defaultRangeSize : recoveryRangeSize;
99-
}
100-
10197
@Override
10298
protected void readWithoutBlobCache(ByteBuffer b) throws Exception {
10399
final long position = getAbsolutePosition();
@@ -108,11 +104,12 @@ protected void readWithoutBlobCache(ByteBuffer b) throws Exception {
108104
final ByteBufferReference byteBufferReference = new ByteBufferReference(b);
109105
logger.trace("readInternal: read [{}-{}] from [{}]", position, position + length, this);
110106
try {
111-
final ByteRange startRangeToWrite = computeRange(position);
112-
final ByteRange endRangeToWrite = computeRange(position + length - 1);
113-
assert startRangeToWrite.end() <= endRangeToWrite.end() : startRangeToWrite + " vs " + endRangeToWrite;
114-
final ByteRange rangeToWrite = startRangeToWrite.minEnvelope(endRangeToWrite);
115-
107+
final ByteRange rangeToWrite = BlobCacheUtils.computeRange(
108+
directory.isRecoveryFinalized() ? defaultRangeSize : recoveryRangeSize,
109+
position,
110+
length,
111+
fileInfo.length()
112+
);
116113
assert rangeToWrite.start() <= position && position + length <= rangeToWrite.end()
117114
: "[" + position + "-" + (position + length) + "] vs " + rangeToWrite;
118115
final ByteRange rangeToRead = ByteRange.of(position, position + length);

x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/xpack/searchablesnapshots/store/input/MetadataCachingIndexInput.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -370,12 +370,6 @@ protected int readDirectlyIfAlreadyClosed(long position, ByteBuffer b, Exception
370370
throw new IOException("failed to read data from cache", e);
371371
}
372372

373-
protected abstract long getDefaultRangeSize();
374-
375-
protected ByteRange computeRange(long position) {
376-
return BlobCacheUtils.computeRange(getDefaultRangeSize(), position, fileInfo.length());
377-
}
378-
379373
@Override
380374
protected void seekInternal(long pos) throws IOException {
381375
BlobCacheUtils.ensureSeek(pos, this);

0 commit comments

Comments
 (0)