Remove Cache.[get|set]ContentLength

Problem: There is nothing in the Cache interface that enforces that
these methods are implemented by reading/writing content metadata,
however our own code (CacheDataSource) relies on this property since
it mixes use of [get|set]ContentLength and use of metadata. Using
metadata is the right approach because it minimizes the number of
index writes (e.g. it allows the redirect URI and the content length
to be committed by a single write).

Solution: Remove [get|set]ContentLength, which are redundant anyway,
and use metadata everywhere. Also expose the keys being used through
the public API; there's no particular reason why they shouldn't be.
We previously had an API for getting and setting content length, but
no API for getting and setting redirect uri.
PiperOrigin-RevId: 225383211
This commit is contained in:
olly 2018-12-13 17:26:01 +00:00 committed by Oliver Woodman
parent 03d6f1370b
commit 845f54a467
13 changed files with 160 additions and 169 deletions

View File

@ -62,7 +62,7 @@ public interface Cache {
void onSpanTouched(Cache cache, CacheSpan oldSpan, CacheSpan newSpan); void onSpanTouched(Cache cache, CacheSpan oldSpan, CacheSpan newSpan);
} }
/** /**
* Thrown when an error is encountered when writing data. * Thrown when an error is encountered when writing data.
*/ */
@ -223,25 +223,6 @@ public interface Cache {
*/ */
long getCachedLength(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;
/**
* Returns the content length for the given key if one set, or {@link
* 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);
/** /**
* Applies {@code mutations} to the {@link ContentMetadata} for the given key. A new {@link * Applies {@code mutations} to the {@link ContentMetadata} for the given key. A new {@link
* CachedContent} is added if there isn't one already with the given key. * CachedContent} is added if there isn't one already with the given key.

View File

@ -299,7 +299,7 @@ public final class CacheDataSource implements DataSource {
if (dataSpec.length != C.LENGTH_UNSET || currentRequestIgnoresCache) { if (dataSpec.length != C.LENGTH_UNSET || currentRequestIgnoresCache) {
bytesRemaining = dataSpec.length; bytesRemaining = dataSpec.length;
} else { } else {
bytesRemaining = cache.getContentLength(key); bytesRemaining = ContentMetadata.getContentLength(cache.getContentMetadata(key));
if (bytesRemaining != C.LENGTH_UNSET) { if (bytesRemaining != C.LENGTH_UNSET) {
bytesRemaining -= dataSpec.position; bytesRemaining -= dataSpec.position;
if (bytesRemaining <= 0) { if (bytesRemaining <= 0) {
@ -484,16 +484,12 @@ public final class CacheDataSource implements DataSource {
ContentMetadataMutations mutations = new ContentMetadataMutations(); ContentMetadataMutations mutations = new ContentMetadataMutations();
if (currentDataSpecLengthUnset && resolvedLength != C.LENGTH_UNSET) { if (currentDataSpecLengthUnset && resolvedLength != C.LENGTH_UNSET) {
bytesRemaining = resolvedLength; bytesRemaining = resolvedLength;
ContentMetadataInternal.setContentLength(mutations, readPosition + bytesRemaining); ContentMetadataMutations.setContentLength(mutations, readPosition + bytesRemaining);
} }
if (isReadingFromUpstream()) { if (isReadingFromUpstream()) {
actualUri = currentDataSource.getUri(); actualUri = currentDataSource.getUri();
boolean isRedirected = !uri.equals(actualUri); boolean isRedirected = !uri.equals(actualUri);
if (isRedirected) { ContentMetadataMutations.setRedirectedUri(mutations, isRedirected ? actualUri : null);
ContentMetadataInternal.setRedirectedUri(mutations, actualUri);
} else {
ContentMetadataInternal.removeRedirectedUri(mutations);
}
} }
if (isWritingToCache()) { if (isWritingToCache()) {
cache.applyContentMetadataMutations(key, mutations); cache.applyContentMetadataMutations(key, mutations);
@ -503,14 +499,15 @@ public final class CacheDataSource implements DataSource {
private void setNoBytesRemainingAndMaybeStoreLength() throws IOException { private void setNoBytesRemainingAndMaybeStoreLength() throws IOException {
bytesRemaining = 0; bytesRemaining = 0;
if (isWritingToCache()) { if (isWritingToCache()) {
cache.setContentLength(key, readPosition); ContentMetadataMutations mutations = new ContentMetadataMutations();
ContentMetadataMutations.setContentLength(mutations, readPosition);
cache.applyContentMetadataMutations(key, mutations);
} }
} }
private static Uri getRedirectedUriOrDefault(Cache cache, String key, Uri defaultUri) { private static Uri getRedirectedUriOrDefault(Cache cache, String key, Uri defaultUri) {
ContentMetadata contentMetadata = cache.getContentMetadata(key); Uri redirectedUri = ContentMetadata.getRedirectedUri(cache.getContentMetadata(key));
Uri redirectedUri = ContentMetadataInternal.getRedirectedUri(contentMetadata); return redirectedUri != null ? redirectedUri : defaultUri;
return redirectedUri == null ? defaultUri : redirectedUri;
} }
private static boolean isCausedByPositionOutOfRange(IOException e) { private static boolean isCausedByPositionOutOfRange(IOException e) {

View File

@ -84,7 +84,10 @@ public final class CacheUtil {
CachingCounters counters) { CachingCounters counters) {
String key = buildCacheKey(dataSpec, cacheKeyFactory); String key = buildCacheKey(dataSpec, cacheKeyFactory);
long start = dataSpec.absoluteStreamPosition; long start = dataSpec.absoluteStreamPosition;
long left = dataSpec.length != C.LENGTH_UNSET ? dataSpec.length : cache.getContentLength(key); long left =
dataSpec.length != C.LENGTH_UNSET
? dataSpec.length
: ContentMetadata.getContentLength(cache.getContentMetadata(key));
counters.contentLength = left; counters.contentLength = left;
counters.alreadyCachedBytes = 0; counters.alreadyCachedBytes = 0;
counters.newlyCachedBytes = 0; counters.newlyCachedBytes = 0;
@ -188,7 +191,10 @@ public final class CacheUtil {
String key = buildCacheKey(dataSpec, cacheKeyFactory); String key = buildCacheKey(dataSpec, cacheKeyFactory);
long start = dataSpec.absoluteStreamPosition; long start = dataSpec.absoluteStreamPosition;
long left = dataSpec.length != C.LENGTH_UNSET ? dataSpec.length : cache.getContentLength(key); long left =
dataSpec.length != C.LENGTH_UNSET
? dataSpec.length
: ContentMetadata.getContentLength(cache.getContentMetadata(key));
while (left != 0) { while (left != 0) {
throwExceptionIfInterruptedOrCancelled(isCanceled); throwExceptionIfInterruptedOrCancelled(isCanceled);
long blockLength = long blockLength =

View File

@ -55,7 +55,7 @@ import java.util.TreeSet;
if (version < VERSION_METADATA_INTRODUCED) { if (version < VERSION_METADATA_INTRODUCED) {
long length = input.readLong(); long length = input.readLong();
ContentMetadataMutations mutations = new ContentMetadataMutations(); ContentMetadataMutations mutations = new ContentMetadataMutations();
ContentMetadataInternal.setContentLength(mutations, length); ContentMetadataMutations.setContentLength(mutations, length);
cachedContent.applyMetadataMutations(mutations); cachedContent.applyMetadataMutations(mutations);
} else { } else {
cachedContent.metadata = DefaultContentMetadata.readFromStream(input); cachedContent.metadata = DefaultContentMetadata.readFromStream(input);
@ -216,7 +216,7 @@ import java.util.TreeSet;
int result = id; int result = id;
result = 31 * result + key.hashCode(); result = 31 * result + key.hashCode();
if (version < VERSION_METADATA_INTRODUCED) { if (version < VERSION_METADATA_INTRODUCED) {
long length = ContentMetadataInternal.getContentLength(metadata); long length = ContentMetadata.getContentLength(metadata);
result = 31 * result + (int) (length ^ (length >>> 32)); result = 31 * result + (int) (length ^ (length >>> 32));
} else { } else {
result = 31 * result + metadata.hashCode(); result = 31 * result + metadata.hashCode();

View File

@ -15,44 +15,73 @@
*/ */
package com.google.android.exoplayer2.upstream.cache; package com.google.android.exoplayer2.upstream.cache;
import android.net.Uri;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C;
/** /**
* Interface for an immutable snapshot of keyed metadata. * Interface for an immutable snapshot of keyed metadata.
*
* <p>Internal metadata names are prefixed with {@value #INTERNAL_METADATA_NAME_PREFIX}. Custom
* metadata names should avoid this prefix to prevent clashes.
*/ */
public interface ContentMetadata { public interface ContentMetadata {
/** Prefix of internal metadata names. */ /**
String INTERNAL_METADATA_NAME_PREFIX = "exo_"; * Prefix for custom metadata keys. Applications can use keys starting with this prefix without
* any risk of their keys colliding with ones defined by the ExoPlayer library.
*/
@SuppressWarnings("unused")
String KEY_CUSTOM_PREFIX = "custom_";
/** Key for redirected uri (type: String). */
String KEY_REDIRECTED_URI = "exo_redir";
/** Key for content length in bytes (type: long). */
String KEY_CONTENT_LENGTH = "exo_len";
/** /**
* Returns a metadata value. * Returns a metadata value.
* *
* @param name Name of the metadata to be returned. * @param key Key of the metadata to be returned.
* @param defaultValue Value to return if the metadata doesn't exist. * @param defaultValue Value to return if the metadata doesn't exist.
* @return The metadata value. * @return The metadata value.
*/ */
byte[] get(String name, byte[] defaultValue); @Nullable
byte[] get(String key, @Nullable byte[] defaultValue);
/** /**
* Returns a metadata value. * Returns a metadata value.
* *
* @param name Name of the metadata to be returned. * @param key Key of the metadata to be returned.
* @param defaultValue Value to return if the metadata doesn't exist. * @param defaultValue Value to return if the metadata doesn't exist.
* @return The metadata value. * @return The metadata value.
*/ */
String get(String name, String defaultValue); @Nullable
String get(String key, @Nullable String defaultValue);
/** /**
* Returns a metadata value. * Returns a metadata value.
* *
* @param name Name of the metadata to be returned. * @param key Key of the metadata to be returned.
* @param defaultValue Value to return if the metadata doesn't exist. * @param defaultValue Value to return if the metadata doesn't exist.
* @return The metadata value. * @return The metadata value.
*/ */
long get(String name, long defaultValue); long get(String key, long defaultValue);
/** Returns whether the metadata is available. */ /** Returns whether the metadata is available. */
boolean contains(String name); boolean contains(String key);
/**
* Returns the value stored under {@link #KEY_CONTENT_LENGTH}, or {@link C#LENGTH_UNSET} if not
* set.
*/
static long getContentLength(ContentMetadata contentMetadata) {
return contentMetadata.get(KEY_CONTENT_LENGTH, C.LENGTH_UNSET);
}
/**
* Returns the value stored under {@link #KEY_REDIRECTED_URI} as a {@link Uri}, or {code null} if
* not set.
*/
@Nullable
static Uri getRedirectedUri(ContentMetadata contentMetadata) {
String redirectedUri = contentMetadata.get(KEY_REDIRECTED_URI, (String) null);
return redirectedUri == null ? null : Uri.parse(redirectedUri);
}
} }

View File

@ -1,66 +0,0 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2.upstream.cache;
import android.net.Uri;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C;
/** Helper classes to easily access and modify internal metadata values. */
/* package */ final class ContentMetadataInternal {
private static final String PREFIX = ContentMetadata.INTERNAL_METADATA_NAME_PREFIX;
private static final String METADATA_NAME_REDIRECTED_URI = PREFIX + "redir";
private static final String METADATA_NAME_CONTENT_LENGTH = PREFIX + "len";
/** Returns the content length metadata, or {@link C#LENGTH_UNSET} if not set. */
public static long getContentLength(ContentMetadata contentMetadata) {
return contentMetadata.get(METADATA_NAME_CONTENT_LENGTH, C.LENGTH_UNSET);
}
/** Adds a mutation to set content length metadata value. */
public static void setContentLength(ContentMetadataMutations mutations, long length) {
mutations.set(METADATA_NAME_CONTENT_LENGTH, length);
}
/** Adds a mutation to remove content length metadata value. */
public static void removeContentLength(ContentMetadataMutations mutations) {
mutations.remove(METADATA_NAME_CONTENT_LENGTH);
}
/** Returns the redirected uri metadata, or {@code null} if not set. */
public @Nullable static Uri getRedirectedUri(ContentMetadata contentMetadata) {
String redirectedUri = contentMetadata.get(METADATA_NAME_REDIRECTED_URI, (String) null);
return redirectedUri == null ? null : Uri.parse(redirectedUri);
}
/**
* Adds a mutation to set redirected uri metadata value. Passing {@code null} as {@code uri} isn't
* allowed.
*/
public static void setRedirectedUri(ContentMetadataMutations mutations, Uri uri) {
mutations.set(METADATA_NAME_REDIRECTED_URI, uri.toString());
}
/** Adds a mutation to remove redirected uri metadata value. */
public static void removeRedirectedUri(ContentMetadataMutations mutations) {
mutations.remove(METADATA_NAME_REDIRECTED_URI);
}
private ContentMetadataInternal() {
// Prevent instantiation.
}
}

View File

@ -15,6 +15,9 @@
*/ */
package com.google.android.exoplayer2.upstream.cache; package com.google.android.exoplayer2.upstream.cache;
import android.net.Uri;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -30,6 +33,36 @@ import java.util.Map.Entry;
*/ */
public class ContentMetadataMutations { public class ContentMetadataMutations {
/**
* Adds a mutation to set the {@link ContentMetadata#KEY_CONTENT_LENGTH} value, or to remove any
* existing value if {@link C#LENGTH_UNSET} is passed.
*
* @param mutations The mutations to modify.
* @param length The length value, or {@link C#LENGTH_UNSET} to remove any existing entry.
* @return The mutations instance, for convenience.
*/
public static ContentMetadataMutations setContentLength(
ContentMetadataMutations mutations, long length) {
return mutations.set(ContentMetadata.KEY_CONTENT_LENGTH, length);
}
/**
* Adds a mutation to set the {@link ContentMetadata#KEY_REDIRECTED_URI} value, or to remove any
* existing entry if {@code null} is passed.
*
* @param mutations The mutations to modify.
* @param uri The {@link Uri} value, or {@code null} to remove any existing entry.
* @return The mutations instance, for convenience.
*/
public static ContentMetadataMutations setRedirectedUri(
ContentMetadataMutations mutations, @Nullable Uri uri) {
if (uri == null) {
return mutations.remove(ContentMetadata.KEY_REDIRECTED_URI);
} else {
return mutations.set(ContentMetadata.KEY_REDIRECTED_URI, uri.toString());
}
}
private final Map<String, Object> editedValues; private final Map<String, Object> editedValues;
private final List<String> removedValues; private final List<String> removedValues;
@ -45,7 +78,7 @@ public class ContentMetadataMutations {
* *
* @param name The name of the metadata value. * @param name The name of the metadata value.
* @param value The value to be set. * @param value The value to be set.
* @return This Editor instance, for convenience. * @return This instance, for convenience.
*/ */
public ContentMetadataMutations set(String name, String value) { public ContentMetadataMutations set(String name, String value) {
return checkAndSet(name, value); return checkAndSet(name, value);
@ -56,7 +89,7 @@ public class ContentMetadataMutations {
* *
* @param name The name of the metadata value. * @param name The name of the metadata value.
* @param value The value to be set. * @param value The value to be set.
* @return This Editor instance, for convenience. * @return This instance, for convenience.
*/ */
public ContentMetadataMutations set(String name, long value) { public ContentMetadataMutations set(String name, long value) {
return checkAndSet(name, value); return checkAndSet(name, value);
@ -68,7 +101,7 @@ public class ContentMetadataMutations {
* *
* @param name The name of the metadata value. * @param name The name of the metadata value.
* @param value The value to be set. * @param value The value to be set.
* @return This Editor instance, for convenience. * @return This instance, for convenience.
*/ */
public ContentMetadataMutations set(String name, byte[] value) { public ContentMetadataMutations set(String name, byte[] value) {
return checkAndSet(name, Arrays.copyOf(value, value.length)); return checkAndSet(name, Arrays.copyOf(value, value.length));
@ -78,7 +111,7 @@ public class ContentMetadataMutations {
* Adds a mutation to remove a metadata value. * Adds a mutation to remove a metadata value.
* *
* @param name The name of the metadata value. * @param name The name of the metadata value.
* @return This Editor instance, for convenience. * @return This instance, for convenience.
*/ */
public ContentMetadataMutations remove(String name) { public ContentMetadataMutations remove(String name) {
removedValues.add(name); removedValues.add(name);

View File

@ -64,6 +64,10 @@ public final class DefaultContentMetadata implements ContentMetadata {
private final Map<String, byte[]> metadata; private final Map<String, byte[]> metadata;
public DefaultContentMetadata() {
this(Collections.emptyMap());
}
private DefaultContentMetadata(Map<String, byte[]> metadata) { private DefaultContentMetadata(Map<String, byte[]> metadata) {
this.metadata = Collections.unmodifiableMap(metadata); this.metadata = Collections.unmodifiableMap(metadata);
} }
@ -74,7 +78,7 @@ public final class DefaultContentMetadata implements ContentMetadata {
*/ */
public DefaultContentMetadata copyWithMutationsApplied(ContentMetadataMutations mutations) { public DefaultContentMetadata copyWithMutationsApplied(ContentMetadataMutations mutations) {
Map<String, byte[]> mutatedMetadata = applyMutations(metadata, mutations); Map<String, byte[]> mutatedMetadata = applyMutations(metadata, mutations);
if (isMetadataEqual(mutatedMetadata)) { if (isMetadataEqual(metadata, mutatedMetadata)) {
return this; return this;
} }
return new DefaultContentMetadata(mutatedMetadata); return new DefaultContentMetadata(mutatedMetadata);
@ -97,7 +101,8 @@ public final class DefaultContentMetadata implements ContentMetadata {
} }
@Override @Override
public final byte[] get(String name, byte[] defaultValue) { @Nullable
public final byte[] get(String name, @Nullable byte[] defaultValue) {
if (metadata.containsKey(name)) { if (metadata.containsKey(name)) {
byte[] bytes = metadata.get(name); byte[] bytes = metadata.get(name);
return Arrays.copyOf(bytes, bytes.length); return Arrays.copyOf(bytes, bytes.length);
@ -107,7 +112,8 @@ public final class DefaultContentMetadata implements ContentMetadata {
} }
@Override @Override
public final String get(String name, String defaultValue) { @Nullable
public final String get(String name, @Nullable String defaultValue) {
if (metadata.containsKey(name)) { if (metadata.containsKey(name)) {
byte[] bytes = metadata.get(name); byte[] bytes = metadata.get(name);
return new String(bytes, Charset.forName(C.UTF8_NAME)); return new String(bytes, Charset.forName(C.UTF8_NAME));
@ -139,21 +145,7 @@ public final class DefaultContentMetadata implements ContentMetadata {
if (o == null || getClass() != o.getClass()) { if (o == null || getClass() != o.getClass()) {
return false; return false;
} }
return isMetadataEqual(((DefaultContentMetadata) o).metadata); return isMetadataEqual(metadata, ((DefaultContentMetadata) o).metadata);
}
private boolean isMetadataEqual(Map<String, byte[]> otherMetadata) {
if (metadata.size() != otherMetadata.size()) {
return false;
}
for (Entry<String, byte[]> entry : metadata.entrySet()) {
byte[] value = entry.getValue();
byte[] otherValue = otherMetadata.get(entry.getKey());
if (!Arrays.equals(value, otherValue)) {
return false;
}
}
return true;
} }
@Override @Override
@ -168,6 +160,20 @@ public final class DefaultContentMetadata implements ContentMetadata {
return hashCode; return hashCode;
} }
private static boolean isMetadataEqual(Map<String, byte[]> first, Map<String, byte[]> second) {
if (first.size() != second.size()) {
return false;
}
for (Entry<String, byte[]> entry : first.entrySet()) {
byte[] value = entry.getValue();
byte[] otherValue = second.get(entry.getKey());
if (!Arrays.equals(value, otherValue)) {
return false;
}
}
return true;
}
private static Map<String, byte[]> applyMutations( private static Map<String, byte[]> applyMutations(
Map<String, byte[]> otherMetadata, ContentMetadataMutations mutations) { Map<String, byte[]> otherMetadata, ContentMetadataMutations mutations) {
HashMap<String, byte[]> metadata = new HashMap<>(otherMetadata); HashMap<String, byte[]> metadata = new HashMap<>(otherMetadata);

View File

@ -293,7 +293,7 @@ public final class SimpleCache implements Cache {
return; return;
} }
// Check if the span conflicts with the set content length // Check if the span conflicts with the set content length
long length = ContentMetadataInternal.getContentLength(cachedContent.getMetadata()); long length = ContentMetadata.getContentLength(cachedContent.getMetadata());
if (length != C.LENGTH_UNSET) { if (length != C.LENGTH_UNSET) {
Assertions.checkState((span.position + span.length) <= length); Assertions.checkState((span.position + span.length) <= length);
} }
@ -333,18 +333,6 @@ public final class SimpleCache implements Cache {
return cachedContent != null ? cachedContent.getCachedBytesLength(position, length) : -length; return cachedContent != null ? cachedContent.getCachedBytesLength(position, length) : -length;
} }
@Override
public synchronized void setContentLength(String key, long length) throws CacheException {
ContentMetadataMutations mutations = new ContentMetadataMutations();
ContentMetadataInternal.setContentLength(mutations, length);
applyContentMetadataMutations(key, mutations);
}
@Override
public synchronized long getContentLength(String key) {
return ContentMetadataInternal.getContentLength(getContentMetadata(key));
}
@Override @Override
public synchronized void applyContentMetadataMutations( public synchronized void applyContentMetadataMutations(
String key, ContentMetadataMutations mutations) throws CacheException { String key, ContentMetadataMutations mutations) throws CacheException {

View File

@ -247,7 +247,8 @@ public final class CacheDataSourceTest {
// Read partial at EOS but don't cross it so length is unknown. // Read partial at EOS but don't cross it so length is unknown.
CacheDataSource cacheDataSource = createCacheDataSource(false, true); CacheDataSource cacheDataSource = createCacheDataSource(false, true);
assertReadData(cacheDataSource, dataSpec, true); assertReadData(cacheDataSource, dataSpec, true);
assertThat(cache.getContentLength(defaultCacheKey)).isEqualTo(C.LENGTH_UNSET); assertThat(ContentMetadata.getContentLength(cache.getContentMetadata(defaultCacheKey)))
.isEqualTo(C.LENGTH_UNSET);
// Now do an unbounded request for whole data. This will cause a bounded request from upstream. // Now do an unbounded request for whole data. This will cause a bounded request from upstream.
// End of data from upstream shouldn't be mixed up with EOS and cause length set wrong. // End of data from upstream shouldn't be mixed up with EOS and cause length set wrong.
@ -285,7 +286,8 @@ public final class CacheDataSourceTest {
cacheDataSource.close(); cacheDataSource.close();
assertThat(upstream.getAndClearOpenedDataSpecs()).hasLength(1); assertThat(upstream.getAndClearOpenedDataSpecs()).hasLength(1);
assertThat(cache.getContentLength(defaultCacheKey)).isEqualTo(TEST_DATA.length); assertThat(ContentMetadata.getContentLength(cache.getContentMetadata(defaultCacheKey)))
.isEqualTo(TEST_DATA.length);
} }
@Test @Test
@ -512,7 +514,9 @@ public final class CacheDataSourceTest {
// If the request was unbounded then the content length should be cached, either because the // If the request was unbounded then the content length should be cached, either because the
// content length was known or because EOS was read. If the request was bounded then the content // content length was known or because EOS was read. If the request was bounded then the content
// length will not have been determined. // length will not have been determined.
assertThat(cache.getContentLength(customCacheKey ? this.customCacheKey : defaultCacheKey)) ContentMetadata metadata =
cache.getContentMetadata(customCacheKey ? this.customCacheKey : defaultCacheKey);
assertThat(ContentMetadata.getContentLength(metadata))
.isEqualTo(dataSpec.length == C.LENGTH_UNSET ? TEST_DATA.length : C.LENGTH_UNSET); .isEqualTo(dataSpec.length == C.LENGTH_UNSET ? TEST_DATA.length : C.LENGTH_UNSET);
} }

View File

@ -79,8 +79,11 @@ public final class CacheUtilTest {
} }
@Override @Override
public long getContentLength(String key) { public ContentMetadata getContentMetadata(String key) {
return contentLength; DefaultContentMetadata metadata = new DefaultContentMetadata();
ContentMetadataMutations mutations = new ContentMetadataMutations();
ContentMetadataMutations.setContentLength(mutations, contentLength);
return metadata.copyWithMutationsApplied(mutations);
} }
} }

View File

@ -154,11 +154,11 @@ public class CachedContentIndexTest {
assertThat(index.assignIdForKey("ABCDE")).isEqualTo(5); assertThat(index.assignIdForKey("ABCDE")).isEqualTo(5);
ContentMetadata metadata = index.get("ABCDE").getMetadata(); ContentMetadata metadata = index.get("ABCDE").getMetadata();
assertThat(ContentMetadataInternal.getContentLength(metadata)).isEqualTo(10); assertThat(ContentMetadata.getContentLength(metadata)).isEqualTo(10);
assertThat(index.assignIdForKey("KLMNO")).isEqualTo(2); assertThat(index.assignIdForKey("KLMNO")).isEqualTo(2);
ContentMetadata metadata2 = index.get("KLMNO").getMetadata(); ContentMetadata metadata2 = index.get("KLMNO").getMetadata();
assertThat(ContentMetadataInternal.getContentLength(metadata2)).isEqualTo(2560); assertThat(ContentMetadata.getContentLength(metadata2)).isEqualTo(2560);
} }
@Test @Test
@ -172,12 +172,12 @@ public class CachedContentIndexTest {
assertThat(index.assignIdForKey("ABCDE")).isEqualTo(5); assertThat(index.assignIdForKey("ABCDE")).isEqualTo(5);
ContentMetadata metadata = index.get("ABCDE").getMetadata(); ContentMetadata metadata = index.get("ABCDE").getMetadata();
assertThat(ContentMetadataInternal.getContentLength(metadata)).isEqualTo(10); assertThat(ContentMetadata.getContentLength(metadata)).isEqualTo(10);
assertThat(ContentMetadataInternal.getRedirectedUri(metadata)).isEqualTo(Uri.parse("abcde")); assertThat(ContentMetadata.getRedirectedUri(metadata)).isEqualTo(Uri.parse("abcde"));
assertThat(index.assignIdForKey("KLMNO")).isEqualTo(2); assertThat(index.assignIdForKey("KLMNO")).isEqualTo(2);
ContentMetadata metadata2 = index.get("KLMNO").getMetadata(); ContentMetadata metadata2 = index.get("KLMNO").getMetadata();
assertThat(ContentMetadataInternal.getContentLength(metadata2)).isEqualTo(2560); assertThat(ContentMetadata.getContentLength(metadata2)).isEqualTo(2560);
} }
@Test @Test
@ -297,11 +297,11 @@ public class CachedContentIndexTest {
private void assertStoredAndLoadedEqual(CachedContentIndex index, CachedContentIndex index2) private void assertStoredAndLoadedEqual(CachedContentIndex index, CachedContentIndex index2)
throws IOException { throws IOException {
ContentMetadataMutations mutations1 = new ContentMetadataMutations(); ContentMetadataMutations mutations1 = new ContentMetadataMutations();
ContentMetadataInternal.setContentLength(mutations1, 2560); ContentMetadataMutations.setContentLength(mutations1, 2560);
index.getOrAdd("KLMNO").applyMetadataMutations(mutations1); index.getOrAdd("KLMNO").applyMetadataMutations(mutations1);
ContentMetadataMutations mutations2 = new ContentMetadataMutations(); ContentMetadataMutations mutations2 = new ContentMetadataMutations();
ContentMetadataInternal.setContentLength(mutations2, 10); ContentMetadataMutations.setContentLength(mutations2, 10);
ContentMetadataInternal.setRedirectedUri(mutations2, Uri.parse("abcde")); ContentMetadataMutations.setRedirectedUri(mutations2, Uri.parse("abcde"));
index.getOrAdd("ABCDE").applyMetadataMutations(mutations2); index.getOrAdd("ABCDE").applyMetadataMutations(mutations2);
index.store(); index.store();

View File

@ -106,18 +106,26 @@ public class SimpleCacheTest {
} }
@Test @Test
public void testSetGetLength() throws Exception { public void testSetGetContentMetadata() throws Exception {
SimpleCache simpleCache = getSimpleCache(); SimpleCache simpleCache = getSimpleCache();
assertThat(simpleCache.getContentLength(KEY_1)).isEqualTo(LENGTH_UNSET); assertThat(ContentMetadata.getContentLength(simpleCache.getContentMetadata(KEY_1)))
.isEqualTo(LENGTH_UNSET);
simpleCache.setContentLength(KEY_1, 15); ContentMetadataMutations mutations = new ContentMetadataMutations();
assertThat(simpleCache.getContentLength(KEY_1)).isEqualTo(15); ContentMetadataMutations.setContentLength(mutations, 15);
simpleCache.applyContentMetadataMutations(KEY_1, mutations);
assertThat(ContentMetadata.getContentLength(simpleCache.getContentMetadata(KEY_1)))
.isEqualTo(15);
simpleCache.startReadWrite(KEY_1, 0); simpleCache.startReadWrite(KEY_1, 0);
addCache(simpleCache, KEY_1, 0, 15); addCache(simpleCache, KEY_1, 0, 15);
simpleCache.setContentLength(KEY_1, 150);
assertThat(simpleCache.getContentLength(KEY_1)).isEqualTo(150); mutations = new ContentMetadataMutations();
ContentMetadataMutations.setContentLength(mutations, 150);
simpleCache.applyContentMetadataMutations(KEY_1, mutations);
assertThat(ContentMetadata.getContentLength(simpleCache.getContentMetadata(KEY_1)))
.isEqualTo(150);
addCache(simpleCache, KEY_1, 140, 10); addCache(simpleCache, KEY_1, 140, 10);
@ -125,14 +133,16 @@ public class SimpleCacheTest {
// Check if values are kept after cache is reloaded. // Check if values are kept after cache is reloaded.
SimpleCache simpleCache2 = getSimpleCache(); SimpleCache simpleCache2 = getSimpleCache();
assertThat(simpleCache2.getContentLength(KEY_1)).isEqualTo(150); assertThat(ContentMetadata.getContentLength(simpleCache2.getContentMetadata(KEY_1)))
.isEqualTo(150);
// Removing the last span shouldn't cause the length be change next time cache loaded // Removing the last span shouldn't cause the length be change next time cache loaded
SimpleCacheSpan lastSpan = simpleCache2.startReadWrite(KEY_1, 145); SimpleCacheSpan lastSpan = simpleCache2.startReadWrite(KEY_1, 145);
simpleCache2.removeSpan(lastSpan); simpleCache2.removeSpan(lastSpan);
simpleCache2.release(); simpleCache2.release();
simpleCache2 = getSimpleCache(); simpleCache2 = getSimpleCache();
assertThat(simpleCache2.getContentLength(KEY_1)).isEqualTo(150); assertThat(ContentMetadata.getContentLength(simpleCache2.getContentMetadata(KEY_1)))
.isEqualTo(150);
} }
@Test @Test