| // Copyright (C) 2012 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.h2; |
| |
| import com.google.common.base.Strings; |
| import com.google.common.cache.Cache; |
| import com.google.common.cache.CacheBuilder; |
| import com.google.common.cache.CacheLoader; |
| import com.google.common.cache.LoadingCache; |
| import com.google.common.cache.Weigher; |
| import com.google.gerrit.lifecycle.LifecycleModule; |
| import com.google.gerrit.server.cache.CacheBinding; |
| import com.google.gerrit.server.cache.ForwardingRemovalListener; |
| import com.google.gerrit.server.cache.MemoryCacheFactory; |
| import com.google.gerrit.server.cache.PersistentCacheFactory; |
| import com.google.gerrit.server.cache.h2.H2CacheImpl.ValueHolder; |
| import com.google.gerrit.server.config.ConfigUtil; |
| import com.google.gerrit.server.config.FactoryModule; |
| import com.google.gerrit.server.config.GerritServerConfig; |
| import com.google.inject.Inject; |
| |
| import org.eclipse.jgit.lib.Config; |
| |
| import java.util.concurrent.TimeUnit; |
| |
| public class DefaultCacheFactory implements MemoryCacheFactory { |
| public static class Module extends LifecycleModule { |
| @Override |
| protected void configure() { |
| install(new FactoryModule() { |
| @Override |
| protected void configure() { |
| factory(ForwardingRemovalListener.Factory.class); |
| } |
| }); |
| |
| bind(DefaultCacheFactory.class); |
| bind(MemoryCacheFactory.class).to(DefaultCacheFactory.class); |
| bind(PersistentCacheFactory.class).to(H2CacheFactory.class); |
| listener().to(H2CacheFactory.class); |
| } |
| } |
| |
| private final Config cfg; |
| private final ForwardingRemovalListener.Factory forwardingRemovalListenerFactory; |
| |
| @Inject |
| public DefaultCacheFactory(@GerritServerConfig Config config, |
| ForwardingRemovalListener.Factory forwardingRemovalListenerFactory) { |
| this.cfg = config; |
| this.forwardingRemovalListenerFactory = forwardingRemovalListenerFactory; |
| } |
| |
| @Override |
| public <K, V> Cache<K, V> build(CacheBinding<K, V> def) { |
| return create(def, false).build(); |
| } |
| |
| @Override |
| public <K, V> LoadingCache<K, V> build( |
| CacheBinding<K, V> def, |
| CacheLoader<K, V> loader) { |
| return create(def, false).build(loader); |
| } |
| |
| @SuppressWarnings("unchecked") |
| <K, V> CacheBuilder<K, V> create( |
| CacheBinding<K, V> def, |
| boolean unwrapValueHolder) { |
| CacheBuilder<K,V> builder = newCacheBuilder(); |
| builder.recordStats(); |
| builder.maximumWeight(cfg.getLong( |
| "cache", def.name(), "memoryLimit", |
| def.maximumWeight())); |
| |
| builder.removalListener(forwardingRemovalListenerFactory.create(def.name())); |
| |
| Weigher<K, V> weigher = def.weigher(); |
| if (weigher != null && unwrapValueHolder) { |
| final Weigher<K, V> impl = weigher; |
| weigher = (Weigher<K, V>) new Weigher<K, ValueHolder<V>> () { |
| @Override |
| public int weigh(K key, ValueHolder<V> value) { |
| return impl.weigh(key, value.value); |
| } |
| }; |
| } else if (weigher == null) { |
| weigher = unitWeight(); |
| } |
| builder.weigher(weigher); |
| |
| Long age = def.expireAfterWrite(TimeUnit.SECONDS); |
| if (has(def.name(), "maxAge")) { |
| builder.expireAfterWrite(ConfigUtil.getTimeUnit(cfg, |
| "cache", def.name(), "maxAge", |
| age != null ? age : 0, |
| TimeUnit.SECONDS), TimeUnit.SECONDS); |
| } else if (age != null) { |
| builder.expireAfterWrite(age, TimeUnit.SECONDS); |
| } |
| |
| return builder; |
| } |
| |
| private boolean has(String name, String var) { |
| return !Strings.isNullOrEmpty(cfg.getString("cache", name, var)); |
| } |
| |
| @SuppressWarnings({"rawtypes", "unchecked"}) |
| private static <K, V> CacheBuilder<K, V> newCacheBuilder() { |
| CacheBuilder builder = CacheBuilder.newBuilder(); |
| return builder; |
| } |
| |
| private static <K, V> Weigher<K, V> unitWeight() { |
| return new Weigher<K, V>() { |
| @Override |
| public int weigh(K key, V value) { |
| return 1; |
| } |
| }; |
| } |
| } |