mirror of
https://github.com/samsonjs/media.git
synced 2026-03-30 10:15:48 +00:00
Don't pass maxCacheFileSize to CacheEvictor if real size is unknown
CacheEvictor.onStartFile currently receives a length, which is the maximum size of the content that might be written. The LRU cache evictor will make sure there's sufficient space for the specified size. If the actual size of the content is unknown, CacheDataSink passes maxCacheFileSize. The current behavior isn't ideal. It seems valid for a developer to specify maxCacheFileSize=Long.MAX_VALUE if they don't want any file fragmentation in the cache. However if they then attempt to cache something with unknown length, LRU cache will try and make room for content of length Long.MAX_VALUE, and end up evicting the entire cache to do so. This change alters the logic so a length is only passed if the actual size of the content is known. In other cases C.LENGTH_UNSET is now passed. The LRU evictor will not evict until after the file is committed. Note a custom LRU evictor could still opt to evict to ensure some application specified amount of space, if that's the desired behavior. PiperOrigin-RevId: 227509525
This commit is contained in:
parent
243b12f37e
commit
3a9557c72f
5 changed files with 22 additions and 15 deletions
|
|
@ -16,6 +16,7 @@
|
|||
package com.google.android.exoplayer2.upstream.cache;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.NavigableSet;
|
||||
|
|
@ -169,12 +170,12 @@ public interface Cache {
|
|||
*
|
||||
* @param key The cache key for the data.
|
||||
* @param position The starting position of the data.
|
||||
* @param maxLength The maximum length of the data to be written. Used only to ensure that there
|
||||
* is enough space in the cache.
|
||||
* @param length The length of the data being written, or {@link C#LENGTH_UNSET} if unknown. 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;
|
||||
File startFile(String key, long position, long length) throws CacheException;
|
||||
|
||||
/**
|
||||
* Commits a file into the cache. Must only be called when holding a corresponding hole {@link
|
||||
|
|
|
|||
|
|
@ -170,10 +170,13 @@ public final class CacheDataSink implements DataSink {
|
|||
}
|
||||
|
||||
private void openNextOutputStream() throws IOException {
|
||||
long maxLength = dataSpec.length == C.LENGTH_UNSET ? maxCacheFileSize
|
||||
: Math.min(dataSpec.length - dataSpecBytesWritten, maxCacheFileSize);
|
||||
file = cache.startFile(dataSpec.key, dataSpec.absoluteStreamPosition + dataSpecBytesWritten,
|
||||
maxLength);
|
||||
long length =
|
||||
dataSpec.length == C.LENGTH_UNSET
|
||||
? C.LENGTH_UNSET
|
||||
: Math.min(dataSpec.length - dataSpecBytesWritten, maxCacheFileSize);
|
||||
file =
|
||||
cache.startFile(
|
||||
dataSpec.key, dataSpec.absoluteStreamPosition + dataSpecBytesWritten, length);
|
||||
underlyingFileOutputStream = new FileOutputStream(file);
|
||||
if (bufferSize > 0) {
|
||||
if (bufferedOutputStream == null) {
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@
|
|||
*/
|
||||
package com.google.android.exoplayer2.upstream.cache;
|
||||
|
||||
import com.google.android.exoplayer2.C;
|
||||
|
||||
/**
|
||||
* Evicts data from a {@link Cache}. Implementations should call {@link Cache#removeSpan(CacheSpan)}
|
||||
* to evict cache entries based on their eviction policies.
|
||||
|
|
@ -32,8 +34,7 @@ public interface CacheEvictor extends Cache.Listener {
|
|||
* @param cache The source of the event.
|
||||
* @param key The key being written.
|
||||
* @param position The starting position of the data being written.
|
||||
* @param maxLength The maximum length of the data being written.
|
||||
* @param length The length of the data being written, or {@link C#LENGTH_UNSET} if unknown.
|
||||
*/
|
||||
void onStartFile(Cache cache, String key, long position, long maxLength);
|
||||
|
||||
void onStartFile(Cache cache, String key, long position, long length);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package com.google.android.exoplayer2.upstream.cache;
|
||||
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.upstream.cache.Cache.CacheException;
|
||||
import java.util.Comparator;
|
||||
import java.util.TreeSet;
|
||||
|
|
@ -40,8 +41,10 @@ public final class LeastRecentlyUsedCacheEvictor implements CacheEvictor, Compar
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onStartFile(Cache cache, String key, long position, long maxLength) {
|
||||
evictCache(cache, maxLength);
|
||||
public void onStartFile(Cache cache, String key, long position, long length) {
|
||||
if (length != C.LENGTH_UNSET) {
|
||||
evictCache(cache, length);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -259,8 +259,7 @@ public final class SimpleCache implements Cache {
|
|||
}
|
||||
|
||||
@Override
|
||||
public synchronized File startFile(String key, long position, long maxLength)
|
||||
throws CacheException {
|
||||
public synchronized File startFile(String key, long position, long length) throws CacheException {
|
||||
Assertions.checkState(!released);
|
||||
CachedContent cachedContent = index.get(key);
|
||||
Assertions.checkNotNull(cachedContent);
|
||||
|
|
@ -270,7 +269,7 @@ public final class SimpleCache implements Cache {
|
|||
cacheDir.mkdirs();
|
||||
removeStaleSpans();
|
||||
}
|
||||
evictor.onStartFile(this, key, position, maxLength);
|
||||
evictor.onStartFile(this, key, position, length);
|
||||
return SimpleCacheSpan.getCacheFile(
|
||||
cacheDir, cachedContent.id, position, System.currentTimeMillis());
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue