This module provides a REST API to help converting existing cache from H2 to chronicle-map, which requires the Administrate Caches
or Administrate Server
capabilities to be executed.
The migration must be executed before switching to use chronicle-map, while Gerrit cache is still backed by H2.
The migration can be run online without any disruption of the Gerrit server. However note that since the migration perform many, sequential reads from the H2 database, it will participate to the overall database load, so you should test accordingly.
The migration would do the following:
NOTE: The existing cache parameters are kept in
gerrit.config
only when they are all defined (avgKeySize, avgValueSize, maxEntries and maxBloatFactor), otherwise the migration process will recalculate them and create the new cache based on the new values.
The following caches will be migrated (if they exist and contain any data):
The migration should be performed as follows:
cache-chroniclemap.jar
file in the plugins/
directory.error_log
:INFO com.google.gerrit.server.plugins.PluginLoader : Loaded plugin cache-chroniclemap
curl -v -XPUT -u <admin> '<gerrit>/a/plugins/cache-chroniclemap/migrate?[size-multiplier=FACTOR]&[bax-bloat-factor=MULTIPLIER]'
This might require some time, depending on the size of the H2 caches and it will terminate with the output of the configuration that should be places in etc/gerrit.config
in order to leverage the newly created caches correctly.
Output example:
[cache "diff"] maxEntries = 216 avgKeySize = 188 avgValueSize = 796 maxBloatFactor = 1 [cache "persisted_projects"] maxEntries = 3 avgKeySize = 80 avgValueSize = 4087 maxBloatFactor = 1 [cache "diff_summary"] maxEntries = 216 avgKeySize = 192 avgValueSize = 254 maxBloatFactor = 1 [cache "accounts"] maxEntries = 2 avgKeySize = 52 avgValueSize = 194 maxBloatFactor = 1 [cache "mergeability"] maxEntries = 2444 avgKeySize = 150 avgValueSize = 20 maxBloatFactor = 1 [cache "web_sessions"] maxEntries = 94852 avgKeySize = 68 avgValueSize = 382 maxBloatFactor = 1
Optionally the REST endpoint can receive the following additional arguments:
maximum number of times chronicle-map cache is allowed to grow in size. default:3
When chroniclemap store is initiated for a cache it locks exclusively the underlying file and keeps it until store is closed. Store is closed when Gerrit is stopped (for core caches) or when plugin is unloaded through either REST or SSH command. The later is problematic from the plugin reload
command perspective as by default it unloads old version of plugin once new version is successfully loaded. Considering that old version holds the lock until it gets unloaded new version load will not succeed. As a result the following (or similar) error is visible in the log:
[2022-08-31T17:37:56.481+02:00] [SSH gerrit plugin reload test-cache-plugin (admin)] WARN com.google.gerrit.server.plugins.PluginLoader : Cannot reload plugin test-cache-plugin com.google.inject.CreationException: Unable to create injector, see the following errors: 1) [Guice/ErrorInCustomProvider]: ChronicleHashRecoveryFailedException: ChronicleFileLockException: Unable to acquire an exclusive file lock for gerrit/cache/test-cache-plugin.test_cache_0.dat. Make sure no other process is using the map. at CacheModule.bindCache(CacheModule.java:188) \_ installed by: Module -> TestCache$1 while locating Cache<String, String> annotated with @Named(value="test_cache") Learn more: https://github.com/google/guice/wiki/ERROR_IN_CUSTOM_PROVIDER Caused by: ChronicleHashRecoveryFailedException: ChronicleFileLockException: Unable to acquire an exclusive file lock for gerrit/cache/test-cache-plugin.test_cache_0.dat. Make sure no other process is using the map. at ChronicleMapBuilder.openWithExistingFile(ChronicleMapBuilder.java:1937) at ChronicleMapBuilder.createWithFile(ChronicleMapBuilder.java:1706) at ChronicleMapBuilder.recoverPersistedTo(ChronicleMapBuilder.java:1622) ...
The following steps can be used in order to perform reload operation:
perform the plugin reload
in two steps by calling remove
first and following it with add
command - the easiest way that doesn't require any code modification
add Gerrit-ReloadMode: restart
to plugin‘s manifest so the when the plugin reload
command is called Gerrit unloads the old version prior loading the new one - requires plugin’s sources modification and build which might be not an option in certain cases