From 1fc250a9f3c877bb2704096c7848f9687bc15847 Mon Sep 17 00:00:00 2001 From: eguven Date: Wed, 10 Jan 2018 02:51:40 -0800 Subject: [PATCH] Make CacheUtil documentation clearer Also fixed some other Cache related javadoc. Issue: #3374 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=181440687 --- .../exoplayer2/upstream/cache/Cache.java | 34 +++++++---- .../upstream/cache/CacheDataSink.java | 2 +- .../exoplayer2/upstream/cache/CacheUtil.java | 14 +++-- .../upstream/cache/CachedContent.java | 2 +- .../upstream/cache/SimpleCache.java | 6 +- .../upstream/cache/SimpleCacheSpan.java | 59 +++++++++++++++++-- .../upstream/cache/CacheAsserts.java | 22 ++++++- .../upstream/cache/CacheUtilTest.java | 2 +- .../upstream/cache/SimpleCacheTest.java | 16 ++--- .../exoplayer2/testutil/CacheAsserts.java | 22 ++++++- 10 files changed, 138 insertions(+), 41 deletions(-) diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/Cache.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/Cache.java index 76481bbdf7..171aa0878a 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/Cache.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/Cache.java @@ -127,23 +127,24 @@ public interface Cache { /** * A caller should invoke this method when they require data from a given position for a given * key. - *

- * If there is a cache entry that overlaps the position, then the returned {@link CacheSpan} + * + *

If there is a cache entry that overlaps the position, then the returned {@link CacheSpan} * defines the file in which the data is stored. {@link CacheSpan#isCached} is true. The caller * may read from the cache file, but does not acquire any locks. - *

- * If there is no cache entry overlapping {@code offset}, then the returned {@link CacheSpan} + * + *

If there is no cache entry overlapping {@code offset}, then the returned {@link CacheSpan} * defines a hole in the cache starting at {@code position} into which the caller may write as it * obtains the data from some other source. The returned {@link CacheSpan} serves as a lock. * Whilst the caller holds the lock it may write data into the hole. It may split data into - * multiple files. When the caller has finished writing a file it should commit it to the cache - * by calling {@link #commitFile(File)}. When the caller has finished writing, it must release - * the lock by calling {@link #releaseHoleSpan}. + * multiple files. When the caller has finished writing a file it should commit it to the cache by + * calling {@link #commitFile(File)}. When the caller has finished writing, it must release the + * lock by calling {@link #releaseHoleSpan}. * * @param key The key of the data being requested. * @param position The position of the data being requested. * @return The {@link CacheSpan}. * @throws InterruptedException If the thread was interrupted. + * @throws CacheException If an error is encountered. */ CacheSpan startReadWrite(String key, long position) throws InterruptedException, CacheException; @@ -154,8 +155,10 @@ public interface Cache { * @param key The key of the data being requested. * @param position The position of the data being requested. * @return The {@link CacheSpan}. Or null if the cache entry is locked. + * @throws CacheException If an error is encountered. */ - @Nullable CacheSpan startReadWriteNonBlocking(String key, long position) throws CacheException; + @Nullable + CacheSpan startReadWriteNonBlocking(String key, long position) throws CacheException; /** * Obtains a cache file into which data can be written. Must only be called when holding a @@ -166,14 +169,16 @@ public interface Cache { * @param maxLength The maximum length of the data to be written. Used only to ensure that there * is enough space in the cache. * @return The file into which data should be written. + * @throws CacheException If an error is encountered. */ File startFile(String key, long position, long maxLength) throws CacheException; /** - * Commits a file into the cache. Must only be called when holding a corresponding hole - * {@link CacheSpan} obtained from {@link #startReadWrite(String, long)} + * Commits a file into the cache. Must only be called when holding a corresponding hole {@link + * CacheSpan} obtained from {@link #startReadWrite(String, long)} * * @param file A newly written cache file. + * @throws CacheException If an error is encountered. */ void commitFile(File file) throws CacheException; @@ -189,6 +194,7 @@ public interface Cache { * Removes a cached {@link CacheSpan} from the cache, deleting the underlying file. * * @param span The {@link CacheSpan} to remove. + * @throws CacheException If an error is encountered. */ void removeSpan(CacheSpan span) throws CacheException; @@ -210,15 +216,16 @@ public interface Cache { * @param key The cache key for the data. * @param position The starting position of the data. * @param length The maximum length of the data to be returned. - * @return the length of the cached or not cached data block length. + * @return The length of the cached or not cached data block length. */ - long getCachedBytes(String key, long position, long length); + long getCachedLength(String key, long position, long length); /** * Sets the content length for the given key. * * @param key The cache key for the data. * @param length The length of the data. + * @throws CacheException If an error is encountered. */ void setContentLength(String key, long length) throws CacheException; @@ -227,7 +234,8 @@ public interface Cache { * com.google.android.exoplayer2.C#LENGTH_UNSET} otherwise. * * @param key The cache key for the data. + * @return The content length for the given key if one set, or {@link + * com.google.android.exoplayer2.C#LENGTH_UNSET} otherwise. */ long getContentLength(String key); - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSink.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSink.java index 1af690e10f..57f5a6ad93 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSink.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSink.java @@ -37,7 +37,7 @@ import java.io.OutputStream; */ public final class CacheDataSink implements DataSink { - /** Default buffer size. */ + /** Default buffer size in bytes. */ public static final int DEFAULT_BUFFER_SIZE = 20480; private final Cache cache; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheUtil.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheUtil.java index 2bf5cde8e0..22150f8e78 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheUtil.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheUtil.java @@ -89,8 +89,8 @@ public final class CacheUtil { counters.alreadyCachedBytes = 0; counters.newlyCachedBytes = 0; while (left != 0) { - long blockLength = cache.getCachedBytes(key, start, - left != C.LENGTH_UNSET ? left : Long.MAX_VALUE); + long blockLength = + cache.getCachedLength(key, start, left != C.LENGTH_UNSET ? left : Long.MAX_VALUE); if (blockLength > 0) { counters.alreadyCachedBytes += blockLength; } else { @@ -126,6 +126,12 @@ public final class CacheUtil { * Caches the data defined by {@code dataSpec} while skipping already cached data. Caching stops * early if end of input is reached and {@code enableEOFException} is false. * + *

If a {@link PriorityTaskManager} is given, it's used to pause and resume caching depending + * on {@code priority} and the priority of other tasks registered to the PriorityTaskManager. + * Please note that it's the responsibility of the calling code to call {@link + * PriorityTaskManager#add} to register with the manager before calling this method, and to call + * {@link PriorityTaskManager#remove} afterwards to unregister. + * * @param dataSpec Defines the data to be cached. * @param cache A {@link Cache} to store the data. * @param dataSource A {@link CacheDataSource} that works on the {@code cache}. @@ -164,8 +170,8 @@ public final class CacheUtil { long start = dataSpec.absoluteStreamPosition; long left = dataSpec.length != C.LENGTH_UNSET ? dataSpec.length : cache.getContentLength(key); while (left != 0) { - long blockLength = cache.getCachedBytes(key, start, - left != C.LENGTH_UNSET ? left : Long.MAX_VALUE); + long blockLength = + cache.getCachedLength(key, start, left != C.LENGTH_UNSET ? left : Long.MAX_VALUE); if (blockLength > 0) { // Skip already cached data. } else { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CachedContent.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CachedContent.java index fb59d23666..34884a457d 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CachedContent.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/CachedContent.java @@ -125,7 +125,7 @@ import java.util.TreeSet; * @param length The maximum length of the data to be returned. * @return the length of the cached or not cached data block length. */ - public long getCachedBytes(long position, long length) { + public long getCachedBytesLength(long position, long length) { SimpleCacheSpan span = getSpan(position); if (span.isHoleSpan()) { // We don't have a span covering the start of the queried region. diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/SimpleCache.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/SimpleCache.java index ffac8a35f1..9d4a661343 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/SimpleCache.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/SimpleCache.java @@ -385,13 +385,13 @@ public final class SimpleCache implements Cache { @Override public synchronized boolean isCached(String key, long position, long length) { CachedContent cachedContent = index.get(key); - return cachedContent != null && cachedContent.getCachedBytes(position, length) >= length; + return cachedContent != null && cachedContent.getCachedBytesLength(position, length) >= length; } @Override - public synchronized long getCachedBytes(String key, long position, long length) { + public synchronized long getCachedLength(String key, long position, long length) { CachedContent cachedContent = index.get(key); - return cachedContent != null ? cachedContent.getCachedBytes(position, length) : -length; + return cachedContent != null ? cachedContent.getCachedBytesLength(position, length) : -length; } @Override diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/SimpleCacheSpan.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/SimpleCacheSpan.java index 8c5b7e26e7..e12d876ce1 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/SimpleCacheSpan.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/cache/SimpleCacheSpan.java @@ -15,6 +15,7 @@ */ package com.google.android.exoplayer2.upstream.cache; +import android.support.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Util; @@ -35,19 +36,50 @@ import java.util.regex.Pattern; private static final Pattern CACHE_FILE_PATTERN_V3 = Pattern.compile( "^(\\d+)\\.(\\d+)\\.(\\d+)\\.v3\\.exo$", Pattern.DOTALL); - public static File getCacheFile(File cacheDir, int id, long position, - long lastAccessTimestamp) { + /** + * Returns a new {@link File} instance from {@code cacheDir}, {@code id}, {@code position}, {@code + * lastAccessTimestamp}. + * + * @param cacheDir The parent abstract pathname. + * @param id The cache file id. + * @param position The position of the stored data in the original stream. + * @param lastAccessTimestamp The last access timestamp. + * @return The cache file. + */ + public static File getCacheFile(File cacheDir, int id, long position, long lastAccessTimestamp) { return new File(cacheDir, id + "." + position + "." + lastAccessTimestamp + SUFFIX); } + /** + * Creates a lookup span. + * + * @param key The cache key. + * @param position The position of the {@link CacheSpan} in the original stream. + * @return The span. + */ public static SimpleCacheSpan createLookup(String key, long position) { return new SimpleCacheSpan(key, position, C.LENGTH_UNSET, C.TIME_UNSET, null); } + /** + * Creates an open hole span. + * + * @param key The cache key. + * @param position The position of the {@link CacheSpan} in the original stream. + * @return The span. + */ public static SimpleCacheSpan createOpenHole(String key, long position) { return new SimpleCacheSpan(key, position, C.LENGTH_UNSET, C.TIME_UNSET, null); } + /** + * Creates a closed hole span. + * + * @param key The cache key. + * @param position The position of the {@link CacheSpan} in the original stream. + * @param length The length of the {@link CacheSpan}. + * @return The span. + */ public static SimpleCacheSpan createClosedHole(String key, long position, long length) { return new SimpleCacheSpan(key, position, length, C.TIME_UNSET, null); } @@ -60,6 +92,7 @@ import java.util.regex.Pattern; * @return The span, or null if the file name is not correctly formatted, or if the id is not * present in the content index. */ + @Nullable public static SimpleCacheSpan createCacheEntry(File file, CachedContentIndex index) { String name = file.getName(); if (!name.endsWith(SUFFIX)) { @@ -81,6 +114,15 @@ import java.util.regex.Pattern; Long.parseLong(matcher.group(3)), file); } + /** + * Upgrades the cache file if it is created by an earlier version of {@link SimpleCache}. + * + * @param file The cache file. + * @param index Cached content index. + * @return Upgraded cache file or {@code null} if the file name is not correctly formatted or the + * file can not be renamed. + */ + @Nullable private static File upgradeFile(File file, CachedContentIndex index) { String key; String filename = file.getName(); @@ -106,8 +148,17 @@ import java.util.regex.Pattern; return newCacheFile; } - private SimpleCacheSpan(String key, long position, long length, long lastAccessTimestamp, - File file) { + /** + * @param key The cache key. + * @param position The position of the {@link CacheSpan} in the original stream. + * @param length The length of the {@link CacheSpan}, or {@link C#LENGTH_UNSET} if this is an + * open-ended hole. + * @param lastAccessTimestamp The last access timestamp, or {@link C#TIME_UNSET} if {@link + * #isCached} is false. + * @param file The file corresponding to this {@link CacheSpan}, or null if it's a hole. + */ + private SimpleCacheSpan( + String key, long position, long length, long lastAccessTimestamp, @Nullable File file) { super(key, position, length, lastAccessTimestamp, file); } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/CacheAsserts.java b/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/CacheAsserts.java index 65850a13e7..c31cd0384e 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/CacheAsserts.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/CacheAsserts.java @@ -31,7 +31,11 @@ import java.util.ArrayList; /** Assertion methods for {@link com.google.android.exoplayer2.upstream.cache.Cache}. */ /* package */ final class CacheAsserts { - /** Asserts that the cache content is equal to the data in the {@code fakeDataSet}. */ + /** + * Asserts that the cache content is equal to the data in the {@code fakeDataSet}. + * + * @throws IOException If an error occurred reading from the Cache. + */ public static void assertCachedData(Cache cache, FakeDataSet fakeDataSet) throws IOException { ArrayList allData = fakeDataSet.getAllData(); Uri[] uris = new Uri[allData.size()]; @@ -43,6 +47,8 @@ import java.util.ArrayList; /** * Asserts that the cache content is equal to the given subset of data in the {@code fakeDataSet}. + * + * @throws IOException If an error occurred reading from the Cache. */ public static void assertCachedData(Cache cache, FakeDataSet fakeDataSet, String... uriStrings) throws IOException { @@ -55,6 +61,8 @@ import java.util.ArrayList; /** * Asserts that the cache content is equal to the given subset of data in the {@code fakeDataSet}. + * + * @throws IOException If an error occurred reading from the Cache. */ public static void assertCachedData(Cache cache, FakeDataSet fakeDataSet, Uri... uris) throws IOException { @@ -67,7 +75,11 @@ import java.util.ArrayList; assertThat(cache.getCacheSpace()).isEqualTo(totalLength); } - /** Asserts that the cache contains the given subset of data in the {@code fakeDataSet}. */ + /** + * Asserts that the cache contains the given subset of data in the {@code fakeDataSet}. + * + * @throws IOException If an error occurred reading from the Cache. + */ public static void assertDataCached(Cache cache, FakeDataSet fakeDataSet, Uri... uris) throws IOException { for (Uri uri : uris) { @@ -75,7 +87,11 @@ import java.util.ArrayList; } } - /** Asserts that the cache contains the given data for {@code uriString}. */ + /** + * Asserts that the cache contains the given data for {@code uriString} or not. + * + * @throws IOException If an error occurred reading from the Cache. + */ public static void assertDataCached(Cache cache, Uri uri, byte[] expected) throws IOException { CacheDataSource dataSource = new CacheDataSource(cache, DummyDataSource.INSTANCE, 0); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); diff --git a/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/CacheUtilTest.java b/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/CacheUtilTest.java index c8231ec4ac..250e09bab4 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/CacheUtilTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/CacheUtilTest.java @@ -72,7 +72,7 @@ public final class CacheUtilTest { } @Override - public long getCachedBytes(String key, long position, long length) { + public long getCachedLength(String key, long position, long length) { for (int i = 0; i < spansAndGaps.length; i++) { int spanOrGap = spansAndGaps[i]; if (position < spanOrGap) { diff --git a/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/SimpleCacheTest.java b/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/SimpleCacheTest.java index 75a80185b9..e62676fc9d 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/SimpleCacheTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/upstream/cache/SimpleCacheTest.java @@ -218,36 +218,36 @@ public class SimpleCacheTest { } @Test - public void testGetCachedBytes() throws Exception { + public void testGetCachedLength() throws Exception { SimpleCache simpleCache = getSimpleCache(); CacheSpan cacheSpan = simpleCache.startReadWrite(KEY_1, 0); // No cached bytes, returns -'length' - assertThat(simpleCache.getCachedBytes(KEY_1, 0, 100)).isEqualTo(-100); + assertThat(simpleCache.getCachedLength(KEY_1, 0, 100)).isEqualTo(-100); // Position value doesn't affect the return value - assertThat(simpleCache.getCachedBytes(KEY_1, 20, 100)).isEqualTo(-100); + assertThat(simpleCache.getCachedLength(KEY_1, 20, 100)).isEqualTo(-100); addCache(simpleCache, KEY_1, 0, 15); // Returns the length of a single span - assertThat(simpleCache.getCachedBytes(KEY_1, 0, 100)).isEqualTo(15); + assertThat(simpleCache.getCachedLength(KEY_1, 0, 100)).isEqualTo(15); // Value is capped by the 'length' - assertThat(simpleCache.getCachedBytes(KEY_1, 0, 10)).isEqualTo(10); + assertThat(simpleCache.getCachedLength(KEY_1, 0, 10)).isEqualTo(10); addCache(simpleCache, KEY_1, 15, 35); // Returns the length of two adjacent spans - assertThat(simpleCache.getCachedBytes(KEY_1, 0, 100)).isEqualTo(50); + assertThat(simpleCache.getCachedLength(KEY_1, 0, 100)).isEqualTo(50); addCache(simpleCache, KEY_1, 60, 10); // Not adjacent span doesn't affect return value - assertThat(simpleCache.getCachedBytes(KEY_1, 0, 100)).isEqualTo(50); + assertThat(simpleCache.getCachedLength(KEY_1, 0, 100)).isEqualTo(50); // Returns length of hole up to the next cached span - assertThat(simpleCache.getCachedBytes(KEY_1, 55, 100)).isEqualTo(-5); + assertThat(simpleCache.getCachedLength(KEY_1, 55, 100)).isEqualTo(-5); simpleCache.releaseHoleSpan(cacheSpan); } diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/CacheAsserts.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/CacheAsserts.java index eb53191dc8..2174de1fd5 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/CacheAsserts.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/CacheAsserts.java @@ -36,7 +36,11 @@ import java.util.ArrayList; */ public final class CacheAsserts { - /** Asserts that the cache content is equal to the data in the {@code fakeDataSet}. */ + /** + * Asserts that the cache content is equal to the data in the {@code fakeDataSet}. + * + * @throws IOException If an error occurred reading from the Cache. + */ public static void assertCachedData(Cache cache, FakeDataSet fakeDataSet) throws IOException { ArrayList allData = fakeDataSet.getAllData(); Uri[] uris = new Uri[allData.size()]; @@ -48,6 +52,8 @@ public final class CacheAsserts { /** * Asserts that the cache content is equal to the given subset of data in the {@code fakeDataSet}. + * + * @throws IOException If an error occurred reading from the Cache. */ public static void assertCachedData(Cache cache, FakeDataSet fakeDataSet, String... uriStrings) throws IOException { @@ -60,6 +66,8 @@ public final class CacheAsserts { /** * Asserts that the cache content is equal to the given subset of data in the {@code fakeDataSet}. + * + * @throws IOException If an error occurred reading from the Cache. */ public static void assertCachedData(Cache cache, FakeDataSet fakeDataSet, Uri... uris) throws IOException { @@ -72,7 +80,11 @@ public final class CacheAsserts { assertEquals(totalLength, cache.getCacheSpace()); } - /** Asserts that the cache contains the given subset of data in the {@code fakeDataSet}. */ + /** + * Asserts that the cache contains the given subset of data in the {@code fakeDataSet}. + * + * @throws IOException If an error occurred reading from the Cache. + */ public static void assertDataCached(Cache cache, FakeDataSet fakeDataSet, Uri... uris) throws IOException { for (Uri uri : uris) { @@ -80,7 +92,11 @@ public final class CacheAsserts { } } - /** Asserts that the cache contains the given data for {@code uriString}. */ + /** + * Asserts that the cache contains the given data for {@code uriString}. + * + * @throws IOException If an error occurred reading from the Cache. + */ public static void assertDataCached(Cache cache, Uri uri, byte[] expected) throws IOException { CacheDataSource dataSource = new CacheDataSource(cache, DummyDataSource.INSTANCE, 0); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); -- GitLab