Introduce CacheImpl annotation

There is existing mechanism to provide different implementation for
instance to secure-store but one can replace only certain binding
with it (through provider class). In this case when H2CacheImpl is
installed it adds more bindings and replacing only this class would
keep leftovers being still initiated/running in Gerrit core.

CacheImpl annotation contains 2 types:
MEMORY
PERSISTENT
It is applied to modules that provide corresponding default caches
implementations.

When CacheImpl annotation is added to lib module then it will
override particular default implementation.

Change-Id: I7562b210fad4c5f6dc67887f627cf76815a378cb
Signed-off-by: Jacek Centkowski <jcentkowski@collab.net>
This commit is contained in:
Jacek Centkowski
2018-05-08 19:04:06 +02:00
committed by David Pursehouse
parent e602b8dacc
commit 5517ec316f
5 changed files with 108 additions and 4 deletions

View File

@@ -23,6 +23,7 @@ import com.google.common.cache.Weigher;
import com.google.gerrit.extensions.config.FactoryModule;
import com.google.gerrit.lifecycle.LifecycleModule;
import com.google.gerrit.server.cache.CacheBinding;
import com.google.gerrit.server.cache.CacheImpl;
import com.google.gerrit.server.cache.ForwardingRemovalListener;
import com.google.gerrit.server.cache.MemoryCacheFactory;
import com.google.gerrit.server.cache.PersistentCacheFactory;
@@ -33,6 +34,7 @@ import java.util.concurrent.TimeUnit;
import org.eclipse.jgit.lib.Config;
public class DefaultCacheFactory implements MemoryCacheFactory {
@CacheImpl(type = CacheImpl.Type.MEMORY)
public static class MemoryCacheModule extends FactoryModule {
@Override
protected void configure() {
@@ -41,6 +43,7 @@ public class DefaultCacheFactory implements MemoryCacheFactory {
}
}
@CacheImpl(type = CacheImpl.Type.PERSISTENT)
public static class PersistentCacheModule extends LifecycleModule {
@Override
protected void configure() {

View File

@@ -50,6 +50,7 @@ import com.google.gerrit.pgm.util.SiteProgram;
import com.google.gerrit.server.LibModuleLoader;
import com.google.gerrit.server.StartupChecks;
import com.google.gerrit.server.account.InternalAccountDirectory;
import com.google.gerrit.server.cache.CacheOverrides;
import com.google.gerrit.server.cache.h2.DefaultCacheFactory;
import com.google.gerrit.server.change.ChangeCleanupRunner;
import com.google.gerrit.server.config.AuthConfig;
@@ -438,8 +439,8 @@ public class Daemon extends SiteProgram {
if (!slave) {
modules.add(new ChangeCleanupRunner.Module());
}
modules.addAll(LibModuleLoader.loadModules(cfgInjector));
return cfgInjector.createChildInjector(modules);
return cfgInjector.createChildInjector(
CacheOverrides.override(modules, LibModuleLoader.loadModules(cfgInjector)));
}
private Module createIndexModule() {

View File

@@ -0,0 +1,34 @@
// Copyright (C) 2018 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;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Retention(RUNTIME)
@Target(TYPE)
@Inherited
public @interface CacheImpl {
enum Type {
MEMORY,
PERSISTENT
}
Type type();
}

View File

@@ -0,0 +1,65 @@
// Copyright (C) 2018 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;
import com.google.inject.Module;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class CacheOverrides {
public static List<Module> override(List<Module> modules, List<Module> overrideCandidates) {
if (overrideCandidates == null || overrideCandidates.isEmpty()) {
return modules;
}
// group candidates by annotation existence
Map<Boolean, List<Module>> grouped =
overrideCandidates
.stream()
.collect(
Collectors.groupingBy(m -> m.getClass().getAnnotation(CacheImpl.class) != null));
// add all non annotated libs to modules list
List<Module> libs = grouped.get(Boolean.FALSE);
if (libs != null) {
modules.addAll(libs);
}
List<Module> overrides = grouped.get(Boolean.TRUE);
if (overrides == null) {
return modules;
}
// swipe cache implementation with alternative provided in lib
return modules
.stream()
.map(
m -> {
CacheImpl a = m.getClass().getAnnotation(CacheImpl.class);
if (a == null) {
return m;
}
return overrides
.stream()
.filter(o -> o.getClass().getAnnotation(CacheImpl.class).type() == a.type())
.findFirst()
.orElse(m);
})
.collect(Collectors.toList());
}
private CacheOverrides() {}
}

View File

@@ -34,6 +34,7 @@ import com.google.gerrit.pgm.util.LogFileCompressor;
import com.google.gerrit.server.LibModuleLoader;
import com.google.gerrit.server.StartupChecks;
import com.google.gerrit.server.account.InternalAccountDirectory;
import com.google.gerrit.server.cache.CacheOverrides;
import com.google.gerrit.server.cache.h2.DefaultCacheFactory;
import com.google.gerrit.server.change.ChangeCleanupRunner;
import com.google.gerrit.server.config.AuthConfig;
@@ -364,8 +365,8 @@ public class WebAppInitializer extends GuiceServletContextListener implements Fi
});
modules.add(new GarbageCollectionModule());
modules.add(new ChangeCleanupRunner.Module());
modules.addAll(LibModuleLoader.loadModules(cfgInjector));
return cfgInjector.createChildInjector(modules);
return cfgInjector.createChildInjector(
CacheOverrides.override(modules, LibModuleLoader.loadModules(cfgInjector)));
}
private Module createIndexModule() {