From f313457af5e9c55f2b6a7f7ef6e9ce4b02b1525c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C5=A1a=20=C5=BDivkov?= Date: Tue, 9 Feb 2016 11:42:46 +0100 Subject: [PATCH] Make H2 database cache size configurable H2 database by default uses up to the half of the amount of memory available for the virtual machine (Runtime.getRuntime().maxMemory()) as described in [1]. In some cases this could contribute to an out-of-memory error in Gerrit. Introduce a new configuration parameter cache.h2CacheSize to limit the H2 memory cache size. In this change this parameter is applied to all persistent caches. [1] http://www.h2database.com/html/features.html#cache_settings Change-Id: I0217d4114f528275ca4094e0f3414ef23af80677 --- Documentation/config-gerrit.txt | 14 ++++++++++++++ .../gerrit/server/cache/h2/H2CacheFactory.java | 12 ++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt index 3dda56cfce..0968c40cfc 100644 --- a/Documentation/config-gerrit.txt +++ b/Documentation/config-gerrit.txt @@ -528,6 +528,20 @@ If not absolute, the path is resolved relative to `$site_path`. + Default is unset, no disk cache. +[[cache.h2CacheSize]]cache.h2CacheSize:: ++ +The size of the H2 database cache, in bytes, used for each persistent cache. +This can be used to limit the H2 cache size and thus prevent out-of-memory +caused by the H2 database using too much memory. ++ +Technically the H2 cache size is configured using the CACHE_SIZE parameter in +the H2 JDBC connection URL, as described +link:http://www.h2database.com/html/features.html#cache_settings[here] ++ +Default is unset, no cache size limit. ++ +Common unit suffixes of 'k', 'm', or 'g' are supported. + [[cache.name.maxAge]]cache..maxAge:: + Maximum age to keep an entry in the cache. Entries are removed from diff --git a/gerrit-cache-h2/src/main/java/com/google/gerrit/server/cache/h2/H2CacheFactory.java b/gerrit-cache-h2/src/main/java/com/google/gerrit/server/cache/h2/H2CacheFactory.java index fcacf78631..3ffb76c2d7 100644 --- a/gerrit-cache-h2/src/main/java/com/google/gerrit/server/cache/h2/H2CacheFactory.java +++ b/gerrit-cache-h2/src/main/java/com/google/gerrit/server/cache/h2/H2CacheFactory.java @@ -58,6 +58,7 @@ class H2CacheFactory implements PersistentCacheFactory, LifecycleListener { private final DynamicMap> cacheMap; private final ExecutorService executor; private final ScheduledExecutorService cleanup; + private final long h2CacheSize; @Inject H2CacheFactory( @@ -68,6 +69,7 @@ class H2CacheFactory implements PersistentCacheFactory, LifecycleListener { defaultFactory = defaultCacheFactory; config = cfg; cacheDir = getCacheDir(site, cfg.getString("cache", null, "directory")); + h2CacheSize = cfg.getLong("cache", null, "h2CacheSize", -1); caches = Lists.newLinkedList(); this.cacheMap = cacheMap; @@ -220,8 +222,14 @@ class H2CacheFactory implements PersistentCacheFactory, LifecycleListener { TypeLiteral keyType, long maxSize, Long expireAfterWrite) { - String url = "jdbc:h2:" + cacheDir.resolve(name).toUri(); - return new SqlStore<>(url, keyType, maxSize, + StringBuilder url = new StringBuilder(); + url.append("jdbc:h2:").append(cacheDir.resolve(name).toUri()); + if (h2CacheSize >= 0) { + url.append(";CACHE_SIZE="); + // H2 CACHE_SIZE is always given in KB + url.append(h2CacheSize / 1024); + } + return new SqlStore<>(url.toString(), keyType, maxSize, expireAfterWrite == null ? 0 : expireAfterWrite.longValue()); } }