Refactor CacheDataSource

Simplified and clarified the code.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=180649983
This commit is contained in:
eguven 2018-01-03 02:46:59 -08:00 committed by Oliver Woodman
parent bf3d6028fa
commit d3ba207a4b

View file

@ -97,7 +97,7 @@ public final class CacheDataSource implements DataSource {
private final boolean ignoreCacheForUnsetLengthRequests; private final boolean ignoreCacheForUnsetLengthRequests;
private DataSource currentDataSource; private DataSource currentDataSource;
private boolean currentRequestUnbounded; private boolean readingUnknownLengthDataFromUpstream;
private Uri uri; private Uri uri;
private int flags; private int flags;
private String key; private String key;
@ -202,7 +202,7 @@ public final class CacheDataSource implements DataSource {
} }
} }
} }
openNextSource(true); openNextSource();
return bytesRemaining; return bytesRemaining;
} catch (IOException e) { } catch (IOException e) {
handleBeforeThrow(e); handleBeforeThrow(e);
@ -229,15 +229,21 @@ public final class CacheDataSource implements DataSource {
bytesRemaining -= bytesRead; bytesRemaining -= bytesRead;
} }
} else { } else {
if (currentRequestUnbounded) { if (readingUnknownLengthDataFromUpstream) {
// We only do unbounded requests to upstream and only when we don't know the actual stream setCurrentDataSourceBytesRemaining(0);
// length. So we reached the end of stream.
setContentLength(readPosition);
bytesRemaining = 0;
} }
closeCurrentSource(); closeCurrentSource();
if (bytesRemaining > 0 || bytesRemaining == C.LENGTH_UNSET) { if (bytesRemaining > 0 || bytesRemaining == C.LENGTH_UNSET) {
if (openNextSource(false)) { try {
openNextSource();
} catch (IOException e) {
if (readingUnknownLengthDataFromUpstream && isCausedByPositionOutOfRange(e)) {
setCurrentDataSourceBytesRemaining(0);
} else {
throw e;
}
}
if (bytesRemaining != 0) {
return read(buffer, offset, readLength); return read(buffer, offset, readLength);
} }
} }
@ -270,9 +276,8 @@ public final class CacheDataSource implements DataSource {
* Opens the next source. If the cache contains data spanning the current read position then * Opens the next source. If the cache contains data spanning the current read position then
* {@link #cacheReadDataSource} is opened to read from it. Else {@link #upstreamDataSource} is * {@link #cacheReadDataSource} is opened to read from it. Else {@link #upstreamDataSource} is
* opened to read from the upstream source and write into the cache. * opened to read from the upstream source and write into the cache.
* @param initial Whether it is the initial open call.
*/ */
private boolean openNextSource(boolean initial) throws IOException { private void openNextSource() throws IOException {
DataSpec dataSpec; DataSpec dataSpec;
CacheSpan span; CacheSpan span;
if (currentRequestIgnoresCache) { if (currentRequestIgnoresCache) {
@ -323,48 +328,38 @@ public final class CacheDataSource implements DataSource {
} }
} }
currentRequestUnbounded = dataSpec.length == C.LENGTH_UNSET; // If the request is unbounded it must be an upstream request.
boolean successful = false; readingUnknownLengthDataFromUpstream = dataSpec.length == C.LENGTH_UNSET;
long currentBytesRemaining = 0;
try {
currentBytesRemaining = currentDataSource.open(dataSpec);
successful = true;
} catch (IOException e) {
// if this isn't the initial open call (we had read some bytes) and an unbounded range request
// failed because of POSITION_OUT_OF_RANGE then mute the exception. We are trying to find the
// end of the stream.
if (!initial && currentRequestUnbounded) {
Throwable cause = e;
while (cause != null) {
if (cause instanceof DataSourceException) {
int reason = ((DataSourceException) cause).reason;
if (reason == DataSourceException.POSITION_OUT_OF_RANGE) {
e = null;
break;
}
}
cause = cause.getCause();
}
}
if (e != null) {
throw e;
}
}
// If we did an unbounded request (which means it's to upstream and long resolvedLength = currentDataSource.open(dataSpec);
// bytesRemaining == C.LENGTH_UNSET) and got a resolved length from open() request if (readingUnknownLengthDataFromUpstream && resolvedLength != C.LENGTH_UNSET) {
if (currentRequestUnbounded && currentBytesRemaining != C.LENGTH_UNSET) { setCurrentDataSourceBytesRemaining(resolvedLength);
bytesRemaining = currentBytesRemaining;
setContentLength(dataSpec.position + bytesRemaining);
} }
return successful;
} }
private void setContentLength(long length) throws IOException { private static boolean isCausedByPositionOutOfRange(IOException e) {
// If writing into cache Throwable cause = e;
if (currentDataSource == cacheWriteDataSource) { while (cause != null) {
cache.setContentLength(key, length); if (cause instanceof DataSourceException) {
int reason = ((DataSourceException) cause).reason;
if (reason == DataSourceException.POSITION_OUT_OF_RANGE) {
return true;
}
}
cause = cause.getCause();
} }
return false;
}
private void setCurrentDataSourceBytesRemaining(long bytesRemaining) throws IOException {
this.bytesRemaining = bytesRemaining;
if (isWritingToCache()) {
cache.setContentLength(key, readPosition + bytesRemaining);
}
}
private boolean isWritingToCache() {
return currentDataSource == cacheWriteDataSource;
} }
private void closeCurrentSource() throws IOException { private void closeCurrentSource() throws IOException {
@ -374,7 +369,7 @@ public final class CacheDataSource implements DataSource {
try { try {
currentDataSource.close(); currentDataSource.close();
currentDataSource = null; currentDataSource = null;
currentRequestUnbounded = false; readingUnknownLengthDataFromUpstream = false;
} finally { } finally {
if (lockedSpan != null) { if (lockedSpan != null) {
cache.releaseHoleSpan(lockedSpan); cache.releaseHoleSpan(lockedSpan);