From 82c2160fd2fa76cece04cb6e0a7261bcb6e73d91 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Mon, 4 Mar 2013 19:37:40 +0100 Subject: [PATCH 01/28] added script to analyze ehcache sizes --- .../scm-script-plugin/analyze-ehcache.groovy | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 support/scm-script-plugin/analyze-ehcache.groovy diff --git a/support/scm-script-plugin/analyze-ehcache.groovy b/support/scm-script-plugin/analyze-ehcache.groovy new file mode 100644 index 0000000000..dd26cc423c --- /dev/null +++ b/support/scm-script-plugin/analyze-ehcache.groovy @@ -0,0 +1,86 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of SCM-Manager; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + +// see https://bitbucket.org/sdorra/scm-manager/issue/345/ehcache-eating-up-all-memory + +def humanReadable(def bytes) { + if (bytes < 1024) return bytes + " B"; + int exp = (int) (Math.log(bytes) / Math.log(1024)); + String pre = "KMGTPE".charAt(exp-1); + return String.format("%.1f %sB", bytes / Math.pow(1024, exp), pre); +} + +def sizeOf(Serializable object){ + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(object); + oos.close(); + return baos.size(); +} + +Runtime runtime = Runtime.getRuntime(); +def maxMemory = runtime.maxMemory(); +def allocatedMemory = runtime.totalMemory(); +def freeMemory = runtime.freeMemory(); + +println "memory:" +println " - max : " + humanReadable(maxMemory); +println " - allocated : " + humanReadable(allocatedMemory); +println " - free : " + humanReadable(freeMemory); + +println ""; +println ""; + +def cacheManager = injector.getInstance(sonia.scm.cache.CacheManager.class).cacheManager; + +def totalCMax = 0; + +def cacheNames = cacheManager.getCacheNames(); +for ( def cacheName : cacheNames ){ + def cache = cacheManager.getCache(cacheName); + def totalMemory = cache.calculateInMemorySize(); + def average = cache.getSize() > 0 ? Math.round( totalMemory / cache.getSize() ) : 0; + def max = cache.getCacheConfiguration().getMaxEntriesLocalHeap(); + def maxSize = average * max; + + totalCMax += maxSize; + + println cache.name + ":"; + println " - size : " + cache.getSize(); + println " - maxsize : " + max; + println " - average : " + humanReadable( average ); + println " - current : " + humanReadable( totalMemory ); + println " - cmax : " + humanReadable( maxSize ); +} + +println ""; +println ""; +println "Total CMax: " + humanReadable(totalCMax); \ No newline at end of file From 1d27d5d581209251b888322da064b7d87dc7a825 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Mon, 4 Mar 2013 20:00:42 +0100 Subject: [PATCH 02/28] improve cache configuration --- .../src/main/resources/config/ehcache.xml | 158 +++++++++++------- 1 file changed, 99 insertions(+), 59 deletions(-) diff --git a/scm-webapp/src/main/resources/config/ehcache.xml b/scm-webapp/src/main/resources/config/ehcache.xml index 73ff38a498..fc5f87261a 100644 --- a/scm-webapp/src/main/resources/config/ehcache.xml +++ b/scm-webapp/src/main/resources/config/ehcache.xml @@ -88,18 +88,23 @@ --> + + + + - + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - From 3ad8dcfbf5ae632b9c3e1f64837511bdb5874ee1 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Mon, 4 Mar 2013 20:06:22 +0100 Subject: [PATCH 03/28] added configuration for authorization cache --- scm-webapp/src/main/resources/config/ehcache.xml | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/scm-webapp/src/main/resources/config/ehcache.xml b/scm-webapp/src/main/resources/config/ehcache.xml index fc5f87261a..bf57c4f9ff 100644 --- a/scm-webapp/src/main/resources/config/ehcache.xml +++ b/scm-webapp/src/main/resources/config/ehcache.xml @@ -111,7 +111,20 @@ timeToLiveSeconds="60" diskPersistent="false" /> - + + + Date: Mon, 4 Mar 2013 20:37:09 +0100 Subject: [PATCH 06/28] use ArrayList instead of ImmutableList for searchresult, because the result must be mutable for decorators --- .../src/main/java/sonia/scm/search/SearchHandler.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/scm-webapp/src/main/java/sonia/scm/search/SearchHandler.java b/scm-webapp/src/main/java/sonia/scm/search/SearchHandler.java index d5cb9ea8fa..e3a0f25c5c 100644 --- a/scm-webapp/src/main/java/sonia/scm/search/SearchHandler.java +++ b/scm-webapp/src/main/java/sonia/scm/search/SearchHandler.java @@ -37,7 +37,7 @@ package sonia.scm.search; import com.google.common.base.Function; import com.google.common.collect.Collections2; -import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; import org.apache.shiro.SecurityUtils; import org.apache.shiro.subject.Subject; @@ -140,8 +140,11 @@ public class SearchHandler Collections2.transform(users, function); result.setSuccess(true); + // create a copy of the result collection to reduce memory - result.setResults(ImmutableList.copyOf(resultCollection)); + // use ArrayList instead of ImmutableList for copy, + // because the list must be mutable for decorators + result.setResults(Lists.newArrayList(resultCollection)); cache.put(queryString, result); } } From 13de1420df75abcc4d644fe47ac8d4c24682da42 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Tue, 19 Mar 2013 07:59:57 +0100 Subject: [PATCH 07/28] allow 10000 cache entries on disk for unknown caches --- scm-webapp/src/main/resources/config/ehcache.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scm-webapp/src/main/resources/config/ehcache.xml b/scm-webapp/src/main/resources/config/ehcache.xml index 6a02a59904..49b5c86e38 100644 --- a/scm-webapp/src/main/resources/config/ehcache.xml +++ b/scm-webapp/src/main/resources/config/ehcache.xml @@ -89,7 +89,7 @@ + + + + + + + + + + + + diff --git a/scm-webapp/src/test/resources/sonia/scm/cache/cache.002.xml b/scm-webapp/src/test/resources/sonia/scm/cache/cache.002.xml new file mode 100644 index 0000000000..6abcd39ad1 --- /dev/null +++ b/scm-webapp/src/test/resources/sonia/scm/cache/cache.002.xml @@ -0,0 +1,44 @@ + + + + + + + + + + diff --git a/scm-webapp/src/test/resources/sonia/scm/cache/cache.003.xml b/scm-webapp/src/test/resources/sonia/scm/cache/cache.003.xml new file mode 100644 index 0000000000..ee3f6e2ded --- /dev/null +++ b/scm-webapp/src/test/resources/sonia/scm/cache/cache.003.xml @@ -0,0 +1,44 @@ + + + + + + + + + + diff --git a/scm-webapp/src/test/resources/sonia/scm/cache/cache.004.xml b/scm-webapp/src/test/resources/sonia/scm/cache/cache.004.xml new file mode 100644 index 0000000000..5252b010bd --- /dev/null +++ b/scm-webapp/src/test/resources/sonia/scm/cache/cache.004.xml @@ -0,0 +1,44 @@ + + + + + + + + + + diff --git a/scm-webapp/src/test/resources/sonia/scm/cache/cache.005.xml b/scm-webapp/src/test/resources/sonia/scm/cache/cache.005.xml new file mode 100644 index 0000000000..445d66b591 --- /dev/null +++ b/scm-webapp/src/test/resources/sonia/scm/cache/cache.005.xml @@ -0,0 +1,41 @@ + + + + + + + + + From 6fdede3823adf6a3208f92d6a681619df3e79d46 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Tue, 19 Mar 2013 13:44:29 +0100 Subject: [PATCH 09/28] disable update check and set maxBytesLocalDisk to 512M --- scm-webapp/src/main/resources/config/ehcache.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scm-webapp/src/main/resources/config/ehcache.xml b/scm-webapp/src/main/resources/config/ehcache.xml index 49b5c86e38..446e35b505 100644 --- a/scm-webapp/src/main/resources/config/ehcache.xml +++ b/scm-webapp/src/main/resources/config/ehcache.xml @@ -40,7 +40,9 @@ Purpose of the document follows. --> - + + + + + + diff --git a/scm-webapp/src/test/resources/sonia/scm/cache/cache.007.xml b/scm-webapp/src/test/resources/sonia/scm/cache/cache.007.xml new file mode 100644 index 0000000000..cc24dd3ca9 --- /dev/null +++ b/scm-webapp/src/test/resources/sonia/scm/cache/cache.007.xml @@ -0,0 +1,38 @@ + + + + + + + From e0cec05b4daaf1dbb0e5aea246350fcee7585fd7 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Tue, 19 Mar 2013 14:19:50 +0100 Subject: [PATCH 11/28] added comments for ehcache logging configuration --- scm-webapp/src/main/resources/logback.default.xml | 5 +++++ scm-webapp/src/main/resources/logback.release.xml | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/scm-webapp/src/main/resources/logback.default.xml b/scm-webapp/src/main/resources/logback.default.xml index 10fd6951a6..280f08bf93 100644 --- a/scm-webapp/src/main/resources/logback.default.xml +++ b/scm-webapp/src/main/resources/logback.default.xml @@ -76,6 +76,11 @@ + + + diff --git a/scm-webapp/src/main/resources/logback.release.xml b/scm-webapp/src/main/resources/logback.release.xml index d1c7ab7624..1d7e15cad5 100644 --- a/scm-webapp/src/main/resources/logback.release.xml +++ b/scm-webapp/src/main/resources/logback.release.xml @@ -98,6 +98,11 @@ + + + From 18e6d6d5ab66cd04c57652853c7b64ec0fd1af05 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Wed, 20 Mar 2013 07:46:52 +0100 Subject: [PATCH 12/28] create a copy of the tag collection to reduce memory on caching --- .../java/sonia/scm/repository/GitChangesetConverter.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitChangesetConverter.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitChangesetConverter.java index 7277ad55ab..27accf504f 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitChangesetConverter.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitChangesetConverter.java @@ -212,9 +212,10 @@ public class GitChangesetConverter implements Closeable Collection tagCollection = tags.get(commit.getId()); - if (tagCollection != null) + if (Util.isNotEmpty(tagCollection)) { - changeset.getTags().addAll(tagCollection); + // create a copy of the tag collection to reduce memory on caching + changeset.getTags().addAll(Lists.newArrayList(tagCollection)); } changeset.setBranches(branches); From 720d6d3405640b38c16a1fa68453b934b8e0eeb0 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sun, 24 Mar 2013 13:44:25 +0100 Subject: [PATCH 13/28] use version 2.6.5 of ehcache --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f909525a1b..5869bf04f8 100644 --- a/pom.xml +++ b/pom.xml @@ -422,7 +422,7 @@ 2.5 3.0 1.17 - 2.6.3 + 2.6.5 2.3.19 7.6.8.v20121106 From 294b9013a323ce147e84142c0ca67540f21acc13 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sun, 24 Mar 2013 13:48:07 +0100 Subject: [PATCH 14/28] implement equals, hashCode and toString of ChangesetPagingResult --- .../scm/repository/ChangesetPagingResult.java | 62 ++++++++++++++++++- .../scm/repository/spi/LogCommandRequest.java | 5 +- 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/scm-core/src/main/java/sonia/scm/repository/ChangesetPagingResult.java b/scm-core/src/main/java/sonia/scm/repository/ChangesetPagingResult.java index 0d2faad088..0712ed40af 100644 --- a/scm-core/src/main/java/sonia/scm/repository/ChangesetPagingResult.java +++ b/scm-core/src/main/java/sonia/scm/repository/ChangesetPagingResult.java @@ -33,6 +33,10 @@ package sonia.scm.repository; +//~--- non-JDK imports -------------------------------------------------------- + +import com.google.common.base.Objects; + //~--- JDK imports ------------------------------------------------------------ import java.io.Serializable; @@ -47,7 +51,7 @@ import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; /** - * The changeset paging result is used to do a paging over the + * The changeset paging result is used to do a paging over the * {@link Changeset}s of a {@link Repository}. * * @author Sebastian Sdorra @@ -83,6 +87,45 @@ public class ChangesetPagingResult implements Iterable, Serializable //~--- methods -------------------------------------------------------------- + /** + * Method description + * + * + * @param obj + * + * @return + */ + @Override + public boolean equals(Object obj) + { + if (obj == null) + { + return false; + } + + if (getClass() != obj.getClass()) + { + return false; + } + + final ChangesetPagingResult other = (ChangesetPagingResult) obj; + + return Objects.equal(changesets, other.changesets) + && Objects.equal(total, other.total); + } + + /** + * Method description + * + * + * @return + */ + @Override + public int hashCode() + { + return Objects.hashCode(changesets, total); + } + /** * Returns an iterator which can iterate over the current list of changesets. * @@ -103,6 +146,23 @@ public class ChangesetPagingResult implements Iterable, Serializable return it; } + /** + * Method description + * + * + * @return + */ + @Override + public String toString() + { + //J- + return Objects.toStringHelper(this) + .add("changesets", changesets) + .add("total", total) + .toString(); + //J+ + } + //~--- get methods ---------------------------------------------------------- /** diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/LogCommandRequest.java b/scm-core/src/main/java/sonia/scm/repository/spi/LogCommandRequest.java index feed50abda..21391e4b3a 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/LogCommandRequest.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/LogCommandRequest.java @@ -77,11 +77,14 @@ public final class LogCommandRequest implements Serializable, Resetable final LogCommandRequest other = (LogCommandRequest) obj; + //J- return Objects.equal(startChangeset, other.startChangeset) && Objects.equal(endChangeset, other.endChangeset) && Objects.equal(pagingStart, other.pagingStart) && Objects.equal(pagingLimit, other.pagingLimit) - && Objects.equal(path, other.path) && Objects.equal(branch, other.branch); + && Objects.equal(path, other.path) + && Objects.equal(branch, other.branch); + //J+ } /** From d2a107d112e7bc98831cdcfd3ae404908af9f1c0 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sun, 24 Mar 2013 14:02:03 +0100 Subject: [PATCH 15/28] added FastByteArrayInputStream, FastByteArrayOutputStream and DeepCopy --- .../src/main/java/sonia/scm/io/DeepCopy.java | 95 +++++++++ .../scm/io/FastByteArrayInputStream.java | 161 +++++++++++++++ .../scm/io/FastByteArrayOutputStream.java | 187 ++++++++++++++++++ 3 files changed, 443 insertions(+) create mode 100644 scm-core/src/main/java/sonia/scm/io/DeepCopy.java create mode 100644 scm-core/src/main/java/sonia/scm/io/FastByteArrayInputStream.java create mode 100644 scm-core/src/main/java/sonia/scm/io/FastByteArrayOutputStream.java diff --git a/scm-core/src/main/java/sonia/scm/io/DeepCopy.java b/scm-core/src/main/java/sonia/scm/io/DeepCopy.java new file mode 100644 index 0000000000..5f6eece040 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/io/DeepCopy.java @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.io; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +/** + * Utility for making deep copies (vs. clone()'s shallow copies) of + * objects. Objects are first serialized and then deserialized. Error + * checking is fairly minimal in this implementation. If an object is + * encountered that cannot be serialized (or that references an object + * that cannot be serialized) an error is printed to System.err and + * null is returned. Depending on your specific application, it might + * make more sense to have copy(...) re-throw the exception. + * + * @author Sebastian Sdorra + * @since 1.29 + * @see http://javatechniques.com/blog/faster-deep-copies-of-java-objects + */ +public final class DeepCopy +{ + + /** + * Returns a copy of the object, or null if the object cannot + * be serialized. + * + * @param orig + * @param + * + * @return + * + * @throws IOException + */ + public static T copy(T orig) throws IOException + { + T obj = null; + + try + { + + // Write the object out to a byte array + FastByteArrayOutputStream fbos = new FastByteArrayOutputStream(); + ObjectOutputStream out = new ObjectOutputStream(fbos); + + out.writeObject(orig); + out.flush(); + out.close(); + + // Retrieve an input stream from the byte array and read + // a copy of the object back in. + ObjectInputStream in = new ObjectInputStream(fbos.getInputStream()); + + obj = (T) in.readObject(); + } + catch (Exception ex) + { + throw new IOException("could not copy object", ex); + } + + return obj; + } +} diff --git a/scm-core/src/main/java/sonia/scm/io/FastByteArrayInputStream.java b/scm-core/src/main/java/sonia/scm/io/FastByteArrayInputStream.java new file mode 100644 index 0000000000..095291ac3b --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/io/FastByteArrayInputStream.java @@ -0,0 +1,161 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.io; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.InputStream; + +/** + * ByteArrayInputStream implementation that does not synchronize methods. + * + * @author Sebastian Sdorra + * @since 1.29 + * @see http://javatechniques.com/blog/faster-deep-copies-of-java-objects + */ +public final class FastByteArrayInputStream extends InputStream +{ + + /** + * Constructs ... + * + * + * @param buf + * @param count + */ + public FastByteArrayInputStream(byte[] buf, int count) + { + this.buf = buf; + this.count = count; + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + @Override + public final int available() + { + return count - pos; + } + + /** + * Method description + * + * + * @return + */ + @Override + public final int read() + { + return (pos < count) + ? (buf[pos++] & 0xff) + : -1; + } + + /** + * Method description + * + * + * @param b + * @param off + * @param len + * + * @return + */ + @Override + public final int read(byte[] b, int off, int len) + { + if (pos >= count) + { + return -1; + } + + if ((pos + len) > count) + { + len = (count - pos); + } + + System.arraycopy(buf, pos, b, off, len); + pos += len; + + return len; + } + + /** + * Method description + * + * + * @param n + * + * @return + */ + @Override + public final long skip(long n) + { + if ((pos + n) > count) + { + n = count - pos; + } + + if (n < 0) + { + return 0; + } + + pos += n; + + return n; + } + + //~--- fields --------------------------------------------------------------- + + /** + * Our byte buffer + */ + private byte[] buf = null; + + /** + * Number of bytes that we can read from the buffer + */ + private int count = 0; + + /** + * Number of bytes that have been read from the buffer + */ + private int pos = 0; +} diff --git a/scm-core/src/main/java/sonia/scm/io/FastByteArrayOutputStream.java b/scm-core/src/main/java/sonia/scm/io/FastByteArrayOutputStream.java new file mode 100644 index 0000000000..e130402d8e --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/io/FastByteArrayOutputStream.java @@ -0,0 +1,187 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.io; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.InputStream; +import java.io.OutputStream; + +/** + * ByteArrayOutputStream implementation that doesn't synchronize methods + * and doesn't copy the data on toByteArray(). + * + * @author Sebastian Sdorra + * @since 1.29 + * @see http://javatechniques.com/blog/faster-deep-copies-of-java-objects + */ +public final class FastByteArrayOutputStream extends OutputStream +{ + + /** + * Constructs a stream with buffer capacity size 5K + */ + public FastByteArrayOutputStream() + { + this(5 * 1024); + } + + /** + * Constructs a stream with the given initial size + * + * @param initSize + */ + public FastByteArrayOutputStream(int initSize) + { + this.size = 0; + this.buf = new byte[initSize]; + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param b + */ + @Override + public final void write(byte b[]) + { + verifyBufferSize(size + b.length); + System.arraycopy(b, 0, buf, size, b.length); + size += b.length; + } + + /** + * Method description + * + * + * @param b + * @param off + * @param len + */ + @Override + public final void write(byte b[], int off, int len) + { + verifyBufferSize(size + len); + System.arraycopy(b, off, buf, size, len); + size += len; + } + + /** + * Method description + * + * + * @param b + */ + @Override + public final void write(int b) + { + verifyBufferSize(size + 1); + buf[size++] = (byte) b; + } + + /** + * Method description + * + */ + public void reset() + { + size = 0; + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Returns the byte array containing the written data. Note that this + * array will almost always be larger than the amount of data actually + * written. + * + * @return + */ + public byte[] getByteArray() + { + return buf; + } + + /** + * Returns a ByteArrayInputStream for reading back the written data + * + * @return + */ + public InputStream getInputStream() + { + return new FastByteArrayInputStream(buf, size); + } + + /** + * Method description + * + * + * @return + */ + public int getSize() + { + return size; + } + + //~--- methods -------------------------------------------------------------- + + /** + * Ensures that we have a large enough buffer for the given size. + * + * @param sz + */ + private void verifyBufferSize(int sz) + { + if (sz > buf.length) + { + byte[] old = buf; + + buf = new byte[Math.max(sz, 2 * buf.length)]; + System.arraycopy(old, 0, buf, 0, old.length); + old = null; + } + } + + //~--- fields --------------------------------------------------------------- + + /** + * Buffer and size + */ + private byte[] buf = null; + + /** Field description */ + private int size = 0; +} From 57f5e31a5421cd8221e27d0ce03387e7ef21b430 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sun, 24 Mar 2013 19:52:06 +0100 Subject: [PATCH 16/28] start implementation of guava based CacheManager --- .../sonia/scm/cache/CacheConfiguration.java | 231 +++++++++++++++ .../java/sonia/scm/cache/CacheException.java | 85 ++++++ .../scm/cache/CacheManagerConfiguration.java | 83 ++++++ .../java/sonia/scm/cache/CopyStrategy.java | 147 +++++++++ .../main/java/sonia/scm/cache/GuavaCache.java | 280 ++++++++++++++++++ .../sonia/scm/cache/GuavaCacheManager.java | 122 ++++++++ 6 files changed, 948 insertions(+) create mode 100644 scm-webapp/src/main/java/sonia/scm/cache/CacheConfiguration.java create mode 100644 scm-webapp/src/main/java/sonia/scm/cache/CacheException.java create mode 100644 scm-webapp/src/main/java/sonia/scm/cache/CacheManagerConfiguration.java create mode 100644 scm-webapp/src/main/java/sonia/scm/cache/CopyStrategy.java create mode 100644 scm-webapp/src/main/java/sonia/scm/cache/GuavaCache.java create mode 100644 scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheManager.java diff --git a/scm-webapp/src/main/java/sonia/scm/cache/CacheConfiguration.java b/scm-webapp/src/main/java/sonia/scm/cache/CacheConfiguration.java new file mode 100644 index 0000000000..8ea1ace268 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/cache/CacheConfiguration.java @@ -0,0 +1,231 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.cache; + +//~--- JDK imports ------------------------------------------------------------ + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * + * @author Sebastian Sdorra + */ +@XmlRootElement(name = "cache") +@XmlAccessorType(XmlAccessType.FIELD) +public class CacheConfiguration +{ + + /** + * Method description + * + * + * @return + */ + public Integer getConcurrencyLevel() + { + return concurrencyLevel; + } + + /** + * Method description + * + * + * @return + */ + public CopyStrategy getCopyStrategy() + { + return copyStrategy; + } + + /** + * Method description + * + * + * @return + */ + public Long getExpireAfterAccess() + { + return expireAfterAccess; + } + + /** + * Method description + * + * + * @return + */ + public Long getExpireAfterWrite() + { + return expireAfterWrite; + } + + /** + * Method description + * + * + * @return + */ + public Integer getInitialCapacity() + { + return initialCapacity; + } + + /** + * Method description + * + * + * @return + */ + public Long getMaximumSize() + { + return maximumSize; + } + + /** + * Method description + * + * + * @return + */ + public Long getMaximumWeight() + { + return maximumWeight; + } + + /** + * Method description + * + * + * @return + */ + public String getName() + { + return name; + } + + /** + * Method description + * + * + * @return + */ + public Boolean getRecordStats() + { + return recordStats; + } + + /** + * Method description + * + * + * @return + */ + public Boolean getSoftValues() + { + return softValues; + } + + /** + * Method description + * + * + * @return + */ + public Boolean getWeakKeys() + { + return weakKeys; + } + + /** + * Method description + * + * + * @return + */ + public Boolean getWeakValues() + { + return weakValues; + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + @XmlAttribute + private Integer concurrencyLevel; + + /** Field description */ + @XmlAttribute + private CopyStrategy copyStrategy; + + /** Field description */ + @XmlAttribute + private Long expireAfterAccess; + + /** Field description */ + @XmlAttribute + private Long expireAfterWrite; + + /** Field description */ + @XmlAttribute + private Integer initialCapacity; + + /** Field description */ + @XmlAttribute + private Long maximumSize; + + /** Field description */ + @XmlAttribute + private Long maximumWeight; + + /** Field description */ + @XmlAttribute + private String name; + + /** Field description */ + @XmlAttribute + private Boolean recordStats; + + /** Field description */ + @XmlAttribute + private Boolean softValues; + + /** Field description */ + @XmlAttribute + private Boolean weakKeys; + + /** Field description */ + @XmlAttribute + private Boolean weakValues; +} diff --git a/scm-webapp/src/main/java/sonia/scm/cache/CacheException.java b/scm-webapp/src/main/java/sonia/scm/cache/CacheException.java new file mode 100644 index 0000000000..817ea81656 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/cache/CacheException.java @@ -0,0 +1,85 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.cache; + +/** + * + * @author Sebastian Sdorra + */ +public class CacheException extends RuntimeException +{ + + /** Field description */ + private static final long serialVersionUID = -1108209749696572319L; + + //~--- constructors --------------------------------------------------------- + + /** + * Constructs ... + * + */ + public CacheException() {} + + /** + * Constructs ... + * + * + * @param message + */ + public CacheException(String message) + { + super(message); + } + + /** + * Constructs ... + * + * + * @param cause + */ + public CacheException(Throwable cause) + { + super(cause); + } + + /** + * Constructs ... + * + * + * @param message + * @param cause + */ + public CacheException(String message, Throwable cause) + { + super(message, cause); + } +} diff --git a/scm-webapp/src/main/java/sonia/scm/cache/CacheManagerConfiguration.java b/scm-webapp/src/main/java/sonia/scm/cache/CacheManagerConfiguration.java new file mode 100644 index 0000000000..0fb3ecb30d --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/cache/CacheManagerConfiguration.java @@ -0,0 +1,83 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.cache; + +//~--- JDK imports ------------------------------------------------------------ + +import java.util.List; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * + * @author Sebastian Sdorra + */ +@XmlRootElement(name = "caches") +@XmlAccessorType(XmlAccessType.FIELD) +public class CacheManagerConfiguration +{ + + /** + * Method description + * + * + * @return + */ + public List getCaches() + { + return caches; + } + + /** + * Method description + * + * + * @return + */ + public CacheConfiguration getDefaultCache() + { + return defaultCache; + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + @XmlElement(name = "cache") + private List caches; + + /** Field description */ + @XmlElement(name = "cache") + private CacheConfiguration defaultCache; +} diff --git a/scm-webapp/src/main/java/sonia/scm/cache/CopyStrategy.java b/scm-webapp/src/main/java/sonia/scm/cache/CopyStrategy.java new file mode 100644 index 0000000000..203f390944 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/cache/CopyStrategy.java @@ -0,0 +1,147 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.cache; + +//~--- non-JDK imports -------------------------------------------------------- + +import sonia.scm.io.DeepCopy; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.IOException; + +import java.util.Locale; + +/** + * + * @author Sebastian Sdorra + */ +public enum CopyStrategy +{ + + NONE(false, false), READ(true, false), WRITE(false, true), + READWRITE(true, true); + + /** + * Constructs ... + * + * + * @param copyOnRead + * @param copyOnWrite + */ + private CopyStrategy(boolean copyOnRead, boolean copyOnWrite) + { + this.copyOnRead = copyOnRead; + this.copyOnWrite = copyOnWrite; + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param value + * + * @return + */ + public static CopyStrategy fromString(String value) + { + return valueOf(value.toUpperCase(Locale.ENGLISH).replace("-", "")); + } + + /** + * Method description + * + * + * @param object + * @param + * + * @return + */ + public T copyOnRead(T object) + { + return copyOnRead + ? deepCopy(object) + : object; + } + + /** + * Method description + * + * + * @param object + * @param + * + * @return + */ + public T copyOnWrite(T object) + { + return copyOnWrite + ? deepCopy(object) + : object; + } + + /** + * Method description + * + * + * @param object + * @param + * + * @return + */ + private T deepCopy(T object) + { + T copy = null; + + try + { + copy = DeepCopy.copy(object); + } + catch (IOException ex) + { + throw new CacheException( + "could not create a copy of ".concat(object.toString()), ex); + } + + return copy; + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private boolean copyOnRead; + + /** Field description */ + private boolean copyOnWrite; +} diff --git a/scm-webapp/src/main/java/sonia/scm/cache/GuavaCache.java b/scm-webapp/src/main/java/sonia/scm/cache/GuavaCache.java new file mode 100644 index 0000000000..9b23f2d062 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/cache/GuavaCache.java @@ -0,0 +1,280 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.cache; + +//~--- non-JDK imports -------------------------------------------------------- + +import com.google.common.cache.CacheBuilder; +import com.google.common.collect.Sets; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import sonia.scm.Filter; + +//~--- JDK imports ------------------------------------------------------------ + +import java.util.Set; +import java.util.concurrent.TimeUnit; + +/** + * + * @author Sebastian Sdorra + * + * @param + * @param + */ +public class GuavaCache implements Cache +{ + + /** + * the logger for GuavaCache + */ + private static final Logger logger = + LoggerFactory.getLogger(GuavaCache.class); + + //~--- constructors --------------------------------------------------------- + + private String name; + + /** + * Constructs ... + * + * + * @param configuration + */ + public GuavaCache(CacheConfiguration configuration) + { + this.name = configuration.getName(); + + if (configuration.getCopyStrategy() != null) + { + copyStrategy = configuration.getCopyStrategy(); + } + + CacheBuilder builder = CacheBuilder.newBuilder(); + + if (configuration.getConcurrencyLevel() != null) + { + builder.concurrencyLevel(configuration.getConcurrencyLevel()); + } + + if (configuration.getExpireAfterAccess() != null) + { + builder.expireAfterAccess(configuration.getExpireAfterAccess(), + TimeUnit.MILLISECONDS); + } + + if (configuration.getExpireAfterWrite() != null) + { + builder.expireAfterWrite(configuration.getExpireAfterWrite(), + TimeUnit.MILLISECONDS); + } + + if (configuration.getInitialCapacity() != null) + { + builder.initialCapacity(configuration.getInitialCapacity()); + } + + if (configuration.getMaximumSize() != null) + { + builder.maximumSize(configuration.getMaximumSize()); + } + + if (configuration.getMaximumWeight() != null) + { + builder.maximumWeight(configuration.getMaximumWeight()); + } + + if (isEnabled(configuration.getRecordStats())) + { + builder.recordStats(); + } + + if (isEnabled(configuration.getSoftValues())) + { + builder.softValues(); + } + + if (isEnabled(configuration.getWeakKeys())) + { + builder.weakKeys(); + } + + if (isEnabled(configuration.getWeakValues())) + { + builder.weakKeys(); + } + + cache = builder.build(); + + if (logger.isTraceEnabled()) + { + logger.trace("create new guava cache from builder: {}", builder); + } + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + */ + @Override + public void clear() + { + if (logger.isDebugEnabled()) + { + logger.debug("clear cache {}", name); + } + cache.invalidateAll(); + } + + /** + * Method description + * + * + * @param key + * + * @return + */ + @Override + public boolean contains(K key) + { + return cache.getIfPresent(key) != null; + } + + /** + * Method description + * + * + * @param key + * @param value + */ + @Override + public void put(K key, V value) + { + cache.put(key, copyStrategy.copyOnWrite(value)); + } + + /** + * Method description + * + * + * @param key + * + * @return + */ + @Override + public boolean remove(K key) + { + cache.invalidate(key); + + return true; + } + + /** + * Method description + * + * + * @param filter + * + * @return + */ + @Override + public boolean removeAll(Filter filter) + { + Set keysToRemove = Sets.newHashSet(); + + for (K key : cache.asMap().keySet()) + { + if (filter.accept(key)) + { + keysToRemove.add(key); + } + } + + boolean result = false; + + if (!keysToRemove.isEmpty()) + { + cache.invalidateAll(keysToRemove); + result = true; + } + + return result; + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @param key + * + * @return + */ + @Override + public V get(K key) + { + V value = cache.getIfPresent(key); + + if (value != null) + { + value = copyStrategy.copyOnRead(value); + } + + return value; + } + + /** + * Method description + * + * + * @param v + * + * @return + */ + private boolean isEnabled(Boolean v) + { + return (v != null) && v; + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private com.google.common.cache.Cache cache; + + /** Field description */ + private CopyStrategy copyStrategy = CopyStrategy.NONE; +} diff --git a/scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheManager.java b/scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheManager.java new file mode 100644 index 0000000000..36fb75e535 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheManager.java @@ -0,0 +1,122 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.cache; + +//~--- non-JDK imports -------------------------------------------------------- + +import com.google.common.collect.Maps; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.IOException; + +import java.util.Map; + +/** + * + * @author Sebastian Sdorra + */ +public class GuavaCacheManager implements CacheManager +{ + + /** + * the logger for GuavaCacheManager + */ + private static final Logger logger = + LoggerFactory.getLogger(GuavaCacheManager.class); + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @throws IOException + */ + @Override + public void close() throws IOException + { + logger.info("close guava cache manager"); + + for (Cache c : cacheMap.values()) + { + c.clear(); + } + + cacheMap.clear(); + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @param key + * @param value + * @param name + * @param + * @param + * + * @return + */ + @Override + public GuavaCache getCache(Class key, Class value, + String name) + { + logger.trace("try to retrieve cache {}", name); + + GuavaCache cache = cacheMap.get(name); + + if (cache == null) + { + logger.debug( + "cache {} does not exists, creating a new instance from default configuration: {}", + name, defaultConfiguration); + cache = new GuavaCache(defaultConfiguration); + cacheMap.put(name, cache); + } + + return cache; + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private Map cacheMap = Maps.newConcurrentMap(); + + /** Field description */ + private CacheConfiguration defaultConfiguration; +} From c941ffb7494a4651a9505574f112c7e525c28f2f Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Mon, 25 Mar 2013 08:03:32 +0100 Subject: [PATCH 17/28] improve configuration objects --- .../sonia/scm/cache/CacheConfiguration.java | 24 +++---- .../scm/cache/CacheManagerConfiguration.java | 4 +- .../main/java/sonia/scm/cache/GuavaCache.java | 26 +++++-- .../sonia/scm/cache/GuavaCacheManager.java | 2 +- .../scm/cache/NamedCacheConfiguration.java | 71 +++++++++++++++++++ 5 files changed, 102 insertions(+), 25 deletions(-) create mode 100644 scm-webapp/src/main/java/sonia/scm/cache/NamedCacheConfiguration.java diff --git a/scm-webapp/src/main/java/sonia/scm/cache/CacheConfiguration.java b/scm-webapp/src/main/java/sonia/scm/cache/CacheConfiguration.java index 8ea1ace268..a01ca2eccb 100644 --- a/scm-webapp/src/main/java/sonia/scm/cache/CacheConfiguration.java +++ b/scm-webapp/src/main/java/sonia/scm/cache/CacheConfiguration.java @@ -33,6 +33,8 @@ package sonia.scm.cache; //~--- JDK imports ------------------------------------------------------------ +import java.io.Serializable; + import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; @@ -44,9 +46,14 @@ import javax.xml.bind.annotation.XmlRootElement; */ @XmlRootElement(name = "cache") @XmlAccessorType(XmlAccessType.FIELD) -public class CacheConfiguration +public class CacheConfiguration implements Serializable { + /** Field description */ + private static final long serialVersionUID = -8734373158089010603L; + + //~--- get methods ---------------------------------------------------------- + /** * Method description * @@ -124,17 +131,6 @@ public class CacheConfiguration return maximumWeight; } - /** - * Method description - * - * - * @return - */ - public String getName() - { - return name; - } - /** * Method description * @@ -209,10 +205,6 @@ public class CacheConfiguration @XmlAttribute private Long maximumWeight; - /** Field description */ - @XmlAttribute - private String name; - /** Field description */ @XmlAttribute private Boolean recordStats; diff --git a/scm-webapp/src/main/java/sonia/scm/cache/CacheManagerConfiguration.java b/scm-webapp/src/main/java/sonia/scm/cache/CacheManagerConfiguration.java index 0fb3ecb30d..8d49bdd149 100644 --- a/scm-webapp/src/main/java/sonia/scm/cache/CacheManagerConfiguration.java +++ b/scm-webapp/src/main/java/sonia/scm/cache/CacheManagerConfiguration.java @@ -55,7 +55,7 @@ public class CacheManagerConfiguration * * @return */ - public List getCaches() + public List getCaches() { return caches; } @@ -75,7 +75,7 @@ public class CacheManagerConfiguration /** Field description */ @XmlElement(name = "cache") - private List caches; + private List caches; /** Field description */ @XmlElement(name = "cache") diff --git a/scm-webapp/src/main/java/sonia/scm/cache/GuavaCache.java b/scm-webapp/src/main/java/sonia/scm/cache/GuavaCache.java index 9b23f2d062..8256c93520 100644 --- a/scm-webapp/src/main/java/sonia/scm/cache/GuavaCache.java +++ b/scm-webapp/src/main/java/sonia/scm/cache/GuavaCache.java @@ -64,18 +64,28 @@ public class GuavaCache implements Cache //~--- constructors --------------------------------------------------------- - private String name; - /** * Constructs ... * * * @param configuration */ - public GuavaCache(CacheConfiguration configuration) + public GuavaCache(NamedCacheConfiguration configuration) { - this.name = configuration.getName(); - + this(configuration, configuration.getName()); + } + + /** + * Constructs ... + * + * + * @param configuration + * @param name + */ + public GuavaCache(CacheConfiguration configuration, String name) + { + this.name = name; + if (configuration.getCopyStrategy() != null) { copyStrategy = configuration.getCopyStrategy(); @@ -152,10 +162,11 @@ public class GuavaCache implements Cache @Override public void clear() { - if (logger.isDebugEnabled()) + if (logger.isDebugEnabled()) { logger.debug("clear cache {}", name); } + cache.invalidateAll(); } @@ -277,4 +288,7 @@ public class GuavaCache implements Cache /** Field description */ private CopyStrategy copyStrategy = CopyStrategy.NONE; + + /** Field description */ + private String name; } diff --git a/scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheManager.java b/scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheManager.java index 36fb75e535..58783f411f 100644 --- a/scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheManager.java +++ b/scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheManager.java @@ -118,5 +118,5 @@ public class GuavaCacheManager implements CacheManager private Map cacheMap = Maps.newConcurrentMap(); /** Field description */ - private CacheConfiguration defaultConfiguration; + private NamedCacheConfiguration defaultConfiguration; } diff --git a/scm-webapp/src/main/java/sonia/scm/cache/NamedCacheConfiguration.java b/scm-webapp/src/main/java/sonia/scm/cache/NamedCacheConfiguration.java new file mode 100644 index 0000000000..162a449b1d --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/cache/NamedCacheConfiguration.java @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.cache; + +//~--- JDK imports ------------------------------------------------------------ + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * + * @author Sebastian Sdorra + */ +@XmlRootElement(name = "cache") +@XmlAccessorType(XmlAccessType.FIELD) +public class NamedCacheConfiguration extends CacheConfiguration +{ + + /** Field description */ + private static final long serialVersionUID = -624795324874828475L; + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + public String getName() + { + return name; + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + @XmlAttribute + private String name; +} From 3dfa6d4fc1347ae83b2d037741e437b860b65d90 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Mon, 25 Mar 2013 08:50:26 +0100 Subject: [PATCH 18/28] added CacheConfigurationReader for GuavaCacheManager --- .../scm/cache/CacheConfigurationReader.java | 294 ++++++++++++++++++ .../sonia/scm/cache/CacheConfigurations.java | 108 +++++++ .../scm/cache/CacheManagerConfiguration.java | 28 +- .../scm/cache/EhCacheConfigurationReader.java | 42 +-- 4 files changed, 435 insertions(+), 37 deletions(-) create mode 100644 scm-webapp/src/main/java/sonia/scm/cache/CacheConfigurationReader.java create mode 100644 scm-webapp/src/main/java/sonia/scm/cache/CacheConfigurations.java diff --git a/scm-webapp/src/main/java/sonia/scm/cache/CacheConfigurationReader.java b/scm-webapp/src/main/java/sonia/scm/cache/CacheConfigurationReader.java new file mode 100644 index 0000000000..a295ef8c33 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/cache/CacheConfigurationReader.java @@ -0,0 +1,294 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.cache; + +//~--- non-JDK imports -------------------------------------------------------- + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Maps; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import sonia.scm.SCMContext; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.File; + +import java.net.MalformedURLException; +import java.net.URL; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; + +/** + * + * @author Sebastian Sdorra + */ +public class CacheConfigurationReader +{ + + /** Field description */ + private static final String DEFAULT = "/config/cache.xml"; + + /** Field description */ + private static final String MANUAL_RESOURCE = + "ext".concat(File.separator).concat("cache.xml"); + + /** Field description */ + private static final String MODULE_RESOURCES = "/META-INF/scm/cache.xml"; + + /** + * the logger for CacheConfigurationReader + */ + private static final Logger logger = + LoggerFactory.getLogger(CacheConfigurationReader.class); + + //~--- constructors --------------------------------------------------------- + + /** + * Constructs ... + * + */ + public CacheConfigurationReader() + { + try + { + this.context = JAXBContext.newInstance(CacheManagerConfiguration.class); + } + catch (JAXBException ex) + { + throw new CacheException( + "could not create jaxb context for cache configuration", ex); + } + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + public CacheManagerConfiguration read() + { + URL defaultConfigUrl = getDefaultResource(); + + if (defaultConfigUrl == null) + { + throw new IllegalStateException( + "could not find default cache configuration"); + } + + CacheManagerConfiguration config = readConfiguration(defaultConfigUrl, + true); + + Iterator it = getModuleResources(); + + while (it.hasNext()) + { + CacheManagerConfiguration moduleConfig = readConfiguration(it.next(), + false); + + if (moduleConfig != null) + { + config = merge(config, moduleConfig); + } + } + + File manualFile = getManualFileResource(); + + if (manualFile.exists()) + { + try + { + CacheManagerConfiguration manualConfig = + readConfiguration(manualFile.toURI().toURL(), false); + + config = merge(config, manualConfig); + } + catch (MalformedURLException ex) + { + logger.error("malformed url", ex); + } + } + else + { + logger.warn("could not find manual configuration at {}", manualFile); + } + + return config; + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + @VisibleForTesting + protected URL getDefaultResource() + { + return CacheConfigurationReader.class.getResource(DEFAULT); + } + + /** + * Method description + * + * + * @return + */ + @VisibleForTesting + protected File getManualFileResource() + { + return new File(SCMContext.getContext().getBaseDirectory(), + MANUAL_RESOURCE); + } + + /** + * Method description + * + * + * @param path + * + * @return + */ + @VisibleForTesting + protected Iterator getModuleResources() + { + return CacheConfigurations.findModuleResources( + EhCacheConfigurationReader.class, MODULE_RESOURCES); + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param caches + * + * @return + */ + private Map createNamedCacheMap( + List caches) + { + Map map = Maps.newLinkedHashMap(); + + for (NamedCacheConfiguration ncc : caches) + { + map.put(ncc.getName(), ncc); + } + + return map; + } + + /** + * Method description + * + * + * @param config + * @param other + * + * @return + */ + private CacheManagerConfiguration merge(CacheManagerConfiguration config, + CacheManagerConfiguration other) + { + CacheConfiguration defaultCache = config.getDefaultCache(); + Map namedCaches = + createNamedCacheMap(config.getCaches()); + + if (other.getDefaultCache() != null) + { + defaultCache = other.getDefaultCache(); + } + + List otherNamedCaches = other.getCaches(); + + for (NamedCacheConfiguration ncc : otherNamedCaches) + { + namedCaches.put(ncc.getName(), ncc); + } + + return new CacheManagerConfiguration(defaultCache, + ImmutableList.copyOf(namedCaches.values())); + } + + /** + * Method description + * + * + * @param url + * @param fail + * + * @return + */ + private CacheManagerConfiguration readConfiguration(URL url, boolean fail) + { + CacheManagerConfiguration config = null; + + try + { + config = + (CacheManagerConfiguration) context.createUnmarshaller().unmarshal(url); + } + catch (JAXBException ex) + { + if (fail) + { + throw new CacheException("could not unmarshall cache configuration", + ex); + } + else + { + logger.warn("could not unmarshall cache configuration", ex); + } + } + + return config; + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private JAXBContext context; +} diff --git a/scm-webapp/src/main/java/sonia/scm/cache/CacheConfigurations.java b/scm-webapp/src/main/java/sonia/scm/cache/CacheConfigurations.java new file mode 100644 index 0000000000..1b7689d497 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/cache/CacheConfigurations.java @@ -0,0 +1,108 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.cache; + +//~--- non-JDK imports -------------------------------------------------------- + +import com.google.common.collect.Iterators; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.IOException; + +import java.net.URL; + +import java.util.Enumeration; +import java.util.Iterator; + +/** + * + * @author Sebastian Sdorra + */ +public class CacheConfigurations +{ + + /** + * the logger for CacheConfigurations + */ + private static final Logger logger = + LoggerFactory.getLogger(CacheConfigurations.class); + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param loadingClass + * @param resource + * + * @return + */ + public static Iterator findModuleResources(Class loadingClass, + String resource) + { + Iterator it = null; + + try + { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + + if (classLoader == null) + { + classLoader = loadingClass.getClassLoader(); + } + + Enumeration enm = classLoader.getResources(resource); + + if (enm != null) + { + it = Iterators.forEnumeration(enm); + } + + } + catch (IOException ex) + { + logger.error("could not read module resources", ex); + } + + if (it == null) + { + it = Iterators.emptyIterator(); + } + + return it; + } +} diff --git a/scm-webapp/src/main/java/sonia/scm/cache/CacheManagerConfiguration.java b/scm-webapp/src/main/java/sonia/scm/cache/CacheManagerConfiguration.java index 8d49bdd149..e0d8c8b4d4 100644 --- a/scm-webapp/src/main/java/sonia/scm/cache/CacheManagerConfiguration.java +++ b/scm-webapp/src/main/java/sonia/scm/cache/CacheManagerConfiguration.java @@ -33,6 +33,7 @@ package sonia.scm.cache; //~--- JDK imports ------------------------------------------------------------ +import java.util.Collections; import java.util.List; import javax.xml.bind.annotation.XmlAccessType; @@ -49,6 +50,28 @@ import javax.xml.bind.annotation.XmlRootElement; public class CacheManagerConfiguration { + /** + * Constructs ... + * + */ + public CacheManagerConfiguration() {} + + /** + * Constructs ... + * + * + * @param defaultCache + * @param caches + */ + public CacheManagerConfiguration(CacheConfiguration defaultCache, + List caches) + { + this.defaultCache = defaultCache; + this.caches = caches; + } + + //~--- get methods ---------------------------------------------------------- + /** * Method description * @@ -57,6 +80,9 @@ public class CacheManagerConfiguration */ public List getCaches() { + if ( caches == null ){ + caches = Collections.EMPTY_LIST; + } return caches; } @@ -78,6 +104,6 @@ public class CacheManagerConfiguration private List caches; /** Field description */ - @XmlElement(name = "cache") + @XmlElement(name = "defaultCache") private CacheConfiguration defaultCache; } diff --git a/scm-webapp/src/main/java/sonia/scm/cache/EhCacheConfigurationReader.java b/scm-webapp/src/main/java/sonia/scm/cache/EhCacheConfigurationReader.java index bac0ced9a5..bf3051cb3f 100644 --- a/scm-webapp/src/main/java/sonia/scm/cache/EhCacheConfigurationReader.java +++ b/scm-webapp/src/main/java/sonia/scm/cache/EhCacheConfigurationReader.java @@ -35,13 +35,13 @@ package sonia.scm.cache; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Objects; -import com.google.common.collect.Iterators; import com.google.common.collect.Maps; import com.google.common.io.Closeables; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; @@ -55,13 +55,11 @@ import sonia.scm.SCMContext; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; -import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; -import java.util.Enumeration; import java.util.Iterator; import java.util.Map; @@ -73,7 +71,6 @@ import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; -import org.w3c.dom.Attr; /** * @@ -90,10 +87,10 @@ public class EhCacheConfigurationReader /** Field description */ private static final String MANUAL_RESOURCE = - "ext".concat(File.separator).concat("cache.xml"); + "ext".concat(File.separator).concat("ehcache.xml"); /** Field description */ - private static final String MODULE_RESOURCES = "/META-INF/scm/cache.xml"; + private static final String MODULE_RESOURCES = "/META-INF/scm/ehcache.xml"; /** * the logger for EhCacheConfigurationReader @@ -209,36 +206,8 @@ public class EhCacheConfigurationReader @VisibleForTesting protected Iterator getModuleResources() { - Iterator it = null; - - try - { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - - if (classLoader == null) - { - classLoader = EhCacheConfigurationReader.class.getClassLoader(); - } - - Enumeration enm = classLoader.getResources(MODULE_RESOURCES); - - if (enm != null) - { - it = Iterators.forEnumeration(enm); - } - - } - catch (IOException ex) - { - logger.error("could not read cache module resources", ex); - } - - if (it == null) - { - it = Iterators.emptyIterator(); - } - - return it; + return CacheConfigurations.findModuleResources( + EhCacheConfigurationReader.class, MODULE_RESOURCES); } //~--- methods -------------------------------------------------------------- @@ -296,6 +265,7 @@ public class EhCacheConfigurationReader for (Attr attribute : attributeMap.values()) { Attr mergedAttr = (Attr) merged.adoptNode(attribute); + rootEl.setAttributeNode(mergedAttr); } From 09d4ea87afdcb1a529dacd4eabffdcdb720bb6d9 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Mon, 25 Mar 2013 10:53:01 +0100 Subject: [PATCH 19/28] improve configuration for guava cache --- .../scm/cache/CacheConfigurationReader.java | 6 +- .../sonia/scm/cache/CacheConfigurations.java | 7 +- .../main/java/sonia/scm/cache/GuavaCache.java | 98 +++-------- .../sonia/scm/cache/GuavaCacheManager.java | 25 ++- .../java/sonia/scm/cache/GuavaCaches.java | 156 ++++++++++++++++++ 5 files changed, 208 insertions(+), 84 deletions(-) create mode 100644 scm-webapp/src/main/java/sonia/scm/cache/GuavaCaches.java diff --git a/scm-webapp/src/main/java/sonia/scm/cache/CacheConfigurationReader.java b/scm-webapp/src/main/java/sonia/scm/cache/CacheConfigurationReader.java index a295ef8c33..43fe88ff58 100644 --- a/scm-webapp/src/main/java/sonia/scm/cache/CacheConfigurationReader.java +++ b/scm-webapp/src/main/java/sonia/scm/cache/CacheConfigurationReader.java @@ -64,14 +64,14 @@ public class CacheConfigurationReader { /** Field description */ - private static final String DEFAULT = "/config/cache.xml"; + private static final String DEFAULT = "/config/gcache.xml"; /** Field description */ private static final String MANUAL_RESOURCE = - "ext".concat(File.separator).concat("cache.xml"); + "ext".concat(File.separator).concat("gcache.xml"); /** Field description */ - private static final String MODULE_RESOURCES = "/META-INF/scm/cache.xml"; + private static final String MODULE_RESOURCES = "/META-INF/scm/gcache.xml"; /** * the logger for CacheConfigurationReader diff --git a/scm-webapp/src/main/java/sonia/scm/cache/CacheConfigurations.java b/scm-webapp/src/main/java/sonia/scm/cache/CacheConfigurations.java index 1b7689d497..ae56117bc5 100644 --- a/scm-webapp/src/main/java/sonia/scm/cache/CacheConfigurations.java +++ b/scm-webapp/src/main/java/sonia/scm/cache/CacheConfigurations.java @@ -51,7 +51,7 @@ import java.util.Iterator; * * @author Sebastian Sdorra */ -public class CacheConfigurations +public final class CacheConfigurations { /** @@ -61,7 +61,12 @@ public class CacheConfigurations LoggerFactory.getLogger(CacheConfigurations.class); //~--- methods -------------------------------------------------------------- + private CacheConfigurations() + { + } + + /** * Method description * diff --git a/scm-webapp/src/main/java/sonia/scm/cache/GuavaCache.java b/scm-webapp/src/main/java/sonia/scm/cache/GuavaCache.java index 8256c93520..082bc6df1c 100644 --- a/scm-webapp/src/main/java/sonia/scm/cache/GuavaCache.java +++ b/scm-webapp/src/main/java/sonia/scm/cache/GuavaCache.java @@ -33,7 +33,7 @@ package sonia.scm.cache; //~--- non-JDK imports -------------------------------------------------------- -import com.google.common.cache.CacheBuilder; +import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.Sets; import org.slf4j.Logger; @@ -44,7 +44,6 @@ import sonia.scm.Filter; //~--- JDK imports ------------------------------------------------------------ import java.util.Set; -import java.util.concurrent.TimeUnit; /** * @@ -84,72 +83,28 @@ public class GuavaCache implements Cache */ public GuavaCache(CacheConfiguration configuration, String name) { + this(GuavaCaches.create(configuration, name), + configuration.getCopyStrategy(), name); + } + + /** + * Constructs ... + * + * + * @param cache + * @param copyStrategy + * @param name + */ + @VisibleForTesting + protected GuavaCache(com.google.common.cache.Cache cache, + CopyStrategy copyStrategy, String name) + { + this.cache = cache; this.name = name; - if (configuration.getCopyStrategy() != null) + if (copyStrategy != null) { - copyStrategy = configuration.getCopyStrategy(); - } - - CacheBuilder builder = CacheBuilder.newBuilder(); - - if (configuration.getConcurrencyLevel() != null) - { - builder.concurrencyLevel(configuration.getConcurrencyLevel()); - } - - if (configuration.getExpireAfterAccess() != null) - { - builder.expireAfterAccess(configuration.getExpireAfterAccess(), - TimeUnit.MILLISECONDS); - } - - if (configuration.getExpireAfterWrite() != null) - { - builder.expireAfterWrite(configuration.getExpireAfterWrite(), - TimeUnit.MILLISECONDS); - } - - if (configuration.getInitialCapacity() != null) - { - builder.initialCapacity(configuration.getInitialCapacity()); - } - - if (configuration.getMaximumSize() != null) - { - builder.maximumSize(configuration.getMaximumSize()); - } - - if (configuration.getMaximumWeight() != null) - { - builder.maximumWeight(configuration.getMaximumWeight()); - } - - if (isEnabled(configuration.getRecordStats())) - { - builder.recordStats(); - } - - if (isEnabled(configuration.getSoftValues())) - { - builder.softValues(); - } - - if (isEnabled(configuration.getWeakKeys())) - { - builder.weakKeys(); - } - - if (isEnabled(configuration.getWeakValues())) - { - builder.weakKeys(); - } - - cache = builder.build(); - - if (logger.isTraceEnabled()) - { - logger.trace("create new guava cache from builder: {}", builder); + this.copyStrategy = copyStrategy; } } @@ -268,19 +223,6 @@ public class GuavaCache implements Cache return value; } - /** - * Method description - * - * - * @param v - * - * @return - */ - private boolean isEnabled(Boolean v) - { - return (v != null) && v; - } - //~--- fields --------------------------------------------------------------- /** Field description */ diff --git a/scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheManager.java b/scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheManager.java index 58783f411f..0cf964c0d5 100644 --- a/scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheManager.java +++ b/scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheManager.java @@ -34,6 +34,7 @@ package sonia.scm.cache; //~--- non-JDK imports -------------------------------------------------------- import com.google.common.collect.Maps; +import com.google.inject.Singleton; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -48,6 +49,7 @@ import java.util.Map; * * @author Sebastian Sdorra */ +@Singleton public class GuavaCacheManager implements CacheManager { @@ -57,6 +59,25 @@ public class GuavaCacheManager implements CacheManager private static final Logger logger = LoggerFactory.getLogger(GuavaCacheManager.class); + //~--- constructors --------------------------------------------------------- + + /** + * Constructs ... + * + */ + public GuavaCacheManager() + { + CacheConfigurationReader reader = new CacheConfigurationReader(); + CacheManagerConfiguration config = reader.read(); + + defaultConfiguration = config.getDefaultCache(); + + for (NamedCacheConfiguration ncc : config.getCaches()) + { + cacheMap.put(ncc.getName(), new GuavaCache(ncc)); + } + } + //~--- methods -------------------------------------------------------------- /** @@ -105,7 +126,7 @@ public class GuavaCacheManager implements CacheManager logger.debug( "cache {} does not exists, creating a new instance from default configuration: {}", name, defaultConfiguration); - cache = new GuavaCache(defaultConfiguration); + cache = new GuavaCache(defaultConfiguration, name); cacheMap.put(name, cache); } @@ -118,5 +139,5 @@ public class GuavaCacheManager implements CacheManager private Map cacheMap = Maps.newConcurrentMap(); /** Field description */ - private NamedCacheConfiguration defaultConfiguration; + private CacheConfiguration defaultConfiguration; } diff --git a/scm-webapp/src/main/java/sonia/scm/cache/GuavaCaches.java b/scm-webapp/src/main/java/sonia/scm/cache/GuavaCaches.java new file mode 100644 index 0000000000..1aba642ab0 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/cache/GuavaCaches.java @@ -0,0 +1,156 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.cache; + +//~--- non-JDK imports -------------------------------------------------------- + +import com.google.common.cache.CacheBuilder; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +//~--- JDK imports ------------------------------------------------------------ + +import java.util.concurrent.TimeUnit; + +/** + * + * @author Sebastian Sdorra + */ +public final class GuavaCaches +{ + + /** + * the logger for GuavaCaches + */ + private static final Logger logger = + LoggerFactory.getLogger(GuavaCaches.class); + + //~--- constructors --------------------------------------------------------- + + /** + * Constructs ... + * + */ + private GuavaCaches() {} + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param configuration + * @param name + * + * @return + */ + public static com.google.common.cache.Cache create( + CacheConfiguration configuration, String name) + { + CacheBuilder builder = CacheBuilder.newBuilder(); + + if (configuration.getConcurrencyLevel() != null) + { + builder.concurrencyLevel(configuration.getConcurrencyLevel()); + } + + if (configuration.getExpireAfterAccess() != null) + { + builder.expireAfterAccess(configuration.getExpireAfterAccess(), + TimeUnit.SECONDS); + } + + if (configuration.getExpireAfterWrite() != null) + { + builder.expireAfterWrite(configuration.getExpireAfterWrite(), + TimeUnit.SECONDS); + } + + if (configuration.getInitialCapacity() != null) + { + builder.initialCapacity(configuration.getInitialCapacity()); + } + + if (configuration.getMaximumSize() != null) + { + builder.maximumSize(configuration.getMaximumSize()); + } + + if (configuration.getMaximumWeight() != null) + { + builder.maximumWeight(configuration.getMaximumWeight()); + } + + if (isEnabled(configuration.getRecordStats())) + { + builder.recordStats(); + } + + if (isEnabled(configuration.getSoftValues())) + { + builder.softValues(); + } + + if (isEnabled(configuration.getWeakKeys())) + { + builder.weakKeys(); + } + + if (isEnabled(configuration.getWeakValues())) + { + builder.weakKeys(); + } + + if (logger.isTraceEnabled()) + { + logger.trace("create new cache {} from builder: {}", name, builder); + } + + return builder.build(); + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @param v + * + * @return + */ + private static boolean isEnabled(Boolean v) + { + return (v != null) && v; + } +} From 2a273f0f84595a49911d4ab11bf90a7a5e16c4e5 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Mon, 25 Mar 2013 10:56:39 +0100 Subject: [PATCH 20/28] added prefix for guava cache classes --- .../sonia/scm/cache/CacheConfigurations.java | 15 +++--- .../main/java/sonia/scm/cache/GuavaCache.java | 4 +- ...tion.java => GuavaCacheConfiguration.java} | 2 +- ...ava => GuavaCacheConfigurationReader.java} | 53 ++++++++++--------- .../sonia/scm/cache/GuavaCacheManager.java | 8 +-- ...va => GuavaCacheManagerConfiguration.java} | 20 +++---- .../java/sonia/scm/cache/GuavaCaches.java | 2 +- ...java => GuavaNamedCacheConfiguration.java} | 2 +- 8 files changed, 57 insertions(+), 49 deletions(-) rename scm-webapp/src/main/java/sonia/scm/cache/{CacheConfiguration.java => GuavaCacheConfiguration.java} (98%) rename scm-webapp/src/main/java/sonia/scm/cache/{CacheConfigurationReader.java => GuavaCacheConfigurationReader.java} (78%) rename scm-webapp/src/main/java/sonia/scm/cache/{CacheManagerConfiguration.java => GuavaCacheManagerConfiguration.java} (85%) rename scm-webapp/src/main/java/sonia/scm/cache/{NamedCacheConfiguration.java => GuavaNamedCacheConfiguration.java} (97%) diff --git a/scm-webapp/src/main/java/sonia/scm/cache/CacheConfigurations.java b/scm-webapp/src/main/java/sonia/scm/cache/CacheConfigurations.java index ae56117bc5..2ebf1bdb77 100644 --- a/scm-webapp/src/main/java/sonia/scm/cache/CacheConfigurations.java +++ b/scm-webapp/src/main/java/sonia/scm/cache/CacheConfigurations.java @@ -60,13 +60,16 @@ public final class CacheConfigurations private static final Logger logger = LoggerFactory.getLogger(CacheConfigurations.class); - //~--- methods -------------------------------------------------------------- - private CacheConfigurations() - { - } + //~--- constructors --------------------------------------------------------- + + /** + * Constructs ... + * + */ + private CacheConfigurations() {} + + //~--- methods -------------------------------------------------------------- - - /** * Method description * diff --git a/scm-webapp/src/main/java/sonia/scm/cache/GuavaCache.java b/scm-webapp/src/main/java/sonia/scm/cache/GuavaCache.java index 082bc6df1c..10ba782bc2 100644 --- a/scm-webapp/src/main/java/sonia/scm/cache/GuavaCache.java +++ b/scm-webapp/src/main/java/sonia/scm/cache/GuavaCache.java @@ -69,7 +69,7 @@ public class GuavaCache implements Cache * * @param configuration */ - public GuavaCache(NamedCacheConfiguration configuration) + public GuavaCache(GuavaNamedCacheConfiguration configuration) { this(configuration, configuration.getName()); } @@ -81,7 +81,7 @@ public class GuavaCache implements Cache * @param configuration * @param name */ - public GuavaCache(CacheConfiguration configuration, String name) + public GuavaCache(GuavaCacheConfiguration configuration, String name) { this(GuavaCaches.create(configuration, name), configuration.getCopyStrategy(), name); diff --git a/scm-webapp/src/main/java/sonia/scm/cache/CacheConfiguration.java b/scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheConfiguration.java similarity index 98% rename from scm-webapp/src/main/java/sonia/scm/cache/CacheConfiguration.java rename to scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheConfiguration.java index a01ca2eccb..d39fd4eab2 100644 --- a/scm-webapp/src/main/java/sonia/scm/cache/CacheConfiguration.java +++ b/scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheConfiguration.java @@ -46,7 +46,7 @@ import javax.xml.bind.annotation.XmlRootElement; */ @XmlRootElement(name = "cache") @XmlAccessorType(XmlAccessType.FIELD) -public class CacheConfiguration implements Serializable +public class GuavaCacheConfiguration implements Serializable { /** Field description */ diff --git a/scm-webapp/src/main/java/sonia/scm/cache/CacheConfigurationReader.java b/scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheConfigurationReader.java similarity index 78% rename from scm-webapp/src/main/java/sonia/scm/cache/CacheConfigurationReader.java rename to scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheConfigurationReader.java index 43fe88ff58..59eb12951e 100644 --- a/scm-webapp/src/main/java/sonia/scm/cache/CacheConfigurationReader.java +++ b/scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheConfigurationReader.java @@ -60,7 +60,7 @@ import javax.xml.bind.JAXBException; * * @author Sebastian Sdorra */ -public class CacheConfigurationReader +public class GuavaCacheConfigurationReader { /** Field description */ @@ -77,7 +77,7 @@ public class CacheConfigurationReader * the logger for CacheConfigurationReader */ private static final Logger logger = - LoggerFactory.getLogger(CacheConfigurationReader.class); + LoggerFactory.getLogger(GuavaCacheConfigurationReader.class); //~--- constructors --------------------------------------------------------- @@ -85,11 +85,12 @@ public class CacheConfigurationReader * Constructs ... * */ - public CacheConfigurationReader() + public GuavaCacheConfigurationReader() { try { - this.context = JAXBContext.newInstance(CacheManagerConfiguration.class); + this.context = + JAXBContext.newInstance(GuavaCacheManagerConfiguration.class); } catch (JAXBException ex) { @@ -106,7 +107,7 @@ public class CacheConfigurationReader * * @return */ - public CacheManagerConfiguration read() + public GuavaCacheManagerConfiguration read() { URL defaultConfigUrl = getDefaultResource(); @@ -116,15 +117,15 @@ public class CacheConfigurationReader "could not find default cache configuration"); } - CacheManagerConfiguration config = readConfiguration(defaultConfigUrl, - true); + GuavaCacheManagerConfiguration config = readConfiguration(defaultConfigUrl, + true); Iterator it = getModuleResources(); while (it.hasNext()) { - CacheManagerConfiguration moduleConfig = readConfiguration(it.next(), - false); + GuavaCacheManagerConfiguration moduleConfig = + readConfiguration(it.next(), false); if (moduleConfig != null) { @@ -138,7 +139,7 @@ public class CacheConfigurationReader { try { - CacheManagerConfiguration manualConfig = + GuavaCacheManagerConfiguration manualConfig = readConfiguration(manualFile.toURI().toURL(), false); config = merge(config, manualConfig); @@ -167,7 +168,7 @@ public class CacheConfigurationReader @VisibleForTesting protected URL getDefaultResource() { - return CacheConfigurationReader.class.getResource(DEFAULT); + return GuavaCacheConfigurationReader.class.getResource(DEFAULT); } /** @@ -208,12 +209,12 @@ public class CacheConfigurationReader * * @return */ - private Map createNamedCacheMap( - List caches) + private Map createNamedCacheMap( + List caches) { - Map map = Maps.newLinkedHashMap(); + Map map = Maps.newLinkedHashMap(); - for (NamedCacheConfiguration ncc : caches) + for (GuavaNamedCacheConfiguration ncc : caches) { map.put(ncc.getName(), ncc); } @@ -230,11 +231,11 @@ public class CacheConfigurationReader * * @return */ - private CacheManagerConfiguration merge(CacheManagerConfiguration config, - CacheManagerConfiguration other) + private GuavaCacheManagerConfiguration merge( + GuavaCacheManagerConfiguration config, GuavaCacheManagerConfiguration other) { - CacheConfiguration defaultCache = config.getDefaultCache(); - Map namedCaches = + GuavaCacheConfiguration defaultCache = config.getDefaultCache(); + Map namedCaches = createNamedCacheMap(config.getCaches()); if (other.getDefaultCache() != null) @@ -242,14 +243,14 @@ public class CacheConfigurationReader defaultCache = other.getDefaultCache(); } - List otherNamedCaches = other.getCaches(); + List otherNamedCaches = other.getCaches(); - for (NamedCacheConfiguration ncc : otherNamedCaches) + for (GuavaNamedCacheConfiguration ncc : otherNamedCaches) { namedCaches.put(ncc.getName(), ncc); } - return new CacheManagerConfiguration(defaultCache, + return new GuavaCacheManagerConfiguration(defaultCache, ImmutableList.copyOf(namedCaches.values())); } @@ -262,14 +263,16 @@ public class CacheConfigurationReader * * @return */ - private CacheManagerConfiguration readConfiguration(URL url, boolean fail) + private GuavaCacheManagerConfiguration readConfiguration(URL url, + boolean fail) { - CacheManagerConfiguration config = null; + GuavaCacheManagerConfiguration config = null; try { config = - (CacheManagerConfiguration) context.createUnmarshaller().unmarshal(url); + (GuavaCacheManagerConfiguration) context.createUnmarshaller().unmarshal( + url); } catch (JAXBException ex) { diff --git a/scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheManager.java b/scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheManager.java index 0cf964c0d5..74b8e8f254 100644 --- a/scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheManager.java +++ b/scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheManager.java @@ -67,12 +67,12 @@ public class GuavaCacheManager implements CacheManager */ public GuavaCacheManager() { - CacheConfigurationReader reader = new CacheConfigurationReader(); - CacheManagerConfiguration config = reader.read(); + GuavaCacheConfigurationReader reader = new GuavaCacheConfigurationReader(); + GuavaCacheManagerConfiguration config = reader.read(); defaultConfiguration = config.getDefaultCache(); - for (NamedCacheConfiguration ncc : config.getCaches()) + for (GuavaNamedCacheConfiguration ncc : config.getCaches()) { cacheMap.put(ncc.getName(), new GuavaCache(ncc)); } @@ -139,5 +139,5 @@ public class GuavaCacheManager implements CacheManager private Map cacheMap = Maps.newConcurrentMap(); /** Field description */ - private CacheConfiguration defaultConfiguration; + private GuavaCacheConfiguration defaultConfiguration; } diff --git a/scm-webapp/src/main/java/sonia/scm/cache/CacheManagerConfiguration.java b/scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheManagerConfiguration.java similarity index 85% rename from scm-webapp/src/main/java/sonia/scm/cache/CacheManagerConfiguration.java rename to scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheManagerConfiguration.java index e0d8c8b4d4..cb9c306bdf 100644 --- a/scm-webapp/src/main/java/sonia/scm/cache/CacheManagerConfiguration.java +++ b/scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheManagerConfiguration.java @@ -47,14 +47,14 @@ import javax.xml.bind.annotation.XmlRootElement; */ @XmlRootElement(name = "caches") @XmlAccessorType(XmlAccessType.FIELD) -public class CacheManagerConfiguration +public class GuavaCacheManagerConfiguration { /** * Constructs ... * */ - public CacheManagerConfiguration() {} + public GuavaCacheManagerConfiguration() {} /** * Constructs ... @@ -63,8 +63,8 @@ public class CacheManagerConfiguration * @param defaultCache * @param caches */ - public CacheManagerConfiguration(CacheConfiguration defaultCache, - List caches) + public GuavaCacheManagerConfiguration(GuavaCacheConfiguration defaultCache, + List caches) { this.defaultCache = defaultCache; this.caches = caches; @@ -78,11 +78,13 @@ public class CacheManagerConfiguration * * @return */ - public List getCaches() + public List getCaches() { - if ( caches == null ){ + if (caches == null) + { caches = Collections.EMPTY_LIST; } + return caches; } @@ -92,7 +94,7 @@ public class CacheManagerConfiguration * * @return */ - public CacheConfiguration getDefaultCache() + public GuavaCacheConfiguration getDefaultCache() { return defaultCache; } @@ -101,9 +103,9 @@ public class CacheManagerConfiguration /** Field description */ @XmlElement(name = "cache") - private List caches; + private List caches; /** Field description */ @XmlElement(name = "defaultCache") - private CacheConfiguration defaultCache; + private GuavaCacheConfiguration defaultCache; } diff --git a/scm-webapp/src/main/java/sonia/scm/cache/GuavaCaches.java b/scm-webapp/src/main/java/sonia/scm/cache/GuavaCaches.java index 1aba642ab0..42b36a6fd6 100644 --- a/scm-webapp/src/main/java/sonia/scm/cache/GuavaCaches.java +++ b/scm-webapp/src/main/java/sonia/scm/cache/GuavaCaches.java @@ -75,7 +75,7 @@ public final class GuavaCaches * @return */ public static com.google.common.cache.Cache create( - CacheConfiguration configuration, String name) + GuavaCacheConfiguration configuration, String name) { CacheBuilder builder = CacheBuilder.newBuilder(); diff --git a/scm-webapp/src/main/java/sonia/scm/cache/NamedCacheConfiguration.java b/scm-webapp/src/main/java/sonia/scm/cache/GuavaNamedCacheConfiguration.java similarity index 97% rename from scm-webapp/src/main/java/sonia/scm/cache/NamedCacheConfiguration.java rename to scm-webapp/src/main/java/sonia/scm/cache/GuavaNamedCacheConfiguration.java index 162a449b1d..a8ae2ac8c5 100644 --- a/scm-webapp/src/main/java/sonia/scm/cache/NamedCacheConfiguration.java +++ b/scm-webapp/src/main/java/sonia/scm/cache/GuavaNamedCacheConfiguration.java @@ -44,7 +44,7 @@ import javax.xml.bind.annotation.XmlRootElement; */ @XmlRootElement(name = "cache") @XmlAccessorType(XmlAccessType.FIELD) -public class NamedCacheConfiguration extends CacheConfiguration +public class GuavaNamedCacheConfiguration extends GuavaCacheConfiguration { /** Field description */ From 0ea4b43a585e33494605e37e77b66d0377e88571 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Mon, 25 Mar 2013 10:57:52 +0100 Subject: [PATCH 21/28] added default guava cache configuration --- .../src/main/resources/config/gcache.xml | 145 ++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 scm-webapp/src/main/resources/config/gcache.xml diff --git a/scm-webapp/src/main/resources/config/gcache.xml b/scm-webapp/src/main/resources/config/gcache.xml new file mode 100644 index 0000000000..7ff9a2053f --- /dev/null +++ b/scm-webapp/src/main/resources/config/gcache.xml @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From f8bb0cf1097eef5a4bcdbca9bd9a79bc37db6330 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Mon, 25 Mar 2013 11:07:47 +0100 Subject: [PATCH 22/28] create static read method for GuavaCacheConfigurationReader --- .../cache/GuavaCacheConfigurationReader.java | 107 ++++++++++-------- .../sonia/scm/cache/GuavaCacheManager.java | 14 ++- 2 files changed, 71 insertions(+), 50 deletions(-) diff --git a/scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheConfigurationReader.java b/scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheConfigurationReader.java index 59eb12951e..4c28f5ce21 100644 --- a/scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheConfigurationReader.java +++ b/scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheConfigurationReader.java @@ -85,7 +85,7 @@ public class GuavaCacheConfigurationReader * Constructs ... * */ - public GuavaCacheConfigurationReader() + private GuavaCacheConfigurationReader() { try { @@ -107,54 +107,9 @@ public class GuavaCacheConfigurationReader * * @return */ - public GuavaCacheManagerConfiguration read() + public static GuavaCacheManagerConfiguration read() { - URL defaultConfigUrl = getDefaultResource(); - - if (defaultConfigUrl == null) - { - throw new IllegalStateException( - "could not find default cache configuration"); - } - - GuavaCacheManagerConfiguration config = readConfiguration(defaultConfigUrl, - true); - - Iterator it = getModuleResources(); - - while (it.hasNext()) - { - GuavaCacheManagerConfiguration moduleConfig = - readConfiguration(it.next(), false); - - if (moduleConfig != null) - { - config = merge(config, moduleConfig); - } - } - - File manualFile = getManualFileResource(); - - if (manualFile.exists()) - { - try - { - GuavaCacheManagerConfiguration manualConfig = - readConfiguration(manualFile.toURI().toURL(), false); - - config = merge(config, manualConfig); - } - catch (MalformedURLException ex) - { - logger.error("malformed url", ex); - } - } - else - { - logger.warn("could not find manual configuration at {}", manualFile); - } - - return config; + return new GuavaCacheConfigurationReader().doRead(); } //~--- get methods ---------------------------------------------------------- @@ -222,6 +177,62 @@ public class GuavaCacheConfigurationReader return map; } + /** + * Method description + * + * + * @return + */ + private GuavaCacheManagerConfiguration doRead() + { + URL defaultConfigUrl = getDefaultResource(); + + if (defaultConfigUrl == null) + { + throw new IllegalStateException( + "could not find default cache configuration"); + } + + GuavaCacheManagerConfiguration config = readConfiguration(defaultConfigUrl, + true); + + Iterator it = getModuleResources(); + + while (it.hasNext()) + { + GuavaCacheManagerConfiguration moduleConfig = + readConfiguration(it.next(), false); + + if (moduleConfig != null) + { + config = merge(config, moduleConfig); + } + } + + File manualFile = getManualFileResource(); + + if (manualFile.exists()) + { + try + { + GuavaCacheManagerConfiguration manualConfig = + readConfiguration(manualFile.toURI().toURL(), false); + + config = merge(config, manualConfig); + } + catch (MalformedURLException ex) + { + logger.error("malformed url", ex); + } + } + else + { + logger.warn("could not find manual configuration at {}", manualFile); + } + + return config; + } + /** * Method description * diff --git a/scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheManager.java b/scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheManager.java index 74b8e8f254..cdc9fd958d 100644 --- a/scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheManager.java +++ b/scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheManager.java @@ -33,6 +33,7 @@ package sonia.scm.cache; //~--- non-JDK imports -------------------------------------------------------- +import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.Maps; import com.google.inject.Singleton; @@ -67,9 +68,18 @@ public class GuavaCacheManager implements CacheManager */ public GuavaCacheManager() { - GuavaCacheConfigurationReader reader = new GuavaCacheConfigurationReader(); - GuavaCacheManagerConfiguration config = reader.read(); + this(GuavaCacheConfigurationReader.read()); + } + /** + * Constructs ... + * + * + * @param config + */ + @VisibleForTesting + protected GuavaCacheManager(GuavaCacheManagerConfiguration config) + { defaultConfiguration = config.getDefaultCache(); for (GuavaNamedCacheConfiguration ncc : config.getCaches()) From 6fa211a5591e5c1b6ab040d0d4e69f333d5c5f01 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Mon, 25 Mar 2013 11:08:54 +0100 Subject: [PATCH 23/28] added simple tests for guava cache --- .../java/sonia/scm/cache/CacheTestBase.java | 165 ++++++++++++++++++ .../java/sonia/scm/cache/EhCacheTest.java | 115 +----------- .../java/sonia/scm/cache/GuavaCacheTest.java | 59 +++++++ 3 files changed, 229 insertions(+), 110 deletions(-) create mode 100644 scm-webapp/src/test/java/sonia/scm/cache/CacheTestBase.java create mode 100644 scm-webapp/src/test/java/sonia/scm/cache/GuavaCacheTest.java diff --git a/scm-webapp/src/test/java/sonia/scm/cache/CacheTestBase.java b/scm-webapp/src/test/java/sonia/scm/cache/CacheTestBase.java new file mode 100644 index 0000000000..17a3d8ad84 --- /dev/null +++ b/scm-webapp/src/test/java/sonia/scm/cache/CacheTestBase.java @@ -0,0 +1,165 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.cache; + +//~--- non-JDK imports -------------------------------------------------------- + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import sonia.scm.Filter; +import sonia.scm.util.IOUtil; + +import static org.junit.Assert.*; + +/** + * + * @author Sebastian Sdorra + */ +public abstract class CacheTestBase +{ + + /** + * Method description + * + * + * @return + */ + protected abstract CacheManager createCacheManager(); + + /** + * Method description + * + */ + @After + public void after() + { + IOUtil.close(cm); + } + + /** + * Method description + * + */ + @Before + public void before() + { + cm = createCacheManager(); + cache = cm.getCache(String.class, String.class, "test"); + } + + /** + * Method description + * + */ + @Test + public void testClear() + { + cache.put("test", "test123"); + cache.put("test-1", "test123"); + cache.clear(); + assertNull(cache.get("test")); + assertNull(cache.get("test-1")); + } + + /** + * Method description + * + */ + @Test + public void testContains() + { + cache.put("test", "test123"); + cache.put("test-1", "test123"); + assertTrue(cache.contains("test")); + assertTrue(cache.contains("test-1")); + assertFalse(cache.contains("test-2")); + } + + /** + * Method description + * + */ + @Test + public void testPutAndGet() + { + cache.put("test", "test123"); + assertEquals("test123", cache.get("test")); + } + + /** + * Method description + * + */ + @Test + public void testRemove() + { + cache.put("test", "test123"); + assertEquals("test123", cache.get("test")); + cache.remove("test"); + assertNull(cache.get("test")); + } + + /** + * Method description + * + */ + @Test + public void testRemoveAll() + { + cache.put("test-1", "test123"); + cache.put("test-2", "test123"); + cache.put("a-1", "test123"); + cache.put("a-2", "test123"); + cache.removeAll(new Filter() + { + @Override + public boolean accept(String item) + { + return item.startsWith("test"); + } + }); + assertNull(cache.get("test-1")); + assertNull(cache.get("test-2")); + assertNotNull(cache.get("a-1")); + assertNotNull(cache.get("a-2")); + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private Cache cache; + + /** Field description */ + private CacheManager cm; +} diff --git a/scm-webapp/src/test/java/sonia/scm/cache/EhCacheTest.java b/scm-webapp/src/test/java/sonia/scm/cache/EhCacheTest.java index 54bb5b9b1a..72d192a2d0 100644 --- a/scm-webapp/src/test/java/sonia/scm/cache/EhCacheTest.java +++ b/scm-webapp/src/test/java/sonia/scm/cache/EhCacheTest.java @@ -33,127 +33,22 @@ package sonia.scm.cache; -//~--- non-JDK imports -------------------------------------------------------- - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import sonia.scm.Filter; -import sonia.scm.util.IOUtil; - -import static org.junit.Assert.*; - /** * * @author Sebastian Sdorra */ -public class EhCacheTest +public class EhCacheTest extends CacheTestBase { - - /** - * Method description - * - */ - @After - public void after() - { - IOUtil.close(cm); - } /** * Method description * - */ - @Before - public void before() - { - cm = new EhCacheManager(net.sf.ehcache.CacheManager.create()); - cache = cm.getCache(String.class, String.class, "test"); - } - - /** - * Method description * + * @return */ - @Test - public void testClear() + @Override + protected CacheManager createCacheManager() { - cache.put("test", "test123"); - cache.put("test-1", "test123"); - cache.clear(); - assertNull(cache.get("test")); - assertNull(cache.get("test-1")); + return new EhCacheManager(net.sf.ehcache.CacheManager.create()); } - - /** - * Method description - * - */ - @Test - public void testContains() - { - cache.put("test", "test123"); - cache.put("test-1", "test123"); - assertTrue(cache.contains("test")); - assertTrue(cache.contains("test-1")); - assertFalse(cache.contains("test-2")); - } - - /** - * Method description - * - */ - @Test - public void testPutAndGet() - { - cache.put("test", "test123"); - assertEquals("test123", cache.get("test")); - } - - /** - * Method description - * - */ - @Test - public void testRemove() - { - cache.put("test", "test123"); - assertEquals("test123", cache.get("test")); - cache.remove("test"); - assertNull(cache.get("test")); - } - - /** - * Method description - * - */ - @Test - public void testRemoveAll() - { - cache.put("test-1", "test123"); - cache.put("test-2", "test123"); - cache.put("a-1", "test123"); - cache.put("a-2", "test123"); - cache.removeAll(new Filter() - { - @Override - public boolean accept(String item) - { - return item.startsWith("test"); - } - }); - assertNull(cache.get("test-1")); - assertNull(cache.get("test-2")); - assertNotNull(cache.get("a-1")); - assertNotNull(cache.get("a-2")); - } - - //~--- fields --------------------------------------------------------------- - - /** Field description */ - private Cache cache; - - /** Field description */ - private CacheManager cm; } diff --git a/scm-webapp/src/test/java/sonia/scm/cache/GuavaCacheTest.java b/scm-webapp/src/test/java/sonia/scm/cache/GuavaCacheTest.java new file mode 100644 index 0000000000..75f518c43a --- /dev/null +++ b/scm-webapp/src/test/java/sonia/scm/cache/GuavaCacheTest.java @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.cache; + +//~--- JDK imports ------------------------------------------------------------ + +import java.util.Collections; + +/** + * + * @author Sebastian Sdorra + */ +public class GuavaCacheTest extends CacheTestBase +{ + + /** + * Method description + * + * + * @return + */ + @Override + protected CacheManager createCacheManager() + { + GuavaCacheConfiguration config = new GuavaCacheConfiguration(); + + return new GuavaCacheManager(new GuavaCacheManagerConfiguration(config, + Collections.EMPTY_LIST)); + } +} From 80ce0f019e80ad2df0c8e0a78cf89dd534a3835a Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Mon, 25 Mar 2013 11:55:57 +0100 Subject: [PATCH 24/28] synchronize getCache method of cache manager implementations --- .../src/main/java/sonia/scm/cache/EhCacheManager.java | 3 ++- .../src/main/java/sonia/scm/cache/GuavaCacheManager.java | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/scm-webapp/src/main/java/sonia/scm/cache/EhCacheManager.java b/scm-webapp/src/main/java/sonia/scm/cache/EhCacheManager.java index 70d068335d..0342ecf32b 100644 --- a/scm-webapp/src/main/java/sonia/scm/cache/EhCacheManager.java +++ b/scm-webapp/src/main/java/sonia/scm/cache/EhCacheManager.java @@ -125,7 +125,8 @@ public class EhCacheManager implements CacheManager * @return */ @Override - public Cache getCache(Class key, Class value, String name) + public synchronized Cache getCache(Class key, Class value, + String name) { net.sf.ehcache.Cache c = cacheManager.getCache(name); diff --git a/scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheManager.java b/scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheManager.java index cdc9fd958d..c0a5a19914 100644 --- a/scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheManager.java +++ b/scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheManager.java @@ -124,8 +124,8 @@ public class GuavaCacheManager implements CacheManager * @return */ @Override - public GuavaCache getCache(Class key, Class value, - String name) + public synchronized GuavaCache getCache(Class key, + Class value, String name) { logger.trace("try to retrieve cache {}", name); @@ -146,7 +146,7 @@ public class GuavaCacheManager implements CacheManager //~--- fields --------------------------------------------------------------- /** Field description */ - private Map cacheMap = Maps.newConcurrentMap(); + private volatile Map cacheMap = Maps.newHashMap(); /** Field description */ private GuavaCacheConfiguration defaultConfiguration; From 1ae6ab4c796830ab2cbe04b0b182aa7bbd3d09dc Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Mon, 25 Mar 2013 11:57:15 +0100 Subject: [PATCH 25/28] improve cache unit tests --- .../java/sonia/scm/cache/CacheTestUtil.java | 77 +++++++++++++++++++ .../java/sonia/scm/cache/EhCacheTest.java | 2 +- .../java/sonia/scm/cache/GuavaCacheTest.java | 7 +- 3 files changed, 79 insertions(+), 7 deletions(-) create mode 100644 scm-webapp/src/test/java/sonia/scm/cache/CacheTestUtil.java diff --git a/scm-webapp/src/test/java/sonia/scm/cache/CacheTestUtil.java b/scm-webapp/src/test/java/sonia/scm/cache/CacheTestUtil.java new file mode 100644 index 0000000000..62f285d50b --- /dev/null +++ b/scm-webapp/src/test/java/sonia/scm/cache/CacheTestUtil.java @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.cache; + +//~--- JDK imports ------------------------------------------------------------ + +import java.util.Collections; + +/** + * + * @author Sebastian Sdorra + */ +public final class CacheTestUtil +{ + + /** + * Constructs ... + * + */ + private CacheTestUtil() {} + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + public static EhCacheManager createDefaultEhCacheManager() + { + return new EhCacheManager(net.sf.ehcache.CacheManager.create()); + } + + /** + * Method description + * + * + * @return + */ + public static GuavaCacheManager createDefaultGuavaCacheManager() + { + GuavaCacheConfiguration config = new GuavaCacheConfiguration(); + + return new GuavaCacheManager(new GuavaCacheManagerConfiguration(config, + Collections.EMPTY_LIST)); + } +} diff --git a/scm-webapp/src/test/java/sonia/scm/cache/EhCacheTest.java b/scm-webapp/src/test/java/sonia/scm/cache/EhCacheTest.java index 72d192a2d0..4dc349a3d7 100644 --- a/scm-webapp/src/test/java/sonia/scm/cache/EhCacheTest.java +++ b/scm-webapp/src/test/java/sonia/scm/cache/EhCacheTest.java @@ -49,6 +49,6 @@ public class EhCacheTest extends CacheTestBase @Override protected CacheManager createCacheManager() { - return new EhCacheManager(net.sf.ehcache.CacheManager.create()); + return CacheTestUtil.createDefaultEhCacheManager(); } } diff --git a/scm-webapp/src/test/java/sonia/scm/cache/GuavaCacheTest.java b/scm-webapp/src/test/java/sonia/scm/cache/GuavaCacheTest.java index 75f518c43a..9be9b5c2d6 100644 --- a/scm-webapp/src/test/java/sonia/scm/cache/GuavaCacheTest.java +++ b/scm-webapp/src/test/java/sonia/scm/cache/GuavaCacheTest.java @@ -33,8 +33,6 @@ package sonia.scm.cache; //~--- JDK imports ------------------------------------------------------------ -import java.util.Collections; - /** * * @author Sebastian Sdorra @@ -51,9 +49,6 @@ public class GuavaCacheTest extends CacheTestBase @Override protected CacheManager createCacheManager() { - GuavaCacheConfiguration config = new GuavaCacheConfiguration(); - - return new GuavaCacheManager(new GuavaCacheManagerConfiguration(config, - Collections.EMPTY_LIST)); + return CacheTestUtil.createDefaultGuavaCacheManager(); } } From 91d5f8085ed683ec1854b8cc6496705c06d2a17a Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Mon, 25 Mar 2013 11:58:05 +0100 Subject: [PATCH 26/28] added reference tests for cache managers --- .../main/java/sonia/scm/cache/EhCache.java | 14 ++ .../sonia/scm/cache/CacheManagerTestBase.java | 224 ++++++++++++++++++ .../sonia/scm/cache/EhCacheManagerTest.java | 84 +++++++ .../scm/cache/GuavaCacheManagerTest.java | 52 ++++ 4 files changed, 374 insertions(+) create mode 100644 scm-webapp/src/test/java/sonia/scm/cache/CacheManagerTestBase.java create mode 100644 scm-webapp/src/test/java/sonia/scm/cache/EhCacheManagerTest.java create mode 100644 scm-webapp/src/test/java/sonia/scm/cache/GuavaCacheManagerTest.java diff --git a/scm-webapp/src/main/java/sonia/scm/cache/EhCache.java b/scm-webapp/src/main/java/sonia/scm/cache/EhCache.java index 802db9d45c..4ac0e2a49e 100644 --- a/scm-webapp/src/main/java/sonia/scm/cache/EhCache.java +++ b/scm-webapp/src/main/java/sonia/scm/cache/EhCache.java @@ -35,6 +35,8 @@ package sonia.scm.cache; //~--- non-JDK imports -------------------------------------------------------- +import com.google.common.annotations.VisibleForTesting; + import net.sf.ehcache.Element; import org.slf4j.Logger; @@ -186,6 +188,18 @@ public class EhCache implements Cache return value; } + /** + * Method description + * + * + * @return + */ + @VisibleForTesting + net.sf.ehcache.Cache getCacheImplementation() + { + return cache; + } + //~--- fields --------------------------------------------------------------- /** Field description */ diff --git a/scm-webapp/src/test/java/sonia/scm/cache/CacheManagerTestBase.java b/scm-webapp/src/test/java/sonia/scm/cache/CacheManagerTestBase.java new file mode 100644 index 0000000000..14d10eee20 --- /dev/null +++ b/scm-webapp/src/test/java/sonia/scm/cache/CacheManagerTestBase.java @@ -0,0 +1,224 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.cache; + +//~--- non-JDK imports -------------------------------------------------------- + +import com.google.common.collect.Sets; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import static org.hamcrest.Matchers.*; + +import static org.junit.Assert.*; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.IOException; + +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +/** + * + * @author Sebastian Sdorra + * + * @param + */ +public abstract class CacheManagerTestBase +{ + + /** + * Method description + * + * + * @return + */ + protected abstract CacheManager createCacheManager(); + + /** + * Method description + * + * + * @throws IOException + */ + @After + public void tearDown() throws IOException + { + cacheManager.close(); + } + + /** + * Method description + * + */ + @Test + public void testSameReference() + { + Cache c1 = cacheManager.getCache(String.class, + String.class, "test-1"); + Cache c2 = cacheManager.getCache(String.class, + String.class, "test-1"); + + assertIsSame(c1, c2); + } + + /** + * Method description + * + * + * @throws ExecutionException + * @throws InterruptedException + */ + @Test + public void testSameReferenceMultiThreaded() + throws InterruptedException, ExecutionException + { + ExecutorService executor = Executors.newFixedThreadPool(2); + + Set> caches = Sets.newHashSet(); + + for (int i = 0; i < 20; i++) + { + //J- + caches.add( + executor.submit(new AcquireCacheCallable(cacheManager, "test-2")) + ); + //J+ + } + + executor.shutdown(); + + Cache c = null; + + for (Future f : caches) + { + Cache nc = f.get(); + + if (c != null) + { + assertIsSame(c, nc); + } + + c = nc; + } + } + + //~--- set methods ---------------------------------------------------------- + + /** + * Method description + * + */ + @Before + public void setUp() + { + cacheManager = createCacheManager(); + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param c1 + * @param c2 + */ + protected void assertIsSame(Cache c1, + Cache c2) + { + assertSame(c1, c2); + } + + //~--- inner classes -------------------------------------------------------- + + /** + * Class description + * + * + * @version Enter version here..., 13/03/25 + * @author Enter your name here... + */ + private static class AcquireCacheCallable implements Callable + { + + /** + * Constructs ... + * + * + * @param cacheManager + * @param name + */ + public AcquireCacheCallable(CacheManager cacheManager, String name) + { + this.cacheManager = cacheManager; + this.name = name; + } + + //~--- methods ------------------------------------------------------------ + + /** + * Method description + * + * + * @return + * + * @throws Exception + */ + @Override + public Cache call() throws Exception + { + return cacheManager.getCache(String.class, String.class, name); + } + + //~--- fields ------------------------------------------------------------- + + /** Field description */ + private CacheManager cacheManager; + + /** Field description */ + private String name; + } + + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private CacheManager cacheManager; +} diff --git a/scm-webapp/src/test/java/sonia/scm/cache/EhCacheManagerTest.java b/scm-webapp/src/test/java/sonia/scm/cache/EhCacheManagerTest.java new file mode 100644 index 0000000000..899de9839b --- /dev/null +++ b/scm-webapp/src/test/java/sonia/scm/cache/EhCacheManagerTest.java @@ -0,0 +1,84 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.cache; + +//~--- non-JDK imports -------------------------------------------------------- + +import org.junit.Assert; + +/** + * + * @author Sebastian Sdorra + */ +public class EhCacheManagerTest extends CacheManagerTestBase +{ + + /** + * Method description + * + * + * @param c1 + * @param c2 + */ + @Override + protected void assertIsSame(Cache c1, Cache c2) + { + Assert.assertSame(getCacheImplementation(c1), getCacheImplementation(c1)); + } + + /** + * Method description + * + * + * @return + */ + @Override + protected CacheManager createCacheManager() + { + return CacheTestUtil.createDefaultEhCacheManager(); + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @param c1 + * + * @return + */ + private net.sf.ehcache.Cache getCacheImplementation(Cache c1) + { + return ((EhCache) c1).getCacheImplementation(); + } +} diff --git a/scm-webapp/src/test/java/sonia/scm/cache/GuavaCacheManagerTest.java b/scm-webapp/src/test/java/sonia/scm/cache/GuavaCacheManagerTest.java new file mode 100644 index 0000000000..6a9380810c --- /dev/null +++ b/scm-webapp/src/test/java/sonia/scm/cache/GuavaCacheManagerTest.java @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.cache; + +/** + * + * @author Sebastian Sdorra + */ +public class GuavaCacheManagerTest extends CacheManagerTestBase +{ + + /** + * Method description + * + * + * @return + */ + @Override + protected CacheManager createCacheManager() + { + return CacheTestUtil.createDefaultGuavaCacheManager(); + } +} From f6cc4c9d36569e73f37759432f37e6b0651a0226 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Wed, 27 Mar 2013 08:50:37 +0100 Subject: [PATCH 27/28] use guava cache as default cache --- scm-webapp/src/main/java/sonia/scm/ScmServletModule.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java b/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java index ec14dbe9c4..35cb5192e6 100644 --- a/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java +++ b/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java @@ -142,6 +142,7 @@ import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; +import sonia.scm.cache.GuavaCacheManager; /** * @@ -272,8 +273,8 @@ public class ScmServletModule extends ServletModule bind(WebSecurityContext.class).to(BasicSecurityContext.class); bind(AdministrationContext.class, DefaultAdministrationContext.class); - // bind security cache - bind(CacheManager.class, EhCacheManager.class); + // bind cache + bind(CacheManager.class, GuavaCacheManager.class); // bind dao bind(GroupDAO.class, XmlGroupDAO.class); From c1d5e539a9c31d5b3d72b0190d077bd329abf67b Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Wed, 27 Mar 2013 08:51:17 +0100 Subject: [PATCH 28/28] close branch issue-345