Initial commit
This commit is contained in:
166
sources/okhttp3/internal/cache/CacheInterceptor.java
vendored
Normal file
166
sources/okhttp3/internal/cache/CacheInterceptor.java
vendored
Normal file
@@ -0,0 +1,166 @@
|
||||
package okhttp3.internal.cache;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import okhttp3.Headers;
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.Protocol;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.internal.Internal;
|
||||
import okhttp3.internal.Util;
|
||||
import okhttp3.internal.cache.CacheStrategy;
|
||||
import okhttp3.internal.http.HttpHeaders;
|
||||
import okhttp3.internal.http.HttpMethod;
|
||||
import okhttp3.internal.http.RealResponseBody;
|
||||
import okio.Buffer;
|
||||
import okio.BufferedSink;
|
||||
import okio.BufferedSource;
|
||||
import okio.Okio;
|
||||
import okio.Sink;
|
||||
import okio.Source;
|
||||
import okio.Timeout;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class CacheInterceptor implements Interceptor {
|
||||
final InternalCache cache;
|
||||
|
||||
public CacheInterceptor(InternalCache internalCache) {
|
||||
this.cache = internalCache;
|
||||
}
|
||||
|
||||
private Response cacheWritingResponse(final CacheRequest cacheRequest, Response response) throws IOException {
|
||||
Sink body;
|
||||
if (cacheRequest == null || (body = cacheRequest.body()) == null) {
|
||||
return response;
|
||||
}
|
||||
final BufferedSource source = response.body().source();
|
||||
final BufferedSink buffer = Okio.buffer(body);
|
||||
return response.newBuilder().body(new RealResponseBody(response.header("Content-Type"), response.body().contentLength(), Okio.buffer(new Source() { // from class: okhttp3.internal.cache.CacheInterceptor.1
|
||||
boolean cacheRequestClosed;
|
||||
|
||||
@Override // okio.Source, java.io.Closeable, java.lang.AutoCloseable
|
||||
public void close() throws IOException {
|
||||
if (!this.cacheRequestClosed && !Util.discard(this, 100, TimeUnit.MILLISECONDS)) {
|
||||
this.cacheRequestClosed = true;
|
||||
cacheRequest.abort();
|
||||
}
|
||||
source.close();
|
||||
}
|
||||
|
||||
@Override // okio.Source
|
||||
public long read(Buffer buffer2, long j) throws IOException {
|
||||
try {
|
||||
long read = source.read(buffer2, j);
|
||||
if (read != -1) {
|
||||
buffer2.copyTo(buffer.buffer(), buffer2.size() - read, read);
|
||||
buffer.emitCompleteSegments();
|
||||
return read;
|
||||
}
|
||||
if (!this.cacheRequestClosed) {
|
||||
this.cacheRequestClosed = true;
|
||||
buffer.close();
|
||||
}
|
||||
return -1L;
|
||||
} catch (IOException e) {
|
||||
if (!this.cacheRequestClosed) {
|
||||
this.cacheRequestClosed = true;
|
||||
cacheRequest.abort();
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okio.Source
|
||||
public Timeout timeout() {
|
||||
return source.timeout();
|
||||
}
|
||||
}))).build();
|
||||
}
|
||||
|
||||
private static Headers combine(Headers headers, Headers headers2) {
|
||||
Headers.Builder builder = new Headers.Builder();
|
||||
int size = headers.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
String name = headers.name(i);
|
||||
String value = headers.value(i);
|
||||
if ((!"Warning".equalsIgnoreCase(name) || !value.startsWith("1")) && (isContentSpecificHeader(name) || !isEndToEnd(name) || headers2.get(name) == null)) {
|
||||
Internal.instance.addLenient(builder, name, value);
|
||||
}
|
||||
}
|
||||
int size2 = headers2.size();
|
||||
for (int i2 = 0; i2 < size2; i2++) {
|
||||
String name2 = headers2.name(i2);
|
||||
if (!isContentSpecificHeader(name2) && isEndToEnd(name2)) {
|
||||
Internal.instance.addLenient(builder, name2, headers2.value(i2));
|
||||
}
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
static boolean isContentSpecificHeader(String str) {
|
||||
return "Content-Length".equalsIgnoreCase(str) || "Content-Encoding".equalsIgnoreCase(str) || "Content-Type".equalsIgnoreCase(str);
|
||||
}
|
||||
|
||||
static boolean isEndToEnd(String str) {
|
||||
return ("Connection".equalsIgnoreCase(str) || "Keep-Alive".equalsIgnoreCase(str) || "Proxy-Authenticate".equalsIgnoreCase(str) || "Proxy-Authorization".equalsIgnoreCase(str) || "TE".equalsIgnoreCase(str) || "Trailers".equalsIgnoreCase(str) || "Transfer-Encoding".equalsIgnoreCase(str) || "Upgrade".equalsIgnoreCase(str)) ? false : true;
|
||||
}
|
||||
|
||||
private static Response stripBody(Response response) {
|
||||
return (response == null || response.body() == null) ? response : response.newBuilder().body(null).build();
|
||||
}
|
||||
|
||||
@Override // okhttp3.Interceptor
|
||||
public Response intercept(Interceptor.Chain chain) throws IOException {
|
||||
InternalCache internalCache = this.cache;
|
||||
Response response = internalCache != null ? internalCache.get(chain.request()) : null;
|
||||
CacheStrategy cacheStrategy = new CacheStrategy.Factory(System.currentTimeMillis(), chain.request(), response).get();
|
||||
Request request = cacheStrategy.networkRequest;
|
||||
Response response2 = cacheStrategy.cacheResponse;
|
||||
InternalCache internalCache2 = this.cache;
|
||||
if (internalCache2 != null) {
|
||||
internalCache2.trackResponse(cacheStrategy);
|
||||
}
|
||||
if (response != null && response2 == null) {
|
||||
Util.closeQuietly(response.body());
|
||||
}
|
||||
if (request == null && response2 == null) {
|
||||
return new Response.Builder().request(chain.request()).protocol(Protocol.HTTP_1_1).code(504).message("Unsatisfiable Request (only-if-cached)").body(Util.EMPTY_RESPONSE).sentRequestAtMillis(-1L).receivedResponseAtMillis(System.currentTimeMillis()).build();
|
||||
}
|
||||
if (request == null) {
|
||||
return response2.newBuilder().cacheResponse(stripBody(response2)).build();
|
||||
}
|
||||
try {
|
||||
Response proceed = chain.proceed(request);
|
||||
if (proceed == null && response != null) {
|
||||
}
|
||||
if (response2 != null) {
|
||||
if (proceed.code() == 304) {
|
||||
Response build = response2.newBuilder().headers(combine(response2.headers(), proceed.headers())).sentRequestAtMillis(proceed.sentRequestAtMillis()).receivedResponseAtMillis(proceed.receivedResponseAtMillis()).cacheResponse(stripBody(response2)).networkResponse(stripBody(proceed)).build();
|
||||
proceed.body().close();
|
||||
this.cache.trackConditionalCacheHit();
|
||||
this.cache.update(response2, build);
|
||||
return build;
|
||||
}
|
||||
Util.closeQuietly(response2.body());
|
||||
}
|
||||
Response build2 = proceed.newBuilder().cacheResponse(stripBody(response2)).networkResponse(stripBody(proceed)).build();
|
||||
if (this.cache != null) {
|
||||
if (HttpHeaders.hasBody(build2) && CacheStrategy.isCacheable(build2, request)) {
|
||||
return cacheWritingResponse(this.cache.put(build2), build2);
|
||||
}
|
||||
if (HttpMethod.invalidatesCache(request.method())) {
|
||||
try {
|
||||
this.cache.remove(request);
|
||||
} catch (IOException unused) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return build2;
|
||||
} finally {
|
||||
if (response != null) {
|
||||
Util.closeQuietly(response.body());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
sources/okhttp3/internal/cache/CacheRequest.java
vendored
Normal file
11
sources/okhttp3/internal/cache/CacheRequest.java
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
package okhttp3.internal.cache;
|
||||
|
||||
import java.io.IOException;
|
||||
import okio.Sink;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public interface CacheRequest {
|
||||
void abort();
|
||||
|
||||
Sink body() throws IOException;
|
||||
}
|
243
sources/okhttp3/internal/cache/CacheStrategy.java
vendored
Normal file
243
sources/okhttp3/internal/cache/CacheStrategy.java
vendored
Normal file
@@ -0,0 +1,243 @@
|
||||
package okhttp3.internal.cache;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import okhttp3.CacheControl;
|
||||
import okhttp3.Headers;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.internal.Internal;
|
||||
import okhttp3.internal.http.HttpDate;
|
||||
import okhttp3.internal.http.HttpHeaders;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class CacheStrategy {
|
||||
public final Response cacheResponse;
|
||||
public final Request networkRequest;
|
||||
|
||||
public static class Factory {
|
||||
private int ageSeconds;
|
||||
final Response cacheResponse;
|
||||
private String etag;
|
||||
private Date expires;
|
||||
private Date lastModified;
|
||||
private String lastModifiedString;
|
||||
final long nowMillis;
|
||||
private long receivedResponseMillis;
|
||||
final Request request;
|
||||
private long sentRequestMillis;
|
||||
private Date servedDate;
|
||||
private String servedDateString;
|
||||
|
||||
public Factory(long j, Request request, Response response) {
|
||||
this.ageSeconds = -1;
|
||||
this.nowMillis = j;
|
||||
this.request = request;
|
||||
this.cacheResponse = response;
|
||||
if (response != null) {
|
||||
this.sentRequestMillis = response.sentRequestAtMillis();
|
||||
this.receivedResponseMillis = response.receivedResponseAtMillis();
|
||||
Headers headers = response.headers();
|
||||
int size = headers.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
String name = headers.name(i);
|
||||
String value = headers.value(i);
|
||||
if ("Date".equalsIgnoreCase(name)) {
|
||||
this.servedDate = HttpDate.parse(value);
|
||||
this.servedDateString = value;
|
||||
} else if ("Expires".equalsIgnoreCase(name)) {
|
||||
this.expires = HttpDate.parse(value);
|
||||
} else if ("Last-Modified".equalsIgnoreCase(name)) {
|
||||
this.lastModified = HttpDate.parse(value);
|
||||
this.lastModifiedString = value;
|
||||
} else if ("ETag".equalsIgnoreCase(name)) {
|
||||
this.etag = value;
|
||||
} else if ("Age".equalsIgnoreCase(name)) {
|
||||
this.ageSeconds = HttpHeaders.parseSeconds(value, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private long cacheResponseAge() {
|
||||
Date date = this.servedDate;
|
||||
long max = date != null ? Math.max(0L, this.receivedResponseMillis - date.getTime()) : 0L;
|
||||
int i = this.ageSeconds;
|
||||
if (i != -1) {
|
||||
max = Math.max(max, TimeUnit.SECONDS.toMillis(i));
|
||||
}
|
||||
long j = this.receivedResponseMillis;
|
||||
return max + (j - this.sentRequestMillis) + (this.nowMillis - j);
|
||||
}
|
||||
|
||||
private long computeFreshnessLifetime() {
|
||||
if (this.cacheResponse.cacheControl().maxAgeSeconds() != -1) {
|
||||
return TimeUnit.SECONDS.toMillis(r0.maxAgeSeconds());
|
||||
}
|
||||
if (this.expires != null) {
|
||||
Date date = this.servedDate;
|
||||
long time = this.expires.getTime() - (date != null ? date.getTime() : this.receivedResponseMillis);
|
||||
if (time > 0) {
|
||||
return time;
|
||||
}
|
||||
return 0L;
|
||||
}
|
||||
if (this.lastModified == null || this.cacheResponse.request().url().query() != null) {
|
||||
return 0L;
|
||||
}
|
||||
Date date2 = this.servedDate;
|
||||
long time2 = (date2 != null ? date2.getTime() : this.sentRequestMillis) - this.lastModified.getTime();
|
||||
if (time2 > 0) {
|
||||
return time2 / 10;
|
||||
}
|
||||
return 0L;
|
||||
}
|
||||
|
||||
private CacheStrategy getCandidate() {
|
||||
if (this.cacheResponse == null) {
|
||||
return new CacheStrategy(this.request, null);
|
||||
}
|
||||
if (this.request.isHttps() && this.cacheResponse.handshake() == null) {
|
||||
return new CacheStrategy(this.request, null);
|
||||
}
|
||||
if (!CacheStrategy.isCacheable(this.cacheResponse, this.request)) {
|
||||
return new CacheStrategy(this.request, null);
|
||||
}
|
||||
CacheControl cacheControl = this.request.cacheControl();
|
||||
if (cacheControl.noCache() || hasConditions(this.request)) {
|
||||
return new CacheStrategy(this.request, null);
|
||||
}
|
||||
CacheControl cacheControl2 = this.cacheResponse.cacheControl();
|
||||
if (cacheControl2.immutable()) {
|
||||
return new CacheStrategy(null, this.cacheResponse);
|
||||
}
|
||||
long cacheResponseAge = cacheResponseAge();
|
||||
long computeFreshnessLifetime = computeFreshnessLifetime();
|
||||
if (cacheControl.maxAgeSeconds() != -1) {
|
||||
computeFreshnessLifetime = Math.min(computeFreshnessLifetime, TimeUnit.SECONDS.toMillis(cacheControl.maxAgeSeconds()));
|
||||
}
|
||||
long j = 0;
|
||||
long millis = cacheControl.minFreshSeconds() != -1 ? TimeUnit.SECONDS.toMillis(cacheControl.minFreshSeconds()) : 0L;
|
||||
if (!cacheControl2.mustRevalidate() && cacheControl.maxStaleSeconds() != -1) {
|
||||
j = TimeUnit.SECONDS.toMillis(cacheControl.maxStaleSeconds());
|
||||
}
|
||||
if (!cacheControl2.noCache()) {
|
||||
long j2 = millis + cacheResponseAge;
|
||||
if (j2 < j + computeFreshnessLifetime) {
|
||||
Response.Builder newBuilder = this.cacheResponse.newBuilder();
|
||||
if (j2 >= computeFreshnessLifetime) {
|
||||
newBuilder.addHeader("Warning", "110 HttpURLConnection \"Response is stale\"");
|
||||
}
|
||||
if (cacheResponseAge > 86400000 && isFreshnessLifetimeHeuristic()) {
|
||||
newBuilder.addHeader("Warning", "113 HttpURLConnection \"Heuristic expiration\"");
|
||||
}
|
||||
return new CacheStrategy(null, newBuilder.build());
|
||||
}
|
||||
}
|
||||
String str = this.etag;
|
||||
String str2 = "If-Modified-Since";
|
||||
if (str != null) {
|
||||
str2 = "If-None-Match";
|
||||
} else if (this.lastModified != null) {
|
||||
str = this.lastModifiedString;
|
||||
} else {
|
||||
if (this.servedDate == null) {
|
||||
return new CacheStrategy(this.request, null);
|
||||
}
|
||||
str = this.servedDateString;
|
||||
}
|
||||
Headers.Builder newBuilder2 = this.request.headers().newBuilder();
|
||||
Internal.instance.addLenient(newBuilder2, str2, str);
|
||||
return new CacheStrategy(this.request.newBuilder().headers(newBuilder2.build()).build(), this.cacheResponse);
|
||||
}
|
||||
|
||||
private static boolean hasConditions(Request request) {
|
||||
return (request.header("If-Modified-Since") == null && request.header("If-None-Match") == null) ? false : true;
|
||||
}
|
||||
|
||||
private boolean isFreshnessLifetimeHeuristic() {
|
||||
return this.cacheResponse.cacheControl().maxAgeSeconds() == -1 && this.expires == null;
|
||||
}
|
||||
|
||||
public CacheStrategy get() {
|
||||
CacheStrategy candidate = getCandidate();
|
||||
return (candidate.networkRequest == null || !this.request.cacheControl().onlyIfCached()) ? candidate : new CacheStrategy(null, null);
|
||||
}
|
||||
}
|
||||
|
||||
CacheStrategy(Request request, Response response) {
|
||||
this.networkRequest = request;
|
||||
this.cacheResponse = response;
|
||||
}
|
||||
|
||||
/* JADX WARN: Code restructure failed: missing block: B:31:0x0056, code lost:
|
||||
|
||||
if (r3.cacheControl().isPrivate() == false) goto L33;
|
||||
*/
|
||||
/*
|
||||
Code decompiled incorrectly, please refer to instructions dump.
|
||||
To view partially-correct code enable 'Show inconsistent code' option in preferences
|
||||
*/
|
||||
public static boolean isCacheable(okhttp3.Response r3, okhttp3.Request r4) {
|
||||
/*
|
||||
int r0 = r3.code()
|
||||
r1 = 200(0xc8, float:2.8E-43)
|
||||
r2 = 0
|
||||
if (r0 == r1) goto L5a
|
||||
r1 = 410(0x19a, float:5.75E-43)
|
||||
if (r0 == r1) goto L5a
|
||||
r1 = 414(0x19e, float:5.8E-43)
|
||||
if (r0 == r1) goto L5a
|
||||
r1 = 501(0x1f5, float:7.02E-43)
|
||||
if (r0 == r1) goto L5a
|
||||
r1 = 203(0xcb, float:2.84E-43)
|
||||
if (r0 == r1) goto L5a
|
||||
r1 = 204(0xcc, float:2.86E-43)
|
||||
if (r0 == r1) goto L5a
|
||||
r1 = 307(0x133, float:4.3E-43)
|
||||
if (r0 == r1) goto L31
|
||||
r1 = 308(0x134, float:4.32E-43)
|
||||
if (r0 == r1) goto L5a
|
||||
r1 = 404(0x194, float:5.66E-43)
|
||||
if (r0 == r1) goto L5a
|
||||
r1 = 405(0x195, float:5.68E-43)
|
||||
if (r0 == r1) goto L5a
|
||||
switch(r0) {
|
||||
case 300: goto L5a;
|
||||
case 301: goto L5a;
|
||||
case 302: goto L31;
|
||||
default: goto L30;
|
||||
}
|
||||
L30:
|
||||
goto L59
|
||||
L31:
|
||||
java.lang.String r0 = "Expires"
|
||||
java.lang.String r0 = r3.header(r0)
|
||||
if (r0 != 0) goto L5a
|
||||
okhttp3.CacheControl r0 = r3.cacheControl()
|
||||
int r0 = r0.maxAgeSeconds()
|
||||
r1 = -1
|
||||
if (r0 != r1) goto L5a
|
||||
okhttp3.CacheControl r0 = r3.cacheControl()
|
||||
boolean r0 = r0.isPublic()
|
||||
if (r0 != 0) goto L5a
|
||||
okhttp3.CacheControl r0 = r3.cacheControl()
|
||||
boolean r0 = r0.isPrivate()
|
||||
if (r0 == 0) goto L59
|
||||
goto L5a
|
||||
L59:
|
||||
return r2
|
||||
L5a:
|
||||
okhttp3.CacheControl r3 = r3.cacheControl()
|
||||
boolean r3 = r3.noStore()
|
||||
if (r3 != 0) goto L6f
|
||||
okhttp3.CacheControl r3 = r4.cacheControl()
|
||||
boolean r3 = r3.noStore()
|
||||
if (r3 != 0) goto L6f
|
||||
r2 = 1
|
||||
L6f:
|
||||
return r2
|
||||
*/
|
||||
throw new UnsupportedOperationException("Method not decompiled: okhttp3.internal.cache.CacheStrategy.isCacheable(okhttp3.Response, okhttp3.Request):boolean");
|
||||
}
|
||||
}
|
794
sources/okhttp3/internal/cache/DiskLruCache.java
vendored
Normal file
794
sources/okhttp3/internal/cache/DiskLruCache.java
vendored
Normal file
@@ -0,0 +1,794 @@
|
||||
package okhttp3.internal.cache;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.EOFException;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.Flushable;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Pattern;
|
||||
import okhttp3.internal.Util;
|
||||
import okhttp3.internal.io.FileSystem;
|
||||
import okhttp3.internal.platform.Platform;
|
||||
import okio.BufferedSink;
|
||||
import okio.BufferedSource;
|
||||
import okio.Okio;
|
||||
import okio.Sink;
|
||||
import okio.Source;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public final class DiskLruCache implements Closeable, Flushable {
|
||||
static final /* synthetic */ boolean $assertionsDisabled = false;
|
||||
static final long ANY_SEQUENCE_NUMBER = -1;
|
||||
private static final String CLEAN = "CLEAN";
|
||||
private static final String DIRTY = "DIRTY";
|
||||
static final String JOURNAL_FILE = "journal";
|
||||
static final String JOURNAL_FILE_BACKUP = "journal.bkp";
|
||||
static final String JOURNAL_FILE_TEMP = "journal.tmp";
|
||||
static final Pattern LEGAL_KEY_PATTERN = Pattern.compile("[a-z0-9_-]{1,120}");
|
||||
static final String MAGIC = "libcore.io.DiskLruCache";
|
||||
private static final String READ = "READ";
|
||||
private static final String REMOVE = "REMOVE";
|
||||
static final String VERSION_1 = "1";
|
||||
private final int appVersion;
|
||||
boolean closed;
|
||||
final File directory;
|
||||
private final Executor executor;
|
||||
final FileSystem fileSystem;
|
||||
boolean hasJournalErrors;
|
||||
boolean initialized;
|
||||
private final File journalFile;
|
||||
private final File journalFileBackup;
|
||||
private final File journalFileTmp;
|
||||
BufferedSink journalWriter;
|
||||
private long maxSize;
|
||||
boolean mostRecentRebuildFailed;
|
||||
boolean mostRecentTrimFailed;
|
||||
int redundantOpCount;
|
||||
final int valueCount;
|
||||
private long size = 0;
|
||||
final LinkedHashMap<String, Entry> lruEntries = new LinkedHashMap<>(0, 0.75f, true);
|
||||
private long nextSequenceNumber = 0;
|
||||
private final Runnable cleanupRunnable = new Runnable() { // from class: okhttp3.internal.cache.DiskLruCache.1
|
||||
@Override // java.lang.Runnable
|
||||
public void run() {
|
||||
synchronized (DiskLruCache.this) {
|
||||
if ((!DiskLruCache.this.initialized) || DiskLruCache.this.closed) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
DiskLruCache.this.trimToSize();
|
||||
} catch (IOException unused) {
|
||||
DiskLruCache.this.mostRecentTrimFailed = true;
|
||||
}
|
||||
try {
|
||||
if (DiskLruCache.this.journalRebuildRequired()) {
|
||||
DiskLruCache.this.rebuildJournal();
|
||||
DiskLruCache.this.redundantOpCount = 0;
|
||||
}
|
||||
} catch (IOException unused2) {
|
||||
DiskLruCache.this.mostRecentRebuildFailed = true;
|
||||
DiskLruCache.this.journalWriter = Okio.buffer(Okio.blackhole());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public final class Editor {
|
||||
private boolean done;
|
||||
final Entry entry;
|
||||
final boolean[] written;
|
||||
|
||||
Editor(Entry entry) {
|
||||
this.entry = entry;
|
||||
this.written = entry.readable ? null : new boolean[DiskLruCache.this.valueCount];
|
||||
}
|
||||
|
||||
public void abort() throws IOException {
|
||||
synchronized (DiskLruCache.this) {
|
||||
if (this.done) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
if (this.entry.currentEditor == this) {
|
||||
DiskLruCache.this.completeEdit(this, false);
|
||||
}
|
||||
this.done = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void abortUnlessCommitted() {
|
||||
synchronized (DiskLruCache.this) {
|
||||
if (!this.done && this.entry.currentEditor == this) {
|
||||
try {
|
||||
DiskLruCache.this.completeEdit(this, false);
|
||||
} catch (IOException unused) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void commit() throws IOException {
|
||||
synchronized (DiskLruCache.this) {
|
||||
if (this.done) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
if (this.entry.currentEditor == this) {
|
||||
DiskLruCache.this.completeEdit(this, true);
|
||||
}
|
||||
this.done = true;
|
||||
}
|
||||
}
|
||||
|
||||
void detach() {
|
||||
if (this.entry.currentEditor != this) {
|
||||
return;
|
||||
}
|
||||
int i = 0;
|
||||
while (true) {
|
||||
DiskLruCache diskLruCache = DiskLruCache.this;
|
||||
if (i >= diskLruCache.valueCount) {
|
||||
this.entry.currentEditor = null;
|
||||
return;
|
||||
} else {
|
||||
try {
|
||||
diskLruCache.fileSystem.delete(this.entry.dirtyFiles[i]);
|
||||
} catch (IOException unused) {
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Sink newSink(int i) {
|
||||
synchronized (DiskLruCache.this) {
|
||||
if (this.done) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
if (this.entry.currentEditor != this) {
|
||||
return Okio.blackhole();
|
||||
}
|
||||
if (!this.entry.readable) {
|
||||
this.written[i] = true;
|
||||
}
|
||||
try {
|
||||
return new FaultHidingSink(DiskLruCache.this.fileSystem.sink(this.entry.dirtyFiles[i])) { // from class: okhttp3.internal.cache.DiskLruCache.Editor.1
|
||||
@Override // okhttp3.internal.cache.FaultHidingSink
|
||||
protected void onException(IOException iOException) {
|
||||
synchronized (DiskLruCache.this) {
|
||||
Editor.this.detach();
|
||||
}
|
||||
}
|
||||
};
|
||||
} catch (FileNotFoundException unused) {
|
||||
return Okio.blackhole();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Source newSource(int i) {
|
||||
synchronized (DiskLruCache.this) {
|
||||
if (this.done) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
if (!this.entry.readable || this.entry.currentEditor != this) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return DiskLruCache.this.fileSystem.source(this.entry.cleanFiles[i]);
|
||||
} catch (FileNotFoundException unused) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final class Entry {
|
||||
final File[] cleanFiles;
|
||||
Editor currentEditor;
|
||||
final File[] dirtyFiles;
|
||||
final String key;
|
||||
final long[] lengths;
|
||||
boolean readable;
|
||||
long sequenceNumber;
|
||||
|
||||
Entry(String str) {
|
||||
this.key = str;
|
||||
int i = DiskLruCache.this.valueCount;
|
||||
this.lengths = new long[i];
|
||||
this.cleanFiles = new File[i];
|
||||
this.dirtyFiles = new File[i];
|
||||
StringBuilder sb = new StringBuilder(str);
|
||||
sb.append('.');
|
||||
int length = sb.length();
|
||||
for (int i2 = 0; i2 < DiskLruCache.this.valueCount; i2++) {
|
||||
sb.append(i2);
|
||||
this.cleanFiles[i2] = new File(DiskLruCache.this.directory, sb.toString());
|
||||
sb.append(".tmp");
|
||||
this.dirtyFiles[i2] = new File(DiskLruCache.this.directory, sb.toString());
|
||||
sb.setLength(length);
|
||||
}
|
||||
}
|
||||
|
||||
private IOException invalidLengths(String[] strArr) throws IOException {
|
||||
throw new IOException("unexpected journal line: " + Arrays.toString(strArr));
|
||||
}
|
||||
|
||||
void setLengths(String[] strArr) throws IOException {
|
||||
if (strArr.length != DiskLruCache.this.valueCount) {
|
||||
throw invalidLengths(strArr);
|
||||
}
|
||||
for (int i = 0; i < strArr.length; i++) {
|
||||
try {
|
||||
this.lengths[i] = Long.parseLong(strArr[i]);
|
||||
} catch (NumberFormatException unused) {
|
||||
throw invalidLengths(strArr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Snapshot snapshot() {
|
||||
if (!Thread.holdsLock(DiskLruCache.this)) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
Source[] sourceArr = new Source[DiskLruCache.this.valueCount];
|
||||
long[] jArr = (long[]) this.lengths.clone();
|
||||
for (int i = 0; i < DiskLruCache.this.valueCount; i++) {
|
||||
try {
|
||||
sourceArr[i] = DiskLruCache.this.fileSystem.source(this.cleanFiles[i]);
|
||||
} catch (FileNotFoundException unused) {
|
||||
for (int i2 = 0; i2 < DiskLruCache.this.valueCount && sourceArr[i2] != null; i2++) {
|
||||
Util.closeQuietly(sourceArr[i2]);
|
||||
}
|
||||
try {
|
||||
DiskLruCache.this.removeEntry(this);
|
||||
return null;
|
||||
} catch (IOException unused2) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return DiskLruCache.this.new Snapshot(this.key, this.sequenceNumber, sourceArr, jArr);
|
||||
}
|
||||
|
||||
void writeLengths(BufferedSink bufferedSink) throws IOException {
|
||||
for (long j : this.lengths) {
|
||||
bufferedSink.writeByte(32).writeDecimalLong(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final class Snapshot implements Closeable {
|
||||
private final String key;
|
||||
private final long[] lengths;
|
||||
private final long sequenceNumber;
|
||||
private final Source[] sources;
|
||||
|
||||
Snapshot(String str, long j, Source[] sourceArr, long[] jArr) {
|
||||
this.key = str;
|
||||
this.sequenceNumber = j;
|
||||
this.sources = sourceArr;
|
||||
this.lengths = jArr;
|
||||
}
|
||||
|
||||
@Override // java.io.Closeable, java.lang.AutoCloseable
|
||||
public void close() {
|
||||
for (Source source : this.sources) {
|
||||
Util.closeQuietly(source);
|
||||
}
|
||||
}
|
||||
|
||||
public Editor edit() throws IOException {
|
||||
return DiskLruCache.this.edit(this.key, this.sequenceNumber);
|
||||
}
|
||||
|
||||
public long getLength(int i) {
|
||||
return this.lengths[i];
|
||||
}
|
||||
|
||||
public Source getSource(int i) {
|
||||
return this.sources[i];
|
||||
}
|
||||
|
||||
public String key() {
|
||||
return this.key;
|
||||
}
|
||||
}
|
||||
|
||||
DiskLruCache(FileSystem fileSystem, File file, int i, int i2, long j, Executor executor) {
|
||||
this.fileSystem = fileSystem;
|
||||
this.directory = file;
|
||||
this.appVersion = i;
|
||||
this.journalFile = new File(file, JOURNAL_FILE);
|
||||
this.journalFileTmp = new File(file, JOURNAL_FILE_TEMP);
|
||||
this.journalFileBackup = new File(file, JOURNAL_FILE_BACKUP);
|
||||
this.valueCount = i2;
|
||||
this.maxSize = j;
|
||||
this.executor = executor;
|
||||
}
|
||||
|
||||
private synchronized void checkNotClosed() {
|
||||
if (isClosed()) {
|
||||
throw new IllegalStateException("cache is closed");
|
||||
}
|
||||
}
|
||||
|
||||
public static DiskLruCache create(FileSystem fileSystem, File file, int i, int i2, long j) {
|
||||
if (j <= 0) {
|
||||
throw new IllegalArgumentException("maxSize <= 0");
|
||||
}
|
||||
if (i2 > 0) {
|
||||
return new DiskLruCache(fileSystem, file, i, i2, j, new ThreadPoolExecutor(0, 1, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue(), Util.threadFactory("OkHttp DiskLruCache", true)));
|
||||
}
|
||||
throw new IllegalArgumentException("valueCount <= 0");
|
||||
}
|
||||
|
||||
private BufferedSink newJournalWriter() throws FileNotFoundException {
|
||||
return Okio.buffer(new FaultHidingSink(this.fileSystem.appendingSink(this.journalFile)) { // from class: okhttp3.internal.cache.DiskLruCache.2
|
||||
static final /* synthetic */ boolean $assertionsDisabled = false;
|
||||
|
||||
@Override // okhttp3.internal.cache.FaultHidingSink
|
||||
protected void onException(IOException iOException) {
|
||||
DiskLruCache.this.hasJournalErrors = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void processJournal() throws IOException {
|
||||
this.fileSystem.delete(this.journalFileTmp);
|
||||
Iterator<Entry> it = this.lruEntries.values().iterator();
|
||||
while (it.hasNext()) {
|
||||
Entry next = it.next();
|
||||
int i = 0;
|
||||
if (next.currentEditor == null) {
|
||||
while (i < this.valueCount) {
|
||||
this.size += next.lengths[i];
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
next.currentEditor = null;
|
||||
while (i < this.valueCount) {
|
||||
this.fileSystem.delete(next.cleanFiles[i]);
|
||||
this.fileSystem.delete(next.dirtyFiles[i]);
|
||||
i++;
|
||||
}
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void readJournal() throws IOException {
|
||||
BufferedSource buffer = Okio.buffer(this.fileSystem.source(this.journalFile));
|
||||
try {
|
||||
String readUtf8LineStrict = buffer.readUtf8LineStrict();
|
||||
String readUtf8LineStrict2 = buffer.readUtf8LineStrict();
|
||||
String readUtf8LineStrict3 = buffer.readUtf8LineStrict();
|
||||
String readUtf8LineStrict4 = buffer.readUtf8LineStrict();
|
||||
String readUtf8LineStrict5 = buffer.readUtf8LineStrict();
|
||||
if (!MAGIC.equals(readUtf8LineStrict) || !"1".equals(readUtf8LineStrict2) || !Integer.toString(this.appVersion).equals(readUtf8LineStrict3) || !Integer.toString(this.valueCount).equals(readUtf8LineStrict4) || !"".equals(readUtf8LineStrict5)) {
|
||||
throw new IOException("unexpected journal header: [" + readUtf8LineStrict + ", " + readUtf8LineStrict2 + ", " + readUtf8LineStrict4 + ", " + readUtf8LineStrict5 + "]");
|
||||
}
|
||||
int i = 0;
|
||||
while (true) {
|
||||
try {
|
||||
readJournalLine(buffer.readUtf8LineStrict());
|
||||
i++;
|
||||
} catch (EOFException unused) {
|
||||
this.redundantOpCount = i - this.lruEntries.size();
|
||||
if (buffer.exhausted()) {
|
||||
this.journalWriter = newJournalWriter();
|
||||
} else {
|
||||
rebuildJournal();
|
||||
}
|
||||
Util.closeQuietly(buffer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (Throwable th) {
|
||||
Util.closeQuietly(buffer);
|
||||
throw th;
|
||||
}
|
||||
}
|
||||
|
||||
private void readJournalLine(String str) throws IOException {
|
||||
String substring;
|
||||
int indexOf = str.indexOf(32);
|
||||
if (indexOf == -1) {
|
||||
throw new IOException("unexpected journal line: " + str);
|
||||
}
|
||||
int i = indexOf + 1;
|
||||
int indexOf2 = str.indexOf(32, i);
|
||||
if (indexOf2 == -1) {
|
||||
substring = str.substring(i);
|
||||
if (indexOf == 6 && str.startsWith(REMOVE)) {
|
||||
this.lruEntries.remove(substring);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
substring = str.substring(i, indexOf2);
|
||||
}
|
||||
Entry entry = this.lruEntries.get(substring);
|
||||
if (entry == null) {
|
||||
entry = new Entry(substring);
|
||||
this.lruEntries.put(substring, entry);
|
||||
}
|
||||
if (indexOf2 != -1 && indexOf == 5 && str.startsWith(CLEAN)) {
|
||||
String[] split = str.substring(indexOf2 + 1).split(" ");
|
||||
entry.readable = true;
|
||||
entry.currentEditor = null;
|
||||
entry.setLengths(split);
|
||||
return;
|
||||
}
|
||||
if (indexOf2 == -1 && indexOf == 5 && str.startsWith(DIRTY)) {
|
||||
entry.currentEditor = new Editor(entry);
|
||||
return;
|
||||
}
|
||||
if (indexOf2 == -1 && indexOf == 4 && str.startsWith(READ)) {
|
||||
return;
|
||||
}
|
||||
throw new IOException("unexpected journal line: " + str);
|
||||
}
|
||||
|
||||
private void validateKey(String str) {
|
||||
if (LEGAL_KEY_PATTERN.matcher(str).matches()) {
|
||||
return;
|
||||
}
|
||||
throw new IllegalArgumentException("keys must match regex [a-z0-9_-]{1,120}: \"" + str + "\"");
|
||||
}
|
||||
|
||||
@Override // java.io.Closeable, java.lang.AutoCloseable
|
||||
public synchronized void close() throws IOException {
|
||||
if (this.initialized && !this.closed) {
|
||||
for (Entry entry : (Entry[]) this.lruEntries.values().toArray(new Entry[this.lruEntries.size()])) {
|
||||
if (entry.currentEditor != null) {
|
||||
entry.currentEditor.abort();
|
||||
}
|
||||
}
|
||||
trimToSize();
|
||||
this.journalWriter.close();
|
||||
this.journalWriter = null;
|
||||
this.closed = true;
|
||||
return;
|
||||
}
|
||||
this.closed = true;
|
||||
}
|
||||
|
||||
synchronized void completeEdit(Editor editor, boolean z) throws IOException {
|
||||
Entry entry = editor.entry;
|
||||
if (entry.currentEditor != editor) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
if (z && !entry.readable) {
|
||||
for (int i = 0; i < this.valueCount; i++) {
|
||||
if (!editor.written[i]) {
|
||||
editor.abort();
|
||||
throw new IllegalStateException("Newly created entry didn't create value for index " + i);
|
||||
}
|
||||
if (!this.fileSystem.exists(entry.dirtyFiles[i])) {
|
||||
editor.abort();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i2 = 0; i2 < this.valueCount; i2++) {
|
||||
File file = entry.dirtyFiles[i2];
|
||||
if (!z) {
|
||||
this.fileSystem.delete(file);
|
||||
} else if (this.fileSystem.exists(file)) {
|
||||
File file2 = entry.cleanFiles[i2];
|
||||
this.fileSystem.rename(file, file2);
|
||||
long j = entry.lengths[i2];
|
||||
long size = this.fileSystem.size(file2);
|
||||
entry.lengths[i2] = size;
|
||||
this.size = (this.size - j) + size;
|
||||
}
|
||||
}
|
||||
this.redundantOpCount++;
|
||||
entry.currentEditor = null;
|
||||
if (entry.readable || z) {
|
||||
entry.readable = true;
|
||||
this.journalWriter.writeUtf8(CLEAN).writeByte(32);
|
||||
this.journalWriter.writeUtf8(entry.key);
|
||||
entry.writeLengths(this.journalWriter);
|
||||
this.journalWriter.writeByte(10);
|
||||
if (z) {
|
||||
long j2 = this.nextSequenceNumber;
|
||||
this.nextSequenceNumber = 1 + j2;
|
||||
entry.sequenceNumber = j2;
|
||||
}
|
||||
} else {
|
||||
this.lruEntries.remove(entry.key);
|
||||
this.journalWriter.writeUtf8(REMOVE).writeByte(32);
|
||||
this.journalWriter.writeUtf8(entry.key);
|
||||
this.journalWriter.writeByte(10);
|
||||
}
|
||||
this.journalWriter.flush();
|
||||
if (this.size > this.maxSize || journalRebuildRequired()) {
|
||||
this.executor.execute(this.cleanupRunnable);
|
||||
}
|
||||
}
|
||||
|
||||
public void delete() throws IOException {
|
||||
close();
|
||||
this.fileSystem.deleteContents(this.directory);
|
||||
}
|
||||
|
||||
public Editor edit(String str) throws IOException {
|
||||
return edit(str, -1L);
|
||||
}
|
||||
|
||||
public synchronized void evictAll() throws IOException {
|
||||
initialize();
|
||||
for (Entry entry : (Entry[]) this.lruEntries.values().toArray(new Entry[this.lruEntries.size()])) {
|
||||
removeEntry(entry);
|
||||
}
|
||||
this.mostRecentTrimFailed = false;
|
||||
}
|
||||
|
||||
@Override // java.io.Flushable
|
||||
public synchronized void flush() throws IOException {
|
||||
if (this.initialized) {
|
||||
checkNotClosed();
|
||||
trimToSize();
|
||||
this.journalWriter.flush();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized Snapshot get(String str) throws IOException {
|
||||
initialize();
|
||||
checkNotClosed();
|
||||
validateKey(str);
|
||||
Entry entry = this.lruEntries.get(str);
|
||||
if (entry != null && entry.readable) {
|
||||
Snapshot snapshot = entry.snapshot();
|
||||
if (snapshot == null) {
|
||||
return null;
|
||||
}
|
||||
this.redundantOpCount++;
|
||||
this.journalWriter.writeUtf8(READ).writeByte(32).writeUtf8(str).writeByte(10);
|
||||
if (journalRebuildRequired()) {
|
||||
this.executor.execute(this.cleanupRunnable);
|
||||
}
|
||||
return snapshot;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public File getDirectory() {
|
||||
return this.directory;
|
||||
}
|
||||
|
||||
public synchronized long getMaxSize() {
|
||||
return this.maxSize;
|
||||
}
|
||||
|
||||
public synchronized void initialize() throws IOException {
|
||||
if (this.initialized) {
|
||||
return;
|
||||
}
|
||||
if (this.fileSystem.exists(this.journalFileBackup)) {
|
||||
if (this.fileSystem.exists(this.journalFile)) {
|
||||
this.fileSystem.delete(this.journalFileBackup);
|
||||
} else {
|
||||
this.fileSystem.rename(this.journalFileBackup, this.journalFile);
|
||||
}
|
||||
}
|
||||
if (this.fileSystem.exists(this.journalFile)) {
|
||||
try {
|
||||
readJournal();
|
||||
processJournal();
|
||||
this.initialized = true;
|
||||
return;
|
||||
} catch (IOException e) {
|
||||
Platform.get().log(5, "DiskLruCache " + this.directory + " is corrupt: " + e.getMessage() + ", removing", e);
|
||||
try {
|
||||
delete();
|
||||
this.closed = false;
|
||||
} catch (Throwable th) {
|
||||
this.closed = false;
|
||||
throw th;
|
||||
}
|
||||
}
|
||||
}
|
||||
rebuildJournal();
|
||||
this.initialized = true;
|
||||
}
|
||||
|
||||
public synchronized boolean isClosed() {
|
||||
return this.closed;
|
||||
}
|
||||
|
||||
boolean journalRebuildRequired() {
|
||||
int i = this.redundantOpCount;
|
||||
return i >= 2000 && i >= this.lruEntries.size();
|
||||
}
|
||||
|
||||
synchronized void rebuildJournal() throws IOException {
|
||||
if (this.journalWriter != null) {
|
||||
this.journalWriter.close();
|
||||
}
|
||||
BufferedSink buffer = Okio.buffer(this.fileSystem.sink(this.journalFileTmp));
|
||||
try {
|
||||
buffer.writeUtf8(MAGIC).writeByte(10);
|
||||
buffer.writeUtf8("1").writeByte(10);
|
||||
buffer.writeDecimalLong(this.appVersion).writeByte(10);
|
||||
buffer.writeDecimalLong(this.valueCount).writeByte(10);
|
||||
buffer.writeByte(10);
|
||||
for (Entry entry : this.lruEntries.values()) {
|
||||
if (entry.currentEditor != null) {
|
||||
buffer.writeUtf8(DIRTY).writeByte(32);
|
||||
buffer.writeUtf8(entry.key);
|
||||
buffer.writeByte(10);
|
||||
} else {
|
||||
buffer.writeUtf8(CLEAN).writeByte(32);
|
||||
buffer.writeUtf8(entry.key);
|
||||
entry.writeLengths(buffer);
|
||||
buffer.writeByte(10);
|
||||
}
|
||||
}
|
||||
buffer.close();
|
||||
if (this.fileSystem.exists(this.journalFile)) {
|
||||
this.fileSystem.rename(this.journalFile, this.journalFileBackup);
|
||||
}
|
||||
this.fileSystem.rename(this.journalFileTmp, this.journalFile);
|
||||
this.fileSystem.delete(this.journalFileBackup);
|
||||
this.journalWriter = newJournalWriter();
|
||||
this.hasJournalErrors = false;
|
||||
this.mostRecentRebuildFailed = false;
|
||||
} catch (Throwable th) {
|
||||
buffer.close();
|
||||
throw th;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized boolean remove(String str) throws IOException {
|
||||
initialize();
|
||||
checkNotClosed();
|
||||
validateKey(str);
|
||||
Entry entry = this.lruEntries.get(str);
|
||||
if (entry == null) {
|
||||
return false;
|
||||
}
|
||||
boolean removeEntry = removeEntry(entry);
|
||||
if (removeEntry && this.size <= this.maxSize) {
|
||||
this.mostRecentTrimFailed = false;
|
||||
}
|
||||
return removeEntry;
|
||||
}
|
||||
|
||||
boolean removeEntry(Entry entry) throws IOException {
|
||||
Editor editor = entry.currentEditor;
|
||||
if (editor != null) {
|
||||
editor.detach();
|
||||
}
|
||||
for (int i = 0; i < this.valueCount; i++) {
|
||||
this.fileSystem.delete(entry.cleanFiles[i]);
|
||||
long j = this.size;
|
||||
long[] jArr = entry.lengths;
|
||||
this.size = j - jArr[i];
|
||||
jArr[i] = 0;
|
||||
}
|
||||
this.redundantOpCount++;
|
||||
this.journalWriter.writeUtf8(REMOVE).writeByte(32).writeUtf8(entry.key).writeByte(10);
|
||||
this.lruEntries.remove(entry.key);
|
||||
if (journalRebuildRequired()) {
|
||||
this.executor.execute(this.cleanupRunnable);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public synchronized void setMaxSize(long j) {
|
||||
this.maxSize = j;
|
||||
if (this.initialized) {
|
||||
this.executor.execute(this.cleanupRunnable);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized long size() throws IOException {
|
||||
initialize();
|
||||
return this.size;
|
||||
}
|
||||
|
||||
public synchronized Iterator<Snapshot> snapshots() throws IOException {
|
||||
initialize();
|
||||
return new Iterator<Snapshot>() { // from class: okhttp3.internal.cache.DiskLruCache.3
|
||||
final Iterator<Entry> delegate;
|
||||
Snapshot nextSnapshot;
|
||||
Snapshot removeSnapshot;
|
||||
|
||||
{
|
||||
this.delegate = new ArrayList(DiskLruCache.this.lruEntries.values()).iterator();
|
||||
}
|
||||
|
||||
@Override // java.util.Iterator
|
||||
public boolean hasNext() {
|
||||
if (this.nextSnapshot != null) {
|
||||
return true;
|
||||
}
|
||||
synchronized (DiskLruCache.this) {
|
||||
if (DiskLruCache.this.closed) {
|
||||
return false;
|
||||
}
|
||||
while (this.delegate.hasNext()) {
|
||||
Snapshot snapshot = this.delegate.next().snapshot();
|
||||
if (snapshot != null) {
|
||||
this.nextSnapshot = snapshot;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override // java.util.Iterator
|
||||
public void remove() {
|
||||
Snapshot snapshot = this.removeSnapshot;
|
||||
if (snapshot == null) {
|
||||
throw new IllegalStateException("remove() before next()");
|
||||
}
|
||||
try {
|
||||
DiskLruCache.this.remove(snapshot.key);
|
||||
} catch (IOException unused) {
|
||||
} catch (Throwable th) {
|
||||
this.removeSnapshot = null;
|
||||
throw th;
|
||||
}
|
||||
this.removeSnapshot = null;
|
||||
}
|
||||
|
||||
@Override // java.util.Iterator
|
||||
public Snapshot next() {
|
||||
if (!hasNext()) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
this.removeSnapshot = this.nextSnapshot;
|
||||
this.nextSnapshot = null;
|
||||
return this.removeSnapshot;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void trimToSize() throws IOException {
|
||||
while (this.size > this.maxSize) {
|
||||
removeEntry(this.lruEntries.values().iterator().next());
|
||||
}
|
||||
this.mostRecentTrimFailed = false;
|
||||
}
|
||||
|
||||
synchronized Editor edit(String str, long j) throws IOException {
|
||||
initialize();
|
||||
checkNotClosed();
|
||||
validateKey(str);
|
||||
Entry entry = this.lruEntries.get(str);
|
||||
if (j != -1 && (entry == null || entry.sequenceNumber != j)) {
|
||||
return null;
|
||||
}
|
||||
if (entry != null && entry.currentEditor != null) {
|
||||
return null;
|
||||
}
|
||||
if (!this.mostRecentTrimFailed && !this.mostRecentRebuildFailed) {
|
||||
this.journalWriter.writeUtf8(DIRTY).writeByte(32).writeUtf8(str).writeByte(10);
|
||||
this.journalWriter.flush();
|
||||
if (this.hasJournalErrors) {
|
||||
return null;
|
||||
}
|
||||
if (entry == null) {
|
||||
entry = new Entry(str);
|
||||
this.lruEntries.put(str, entry);
|
||||
}
|
||||
Editor editor = new Editor(entry);
|
||||
entry.currentEditor = editor;
|
||||
return editor;
|
||||
}
|
||||
this.executor.execute(this.cleanupRunnable);
|
||||
return null;
|
||||
}
|
||||
}
|
58
sources/okhttp3/internal/cache/FaultHidingSink.java
vendored
Normal file
58
sources/okhttp3/internal/cache/FaultHidingSink.java
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
package okhttp3.internal.cache;
|
||||
|
||||
import java.io.IOException;
|
||||
import okio.Buffer;
|
||||
import okio.ForwardingSink;
|
||||
import okio.Sink;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
class FaultHidingSink extends ForwardingSink {
|
||||
private boolean hasErrors;
|
||||
|
||||
FaultHidingSink(Sink sink) {
|
||||
super(sink);
|
||||
}
|
||||
|
||||
@Override // okio.ForwardingSink, okio.Sink, java.io.Closeable, java.lang.AutoCloseable
|
||||
public void close() throws IOException {
|
||||
if (this.hasErrors) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
super.close();
|
||||
} catch (IOException e) {
|
||||
this.hasErrors = true;
|
||||
onException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // okio.ForwardingSink, okio.Sink, java.io.Flushable
|
||||
public void flush() throws IOException {
|
||||
if (this.hasErrors) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
super.flush();
|
||||
} catch (IOException e) {
|
||||
this.hasErrors = true;
|
||||
onException(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void onException(IOException iOException) {
|
||||
}
|
||||
|
||||
@Override // okio.ForwardingSink, okio.Sink
|
||||
public void write(Buffer buffer, long j) throws IOException {
|
||||
if (this.hasErrors) {
|
||||
buffer.skip(j);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
super.write(buffer, j);
|
||||
} catch (IOException e) {
|
||||
this.hasErrors = true;
|
||||
onException(e);
|
||||
}
|
||||
}
|
||||
}
|
20
sources/okhttp3/internal/cache/InternalCache.java
vendored
Normal file
20
sources/okhttp3/internal/cache/InternalCache.java
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
package okhttp3.internal.cache;
|
||||
|
||||
import java.io.IOException;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
/* loaded from: classes2.dex */
|
||||
public interface InternalCache {
|
||||
Response get(Request request) throws IOException;
|
||||
|
||||
CacheRequest put(Response response) throws IOException;
|
||||
|
||||
void remove(Request request) throws IOException;
|
||||
|
||||
void trackConditionalCacheHit();
|
||||
|
||||
void trackResponse(CacheStrategy cacheStrategy);
|
||||
|
||||
void update(Response response, Response response2);
|
||||
}
|
Reference in New Issue
Block a user