HTTPCLIENT-2284: internal cache storage improvements (#478)
This commit is contained in:
parent
8466b19861
commit
893574e092
|
@ -52,13 +52,13 @@ import org.apache.hc.core5.util.Args;
|
|||
@Contract(threading = ThreadingBehavior.SAFE)
|
||||
public class BasicHttpCacheStorage implements HttpCacheStorage {
|
||||
|
||||
private final CacheMap entries;
|
||||
private final InternalCacheStorage entries;
|
||||
|
||||
private final ReentrantLock lock;
|
||||
|
||||
public BasicHttpCacheStorage(final CacheConfig config) {
|
||||
super();
|
||||
this.entries = new CacheMap(config.getMaxCacheEntries());
|
||||
this.entries = new InternalCacheStorage(config.getMaxCacheEntries(), null);
|
||||
this.lock = new ReentrantLock();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
package org.apache.hc.client5.http.impl.cache;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.hc.client5.http.cache.HttpCacheEntry;
|
||||
|
||||
final class CacheMap extends LinkedHashMap<String, HttpCacheEntry> {
|
||||
|
||||
private static final long serialVersionUID = -7750025207539768511L;
|
||||
|
||||
private final int maxEntries;
|
||||
|
||||
CacheMap(final int maxEntries) {
|
||||
super(20, 0.75f, true);
|
||||
this.maxEntries = maxEntries;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean removeEldestEntry(final Map.Entry<String, HttpCacheEntry> eldest) {
|
||||
return size() > this.maxEntries;
|
||||
}
|
||||
|
||||
}
|
96
httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/InternalCacheStorage.java
vendored
Normal file
96
httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/InternalCacheStorage.java
vendored
Normal file
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
package org.apache.hc.client5.http.impl.cache;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.apache.hc.client5.http.cache.HttpCacheEntry;
|
||||
import org.apache.hc.client5.http.cache.HttpCacheStorageEntry;
|
||||
import org.apache.hc.core5.annotation.Internal;
|
||||
|
||||
@Internal
|
||||
final public class InternalCacheStorage {
|
||||
|
||||
private final Map<String, HttpCacheEntry> map;
|
||||
private final Queue<HttpCacheStorageEntry> evictionQueue;
|
||||
private final Consumer<HttpCacheStorageEntry> evictionCallback;
|
||||
|
||||
public InternalCacheStorage(final int maxEntries, final Consumer<HttpCacheStorageEntry> evictionCallback) {
|
||||
this.evictionCallback = evictionCallback;
|
||||
this.map = new LinkedHashMap<String, HttpCacheEntry>(20, 0.75f, true) {
|
||||
|
||||
@Override
|
||||
protected boolean removeEldestEntry(final Map.Entry<String, HttpCacheEntry> eldest) {
|
||||
if (size() > maxEntries) {
|
||||
if (evictionCallback != null) {
|
||||
evictionQueue.add(new HttpCacheStorageEntry(eldest.getKey(), eldest.getValue()));
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
this.evictionQueue = new LinkedList<>();
|
||||
}
|
||||
|
||||
public InternalCacheStorage(final int maxEntries) {
|
||||
this(maxEntries, null);
|
||||
}
|
||||
|
||||
public InternalCacheStorage() {
|
||||
this(Integer.MAX_VALUE, null);
|
||||
}
|
||||
|
||||
public void put(final String key, final HttpCacheEntry entry) {
|
||||
map.put(key, entry);
|
||||
HttpCacheStorageEntry evicted;
|
||||
while ((evicted = evictionQueue.poll()) != null) {
|
||||
if (evictionCallback != null) {
|
||||
evictionCallback.accept(evicted);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public HttpCacheEntry get(final String key) {
|
||||
return map.get(key);
|
||||
}
|
||||
|
||||
public HttpCacheEntry remove(final String key) {
|
||||
return map.remove(key);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
map.clear();
|
||||
}
|
||||
|
||||
}
|
|
@ -78,7 +78,7 @@ import org.apache.hc.core5.util.Args;
|
|||
@Contract(threading = ThreadingBehavior.SAFE)
|
||||
public class ManagedHttpCacheStorage implements HttpCacheStorage, Closeable {
|
||||
|
||||
private final CacheMap entries;
|
||||
private final InternalCacheStorage entries;
|
||||
private final ReferenceQueue<HttpCacheEntry> morque;
|
||||
private final Set<ResourceReference> resources;
|
||||
private final AtomicBoolean active;
|
||||
|
@ -87,7 +87,7 @@ public class ManagedHttpCacheStorage implements HttpCacheStorage, Closeable {
|
|||
|
||||
public ManagedHttpCacheStorage(final CacheConfig config) {
|
||||
super();
|
||||
this.entries = new CacheMap(config.getMaxCacheEntries());
|
||||
this.entries = new InternalCacheStorage(config.getMaxCacheEntries(), null);
|
||||
this.morque = new ReferenceQueue<>();
|
||||
this.resources = new HashSet<>();
|
||||
this.active = new AtomicBoolean(true);
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
package org.apache.hc.client5.http.impl.cache;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
|
||||
import org.apache.hc.client5.http.cache.HttpCacheEntry;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class TestInternalCacheStorage {
|
||||
|
||||
@Test
|
||||
public void testCacheBasics() {
|
||||
final InternalCacheStorage storage = new InternalCacheStorage();
|
||||
final String key1 = "some-key-1";
|
||||
Assertions.assertNull(storage.get(key1));
|
||||
Assertions.assertNull(storage.remove(key1));
|
||||
final HttpCacheEntry entry1 = HttpTestUtils.makeCacheEntry();
|
||||
storage.put(key1, entry1);
|
||||
Assertions.assertSame(entry1, storage.get(key1));
|
||||
Assertions.assertSame(entry1, storage.remove(key1));
|
||||
Assertions.assertNull(storage.get(key1));
|
||||
Assertions.assertNull(storage.remove(key1));
|
||||
final String key2 = "some-key-2";
|
||||
final HttpCacheEntry entry2 = HttpTestUtils.makeCacheEntry();
|
||||
final String key3 = "some-key-3";
|
||||
final HttpCacheEntry entry3 = HttpTestUtils.makeCacheEntry();
|
||||
storage.put(key2, entry2);
|
||||
storage.put(key3, entry3);
|
||||
Assertions.assertSame(entry2, storage.get(key2));
|
||||
Assertions.assertSame(entry3, storage.get(key3));
|
||||
storage.clear();
|
||||
Assertions.assertNull(storage.get(key2));
|
||||
Assertions.assertNull(storage.get(key3));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCacheEviction() {
|
||||
final Queue<HttpCacheEntry> evictedEntries = new LinkedList<>();
|
||||
final InternalCacheStorage storage = new InternalCacheStorage(2, e -> evictedEntries.add(e.getContent()));
|
||||
final String key1 = "some-key-1";
|
||||
final String key2 = "some-key-2";
|
||||
final String key3 = "some-key-3";
|
||||
final String key4 = "some-key-4";
|
||||
final HttpCacheEntry entry1 = HttpTestUtils.makeCacheEntry();
|
||||
final HttpCacheEntry entry2 = HttpTestUtils.makeCacheEntry();
|
||||
final HttpCacheEntry entry3 = HttpTestUtils.makeCacheEntry();
|
||||
final HttpCacheEntry entry4 = HttpTestUtils.makeCacheEntry();
|
||||
|
||||
storage.put(key1, entry1);
|
||||
storage.put(key2, entry2);
|
||||
storage.put(key3, entry3);
|
||||
storage.put(key4, entry4);
|
||||
Assertions.assertSame(entry1, evictedEntries.poll());
|
||||
Assertions.assertSame(entry2, evictedEntries.poll());
|
||||
Assertions.assertNull(evictedEntries.poll());
|
||||
|
||||
storage.clear();
|
||||
storage.put(key1, entry1);
|
||||
storage.put(key2, entry2);
|
||||
storage.get(key1);
|
||||
storage.put(key3, entry3);
|
||||
storage.get(key1);
|
||||
storage.put(key4, entry4);
|
||||
|
||||
Assertions.assertSame(entry2, evictedEntries.poll());
|
||||
Assertions.assertSame(entry3, evictedEntries.poll());
|
||||
Assertions.assertNull(evictedEntries.poll());
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue