提交 1fc250a9 编写于 作者: E eguven 提交者: Oliver Woodman

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
上级 11bae0af
......@@ -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.
* <p>
* If there is a cache entry that overlaps the position, then the returned {@link CacheSpan}
*
* <p>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.
* <p>
* If there is no cache entry overlapping {@code offset}, then the returned {@link CacheSpan}
*
* <p>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);
}
......@@ -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;
......
......@@ -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.
*
* <p>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 {
......
......@@ -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.
......
......@@ -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
......
......@@ -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);
}
......
......@@ -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<FakeData> 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();
......
......@@ -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) {
......
......@@ -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);
}
......
......@@ -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<FakeData> 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();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册