Browse Source

Cache access tweaks (#750)

* don't create new cache key when there are no filters, just use the path

* fix non volatile double checked locking cache initialisation, replace with variant of holder pattern
pull/763/head
Richard Startin 3 years ago committed by GitHub
parent
commit
491dfbc15e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      json-path/src/main/java/com/jayway/jsonpath/internal/JsonContext.java
  2. 46
      json-path/src/main/java/com/jayway/jsonpath/spi/cache/CacheProvider.java

6
json-path/src/main/java/com/jayway/jsonpath/internal/JsonContext.java

@ -29,13 +29,12 @@ import com.jayway.jsonpath.spi.cache.CacheProvider;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.LinkedList; import java.util.Arrays;
import java.util.List; import java.util.List;
import static com.jayway.jsonpath.JsonPath.compile; import static com.jayway.jsonpath.JsonPath.compile;
import static com.jayway.jsonpath.internal.Utils.notEmpty; import static com.jayway.jsonpath.internal.Utils.notEmpty;
import static com.jayway.jsonpath.internal.Utils.notNull; import static com.jayway.jsonpath.internal.Utils.notNull;
import static java.util.Arrays.asList;
public class JsonContext implements DocumentContext { public class JsonContext implements DocumentContext {
@ -216,7 +215,8 @@ public class JsonContext implements DocumentContext {
private JsonPath pathFromCache(String path, Predicate[] filters) { private JsonPath pathFromCache(String path, Predicate[] filters) {
Cache cache = CacheProvider.getCache(); Cache cache = CacheProvider.getCache();
String cacheKey = Utils.concat(path, new LinkedList<Predicate>(asList(filters)).toString()); String cacheKey = filters == null || filters.length == 0
? path : Utils.concat(path, Arrays.toString(filters));
JsonPath jsonPath = cache.get(cacheKey); JsonPath jsonPath = cache.get(cacheKey);
if (jsonPath == null) { if (jsonPath == null) {
jsonPath = compile(path, filters); jsonPath = compile(path, filters);

46
json-path/src/main/java/com/jayway/jsonpath/spi/cache/CacheProvider.java vendored

@ -2,31 +2,47 @@ package com.jayway.jsonpath.spi.cache;
import com.jayway.jsonpath.JsonPathException; import com.jayway.jsonpath.JsonPathException;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
import static com.jayway.jsonpath.internal.Utils.notNull; import static com.jayway.jsonpath.internal.Utils.notNull;
public class CacheProvider { public class CacheProvider {
private static Cache cache;
private static final AtomicReferenceFieldUpdater<CacheProvider, Cache> UPDATER =
AtomicReferenceFieldUpdater.newUpdater(CacheProvider.class, Cache.class, "cache");
private static final CacheProvider instance = new CacheProvider();
private volatile Cache cache;
private static class CacheHolder {
static final Cache CACHE;
static {
Cache cache = CacheProvider.instance.cache;
// the application is trying to use the cache
// and if no external implementation has been registered,
// we need to initialise it to the default LRUCache
if (cache == null) {
cache = getDefaultCache();
// on the off chance that the cache implementation was registered during
// initialisation of the holder, this should be respected, so if the
// default cache can't be written back, just read the user supplied value again
if (!UPDATER.compareAndSet(instance, null, cache)) {
cache = CacheProvider.instance.cache;
}
}
CACHE = cache;
}
}
public static void setCache(Cache cache){ public static void setCache(Cache cache){
notNull(cache, "Cache may not be null"); notNull(cache, "Cache may not be null");
synchronized (CacheProvider.class){ if (!UPDATER.compareAndSet(instance, null, cache)) {
if(CacheProvider.cache != null){ throw new JsonPathException("Cache provider must be configured before cache is accessed and must not be registered twice.");
throw new JsonPathException("Cache provider must be configured before cache is accessed.");
} else {
CacheProvider.cache = cache;
}
} }
} }
public static Cache getCache() { public static Cache getCache() {
if(CacheProvider.cache == null){ return CacheHolder.CACHE;
synchronized (CacheProvider.class){
if(CacheProvider.cache == null){
CacheProvider.cache = getDefaultCache();
}
}
}
return CacheProvider.cache;
} }

Loading…
Cancel
Save