mirror of
https://github.com/scm-manager/scm-manager.git
synced 2026-02-05 22:29:11 +01:00
Caches for internal stores and files
This adds optional caches for configuration stores and backing data files for data stores. These stores can be enabled using the system properties `scm.storeCache.enabled=true` and `scm.cache.dataFileCache.enabled=true`. In addition, this adds the possibility to overwrite cache configurations from the guice cache (see file `gcache.xml`) with system properties. The maximum size of the external group cache for example can be overwritten with the system property `scm.cache.externalGroups.maximumSize`. Co-authored-by: René Pfeuffer <rene.pfeuffer@cloudogu.com>
This commit is contained in:
@@ -21,10 +21,8 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package sonia.scm.cache;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
package sonia.scm.cache;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
|
||||
@@ -35,215 +33,138 @@ import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
||||
import java.io.Serializable;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@XmlRootElement(name = "cache")
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class GuavaCacheConfiguration implements Serializable
|
||||
{
|
||||
@XmlAccessorType(XmlAccessType.PROPERTY)
|
||||
public class GuavaCacheConfiguration implements Serializable {
|
||||
|
||||
/** Field description */
|
||||
private static final long serialVersionUID = -8734373158089010603L;
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
private Integer concurrencyLevel;
|
||||
private CopyStrategy copyStrategy;
|
||||
private Long expireAfterAccess;
|
||||
private Long expireAfterWrite;
|
||||
private Integer initialCapacity;
|
||||
private Long maximumSize;
|
||||
private Long maximumWeight;
|
||||
private Boolean recordStats;
|
||||
private Boolean softValues;
|
||||
private Boolean weakKeys;
|
||||
private Boolean weakValues;
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
//J-
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper(this)
|
||||
.add("concurrencyLevel", concurrencyLevel)
|
||||
.add("copyStrategy", copyStrategy)
|
||||
.add("expireAfterAccess", expireAfterAccess)
|
||||
.add("expireAfterWrite", expireAfterWrite)
|
||||
.add("initialCapacity", initialCapacity)
|
||||
.add("maximumSize", maximumSize)
|
||||
.add("maximumWeight", maximumWeight)
|
||||
.add("recordStats", recordStats)
|
||||
.add("softValues", softValues)
|
||||
.add("weakKeys", weakKeys)
|
||||
.add("weakValues", weakValues)
|
||||
.omitNullValues().toString();
|
||||
//J+
|
||||
.add("concurrencyLevel", concurrencyLevel)
|
||||
.add("copyStrategy", copyStrategy)
|
||||
.add("expireAfterAccess", expireAfterAccess)
|
||||
.add("expireAfterWrite", expireAfterWrite)
|
||||
.add("initialCapacity", initialCapacity)
|
||||
.add("maximumSize", maximumSize)
|
||||
.add("maximumWeight", maximumWeight)
|
||||
.add("recordStats", recordStats)
|
||||
.add("softValues", softValues)
|
||||
.add("weakKeys", weakKeys)
|
||||
.add("weakValues", weakValues)
|
||||
.omitNullValues().toString();
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Integer getConcurrencyLevel()
|
||||
{
|
||||
public Integer getConcurrencyLevel() {
|
||||
return concurrencyLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public CopyStrategy getCopyStrategy()
|
||||
{
|
||||
public CopyStrategy getCopyStrategy() {
|
||||
return copyStrategy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Long getExpireAfterAccess()
|
||||
{
|
||||
public Long getExpireAfterAccess() {
|
||||
return expireAfterAccess;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Long getExpireAfterWrite()
|
||||
{
|
||||
public Long getExpireAfterWrite() {
|
||||
return expireAfterWrite;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Integer getInitialCapacity()
|
||||
{
|
||||
public Integer getInitialCapacity() {
|
||||
return initialCapacity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Long getMaximumSize()
|
||||
{
|
||||
public Long getMaximumSize() {
|
||||
return maximumSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Long getMaximumWeight()
|
||||
{
|
||||
public Long getMaximumWeight() {
|
||||
return maximumWeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Boolean getRecordStats()
|
||||
{
|
||||
public Boolean getRecordStats() {
|
||||
return recordStats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Boolean getSoftValues()
|
||||
{
|
||||
public Boolean getSoftValues() {
|
||||
return softValues;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Boolean getWeakKeys()
|
||||
{
|
||||
public Boolean getWeakKeys() {
|
||||
return weakKeys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Boolean getWeakValues()
|
||||
{
|
||||
public Boolean getWeakValues() {
|
||||
return weakValues;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
@XmlAttribute
|
||||
private Integer concurrencyLevel;
|
||||
void setConcurrencyLevel(Integer concurrencyLevel) {
|
||||
this.concurrencyLevel = concurrencyLevel;
|
||||
}
|
||||
|
||||
/** Field description */
|
||||
@XmlAttribute
|
||||
@XmlJavaTypeAdapter(XmlCopyStrategyAdapter.class)
|
||||
private CopyStrategy copyStrategy;
|
||||
void setCopyStrategy(CopyStrategy copyStrategy) {
|
||||
this.copyStrategy = copyStrategy;
|
||||
}
|
||||
|
||||
/** Field description */
|
||||
@XmlAttribute
|
||||
private Long expireAfterAccess;
|
||||
void setExpireAfterAccess(Long expireAfterAccess) {
|
||||
this.expireAfterAccess = expireAfterAccess;
|
||||
}
|
||||
|
||||
/** Field description */
|
||||
@XmlAttribute
|
||||
private Long expireAfterWrite;
|
||||
void setExpireAfterWrite(Long expireAfterWrite) {
|
||||
this.expireAfterWrite = expireAfterWrite;
|
||||
}
|
||||
|
||||
/** Field description */
|
||||
@XmlAttribute
|
||||
private Integer initialCapacity;
|
||||
void setInitialCapacity(Integer initialCapacity) {
|
||||
this.initialCapacity = initialCapacity;
|
||||
}
|
||||
|
||||
/** Field description */
|
||||
@XmlAttribute
|
||||
private Long maximumSize;
|
||||
void setMaximumSize(Long maximumSize) {
|
||||
this.maximumSize = maximumSize;
|
||||
}
|
||||
|
||||
/** Field description */
|
||||
@XmlAttribute
|
||||
private Long maximumWeight;
|
||||
void setMaximumWeight(Long maximumWeight) {
|
||||
this.maximumWeight = maximumWeight;
|
||||
}
|
||||
|
||||
/** Field description */
|
||||
@XmlAttribute
|
||||
private Boolean recordStats;
|
||||
void setRecordStats(Boolean recordStats) {
|
||||
this.recordStats = recordStats;
|
||||
}
|
||||
|
||||
/** Field description */
|
||||
@XmlAttribute
|
||||
private Boolean softValues;
|
||||
void setSoftValues(Boolean softValues) {
|
||||
this.softValues = softValues;
|
||||
}
|
||||
|
||||
/** Field description */
|
||||
@XmlAttribute
|
||||
private Boolean weakKeys;
|
||||
void setWeakKeys(Boolean weakKeys) {
|
||||
this.weakKeys = weakKeys;
|
||||
}
|
||||
|
||||
/** Field description */
|
||||
@XmlAttribute
|
||||
private Boolean weakValues;
|
||||
void setWeakValues(Boolean weakValues) {
|
||||
this.weakValues = weakValues;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,44 +21,133 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
package sonia.scm.cache;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static java.util.Optional.empty;
|
||||
import static java.util.Optional.of;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@XmlRootElement(name = "cache")
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class GuavaNamedCacheConfiguration extends GuavaCacheConfiguration
|
||||
{
|
||||
@XmlAccessorType(XmlAccessType.PROPERTY)
|
||||
public class GuavaNamedCacheConfiguration extends GuavaCacheConfiguration {
|
||||
|
||||
/** Field description */
|
||||
private static final long serialVersionUID = -624795324874828475L;
|
||||
private static final Logger LOG = LoggerFactory.getLogger(GuavaNamedCacheConfiguration.class);
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
@XmlAttribute
|
||||
private String name;
|
||||
private void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
void setConcurrencyLevel(Integer concurrencyLevel) {
|
||||
setIntegerValue("concurrencyLevel", concurrencyLevel, super::setConcurrencyLevel);
|
||||
}
|
||||
|
||||
@Override
|
||||
void setCopyStrategy(CopyStrategy copyStrategy) {
|
||||
setValue("copyStrategy", copyStrategy, super::setCopyStrategy, propertyName -> of(System.getProperty(propertyName)).map(CopyStrategy::valueOf).orElse(null));
|
||||
}
|
||||
|
||||
@Override
|
||||
void setExpireAfterAccess(Long expireAfterAccess) {
|
||||
setLongValue("expireAfterAccess", expireAfterAccess, super::setExpireAfterAccess);
|
||||
}
|
||||
|
||||
@Override
|
||||
void setExpireAfterWrite(Long expireAfterWrite) {
|
||||
setLongValue("expireAfterWrite", expireAfterWrite, super::setExpireAfterWrite);
|
||||
}
|
||||
|
||||
@Override
|
||||
void setInitialCapacity(Integer initialCapacity) {
|
||||
setIntegerValue("initialCapacity", initialCapacity, super::setInitialCapacity);
|
||||
}
|
||||
|
||||
@Override
|
||||
void setMaximumSize(Long maximumSize) {
|
||||
setLongValue("maximumSize", maximumSize, super::setMaximumSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
void setMaximumWeight(Long maximumWeight) {
|
||||
setLongValue("maximumWeight", maximumWeight, super::setMaximumWeight);
|
||||
}
|
||||
|
||||
@Override
|
||||
void setRecordStats(Boolean recordStats) {
|
||||
setBooleanValue("recordStats", recordStats, super::setRecordStats);
|
||||
}
|
||||
|
||||
@Override
|
||||
void setSoftValues(Boolean softValues) {
|
||||
setBooleanValue("softValues", softValues, super::setSoftValues);
|
||||
}
|
||||
|
||||
@Override
|
||||
void setWeakKeys(Boolean weakKeys) {
|
||||
setBooleanValue("weakKeys", weakKeys, super::setWeakKeys);
|
||||
}
|
||||
|
||||
@Override
|
||||
void setWeakValues(Boolean weakValues) {
|
||||
setBooleanValue("weakValues", weakValues, super::setWeakValues);
|
||||
}
|
||||
|
||||
private void setIntegerValue(String propertyName, Integer originalValue, Consumer<Integer> setter) {
|
||||
setValue(propertyName, originalValue, setter, Integer::getInteger);
|
||||
}
|
||||
|
||||
private void setLongValue(String propertyName, Long originalValue, Consumer<Long> setter) {
|
||||
setValue(propertyName, originalValue, setter, Long::getLong);
|
||||
}
|
||||
|
||||
private void setBooleanValue(String propertyName, Boolean originalValue, Consumer<Boolean> setter) {
|
||||
setValue(propertyName, originalValue, setter, Boolean::getBoolean);
|
||||
}
|
||||
|
||||
private <T> void setValue(String propertyName, T originalValue, Consumer<T> setter, Function<String, T> systemPropertyReader) {
|
||||
setter.accept(originalValue);
|
||||
createPropertyName(propertyName)
|
||||
.map(systemPropertyReader)
|
||||
.ifPresent(value -> {
|
||||
logOverwrite(propertyName, originalValue, value);
|
||||
setter.accept(value);
|
||||
});
|
||||
}
|
||||
|
||||
private void logOverwrite(String propertyName, Object originalValue, Object overwrittenValue) {
|
||||
LOG.debug("overwrite {} of cache '{}' with system property value {} (original value: {})", propertyName, name, overwrittenValue, originalValue);
|
||||
}
|
||||
|
||||
private Optional<String> createPropertyName(String fieldName) {
|
||||
if (name == null) {
|
||||
LOG.warn("failed to overwrite cache configuration with system properties, because name has not been set yet");
|
||||
return empty();
|
||||
}
|
||||
if (name.startsWith("sonia.cache.")) {
|
||||
return of("scm.cache." + name.substring("sonia.cache.".length()) + "." + fieldName);
|
||||
}
|
||||
return empty();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,14 +28,19 @@ import com.google.inject.AbstractModule;
|
||||
import com.google.inject.TypeLiteral;
|
||||
import com.google.inject.multibindings.Multibinder;
|
||||
import com.google.inject.throwingproviders.ThrowingProviderBinder;
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.SCMContext;
|
||||
import sonia.scm.SCMContextProvider;
|
||||
import sonia.scm.cache.CacheManager;
|
||||
import sonia.scm.cache.GuavaCacheManager;
|
||||
import sonia.scm.io.DefaultFileSystem;
|
||||
import sonia.scm.io.FileSystem;
|
||||
import sonia.scm.lifecycle.DefaultRestarter;
|
||||
import sonia.scm.lifecycle.Restarter;
|
||||
import sonia.scm.metrics.MeterRegistryProvider;
|
||||
import sonia.scm.metrics.MonitoringSystem;
|
||||
import sonia.scm.plugin.PluginLoader;
|
||||
import sonia.scm.repository.DefaultRepositoryExportingCheck;
|
||||
import sonia.scm.repository.EventDrivenRepositoryArchiveCheck;
|
||||
@@ -121,6 +126,14 @@ public class BootstrapModule extends AbstractModule {
|
||||
bind(RepositoryUpdateIterator.class, FileRepositoryUpdateIterator.class);
|
||||
bind(StoreUpdateStepUtilFactory.class, FileStoreUpdateStepUtilFactory.class);
|
||||
bind(new TypeLiteral<UpdateStepRepositoryMetadataAccess<Path>>() {}).to(new TypeLiteral<MetadataStore>() {});
|
||||
|
||||
// bind metrics
|
||||
bind(MeterRegistry.class).toProvider(MeterRegistryProvider.class).asEagerSingleton();
|
||||
Multibinder.newSetBinder(binder(), MonitoringSystem.class);
|
||||
|
||||
// bind cache
|
||||
bind(CacheManager.class, GuavaCacheManager.class);
|
||||
bind(org.apache.shiro.cache.CacheManager.class, GuavaCacheManager.class);
|
||||
}
|
||||
|
||||
private <T> void bind(Class<T> clazz, Class<? extends T> defaultImplementation) {
|
||||
|
||||
@@ -30,7 +30,6 @@ import com.google.inject.multibindings.Multibinder;
|
||||
import com.google.inject.servlet.RequestScoped;
|
||||
import com.google.inject.servlet.ServletModule;
|
||||
import com.google.inject.throwingproviders.ThrowingProviderBinder;
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.Default;
|
||||
@@ -39,14 +38,13 @@ import sonia.scm.PushStateDispatcher;
|
||||
import sonia.scm.PushStateDispatcherProvider;
|
||||
import sonia.scm.RootURL;
|
||||
import sonia.scm.Undecorated;
|
||||
import sonia.scm.admin.ScmConfigurationStore;
|
||||
import sonia.scm.api.rest.ObjectMapperProvider;
|
||||
import sonia.scm.api.v2.resources.BranchLinkProvider;
|
||||
import sonia.scm.api.v2.resources.DefaultBranchLinkProvider;
|
||||
import sonia.scm.api.v2.resources.DefaultRepositoryLinkProvider;
|
||||
import sonia.scm.api.v2.resources.RepositoryLinkProvider;
|
||||
import sonia.scm.auditlog.AuditLogConfigurationStoreDecoratorFactory;
|
||||
import sonia.scm.cache.CacheManager;
|
||||
import sonia.scm.cache.GuavaCacheManager;
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.event.ScmEventBus;
|
||||
import sonia.scm.group.DefaultGroupCollector;
|
||||
@@ -65,7 +63,6 @@ import sonia.scm.initialization.InitializationCookieIssuer;
|
||||
import sonia.scm.initialization.InitializationFinisher;
|
||||
import sonia.scm.io.ContentTypeResolver;
|
||||
import sonia.scm.io.DefaultContentTypeResolver;
|
||||
import sonia.scm.metrics.MeterRegistryProvider;
|
||||
import sonia.scm.migration.MigrationDAO;
|
||||
import sonia.scm.net.SSLContextProvider;
|
||||
import sonia.scm.net.TrustManagerProvider;
|
||||
@@ -134,7 +131,6 @@ import sonia.scm.user.UserManager;
|
||||
import sonia.scm.user.UserManagerProvider;
|
||||
import sonia.scm.user.xml.XmlUserDAO;
|
||||
import sonia.scm.util.DebugServlet;
|
||||
import sonia.scm.admin.ScmConfigurationStore;
|
||||
import sonia.scm.web.UserAgentParser;
|
||||
import sonia.scm.web.cgi.CGIExecutorFactory;
|
||||
import sonia.scm.web.cgi.DefaultCGIExecutorFactory;
|
||||
@@ -200,8 +196,6 @@ class ScmServletModule extends ServletModule {
|
||||
// bind extensions
|
||||
pluginLoader.getExtensionProcessor().processAutoBindExtensions(binder());
|
||||
|
||||
// bind metrics
|
||||
bind(MeterRegistry.class).toProvider(MeterRegistryProvider.class).asEagerSingleton();
|
||||
|
||||
// bind security stuff
|
||||
bind(LoginAttemptHandler.class).to(ConfigurableLoginAttemptHandler.class);
|
||||
@@ -210,10 +204,6 @@ class ScmServletModule extends ServletModule {
|
||||
bind(SecuritySystem.class).to(DefaultSecuritySystem.class);
|
||||
bind(AdministrationContext.class, DefaultAdministrationContext.class);
|
||||
|
||||
// bind cache
|
||||
bind(CacheManager.class, GuavaCacheManager.class);
|
||||
bind(org.apache.shiro.cache.CacheManager.class, GuavaCacheManager.class);
|
||||
|
||||
// bind dao
|
||||
bind(GroupDAO.class, XmlGroupDAO.class);
|
||||
bind(UserDAO.class, XmlUserDAO.class);
|
||||
|
||||
Reference in New Issue
Block a user