1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package org.mozilla.thirdparty.com.google.android.exoplayer2.upstream.cache; 17 18 import androidx.annotation.Nullable; 19 import androidx.annotation.WorkerThread; 20 import org.mozilla.thirdparty.com.google.android.exoplayer2.C; 21 import java.io.File; 22 import java.io.IOException; 23 import java.util.NavigableSet; 24 import java.util.Set; 25 26 /** 27 * An interface for cache. 28 */ 29 public interface Cache { 30 31 /** 32 * Listener of {@link Cache} events. 33 */ 34 interface Listener { 35 36 /** 37 * Called when a {@link CacheSpan} is added to the cache. 38 * 39 * @param cache The source of the event. 40 * @param span The added {@link CacheSpan}. 41 */ onSpanAdded(Cache cache, CacheSpan span)42 void onSpanAdded(Cache cache, CacheSpan span); 43 44 /** 45 * Called when a {@link CacheSpan} is removed from the cache. 46 * 47 * @param cache The source of the event. 48 * @param span The removed {@link CacheSpan}. 49 */ onSpanRemoved(Cache cache, CacheSpan span)50 void onSpanRemoved(Cache cache, CacheSpan span); 51 52 /** 53 * Called when an existing {@link CacheSpan} is touched, causing it to be replaced. The new 54 * {@link CacheSpan} is guaranteed to represent the same data as the one it replaces, however 55 * {@link CacheSpan#file} and {@link CacheSpan#lastTouchTimestamp} may have changed. 56 * 57 * <p>Note that for span replacement, {@link #onSpanAdded(Cache, CacheSpan)} and {@link 58 * #onSpanRemoved(Cache, CacheSpan)} are not called in addition to this method. 59 * 60 * @param cache The source of the event. 61 * @param oldSpan The old {@link CacheSpan}, which has been removed from the cache. 62 * @param newSpan The new {@link CacheSpan}, which has been added to the cache. 63 */ onSpanTouched(Cache cache, CacheSpan oldSpan, CacheSpan newSpan)64 void onSpanTouched(Cache cache, CacheSpan oldSpan, CacheSpan newSpan); 65 } 66 67 /** 68 * Thrown when an error is encountered when writing data. 69 */ 70 class CacheException extends IOException { 71 CacheException(String message)72 public CacheException(String message) { 73 super(message); 74 } 75 CacheException(Throwable cause)76 public CacheException(Throwable cause) { 77 super(cause); 78 } 79 CacheException(String message, Throwable cause)80 public CacheException(String message, Throwable cause) { 81 super(message, cause); 82 } 83 } 84 85 /** 86 * Returned by {@link #getUid()} if initialization failed before the unique identifier was read or 87 * generated. 88 */ 89 long UID_UNSET = -1; 90 91 /** 92 * Returns a non-negative unique identifier for the cache, or {@link #UID_UNSET} if initialization 93 * failed before the unique identifier was determined. 94 * 95 * <p>Implementations are expected to generate and store the unique identifier alongside the 96 * cached content. If the location of the cache is deleted or swapped, it is expected that a new 97 * unique identifier will be generated when the cache is recreated. 98 */ getUid()99 long getUid(); 100 101 /** 102 * Releases the cache. This method must be called when the cache is no longer required. The cache 103 * must not be used after calling this method. 104 * 105 * <p>This method may be slow and shouldn't normally be called on the main thread. 106 */ 107 @WorkerThread release()108 void release(); 109 110 /** 111 * Registers a listener to listen for changes to a given key. 112 * 113 * <p>No guarantees are made about the thread or threads on which the listener is called, but it 114 * is guaranteed that listener methods will be called in a serial fashion (i.e. one at a time) and 115 * in the same order as events occurred. 116 * 117 * @param key The key to listen to. 118 * @param listener The listener to add. 119 * @return The current spans for the key. 120 */ addListener(String key, Listener listener)121 NavigableSet<CacheSpan> addListener(String key, Listener listener); 122 123 /** 124 * Unregisters a listener. 125 * 126 * @param key The key to stop listening to. 127 * @param listener The listener to remove. 128 */ removeListener(String key, Listener listener)129 void removeListener(String key, Listener listener); 130 131 /** 132 * Returns the cached spans for a given cache key. 133 * 134 * @param key The key for which spans should be returned. 135 * @return The spans for the key. 136 */ getCachedSpans(String key)137 NavigableSet<CacheSpan> getCachedSpans(String key); 138 139 /** 140 * Returns all keys in the cache. 141 * 142 * @return All the keys in the cache. 143 */ getKeys()144 Set<String> getKeys(); 145 146 /** 147 * Returns the total disk space in bytes used by the cache. 148 * 149 * @return The total disk space in bytes. 150 */ getCacheSpace()151 long getCacheSpace(); 152 153 /** 154 * A caller should invoke this method when they require data from a given position for a given 155 * key. 156 * 157 * <p>If there is a cache entry that overlaps the position, then the returned {@link CacheSpan} 158 * defines the file in which the data is stored. {@link CacheSpan#isCached} is true. The caller 159 * may read from the cache file, but does not acquire any locks. 160 * 161 * <p>If there is no cache entry overlapping {@code offset}, then the returned {@link CacheSpan} 162 * defines a hole in the cache starting at {@code position} into which the caller may write as it 163 * obtains the data from some other source. The returned {@link CacheSpan} serves as a lock. 164 * Whilst the caller holds the lock it may write data into the hole. It may split data into 165 * multiple files. When the caller has finished writing a file it should commit it to the cache by 166 * calling {@link #commitFile(File, long)}. When the caller has finished writing, it must release 167 * the lock by calling {@link #releaseHoleSpan}. 168 * 169 * <p>This method may be slow and shouldn't normally be called on the main thread. 170 * 171 * @param key The key of the data being requested. 172 * @param position The position of the data being requested. 173 * @return The {@link CacheSpan}. 174 * @throws InterruptedException If the thread was interrupted. 175 * @throws CacheException If an error is encountered. 176 */ 177 @WorkerThread startReadWrite(String key, long position)178 CacheSpan startReadWrite(String key, long position) throws InterruptedException, CacheException; 179 180 /** 181 * Same as {@link #startReadWrite(String, long)}. However, if the cache entry is locked, then 182 * instead of blocking, this method will return null as the {@link CacheSpan}. 183 * 184 * <p>This method may be slow and shouldn't normally be called on the main thread. 185 * 186 * @param key The key of the data being requested. 187 * @param position The position of the data being requested. 188 * @return The {@link CacheSpan}. Or null if the cache entry is locked. 189 * @throws CacheException If an error is encountered. 190 */ 191 @WorkerThread 192 @Nullable startReadWriteNonBlocking(String key, long position)193 CacheSpan startReadWriteNonBlocking(String key, long position) throws CacheException; 194 195 /** 196 * Obtains a cache file into which data can be written. Must only be called when holding a 197 * corresponding hole {@link CacheSpan} obtained from {@link #startReadWrite(String, long)}. 198 * 199 * <p>This method may be slow and shouldn't normally be called on the main thread. 200 * 201 * @param key The cache key for the data. 202 * @param position The starting position of the data. 203 * @param length The length of the data being written, or {@link C#LENGTH_UNSET} if unknown. Used 204 * only to ensure that there is enough space in the cache. 205 * @return The file into which data should be written. 206 * @throws CacheException If an error is encountered. 207 */ 208 @WorkerThread startFile(String key, long position, long length)209 File startFile(String key, long position, long length) throws CacheException; 210 211 /** 212 * Commits a file into the cache. Must only be called when holding a corresponding hole {@link 213 * CacheSpan} obtained from {@link #startReadWrite(String, long)}. 214 * 215 * <p>This method may be slow and shouldn't normally be called on the main thread. 216 * 217 * @param file A newly written cache file. 218 * @param length The length of the newly written cache file in bytes. 219 * @throws CacheException If an error is encountered. 220 */ 221 @WorkerThread commitFile(File file, long length)222 void commitFile(File file, long length) throws CacheException; 223 224 /** 225 * Releases a {@link CacheSpan} obtained from {@link #startReadWrite(String, long)} which 226 * corresponded to a hole in the cache. 227 * 228 * @param holeSpan The {@link CacheSpan} being released. 229 */ releaseHoleSpan(CacheSpan holeSpan)230 void releaseHoleSpan(CacheSpan holeSpan); 231 232 /** 233 * Removes a cached {@link CacheSpan} from the cache, deleting the underlying file. 234 * 235 * <p>This method may be slow and shouldn't normally be called on the main thread. 236 * 237 * @param span The {@link CacheSpan} to remove. 238 * @throws CacheException If an error is encountered. 239 */ 240 @WorkerThread removeSpan(CacheSpan span)241 void removeSpan(CacheSpan span) throws CacheException; 242 243 /** 244 * Queries if a range is entirely available in the cache. 245 * 246 * @param key The cache key for the data. 247 * @param position The starting position of the data. 248 * @param length The length of the data. 249 * @return true if the data is available in the Cache otherwise false; 250 */ isCached(String key, long position, long length)251 boolean isCached(String key, long position, long length); 252 253 /** 254 * Returns the length of the cached data block starting from the {@code position} to the block end 255 * up to {@code length} bytes. If the {@code position} isn't cached then -(the length of the gap 256 * to the next cached data up to {@code length} bytes) is returned. 257 * 258 * @param key The cache key for the data. 259 * @param position The starting position of the data. 260 * @param length The maximum length of the data to be returned. 261 * @return The length of the cached or not cached data block length. 262 */ getCachedLength(String key, long position, long length)263 long getCachedLength(String key, long position, long length); 264 265 /** 266 * Applies {@code mutations} to the {@link ContentMetadata} for the given key. A new {@link 267 * CachedContent} is added if there isn't one already with the given key. 268 * 269 * <p>This method may be slow and shouldn't normally be called on the main thread. 270 * 271 * @param key The cache key for the data. 272 * @param mutations Contains mutations to be applied to the metadata. 273 * @throws CacheException If an error is encountered. 274 */ 275 @WorkerThread applyContentMetadataMutations(String key, ContentMetadataMutations mutations)276 void applyContentMetadataMutations(String key, ContentMetadataMutations mutations) 277 throws CacheException; 278 279 /** 280 * Returns a {@link ContentMetadata} for the given key. 281 * 282 * @param key The cache key for the data. 283 * @return A {@link ContentMetadata} for the given key. 284 */ getContentMetadata(String key)285 ContentMetadata getContentMetadata(String key); 286 } 287