Merge branch 'stable-2.16' into stable-3.0

* stable-2.16:
  Switch PatchListCache to using legacy cache backend
  Replace guava caches with caffeine

Add caffeine and caffeine-guava to Documentation/licenses.txt
which did not exist on earlier branches.

Change-Id: I40fb2798a8b6eda2e92e4409c1e57042a8e59ef4
This commit is contained in:
David Pursehouse 2019-12-04 17:43:38 +09:00
commit 791d19e0f4
14 changed files with 243 additions and 32 deletions

View File

@ -90,6 +90,8 @@ Apache2.0
* openid:xerces * openid:xerces
* polymer_externs:polymer_closure * polymer_externs:polymer_closure
* blame-cache * blame-cache
* caffeine
* caffeine-guava
* gson * gson
* guava * guava
* guava-failureaccess * guava-failureaccess

View File

@ -214,6 +214,31 @@ maven_jar(
sha1 = GUAVA_BIN_SHA1, sha1 = GUAVA_BIN_SHA1,
) )
CAFFEINE_VERS = "2.8.0"
maven_jar(
name = "caffeine",
artifact = "com.github.ben-manes.caffeine:caffeine:" + CAFFEINE_VERS,
sha1 = "6000774d7f8412ced005a704188ced78beeed2bb",
)
# TODO(davido): Rename guava.jar to caffeine-guava.jar on fetch to prevent potential
# naming collision between caffeine guava adapater and guava library itself.
# Remove this renaming procedure, once this upstream issue is fixed:
# https://github.com/ben-manes/caffeine/issues/364.
http_file(
name = "caffeine-guava-renamed",
downloaded_file_path = "caffeine-guava-" + CAFFEINE_VERS + ".jar",
sha256 = "3a66ee3ec70971dee0bae6e56bda7b8742bc4bedd7489161bfbbaaf7137d89e1",
urls = [
"https://repo1.maven.org/maven2/com/github/ben-manes/caffeine/guava/" +
CAFFEINE_VERS +
"/guava-" +
CAFFEINE_VERS +
".jar",
],
)
maven_jar( maven_jar(
name = "guava-failureaccess", name = "guava-failureaccess",
artifact = "com.google.guava:failureaccess:1.0.1", artifact = "com.google.guava:failureaccess:1.0.1",

View File

@ -0,0 +1,25 @@
// Copyright (C) 2019 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.gerrit.server.cache;
/** Caffeine is used as default cache backend, but can be overridden with Guava backend. */
public enum CacheBackend {
CAFFEINE,
GUAVA;
public boolean isLegacyBackend() {
return this == GUAVA;
}
}

View File

@ -68,7 +68,8 @@ public abstract class CacheModule extends FactoryModule {
*/ */
protected <K, V> CacheBinding<K, V> cache( protected <K, V> CacheBinding<K, V> cache(
String name, TypeLiteral<K> keyType, TypeLiteral<V> valType) { String name, TypeLiteral<K> keyType, TypeLiteral<V> valType) {
CacheProvider<K, V> m = new CacheProvider<>(this, name, keyType, valType); CacheProvider<K, V> m =
new CacheProvider<>(this, name, keyType, valType, CacheBackend.CAFFEINE);
bindCache(m, name, keyType, valType); bindCache(m, name, keyType, valType);
return m; return m;
} }
@ -123,7 +124,20 @@ public abstract class CacheModule extends FactoryModule {
*/ */
protected <K, V> PersistentCacheBinding<K, V> persist( protected <K, V> PersistentCacheBinding<K, V> persist(
String name, Class<K> keyType, Class<V> valType) { String name, Class<K> keyType, Class<V> valType) {
return persist(name, TypeLiteral.get(keyType), TypeLiteral.get(valType)); return persist(name, TypeLiteral.get(keyType), TypeLiteral.get(valType), CacheBackend.CAFFEINE);
}
/**
* Declare a named in-memory/on-disk cache.
*
* @param <K> type of key used to lookup entries.
* @param <V> type of value stored by the cache.
* @param backend cache backend.
* @return binding to describe the cache.
*/
protected <K, V> PersistentCacheBinding<K, V> persist(
String name, Class<K> keyType, Class<V> valType, CacheBackend backend) {
return persist(name, TypeLiteral.get(keyType), TypeLiteral.get(valType), backend);
} }
/** /**
@ -135,7 +149,7 @@ public abstract class CacheModule extends FactoryModule {
*/ */
protected <K, V> PersistentCacheBinding<K, V> persist( protected <K, V> PersistentCacheBinding<K, V> persist(
String name, Class<K> keyType, TypeLiteral<V> valType) { String name, Class<K> keyType, TypeLiteral<V> valType) {
return persist(name, TypeLiteral.get(keyType), valType); return persist(name, TypeLiteral.get(keyType), valType, CacheBackend.CAFFEINE);
} }
/** /**
@ -146,8 +160,9 @@ public abstract class CacheModule extends FactoryModule {
* @return binding to describe the cache. * @return binding to describe the cache.
*/ */
protected <K, V> PersistentCacheBinding<K, V> persist( protected <K, V> PersistentCacheBinding<K, V> persist(
String name, TypeLiteral<K> keyType, TypeLiteral<V> valType) { String name, TypeLiteral<K> keyType, TypeLiteral<V> valType, CacheBackend backend) {
PersistentCacheProvider<K, V> m = new PersistentCacheProvider<>(this, name, keyType, valType); PersistentCacheProvider<K, V> m =
new PersistentCacheProvider<>(this, name, keyType, valType, backend);
bindCache(m, name, keyType, valType); bindCache(m, name, keyType, valType);
Type cacheDefType = Type cacheDefType =

View File

@ -30,6 +30,7 @@ import java.time.Duration;
class CacheProvider<K, V> implements Provider<Cache<K, V>>, CacheBinding<K, V>, CacheDef<K, V> { class CacheProvider<K, V> implements Provider<Cache<K, V>>, CacheBinding<K, V>, CacheDef<K, V> {
private final CacheModule module; private final CacheModule module;
private final CacheBackend backend;
final String name; final String name;
private final TypeLiteral<K> keyType; private final TypeLiteral<K> keyType;
private final TypeLiteral<V> valType; private final TypeLiteral<V> valType;
@ -44,11 +45,17 @@ class CacheProvider<K, V> implements Provider<Cache<K, V>>, CacheBinding<K, V>,
private MemoryCacheFactory memoryCacheFactory; private MemoryCacheFactory memoryCacheFactory;
private boolean frozen; private boolean frozen;
CacheProvider(CacheModule module, String name, TypeLiteral<K> keyType, TypeLiteral<V> valType) { CacheProvider(
CacheModule module,
String name,
TypeLiteral<K> keyType,
TypeLiteral<V> valType,
CacheBackend backend) {
this.module = module; this.module = module;
this.name = name; this.name = name;
this.keyType = keyType; this.keyType = keyType;
this.valType = valType; this.valType = valType;
this.backend = backend;
} }
@Inject(optional = true) @Inject(optional = true)
@ -159,7 +166,9 @@ class CacheProvider<K, V> implements Provider<Cache<K, V>>, CacheBinding<K, V>,
public Cache<K, V> get() { public Cache<K, V> get() {
freeze(); freeze();
CacheLoader<K, V> ldr = loader(); CacheLoader<K, V> ldr = loader();
return ldr != null ? memoryCacheFactory.build(this, ldr) : memoryCacheFactory.build(this); return ldr != null
? memoryCacheFactory.build(this, ldr, backend)
: memoryCacheFactory.build(this, backend);
} }
protected void checkNotFrozen() { protected void checkNotFrozen() {

View File

@ -19,7 +19,8 @@ import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache; import com.google.common.cache.LoadingCache;
public interface MemoryCacheFactory { public interface MemoryCacheFactory {
<K, V> Cache<K, V> build(CacheDef<K, V> def); <K, V> Cache<K, V> build(CacheDef<K, V> def, CacheBackend backend);
<K, V> LoadingCache<K, V> build(CacheDef<K, V> def, CacheLoader<K, V> loader); <K, V> LoadingCache<K, V> build(
CacheDef<K, V> def, CacheLoader<K, V> loader, CacheBackend backend);
} }

View File

@ -19,9 +19,10 @@ import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache; import com.google.common.cache.LoadingCache;
public interface PersistentCacheFactory { public interface PersistentCacheFactory {
<K, V> Cache<K, V> build(PersistentCacheDef<K, V> def); <K, V> Cache<K, V> build(PersistentCacheDef<K, V> def, CacheBackend backend);
<K, V> LoadingCache<K, V> build(PersistentCacheDef<K, V> def, CacheLoader<K, V> loader); <K, V> LoadingCache<K, V> build(
PersistentCacheDef<K, V> def, CacheLoader<K, V> loader, CacheBackend backend);
void onStop(String plugin); void onStop(String plugin);
} }

View File

@ -30,6 +30,7 @@ import java.time.Duration;
class PersistentCacheProvider<K, V> extends CacheProvider<K, V> class PersistentCacheProvider<K, V> extends CacheProvider<K, V>
implements Provider<Cache<K, V>>, PersistentCacheBinding<K, V>, PersistentCacheDef<K, V> { implements Provider<Cache<K, V>>, PersistentCacheBinding<K, V>, PersistentCacheDef<K, V> {
private final CacheBackend backend;
private int version; private int version;
private long diskLimit; private long diskLimit;
private CacheSerializer<K> keySerializer; private CacheSerializer<K> keySerializer;
@ -39,9 +40,19 @@ class PersistentCacheProvider<K, V> extends CacheProvider<K, V>
PersistentCacheProvider( PersistentCacheProvider(
CacheModule module, String name, TypeLiteral<K> keyType, TypeLiteral<V> valType) { CacheModule module, String name, TypeLiteral<K> keyType, TypeLiteral<V> valType) {
super(module, name, keyType, valType); this(module, name, keyType, valType, CacheBackend.CAFFEINE);
}
PersistentCacheProvider(
CacheModule module,
String name,
TypeLiteral<K> keyType,
TypeLiteral<V> valType,
CacheBackend backend) {
super(module, name, keyType, valType, backend);
version = -1; version = -1;
diskLimit = 128 << 20; diskLimit = 128 << 20;
this.backend = backend;
} }
@Inject(optional = true) @Inject(optional = true)
@ -130,8 +141,8 @@ class PersistentCacheProvider<K, V> extends CacheProvider<K, V>
freeze(); freeze();
CacheLoader<K, V> ldr = loader(); CacheLoader<K, V> ldr = loader();
return ldr != null return ldr != null
? persistentCacheFactory.build(this, ldr) ? persistentCacheFactory.build(this, ldr, backend)
: persistentCacheFactory.build(this); : persistentCacheFactory.build(this, backend);
} }
private static <T> void checkSerializer( private static <T> void checkSerializer(

View File

@ -21,6 +21,7 @@ import com.google.common.flogger.FluentLogger;
import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.google.gerrit.extensions.events.LifecycleListener; import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.extensions.registration.DynamicMap; import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.server.cache.CacheBackend;
import com.google.gerrit.server.cache.MemoryCacheFactory; import com.google.gerrit.server.cache.MemoryCacheFactory;
import com.google.gerrit.server.cache.PersistentCacheDef; import com.google.gerrit.server.cache.PersistentCacheDef;
import com.google.gerrit.server.cache.PersistentCacheFactory; import com.google.gerrit.server.cache.PersistentCacheFactory;
@ -156,18 +157,21 @@ class H2CacheFactory implements PersistentCacheFactory, LifecycleListener {
@SuppressWarnings({"unchecked"}) @SuppressWarnings({"unchecked"})
@Override @Override
public <K, V> Cache<K, V> build(PersistentCacheDef<K, V> in) { public <K, V> Cache<K, V> build(PersistentCacheDef<K, V> in, CacheBackend backend) {
long limit = config.getLong("cache", in.configKey(), "diskLimit", in.diskLimit()); long limit = config.getLong("cache", in.configKey(), "diskLimit", in.diskLimit());
if (cacheDir == null || limit <= 0) { if (cacheDir == null || limit <= 0) {
return memCacheFactory.build(in); return memCacheFactory.build(in, backend);
} }
H2CacheDefProxy<K, V> def = new H2CacheDefProxy<>(in); H2CacheDefProxy<K, V> def = new H2CacheDefProxy<>(in);
SqlStore<K, V> store = newSqlStore(def, limit); SqlStore<K, V> store = newSqlStore(def, limit);
H2CacheImpl<K, V> cache = H2CacheImpl<K, V> cache =
new H2CacheImpl<>( new H2CacheImpl<>(
executor, store, def.keyType(), (Cache<K, ValueHolder<V>>) memCacheFactory.build(def)); executor,
store,
def.keyType(),
(Cache<K, ValueHolder<V>>) memCacheFactory.build(def, backend));
synchronized (caches) { synchronized (caches) {
caches.add(cache); caches.add(cache);
} }
@ -176,11 +180,12 @@ class H2CacheFactory implements PersistentCacheFactory, LifecycleListener {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public <K, V> LoadingCache<K, V> build(PersistentCacheDef<K, V> in, CacheLoader<K, V> loader) { public <K, V> LoadingCache<K, V> build(
PersistentCacheDef<K, V> in, CacheLoader<K, V> loader, CacheBackend backend) {
long limit = config.getLong("cache", in.configKey(), "diskLimit", in.diskLimit()); long limit = config.getLong("cache", in.configKey(), "diskLimit", in.diskLimit());
if (cacheDir == null || limit <= 0) { if (cacheDir == null || limit <= 0) {
return memCacheFactory.build(in, loader); return memCacheFactory.build(in, loader, backend);
} }
H2CacheDefProxy<K, V> def = new H2CacheDefProxy<>(in); H2CacheDefProxy<K, V> def = new H2CacheDefProxy<>(in);
@ -188,7 +193,9 @@ class H2CacheFactory implements PersistentCacheFactory, LifecycleListener {
Cache<K, ValueHolder<V>> mem = Cache<K, ValueHolder<V>> mem =
(Cache<K, ValueHolder<V>>) (Cache<K, ValueHolder<V>>)
memCacheFactory.build( memCacheFactory.build(
def, (CacheLoader<K, V>) new H2CacheImpl.Loader<>(executor, store, loader)); def,
(CacheLoader<K, V>) new H2CacheImpl.Loader<>(executor, store, loader),
backend);
H2CacheImpl<K, V> cache = new H2CacheImpl<>(executor, store, def.keyType(), mem); H2CacheImpl<K, V> cache = new H2CacheImpl<>(executor, store, def.keyType(), mem);
synchronized (caches) { synchronized (caches) {
caches.add(cache); caches.add(cache);

View File

@ -8,6 +8,8 @@ java_library(
"//java/com/google/gerrit/common:annotations", "//java/com/google/gerrit/common:annotations",
"//java/com/google/gerrit/extensions:api", "//java/com/google/gerrit/extensions:api",
"//java/com/google/gerrit/server", "//java/com/google/gerrit/server",
"//lib:caffeine",
"//lib:caffeine-guava",
"//lib:guava", "//lib:guava",
"//lib/guice", "//lib/guice",
"//lib/jgit/org.eclipse.jgit:jgit", "//lib/jgit/org.eclipse.jgit:jgit",

View File

@ -17,13 +17,18 @@ package com.google.gerrit.server.cache.mem;
import static java.util.concurrent.TimeUnit.NANOSECONDS; import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static java.util.concurrent.TimeUnit.SECONDS; import static java.util.concurrent.TimeUnit.SECONDS;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.RemovalListener;
import com.github.benmanes.caffeine.cache.Weigher;
import com.github.benmanes.caffeine.guava.CaffeinatedGuava;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.google.common.cache.Cache; import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader; import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache; import com.google.common.cache.LoadingCache;
import com.google.common.cache.Weigher; import com.google.common.cache.RemovalNotification;
import com.google.gerrit.common.Nullable; import com.google.gerrit.common.Nullable;
import com.google.gerrit.server.cache.CacheBackend;
import com.google.gerrit.server.cache.CacheDef; import com.google.gerrit.server.cache.CacheDef;
import com.google.gerrit.server.cache.ForwardingRemovalListener; import com.google.gerrit.server.cache.ForwardingRemovalListener;
import com.google.gerrit.server.cache.MemoryCacheFactory; import com.google.gerrit.server.cache.MemoryCacheFactory;
@ -46,25 +51,30 @@ class DefaultMemoryCacheFactory implements MemoryCacheFactory {
} }
@Override @Override
public <K, V> Cache<K, V> build(CacheDef<K, V> def) { public <K, V> Cache<K, V> build(CacheDef<K, V> def, CacheBackend backend) {
return create(def).build(); return backend.isLegacyBackend()
? createLegacy(def).build()
: CaffeinatedGuava.build(create(def));
} }
@Override @Override
public <K, V> LoadingCache<K, V> build(CacheDef<K, V> def, CacheLoader<K, V> loader) { public <K, V> LoadingCache<K, V> build(
return create(def).build(loader); CacheDef<K, V> def, CacheLoader<K, V> loader, CacheBackend backend) {
return backend.isLegacyBackend()
? createLegacy(def).build(loader)
: CaffeinatedGuava.build(create(def), loader);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private <K, V> CacheBuilder<K, V> create(CacheDef<K, V> def) { private <K, V> CacheBuilder<K, V> createLegacy(CacheDef<K, V> def) {
CacheBuilder<K, V> builder = newCacheBuilder(); CacheBuilder<K, V> builder = newLegacyCacheBuilder();
builder.recordStats(); builder.recordStats();
builder.maximumWeight( builder.maximumWeight(
cfg.getLong("cache", def.configKey(), "memoryLimit", def.maximumWeight())); cfg.getLong("cache", def.configKey(), "memoryLimit", def.maximumWeight()));
builder = builder.removalListener(forwardingRemovalListenerFactory.create(def.name())); builder = builder.removalListener(forwardingRemovalListenerFactory.create(def.name()));
Weigher<K, V> weigher = def.weigher(); com.google.common.cache.Weigher<K, V> weigher = def.weigher();
if (weigher == null) { if (weigher == null) {
weigher = unitWeight(); weigher = unitWeight();
} }
@ -98,6 +108,42 @@ class DefaultMemoryCacheFactory implements MemoryCacheFactory {
return builder; return builder;
} }
private <K, V> Caffeine<K, V> create(CacheDef<K, V> def) {
Caffeine<K, V> builder = newCacheBuilder();
builder.recordStats();
builder.maximumWeight(
cfg.getLong("cache", def.configKey(), "memoryLimit", def.maximumWeight()));
builder = builder.removalListener(newRemovalListener(def.name()));
builder.weigher(newWeigher(def.weigher()));
Duration expireAfterWrite = def.expireAfterWrite();
if (has(def.configKey(), "maxAge")) {
builder.expireAfterWrite(
ConfigUtil.getTimeUnit(
cfg, "cache", def.configKey(), "maxAge", toSeconds(expireAfterWrite), SECONDS),
SECONDS);
} else if (expireAfterWrite != null) {
builder.expireAfterWrite(expireAfterWrite.toNanos(), NANOSECONDS);
}
Duration expireAfterAccess = def.expireFromMemoryAfterAccess();
if (has(def.configKey(), "expireFromMemoryAfterAccess")) {
builder.expireAfterAccess(
ConfigUtil.getTimeUnit(
cfg,
"cache",
def.configKey(),
"expireFromMemoryAfterAccess",
toSeconds(expireAfterAccess),
SECONDS),
SECONDS);
} else if (expireAfterAccess != null) {
builder.expireAfterAccess(expireAfterAccess.toNanos(), NANOSECONDS);
}
return builder;
}
private static long toSeconds(@Nullable Duration duration) { private static long toSeconds(@Nullable Duration duration) {
return duration != null ? duration.getSeconds() : 0; return duration != null ? duration.getSeconds() : 0;
} }
@ -107,11 +153,31 @@ class DefaultMemoryCacheFactory implements MemoryCacheFactory {
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private static <K, V> CacheBuilder<K, V> newCacheBuilder() { private static <K, V> CacheBuilder<K, V> newLegacyCacheBuilder() {
return (CacheBuilder<K, V>) CacheBuilder.newBuilder(); return (CacheBuilder<K, V>) CacheBuilder.newBuilder();
} }
private static <K, V> Weigher<K, V> unitWeight() { private static <K, V> com.google.common.cache.Weigher<K, V> unitWeight() {
return (key, value) -> 1; return (key, value) -> 1;
} }
@SuppressWarnings("unchecked")
private static <K, V> Caffeine<K, V> newCacheBuilder() {
return (Caffeine<K, V>) Caffeine.newBuilder();
}
@SuppressWarnings("unchecked")
private <V, K> RemovalListener<K, V> newRemovalListener(String cacheName) {
return (k, v, cause) ->
forwardingRemovalListenerFactory
.create(cacheName)
.onRemoval(
RemovalNotification.create(
k, v, com.google.common.cache.RemovalCause.valueOf(cause.name())));
}
private static <K, V> Weigher<K, V> newWeigher(
com.google.common.cache.Weigher<K, V> guavaWeigher) {
return guavaWeigher == null ? Weigher.singletonWeigher() : (k, v) -> guavaWeigher.weigh(k, v);
}
} }

View File

@ -22,6 +22,7 @@ import com.google.gerrit.extensions.client.DiffPreferencesInfo.Whitespace;
import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet; import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.cache.CacheBackend;
import com.google.gerrit.server.cache.CacheModule; import com.google.gerrit.server.cache.CacheModule;
import com.google.gerrit.server.config.GerritServerConfig; import com.google.gerrit.server.config.GerritServerConfig;
import com.google.inject.Inject; import com.google.inject.Inject;
@ -45,7 +46,9 @@ public class PatchListCacheImpl implements PatchListCache {
@Override @Override
protected void configure() { protected void configure() {
factory(PatchListLoader.Factory.class); factory(PatchListLoader.Factory.class);
persist(FILE_NAME, PatchListKey.class, PatchList.class) // TODO(davido): Switch off using legacy cache backend, after fixing PatchListLoader
// to be recursion free.
persist(FILE_NAME, PatchListKey.class, PatchList.class, CacheBackend.GUAVA)
.maximumWeight(10 << 20) .maximumWeight(10 << 20)
.weigher(PatchListWeigher.class); .weigher(PatchListWeigher.class);

View File

@ -39,7 +39,9 @@ import com.google.gerrit.server.patch.PatchListKey;
import com.google.gerrit.server.patch.Text; import com.google.gerrit.server.patch.Text;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.name.Named; import com.google.inject.name.Named;
import java.lang.reflect.Field;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
@ -65,6 +67,25 @@ public class PatchListCacheIT extends AbstractDaemonTest {
@Named("diff") @Named("diff")
private Cache<PatchListKey, PatchList> abstractPatchListCache; private Cache<PatchListKey, PatchList> abstractPatchListCache;
@Test
public void ensureLegacyBackendIsUsedForFileCacheBackend() throws Exception {
Field fileCacheField = patchListCache.getClass().getDeclaredField("fileCache");
fileCacheField.setAccessible(true);
// Use the reflection to access "localCache" field that is only present in Guava backend.
assertThat(
Arrays.stream(fileCacheField.get(patchListCache).getClass().getDeclaredFields())
.anyMatch(f -> f.getName().equals("localCache")))
.isTrue();
// intraCache (and all other cache backends) should use Caffeine backend.
Field intraCacheField = patchListCache.getClass().getDeclaredField("intraCache");
intraCacheField.setAccessible(true);
assertThat(
Arrays.stream(intraCacheField.get(patchListCache).getClass().getDeclaredFields())
.noneMatch(f -> f.getName().equals("localCache")))
.isTrue();
}
@Test @Test
public void listPatchesAgainstBase() throws Exception { public void listPatchesAgainstBase() throws Exception {
commitBuilder().add(FILE_D, "4").message(SUBJECT_1).create(); commitBuilder().add(FILE_D, "4").message(SUBJECT_1).create();

View File

@ -1,4 +1,4 @@
load("@rules_java//java:defs.bzl", "java_library") load("@rules_java//java:defs.bzl", "java_import", "java_library")
exports_files(glob([ exports_files(glob([
"LICENSE-*", "LICENSE-*",
@ -67,6 +67,29 @@ java_library(
], ],
) )
java_library(
name = "caffeine",
data = ["//lib:LICENSE-Apache2.0"],
visibility = [
"//java/com/google/gerrit/server/cache/mem:__pkg__",
],
exports = ["@caffeine//jar"],
)
java_import(
name = "caffeine-guava-renamed",
jars = ["@caffeine-guava-renamed//file"],
)
java_library(
name = "caffeine-guava",
data = ["//lib:LICENSE-Apache2.0"],
visibility = [
"//java/com/google/gerrit/server/cache/mem:__pkg__",
],
exports = [":caffeine-guava-renamed"],
)
java_library( java_library(
name = "jsch", name = "jsch",
data = ["//lib:LICENSE-jsch"], data = ["//lib:LICENSE-jsch"],