LCOV - code coverage report
Current view: top level - server/cache/mem - DefaultMemoryCacheFactory.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 36 48 75.0 %
Date: 2022-11-19 15:00:39 Functions: 11 12 91.7 %

          Line data    Source code
       1             : // Copyright (C) 2012 The Android Open Source Project
       2             : //
       3             : // Licensed under the Apache License, Version 2.0 (the "License");
       4             : // you may not use this file except in compliance with the License.
       5             : // You may obtain a copy of the License at
       6             : //
       7             : // http://www.apache.org/licenses/LICENSE-2.0
       8             : //
       9             : // Unless required by applicable law or agreed to in writing, software
      10             : // distributed under the License is distributed on an "AS IS" BASIS,
      11             : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             : // See the License for the specific language governing permissions and
      13             : // limitations under the License.
      14             : 
      15             : package com.google.gerrit.server.cache.mem;
      16             : 
      17             : import static java.util.concurrent.TimeUnit.NANOSECONDS;
      18             : import static java.util.concurrent.TimeUnit.SECONDS;
      19             : 
      20             : import com.github.benmanes.caffeine.cache.Caffeine;
      21             : import com.github.benmanes.caffeine.cache.RemovalListener;
      22             : import com.github.benmanes.caffeine.cache.Weigher;
      23             : import com.github.benmanes.caffeine.guava.CaffeinatedGuava;
      24             : import com.google.common.base.Strings;
      25             : import com.google.common.cache.Cache;
      26             : import com.google.common.cache.CacheLoader;
      27             : import com.google.common.cache.LoadingCache;
      28             : import com.google.common.cache.RemovalNotification;
      29             : import com.google.gerrit.common.Nullable;
      30             : import com.google.gerrit.server.cache.CacheDef;
      31             : import com.google.gerrit.server.cache.ForwardingRemovalListener;
      32             : import com.google.gerrit.server.cache.MemoryCacheFactory;
      33             : import com.google.gerrit.server.config.ConfigUtil;
      34             : import com.google.gerrit.server.config.GerritServerConfig;
      35             : import com.google.inject.Inject;
      36             : import java.time.Duration;
      37             : import org.eclipse.jgit.lib.Config;
      38             : 
      39             : class DefaultMemoryCacheFactory implements MemoryCacheFactory {
      40             :   private final Config cfg;
      41             :   private final ForwardingRemovalListener.Factory forwardingRemovalListenerFactory;
      42             : 
      43             :   @Inject
      44             :   DefaultMemoryCacheFactory(
      45             :       @GerritServerConfig Config config,
      46         153 :       ForwardingRemovalListener.Factory forwardingRemovalListenerFactory) {
      47         153 :     this.cfg = config;
      48         153 :     this.forwardingRemovalListenerFactory = forwardingRemovalListenerFactory;
      49         153 :   }
      50             : 
      51             :   @Override
      52             :   public <K, V> Cache<K, V> build(CacheDef<K, V> def) {
      53         152 :     return CaffeinatedGuava.build(create(def));
      54             :   }
      55             : 
      56             :   @Override
      57             :   public <K, V> LoadingCache<K, V> build(CacheDef<K, V> def, CacheLoader<K, V> loader) {
      58         153 :     return cacheMaximumWeight(def) == 0
      59         153 :         ? new PassthroughLoadingCache<>(loader)
      60         153 :         : CaffeinatedGuava.build(create(def), loader);
      61             :   }
      62             : 
      63             :   private <K, V> Caffeine<K, V> create(CacheDef<K, V> def) {
      64         153 :     Caffeine<K, V> builder = newCacheBuilder();
      65         153 :     builder.recordStats();
      66         153 :     builder.maximumWeight(cacheMaximumWeight(def));
      67         153 :     builder = builder.removalListener(newRemovalListener(def.name()));
      68         153 :     builder.weigher(newWeigher(def.weigher()));
      69             : 
      70         153 :     Duration expireAfterWrite = def.expireAfterWrite();
      71         153 :     if (has(def.configKey(), "maxAge")) {
      72           0 :       builder.expireAfterWrite(
      73           0 :           ConfigUtil.getTimeUnit(
      74           0 :               cfg, "cache", def.configKey(), "maxAge", toSeconds(expireAfterWrite), SECONDS),
      75             :           SECONDS);
      76         153 :     } else if (expireAfterWrite != null) {
      77         152 :       builder.expireAfterWrite(expireAfterWrite.toNanos(), NANOSECONDS);
      78             :     }
      79             : 
      80         153 :     Duration expireAfterAccess = def.expireFromMemoryAfterAccess();
      81         153 :     if (has(def.configKey(), "expireFromMemoryAfterAccess")) {
      82           0 :       builder.expireAfterAccess(
      83           0 :           ConfigUtil.getTimeUnit(
      84             :               cfg,
      85             :               "cache",
      86           0 :               def.configKey(),
      87             :               "expireFromMemoryAfterAccess",
      88           0 :               toSeconds(expireAfterAccess),
      89             :               SECONDS),
      90             :           SECONDS);
      91         153 :     } else if (expireAfterAccess != null) {
      92         152 :       builder.expireAfterAccess(expireAfterAccess.toNanos(), NANOSECONDS);
      93             :     }
      94             : 
      95         153 :     Duration refreshAfterWrite = def.refreshAfterWrite();
      96         153 :     if (has(def.configKey(), "refreshAfterWrite")) {
      97           0 :       builder.refreshAfterWrite(
      98           0 :           ConfigUtil.getTimeUnit(
      99             :               cfg,
     100             :               "cache",
     101           0 :               def.configKey(),
     102             :               "refreshAfterWrite",
     103           0 :               toSeconds(refreshAfterWrite),
     104             :               SECONDS),
     105             :           SECONDS);
     106         153 :     } else if (refreshAfterWrite != null) {
     107         152 :       builder.refreshAfterWrite(refreshAfterWrite.toNanos(), NANOSECONDS);
     108             :     }
     109             : 
     110         153 :     return builder;
     111             :   }
     112             : 
     113             :   private <K, V> long cacheMaximumWeight(CacheDef<K, V> def) {
     114         153 :     return cfg.getLong("cache", def.configKey(), "memoryLimit", def.maximumWeight());
     115             :   }
     116             : 
     117             :   private static long toSeconds(@Nullable Duration duration) {
     118           0 :     return duration != null ? duration.getSeconds() : 0;
     119             :   }
     120             : 
     121             :   private boolean has(String name, String var) {
     122         153 :     return !Strings.isNullOrEmpty(cfg.getString("cache", name, var));
     123             :   }
     124             : 
     125             :   @SuppressWarnings("unchecked")
     126             :   private static <K, V> Caffeine<K, V> newCacheBuilder() {
     127         153 :     return (Caffeine<K, V>) Caffeine.newBuilder();
     128             :   }
     129             : 
     130             :   @SuppressWarnings("unchecked")
     131             :   private <V, K> RemovalListener<K, V> newRemovalListener(String cacheName) {
     132         153 :     return (k, v, cause) ->
     133         152 :         forwardingRemovalListenerFactory
     134         151 :             .create(cacheName)
     135         151 :             .onRemoval(
     136         151 :                 RemovalNotification.create(
     137         151 :                     k, v, com.google.common.cache.RemovalCause.valueOf(cause.name())));
     138             :   }
     139             : 
     140             :   private static <K, V> Weigher<K, V> newWeigher(
     141             :       com.google.common.cache.Weigher<K, V> guavaWeigher) {
     142         153 :     return guavaWeigher == null ? Weigher.singletonWeigher() : (k, v) -> guavaWeigher.weigh(k, v);
     143             :   }
     144             : }

Generated by: LCOV version 1.16+git.20220603.dfeb750