added caching for the repositorymanager

This commit is contained in:
Sebastian Sdorra
2010-10-14 07:58:51 +02:00
parent 8d8f74bce3
commit e891d762fb
10 changed files with 749 additions and 1 deletions

View File

@@ -85,6 +85,12 @@
<version>${guice.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>

View File

@@ -10,9 +10,13 @@ package sonia.scm;
//~--- non-JDK imports --------------------------------------------------------
import com.google.inject.multibindings.Multibinder;
import com.google.inject.name.Names;
import com.google.inject.servlet.ServletModule;
import sonia.scm.api.rest.UriExtensionsConfig;
import sonia.scm.cache.CacheManager;
import sonia.scm.cache.CacheRepositoryManagerDecorator;
import sonia.scm.cache.EhCacheManager;
import sonia.scm.plugin.SCMPluginManager;
import sonia.scm.plugin.ScriptResourceServlet;
import sonia.scm.repository.BasicRepositoryManager;
@@ -118,8 +122,11 @@ public class ScmServletModule extends ServletModule
repositoryHandlerBinder.addBinding().to(handler);
}
bind(CacheManager.class).to(EhCacheManager.class);
bind(Authenticator.class).to(DemoAuthenticator.class);
bind(RepositoryManager.class).to(BasicRepositoryManager.class);
bind(RepositoryManager.class).annotatedWith(Undecorated.class).to(
BasicRepositoryManager.class);
bind(RepositoryManager.class).to(CacheRepositoryManagerDecorator.class);
bind(ScmWebPluginContext.class).toInstance(webPluginContext);
/*

View File

@@ -0,0 +1,28 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package sonia.scm;
//~--- non-JDK imports --------------------------------------------------------
import com.google.inject.BindingAnnotation;
//~--- JDK imports ------------------------------------------------------------
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*
* @author Sebastian Sdorra
*/
@BindingAnnotation
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
public @interface Undecorated {}

View File

@@ -0,0 +1,46 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package sonia.scm.cache;
/**
*
* @author Sebastian Sdorra
*/
public interface CacheManager
{
/**
* Method description
*
*
* @param key
* @param value
* @param name
* @param <K>
* @param <V>
*
* @return
*/
public <K, V> ExtendedCache<K, V> getExtendedCache(Class<K> key,
Class<V> value, String name);
/**
* Method description
*
*
* @param key
* @param value
* @param name
* @param <K>
* @param <V>
*
* @return
*/
public <K, V> SimpleCache<K, V> getSimpleCache(Class<K> key, Class<V> value,
String name);
}

View File

@@ -0,0 +1,217 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package sonia.scm.cache;
//~--- non-JDK imports --------------------------------------------------------
import com.google.inject.Inject;
import com.google.inject.name.Named;
import sonia.scm.repository.AbstractRepositoryManagerDecorator;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryException;
import sonia.scm.repository.RepositoryManager;
import sonia.scm.util.AssertUtil;
import sonia.scm.util.Util;
//~--- JDK imports ------------------------------------------------------------
import java.io.IOException;
import java.util.Collection;
import sonia.scm.Undecorated;
/**
*
* @author Sebastian Sdorra
*/
public class CacheRepositoryManagerDecorator
extends AbstractRepositoryManagerDecorator
{
/** Field description */
public static final String CACHE_KEY_ALL = "__all";
/** Field description */
public static final String CACHE_REPOSITORY = "sonia.cache.repository";
//~--- constructors ---------------------------------------------------------
/**
* Constructs ...
*
*
* @param manager
* @param cacheManager
*/
@Inject
public CacheRepositoryManagerDecorator(
@Undecorated RepositoryManager manager,
CacheManager cacheManager)
{
super(manager);
cache = cacheManager.getExtendedCache(String.class, Repository.class,
CACHE_REPOSITORY);
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param repository
*
* @throws IOException
* @throws RepositoryException
*/
@Override
public void create(Repository repository)
throws RepositoryException, IOException
{
orginal.create(repository);
putToCache(repository);
}
/**
* Method description
*
*
* @param repository
*
* @throws IOException
* @throws RepositoryException
*/
@Override
public void delete(Repository repository)
throws RepositoryException, IOException
{
orginal.delete(repository);
removeFromCache(repository);
}
/**
* Method description
*
*
* @param repository
*
* @throws IOException
* @throws RepositoryException
*/
@Override
public void modify(Repository repository)
throws RepositoryException, IOException
{
cache.remove(repository.getId());
orginal.modify(repository);
putToCache(repository);
}
/**
* Method description
*
*
* @param repository
*
* @throws IOException
* @throws RepositoryException
*/
@Override
public void refresh(Repository repository)
throws RepositoryException, IOException
{
orginal.refresh(repository);
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @param id
*
* @return
*/
@Override
public Repository get(String id)
{
AssertUtil.assertIsNotEmpty(id);
Repository repository = cache.get(id);
if (repository == null)
{
repository = orginal.get(id);
if (repository != null)
{
putToCache(repository);
}
}
return repository;
}
/**
* Method description
*
*
* @return
*/
@Override
public Collection<Repository> getAll()
{
Collection<Repository> repositories = cache.getCollection(CACHE_KEY_ALL);
if (repositories == null)
{
repositories = orginal.getAll();
cache.putCollection(CACHE_KEY_ALL, repositories);
}
return repositories;
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param repository
*/
private void putToCache(Repository repository)
{
String id = repository.getId();
if (Util.isNotEmpty(id))
{
cache.put(id, repository);
cache.removeCollection(CACHE_KEY_ALL);
}
}
/**
* Method description
*
*
* @param repository
*/
private void removeFromCache(Repository repository)
{
cache.remove(repository.getId());
cache.removeCollection(CACHE_KEY_ALL);
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private ExtendedCache<String, Repository> cache;
}

View File

@@ -0,0 +1,156 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package sonia.scm.cache;
//~--- non-JDK imports --------------------------------------------------------
import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;
//~--- JDK imports ------------------------------------------------------------
import java.util.Collection;
/**
*
* @author Sebastian Sdorra
*
* @param <K>
* @param <V>
*/
public class EhCache<K, V> implements ExtendedCache<K, V>
{
/**
* Constructs ...
*
*
* @param cache
*/
public EhCache(Cache cache)
{
this.cache = cache;
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*/
@Override
public void clear()
{
cache.removeAll();
}
/**
* Method description
*
*
* @param key
* @param value
*/
@Override
public void put(K key, V value)
{
cache.put(new Element(key, value));
}
/**
* Method description
*
*
* @param key
* @param value
*/
@Override
public void putCollection(K key, Collection<V> value)
{
cache.put(new Element(key, value));
}
/**
* Method description
*
*
* @param key
*
* @return
*/
@Override
public boolean remove(K key)
{
return cache.remove(key);
}
/**
* Method description
*
*
* @param key
*
* @return
*/
@Override
public boolean removeCollection(K key)
{
return cache.remove(key);
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @param key
*
* @return
*/
@Override
public V get(K key)
{
V value = null;
Element el = cache.get(key);
if (el != null)
{
value = (V) el.getObjectValue();
}
return value;
}
/**
* Method description
*
*
* @param key
*
* @return
*/
@Override
public Collection<V> getCollection(K key)
{
Collection<V> value = null;
Element el = cache.get(key);
if (el != null)
{
value = (Collection<V>) el.getObjectValue();
}
return value;
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private Cache cache;
}

View File

@@ -0,0 +1,99 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package sonia.scm.cache;
//~--- non-JDK imports --------------------------------------------------------
import com.google.inject.Singleton;
/**
*
* @author Sebastian Sdorra
*/
@Singleton
public class EhCacheManager implements CacheManager
{
/** Field description */
public static final String CONFIG = "/config/ehcache.xml";
//~--- constructors ---------------------------------------------------------
/**
* Constructs ...
*
*/
public EhCacheManager()
{
cacheManager =
new net.sf.ehcache.CacheManager(EhCacheManager.class.getResource(CONFIG));
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @param key
* @param value
* @param name
* @param <K>
* @param <V>
*
* @return
*/
@Override
public <K, V> ExtendedCache<K, V> getExtendedCache(Class<K> key,
Class<V> value, String name)
{
return getCache(key, value, name);
}
/**
* Method description
*
*
* @param key
* @param value
* @param name
* @param <K>
* @param <V>
*
* @return
*/
@Override
public <K, V> SimpleCache<K, V> getSimpleCache(Class<K> key, Class<V> value,
String name)
{
return getCache(key, value, name);
}
/**
* Method description
*
*
* @param key
* @param value
* @param name
* @param <K>
* @param <V>
*
* @return
*/
private <K, V> EhCache<K, V> getCache(Class<K> key, Class<V> value,
String name)
{
return new EhCache<K, V>(cacheManager.getCache(name));
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private net.sf.ehcache.CacheManager cacheManager;
}

View File

@@ -0,0 +1,54 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package sonia.scm.cache;
//~--- JDK imports ------------------------------------------------------------
import java.util.Collection;
/**
*
* @author Sebastian Sdorra
*
* @param <K>
* @param <V>
*/
public interface ExtendedCache<K, V> extends SimpleCache<K, V>
{
/**
* Method description
*
*
* @param key
* @param value
*/
public void putCollection(K key, Collection<V> value);
/**
* Method description
*
*
* @param key
*
* @return
*/
public boolean removeCollection(K key);
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @param key
*
* @return
*/
public Collection<V> getCollection(K key);
}

View File

@@ -0,0 +1,56 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package sonia.scm.cache;
/**
*
* @author Sebastian Sdorra
*
* @param <K>
* @param <V>
*/
public interface SimpleCache<K, V>
{
/**
* Method description
*
*/
public void clear();
/**
* Method description
*
*
* @param key
* @param value
*/
public void put(K key, V value);
/**
* Method description
*
*
* @param key
*
* @return
*/
public boolean remove(K key);
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @param key
*
* @return
*/
public V get(K key);
}

View File

@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Document : ehcache.xml
Created on : October 14, 2010, 6:54 AM
Author : sdorra
Description:
Purpose of the document follows.
-->
<ehcache xmlns="http://ehcache.org/ehcache.xsd">
<!--
Sets the path to the directory where cache .data files are created.
If the path is a Java System Property it is replaced by
its value in the running VM.
The following properties are translated:
user.home - User's home directory
user.dir - User's current working directory
java.io.tmpdir - Default temp file path
-->
<diskStore path="java.io.tmpdir"/>
<!--
Default Cache configuration. These will applied to caches programmatically created through
the CacheManager.
The following attributes are required:
maxElementsInMemory - Sets the maximum number of objects that will be created in memory
eternal - Sets whether elements are eternal. If eternal, timeouts are ignored and the
element is never expired.
overflowToDisk - Sets whether elements can overflow to disk when the in-memory cache
has reached the maxInMemory limit.
The following attributes are optional:
timeToIdleSeconds - Sets the time to idle for an element before it expires.
i.e. The maximum amount of time between accesses before an element expires
Is only used if the element is not eternal.
Optional attribute. A value of 0 means that an Element can idle for infinity.
The default value is 0.
timeToLiveSeconds - Sets the time to live for an element before it expires.
i.e. The maximum time between creation time and when an element expires.
Is only used if the element is not eternal.
Optional attribute. A value of 0 means that and Element can live for infinity.
The default value is 0.
diskPersistent - Whether the disk store persists between restarts of the Virtual Machine.
The default value is false.
diskExpiryThreadIntervalSeconds- The number of seconds between runs of the disk expiry thread. The default value
is 120 seconds.
-->
<defaultCache
maxElementsInMemory="20000"
eternal="false"
overflowToDisk="true"
timeToIdleSeconds="1200"
timeToLiveSeconds="2400"
diskPersistent="true"
diskExpiryThreadIntervalSeconds="2400"
/>
<cache
name="sonia.cache.repository"
maxElementsInMemory="20000"
eternal="false"
overflowToDisk="true"
timeToIdleSeconds="1200"
timeToLiveSeconds="2400"
diskPersistent="true"
diskExpiryThreadIntervalSeconds="2400"
/>
</ehcache>