You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2006/07/31 21:29:08 UTC
svn commit: r427221 - in
/incubator/cayenne/main/trunk/core/cayenne-jdk1.4-core/src:
main/java/org/apache/cayenne/cache/OSQueryCache.java
main/java/org/apache/cayenne/cache/OSQueryCacheFactory.java
test/java/org/apache/cayenne/cache/OSQueryCacheTst.java
Author: aadamchik
Date: Mon Jul 31 12:29:07 2006
New Revision: 427221
URL: http://svn.apache.org/viewvc?rev=427221&view=rev
Log:
CAY-613 - support for per-query expiration policy
Added:
incubator/cayenne/main/trunk/core/cayenne-jdk1.4-core/src/test/java/org/apache/cayenne/cache/OSQueryCacheTst.java
Modified:
incubator/cayenne/main/trunk/core/cayenne-jdk1.4-core/src/main/java/org/apache/cayenne/cache/OSQueryCache.java
incubator/cayenne/main/trunk/core/cayenne-jdk1.4-core/src/main/java/org/apache/cayenne/cache/OSQueryCacheFactory.java
Modified: incubator/cayenne/main/trunk/core/cayenne-jdk1.4-core/src/main/java/org/apache/cayenne/cache/OSQueryCache.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/core/cayenne-jdk1.4-core/src/main/java/org/apache/cayenne/cache/OSQueryCache.java?rev=427221&r1=427220&r2=427221&view=diff
==============================================================================
--- incubator/cayenne/main/trunk/core/cayenne-jdk1.4-core/src/main/java/org/apache/cayenne/cache/OSQueryCache.java (original)
+++ incubator/cayenne/main/trunk/core/cayenne-jdk1.4-core/src/main/java/org/apache/cayenne/cache/OSQueryCache.java Mon Jul 31 12:29:07 2006
@@ -18,11 +18,16 @@
****************************************************************/
package org.apache.cayenne.cache;
+import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
+import java.util.Map;
+import java.util.Properties;
import org.apache.cayenne.map.ObjEntity;
import org.apache.cayenne.query.QueryMetadata;
+import com.opensymphony.oscache.base.CacheEntry;
import com.opensymphony.oscache.base.NeedsRefreshException;
import com.opensymphony.oscache.general.GeneralCacheAdministrator;
@@ -30,25 +35,129 @@
* A {@link QueryCache} implementation based on OpenSymphony OSCache. Query cache
* parameters are initialized from "/oscache.properties" file per <a
* href="http://www.opensymphony.com/oscache/wiki/Configuration.html">OSCache</a>
- * documentation.
+ * documentation. In addition to the standard OSCache parameters, Cayenne provdier allows
+ * to setup global and per-query cache expiration parameters. A sample oscache.properties
+ * may look like this:
+ *
+ * <pre>
+ * # OSCache configuration file
+ *
+ * # OSCache standard configuration per
+ * # http://www.opensymphony.com/oscache/wiki/Configuration.html
+ * # ---------------------------------------------------------------
+ *
+ * #cache.memory=true
+ * cache.capacity=5000
+ * cache.algorithm=com.opensymphony.oscache.base.algorithm.LRUCache
+ *
+ *
+ * # Cayenne specific properties
+ * # ---------------------------------------------------------------
+ *
+ * # Default refresh period in seconds:
+ * cayenne.default.refresh = 60
+ *
+ * # Default expiry specified as cron expressions per
+ * # http://www.opensymphony.com/oscache/wiki/Cron%20Expressions.html
+ * # expire entries every hour on the 10's minute
+ * cayenne.default.cron = 10 * * * *
+ *
+ * # Same parameters can be overriden per query
+ * cayenne.query.xyz.refresh = 120
+ * cayenne.query.xyz.cron = 10 1 * * *
+ * </pre>
*
* @since 3.0
* @author Andrus Adamchik
*/
public class OSQueryCache implements QueryCache {
+ public static final int DEFAULT_REFRESH_PERIOD = CacheEntry.INDEFINITE_EXPIRY;
+
+ static String DEFAULT_REFRESH_KEY = "cayenne.default.refresh";
+ static String DEFAULT_CRON_KEY = "cayenne.default.cron";
+
+ static String QUERY_PREFIX = "cayenne.query.";
+ static String REFRESH_SUFFIX = ".refresh";
+ static String CRON_SUFFIX = ".cron";
+
protected GeneralCacheAdministrator cache;
- protected int refreshPeriod;
- protected String cronExpression;
- public OSQueryCache(int refreshPeriod, String cronExpression) {
- this(new GeneralCacheAdministrator(), refreshPeriod, cronExpression);
+ RefreshSpecification defaultRefreshSpecification;
+ Map refreshSpecifications;
+
+ public OSQueryCache() {
+ OSCacheAdministrator admin = new OSCacheAdministrator();
+ init(admin, admin.getProperties());
+ }
+
+ public OSQueryCache(Properties properties) {
+ init(new GeneralCacheAdministrator(), properties);
}
- OSQueryCache(GeneralCacheAdministrator cache, int refreshPeriod, String cronExpression) {
+ OSQueryCache(GeneralCacheAdministrator cache, Properties properties) {
+ init(cache, properties);
+ }
+
+ void init(GeneralCacheAdministrator cache, Properties properties) {
+
this.cache = cache;
- this.refreshPeriod = refreshPeriod;
- this.cronExpression = cronExpression;
+ this.defaultRefreshSpecification = new RefreshSpecification();
+
+ // load defaults and per-query settings
+ if (properties != null) {
+ Iterator it = properties.entrySet().iterator();
+ while (it.hasNext()) {
+
+ Map.Entry entry = (Map.Entry) it.next();
+
+ if (entry.getKey() == null || entry.getValue() == null) {
+ continue;
+ }
+
+ String key = entry.getKey().toString();
+ if (key.startsWith(QUERY_PREFIX)) {
+
+ if (key.endsWith(REFRESH_SUFFIX)) {
+ String name = key.substring(QUERY_PREFIX.length(), key.length()
+ - REFRESH_SUFFIX.length());
+
+ nonNullSpec(name).setRefreshPeriod(entry.getValue());
+ }
+ else if (key.endsWith(CRON_SUFFIX)) {
+ String name = key.substring(QUERY_PREFIX.length(), key.length()
+ - CRON_SUFFIX.length());
+
+ nonNullSpec(name).cronExpression = entry.getValue().toString();
+ }
+
+ }
+ else if (key.equals(DEFAULT_REFRESH_KEY)) {
+ defaultRefreshSpecification.setRefreshPeriod(entry.getValue());
+ }
+ else if (key.equals(DEFAULT_CRON_KEY)) {
+ defaultRefreshSpecification.cronExpression = entry
+ .getValue()
+ .toString();
+ }
+ }
+ }
+
+ }
+
+ private RefreshSpecification nonNullSpec(String name) {
+ if (refreshSpecifications == null) {
+ refreshSpecifications = new HashMap();
+ }
+
+ RefreshSpecification spec = (RefreshSpecification) refreshSpecifications
+ .get(name);
+ if (spec == null) {
+ spec = new RefreshSpecification();
+ refreshSpecifications.put(name, spec);
+ }
+
+ return spec;
}
public List get(QueryMetadata metadata) {
@@ -57,8 +166,21 @@
return null;
}
+ RefreshSpecification refresh = null;
+
+ if (refreshSpecifications != null) {
+ refresh = (RefreshSpecification) refreshSpecifications.get(key);
+ }
+
+ if (refresh == null) {
+ refresh = defaultRefreshSpecification;
+ }
+
try {
- return (List) cache.getFromCache(key, refreshPeriod, cronExpression);
+ return (List) cache.getFromCache(
+ key,
+ refresh.refreshPeriod,
+ refresh.cronExpression);
}
catch (NeedsRefreshException e) {
cache.cancelUpdate(key);
@@ -99,4 +221,43 @@
public int size() {
return cache.getCache().getSize();
}
+
+ final static class RefreshSpecification {
+
+ int refreshPeriod;
+ String cronExpression;
+
+ RefreshSpecification() {
+ this.refreshPeriod = DEFAULT_REFRESH_PERIOD;
+ }
+
+ RefreshSpecification(int refrehsPeriod, String cronExpression) {
+ this.refreshPeriod = refrehsPeriod;
+ this.cronExpression = cronExpression;
+ }
+
+ void setRefreshPeriod(Object value) {
+ try {
+ refreshPeriod = Integer.parseInt(value.toString());
+ }
+ catch (NumberFormatException e) {
+ // ignore...
+ }
+ }
+ }
+
+ final class OSCacheAdministrator extends GeneralCacheAdministrator {
+
+ OSCacheAdministrator() {
+ }
+
+ OSCacheAdministrator(Properties properties) {
+ super(properties);
+ }
+
+ Properties getProperties() {
+ return super.config.getProperties();
+ }
+ }
+
}
Modified: incubator/cayenne/main/trunk/core/cayenne-jdk1.4-core/src/main/java/org/apache/cayenne/cache/OSQueryCacheFactory.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/core/cayenne-jdk1.4-core/src/main/java/org/apache/cayenne/cache/OSQueryCacheFactory.java?rev=427221&r1=427220&r2=427221&view=diff
==============================================================================
--- incubator/cayenne/main/trunk/core/cayenne-jdk1.4-core/src/main/java/org/apache/cayenne/cache/OSQueryCacheFactory.java (original)
+++ incubator/cayenne/main/trunk/core/cayenne-jdk1.4-core/src/main/java/org/apache/cayenne/cache/OSQueryCacheFactory.java Mon Jul 31 12:29:07 2006
@@ -18,69 +18,22 @@
****************************************************************/
package org.apache.cayenne.cache;
-import java.util.Collections;
import java.util.Map;
-import com.opensymphony.oscache.base.CacheEntry;
-import com.opensymphony.oscache.general.GeneralCacheAdministrator;
-
/**
- * A factory for the OSCache factory. A few extra properties in addition to what OSCache
- * supports can be read from "/oscache.properties" file. Those are
- * {@link OSQueryCacheFactory#OSCACHE_CRON_EXPRESSION_PROPERTY} and
- * {@link OSQueryCacheFactory#OSCACHE_REFRESH_PERIOD_PROPERTY}.
+ * A factory for the OSCache factory. "/oscache.properties" file is read to load the
+ * standard OSCache properties and also extra properties
*
* @since 3.0
* @author Andrus Adamchik
*/
public class OSQueryCacheFactory implements QueryCacheFactory {
- public static final String OSCACHE_REFRESH_PERIOD_PROPERTY = "cayenne.OSQueryCacheFactory.refresh";
- public static final String OSCACHE_CRON_EXPRESSION_PROPERTY = "cayenne.OSQueryCacheFactory.cron";
-
- protected OSQueryCache createCache(
- GeneralCacheAdministrator cache,
- int refreshPeriod,
- String cronExpression) {
- return new OSQueryCache(cache, refreshPeriod, cronExpression);
- }
-
+ /**
+ * Creates QueryCache, ignoring provided properties, and reading data from
+ * "oscache.properties" file instead.
+ */
public QueryCache getQueryCache(Map properties) {
-
- int refreshPeriod = CacheEntry.INDEFINITE_EXPIRY;
- String cronExpression = null;
-
- // this code loads oscache.properties. Use it as a failover for Cayenne-specific
- // properties.
- GeneralCacheAdministrator cache = new GeneralCacheAdministrator();
-
- if (properties == null) {
- properties = Collections.EMPTY_MAP;
- }
-
- Object refreshPeriodProperty = properties.get(OSCACHE_REFRESH_PERIOD_PROPERTY);
- if (refreshPeriodProperty == null) {
- refreshPeriodProperty = cache.getProperty(OSCACHE_REFRESH_PERIOD_PROPERTY);
- }
-
- if (refreshPeriodProperty != null) {
- try {
- refreshPeriod = Integer.parseInt(refreshPeriodProperty.toString());
- }
- catch (NumberFormatException e) {
- // ignore
- }
- }
-
- Object cronExpressionProperty = properties.get(OSCACHE_CRON_EXPRESSION_PROPERTY);
- if (cronExpressionProperty == null) {
- cronExpressionProperty = cache.getProperty(OSCACHE_CRON_EXPRESSION_PROPERTY);
- }
-
- if (cronExpressionProperty != null) {
- cronExpression = cronExpressionProperty.toString();
- }
-
- return createCache(cache, refreshPeriod, cronExpression);
+ return new OSQueryCache();
}
}
Added: incubator/cayenne/main/trunk/core/cayenne-jdk1.4-core/src/test/java/org/apache/cayenne/cache/OSQueryCacheTst.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/core/cayenne-jdk1.4-core/src/test/java/org/apache/cayenne/cache/OSQueryCacheTst.java?rev=427221&view=auto
==============================================================================
--- incubator/cayenne/main/trunk/core/cayenne-jdk1.4-core/src/test/java/org/apache/cayenne/cache/OSQueryCacheTst.java (added)
+++ incubator/cayenne/main/trunk/core/cayenne-jdk1.4-core/src/test/java/org/apache/cayenne/cache/OSQueryCacheTst.java Mon Jul 31 12:29:07 2006
@@ -0,0 +1,82 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ****************************************************************/
+package org.apache.cayenne.cache;
+
+import java.util.Properties;
+
+import org.apache.cayenne.cache.OSQueryCache.RefreshSpecification;
+
+import junit.framework.TestCase;
+
+import com.opensymphony.oscache.base.CacheEntry;
+
+public class OSQueryCacheTst extends TestCase {
+
+ public void testDefaults() {
+ OSQueryCache cache = new OSQueryCache();
+
+ assertNull(cache.refreshSpecifications);
+ assertNull(cache.defaultRefreshSpecification.cronExpression);
+ assertEquals(
+ CacheEntry.INDEFINITE_EXPIRY,
+ cache.defaultRefreshSpecification.refreshPeriod);
+ }
+
+ public void testDefaultOverrides() {
+
+ Properties props = new Properties();
+ props.put(OSQueryCache.DEFAULT_REFRESH_KEY, "15");
+ props.put(OSQueryCache.DEFAULT_CRON_KEY, "9 * * * * *");
+ OSQueryCache cache = new OSQueryCache(props);
+
+ assertNull(cache.refreshSpecifications);
+ assertEquals("9 * * * * *", cache.defaultRefreshSpecification.cronExpression);
+ assertEquals(15, cache.defaultRefreshSpecification.refreshPeriod);
+ }
+
+ public void testQueryOverrides() {
+
+ Properties props = new Properties();
+ props.put(OSQueryCache.QUERY_PREFIX + "ABC" + OSQueryCache.REFRESH_SUFFIX, "25");
+ props.put(
+ OSQueryCache.QUERY_PREFIX + "ABC" + OSQueryCache.CRON_SUFFIX,
+ "12 * * * * *");
+ props.put(OSQueryCache.QUERY_PREFIX + "XYZ" + OSQueryCache.REFRESH_SUFFIX, "35");
+ props.put(
+ OSQueryCache.QUERY_PREFIX + "XYZ" + OSQueryCache.CRON_SUFFIX,
+ "24 * * * * *");
+
+ OSQueryCache cache = new OSQueryCache(props);
+
+ assertNotNull(cache.refreshSpecifications);
+ assertEquals(2, cache.refreshSpecifications.size());
+
+ RefreshSpecification abc = (RefreshSpecification) cache.refreshSpecifications
+ .get("ABC");
+ assertNotNull(abc);
+ assertEquals("12 * * * * *", abc.cronExpression);
+ assertEquals(25, abc.refreshPeriod);
+
+ RefreshSpecification xyz = (RefreshSpecification) cache.refreshSpecifications
+ .get("XYZ");
+ assertNotNull(xyz);
+ assertEquals("24 * * * * *", xyz.cronExpression);
+ assertEquals(35, xyz.refreshPeriod);
+ }
+}