mirror of
https://github.com/samsonjs/media.git
synced 2026-03-27 09:45:47 +00:00
Fix bug when caching from non-zero position
The position should be subtracted from the total content length retrieved from the cache in this case, both for iteration and for filling out counters.contentLength (for the latter, note not doing it this way is inconsistent with what happens when dataSpec length is set to a known value). PiperOrigin-RevId: 242445034
This commit is contained in:
parent
0daaba443c
commit
66e416b615
2 changed files with 64 additions and 33 deletions
|
|
@ -95,17 +95,21 @@ public final class CacheUtil {
|
|||
@Nullable CacheKeyFactory cacheKeyFactory,
|
||||
CachingCounters counters) {
|
||||
String key = buildCacheKey(dataSpec, cacheKeyFactory);
|
||||
long start = dataSpec.absoluteStreamPosition;
|
||||
long left =
|
||||
dataSpec.length != C.LENGTH_UNSET
|
||||
? dataSpec.length
|
||||
: ContentMetadata.getContentLength(cache.getContentMetadata(key));
|
||||
counters.contentLength = left;
|
||||
long position = dataSpec.absoluteStreamPosition;
|
||||
long bytesLeft;
|
||||
if (dataSpec.length != C.LENGTH_UNSET) {
|
||||
bytesLeft = dataSpec.length;
|
||||
} else {
|
||||
long contentLength = ContentMetadata.getContentLength(cache.getContentMetadata(key));
|
||||
bytesLeft = contentLength == C.LENGTH_UNSET ? C.LENGTH_UNSET : contentLength - position;
|
||||
}
|
||||
counters.contentLength = bytesLeft;
|
||||
counters.alreadyCachedBytes = 0;
|
||||
counters.newlyCachedBytes = 0;
|
||||
while (left != 0) {
|
||||
while (bytesLeft != 0) {
|
||||
long blockLength =
|
||||
cache.getCachedLength(key, start, left != C.LENGTH_UNSET ? left : Long.MAX_VALUE);
|
||||
cache.getCachedLength(
|
||||
key, position, bytesLeft != C.LENGTH_UNSET ? bytesLeft : Long.MAX_VALUE);
|
||||
if (blockLength > 0) {
|
||||
counters.alreadyCachedBytes += blockLength;
|
||||
} else {
|
||||
|
|
@ -114,8 +118,8 @@ public final class CacheUtil {
|
|||
return;
|
||||
}
|
||||
}
|
||||
start += blockLength;
|
||||
left -= left == C.LENGTH_UNSET ? 0 : blockLength;
|
||||
position += blockLength;
|
||||
bytesLeft -= bytesLeft == C.LENGTH_UNSET ? 0 : blockLength;
|
||||
}
|
||||
counters.updatePercentage();
|
||||
}
|
||||
|
|
@ -203,15 +207,19 @@ public final class CacheUtil {
|
|||
}
|
||||
|
||||
String key = buildCacheKey(dataSpec, cacheKeyFactory);
|
||||
long start = dataSpec.absoluteStreamPosition;
|
||||
long left =
|
||||
dataSpec.length != C.LENGTH_UNSET
|
||||
? dataSpec.length
|
||||
: ContentMetadata.getContentLength(cache.getContentMetadata(key));
|
||||
while (left != 0) {
|
||||
long position = dataSpec.absoluteStreamPosition;
|
||||
long bytesLeft;
|
||||
if (dataSpec.length != C.LENGTH_UNSET) {
|
||||
bytesLeft = dataSpec.length;
|
||||
} else {
|
||||
long contentLength = ContentMetadata.getContentLength(cache.getContentMetadata(key));
|
||||
bytesLeft = contentLength == C.LENGTH_UNSET ? C.LENGTH_UNSET : contentLength - position;
|
||||
}
|
||||
while (bytesLeft != 0) {
|
||||
throwExceptionIfInterruptedOrCancelled(isCanceled);
|
||||
long blockLength =
|
||||
cache.getCachedLength(key, start, left != C.LENGTH_UNSET ? left : Long.MAX_VALUE);
|
||||
cache.getCachedLength(
|
||||
key, position, bytesLeft != C.LENGTH_UNSET ? bytesLeft : Long.MAX_VALUE);
|
||||
if (blockLength > 0) {
|
||||
// Skip already cached data.
|
||||
} else {
|
||||
|
|
@ -220,7 +228,7 @@ public final class CacheUtil {
|
|||
long read =
|
||||
readAndDiscard(
|
||||
dataSpec,
|
||||
start,
|
||||
position,
|
||||
blockLength,
|
||||
dataSource,
|
||||
buffer,
|
||||
|
|
@ -230,14 +238,14 @@ public final class CacheUtil {
|
|||
isCanceled);
|
||||
if (read < blockLength) {
|
||||
// Reached to the end of the data.
|
||||
if (enableEOFException && left != C.LENGTH_UNSET) {
|
||||
if (enableEOFException && bytesLeft != C.LENGTH_UNSET) {
|
||||
throw new EOFException();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
start += blockLength;
|
||||
left -= left == C.LENGTH_UNSET ? 0 : blockLength;
|
||||
position += blockLength;
|
||||
bytesLeft -= bytesLeft == C.LENGTH_UNSET ? 0 : blockLength;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -269,6 +277,7 @@ public final class CacheUtil {
|
|||
CachingCounters counters,
|
||||
AtomicBoolean isCanceled)
|
||||
throws IOException, InterruptedException {
|
||||
long positionOffset = absoluteStreamPosition - dataSpec.absoluteStreamPosition;
|
||||
while (true) {
|
||||
if (priorityTaskManager != null) {
|
||||
// Wait for any other thread with higher priority to finish its job.
|
||||
|
|
@ -284,31 +293,35 @@ public final class CacheUtil {
|
|||
dataSpec.httpMethod,
|
||||
dataSpec.httpBody,
|
||||
absoluteStreamPosition,
|
||||
dataSpec.position + absoluteStreamPosition - dataSpec.absoluteStreamPosition,
|
||||
/* position= */ dataSpec.position + positionOffset,
|
||||
C.LENGTH_UNSET,
|
||||
dataSpec.key,
|
||||
dataSpec.flags);
|
||||
long resolvedLength = dataSource.open(dataSpec);
|
||||
if (counters.contentLength == C.LENGTH_UNSET && resolvedLength != C.LENGTH_UNSET) {
|
||||
counters.contentLength = dataSpec.absoluteStreamPosition + resolvedLength;
|
||||
counters.contentLength = positionOffset + resolvedLength;
|
||||
}
|
||||
long totalRead = 0;
|
||||
while (totalRead != length) {
|
||||
long totalBytesRead = 0;
|
||||
while (totalBytesRead != length) {
|
||||
throwExceptionIfInterruptedOrCancelled(isCanceled);
|
||||
int read = dataSource.read(buffer, 0,
|
||||
length != C.LENGTH_UNSET ? (int) Math.min(buffer.length, length - totalRead)
|
||||
: buffer.length);
|
||||
if (read == C.RESULT_END_OF_INPUT) {
|
||||
int bytesRead =
|
||||
dataSource.read(
|
||||
buffer,
|
||||
0,
|
||||
length != C.LENGTH_UNSET
|
||||
? (int) Math.min(buffer.length, length - totalBytesRead)
|
||||
: buffer.length);
|
||||
if (bytesRead == C.RESULT_END_OF_INPUT) {
|
||||
if (counters.contentLength == C.LENGTH_UNSET) {
|
||||
counters.contentLength = dataSpec.absoluteStreamPosition + totalRead;
|
||||
counters.contentLength = positionOffset + totalBytesRead;
|
||||
}
|
||||
break;
|
||||
}
|
||||
totalRead += read;
|
||||
counters.newlyCachedBytes += read;
|
||||
totalBytesRead += bytesRead;
|
||||
counters.newlyCachedBytes += bytesRead;
|
||||
counters.updatePercentage();
|
||||
}
|
||||
return totalRead;
|
||||
return totalBytesRead;
|
||||
} catch (PriorityTaskManager.PriorityTooLowException exception) {
|
||||
// catch and try again
|
||||
} finally {
|
||||
|
|
|
|||
|
|
@ -176,6 +176,24 @@ public final class CacheUtilTest {
|
|||
assertCounters(counters, 300, 0, 1000);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCachedFromNonZeroPosition() throws Exception {
|
||||
mockCache.contentLength = 1000;
|
||||
mockCache.spansAndGaps = new int[] {100, 100, 200};
|
||||
CachingCounters counters = new CachingCounters();
|
||||
CacheUtil.getCached(
|
||||
new DataSpec(
|
||||
Uri.parse("test"),
|
||||
/* absoluteStreamPosition= */ 100,
|
||||
/* length= */ C.LENGTH_UNSET,
|
||||
/* key= */ null),
|
||||
mockCache,
|
||||
/* cacheKeyFactory= */ null,
|
||||
counters);
|
||||
|
||||
assertCounters(counters, 200, 0, 900);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCache() throws Exception {
|
||||
FakeDataSet fakeDataSet = new FakeDataSet().setRandomData("test_data", 100);
|
||||
|
|
|
|||
Loading…
Reference in a new issue