Author: aadamchik
Date: Thu Jul 27 14:08:12 2006
New Revision: 426241
URL: http://svn.apache.org/viewvc?rev=426241&view=rev
Log:
CAY-613 - switching local cache to use QueryCache.
Added:
incubator/cayenne/main/trunk/cayenne/cayenne-java/lib-src/oscache-2.3.2-src.jar
(with props)
incubator/cayenne/main/trunk/cayenne/cayenne-java/lib/oscache-2.3.2.jar
(with props)
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/cache/
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/cache/MapQueryCache.java
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/cache/MapQueryCacheFactory.java
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/cache/OSQueryCache.java
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/cache/OSQueryCacheFactory.java
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/cache/QueryCache.java
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/cache/QueryCacheFactory.java
Modified:
incubator/cayenne/main/trunk/cayenne/cayenne-java/.classpath
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/access/ClientServerChannel.java
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/access/ClientServerChannelQueryAction.java
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/access/DataContext.java
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/access/DataContextQueryAction.java
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/access/DataDomain.java
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/access/ObjectStore.java
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/tests/java/org/apache/cayenne/access/DataContextNamedQueryCachingTst.java
Modified: incubator/cayenne/main/trunk/cayenne/cayenne-java/.classpath
URL:
http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/cayenne/cayenne-java/.classpath?rev=426241&r1=426240&r2=426241&view=diff
==============================================================================
--- incubator/cayenne/main/trunk/cayenne/cayenne-java/.classpath (original)
+++ incubator/cayenne/main/trunk/cayenne/cayenne-java/.classpath Thu Jul 27
14:08:12 2006
@@ -39,5 +39,6 @@
<classpathentry exported="true" kind="lib"
path="lib/velocity-dep-1.3.jar"/>
<classpathentry kind="con"
path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry sourcepath="lib-src/hsqldb-1.8.0.2-src.jar" kind="lib"
path="lib/hsqldb-1.8.0.2.jar"/>
+ <classpathentry sourcepath="lib-src/oscache-2.3.2-src.jar" kind="lib"
path="lib/oscache-2.3.2.jar"/>
<classpathentry kind="output" path="build/eclipse"/>
</classpath>
Added:
incubator/cayenne/main/trunk/cayenne/cayenne-java/lib-src/oscache-2.3.2-src.jar
URL:
http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/cayenne/cayenne-java/lib-src/oscache-2.3.2-src.jar?rev=426241&view=auto
==============================================================================
Binary file - no diff available.
Propchange:
incubator/cayenne/main/trunk/cayenne/cayenne-java/lib-src/oscache-2.3.2-src.jar
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Added: incubator/cayenne/main/trunk/cayenne/cayenne-java/lib/oscache-2.3.2.jar
URL:
http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/cayenne/cayenne-java/lib/oscache-2.3.2.jar?rev=426241&view=auto
==============================================================================
Binary file - no diff available.
Propchange:
incubator/cayenne/main/trunk/cayenne/cayenne-java/lib/oscache-2.3.2.jar
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Modified:
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/access/ClientServerChannel.java
URL:
http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/access/ClientServerChannel.java?rev=426241&r1=426240&r2=426241&view=diff
==============================================================================
---
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/access/ClientServerChannel.java
(original)
+++
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/access/ClientServerChannel.java
Thu Jul 27 14:08:12 2006
@@ -19,8 +19,6 @@
package org.apache.cayenne.access;
-import java.util.List;
-
import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.DataChannel;
import org.apache.cayenne.ObjectContext;
@@ -59,17 +57,6 @@
public QueryResponse onQuery(ObjectContext context, Query query) {
return new ClientServerChannelQueryAction(this, query).execute();
- }
-
- void addPaginatedResult(String cacheKey, IncrementalFaultList result) {
- serverContext.getObjectStore().cacheQueryResult(cacheKey, result);
- }
-
- IncrementalFaultList getPaginatedResult(String cacheKey) {
- List result =
serverContext.getObjectStore().getCachedQueryResult(cacheKey);
- return (result instanceof IncrementalFaultList)
- ? (IncrementalFaultList) result
- : null;
}
DataContext getServerContext() {
Modified:
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/access/ClientServerChannelQueryAction.java
URL:
http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/access/ClientServerChannelQueryAction.java?rev=426241&r1=426240&r2=426241&view=diff
==============================================================================
---
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/access/ClientServerChannelQueryAction.java
(original)
+++
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/access/ClientServerChannelQueryAction.java
Thu Jul 27 14:08:12 2006
@@ -80,8 +80,8 @@
&& serverMetadata.getFetchLimit() > 0
&& serverMetadata.getCacheKey() != null) {
- IncrementalFaultList cachedList =
channel.getPaginatedResult(serverMetadata
- .getCacheKey());
+ List cachedList = channel.getServerContext().getQueryCache().get(
+ serverMetadata);
if (cachedList == null) {
throw new CayenneRuntimeException("No cached list for "
+ serverMetadata.getCacheKey());
@@ -114,9 +114,7 @@
if (list.size() > pageSize && list instanceof
IncrementalFaultList) {
// cache
- channel.addPaginatedResult(
- serverMetadata.getCacheKey(),
- ((IncrementalFaultList) list));
+ channel.getServerContext().getQueryCache().put(serverMetadata,
list);
// extract and convert firts page
Modified:
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/access/DataContext.java
URL:
http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/access/DataContext.java?rev=426241&r1=426240&r2=426241&view=diff
==============================================================================
---
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/access/DataContext.java
(original)
+++
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/access/DataContext.java
Thu Jul 27 14:08:12 2006
@@ -47,6 +47,8 @@
import org.apache.cayenne.QueryResponse;
import org.apache.cayenne.access.event.DataContextEvent;
import org.apache.cayenne.access.util.IteratedSelectObserver;
+import org.apache.cayenne.cache.QueryCache;
+import org.apache.cayenne.cache.QueryCacheFactory;
import org.apache.cayenne.conf.Configuration;
import org.apache.cayenne.event.EventManager;
import org.apache.cayenne.event.EventSubject;
@@ -133,6 +135,7 @@
protected boolean usingSharedSnaphsotCache;
protected boolean validatingObjectsOnCommit;
protected ObjectStore objectStore;
+ protected QueryCache queryCache;
protected transient DataChannel channel;
@@ -267,6 +270,28 @@
this.usingSharedSnaphsotCache = domain != null
&& objectStore.getDataRowCache() ==
domain.getSharedSnapshotCache();
}
+ }
+
+ /**
+ * Returns [EMAIL PROTECTED] QueryCache} used by this DataContext,
creating it on the fly if
+ * needed. Uses parent DataDomain [EMAIL PROTECTED] QueryCacheFactory} to
initialize the cache
+ * for the first time.
+ *
+ * @since 3.0
+ */
+ public QueryCache getQueryCache() {
+
+ if (queryCache == null) {
+ synchronized (this) {
+ if (queryCache == null) {
+ queryCache = getParentDataDomain()
+ .getQueryCacheFactory()
+ .getQueryCache(Collections.EMPTY_MAP);
+ }
+ }
+ }
+
+ return queryCache;
}
/**
Modified:
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/access/DataContextQueryAction.java
URL:
http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/access/DataContextQueryAction.java?rev=426241&r1=426240&r2=426241&view=diff
==============================================================================
---
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/access/DataContextQueryAction.java
(original)
+++
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/access/DataContextQueryAction.java
Thu Jul 27 14:08:12 2006
@@ -19,13 +19,12 @@
package org.apache.cayenne.access;
-import java.util.Iterator;
import java.util.List;
-import java.util.Map;
import org.apache.cayenne.DataObject;
import org.apache.cayenne.ObjectContext;
import org.apache.cayenne.QueryResponse;
+import org.apache.cayenne.cache.QueryCache;
import org.apache.cayenne.query.InvalidateListCacheQuery;
import org.apache.cayenne.query.ObjectIdQuery;
import org.apache.cayenne.query.Query;
@@ -109,8 +108,7 @@
*/
private boolean interceptLocalCache() {
- String cacheKey = metadata.getCacheKey();
- if (cacheKey == null) {
+ if (metadata.getCacheKey() == null) {
return !DONE;
}
@@ -122,10 +120,11 @@
return !DONE;
}
- ObjectStore objectStore = ((DataContext)
actingContext).getObjectStore();
+ QueryCache queryCache = ((DataContext) actingContext).getQueryCache();
+
if (cache) {
- List cachedResults = objectStore.getCachedQueryResult(cacheKey);
+ List cachedResults = queryCache.get(metadata);
if (cachedResults != null) {
response = new ListResponse(cachedResults);
return DONE;
@@ -133,7 +132,7 @@
}
runQuery();
- objectStore.cacheQueryResult(cacheKey, response.firstList());
+ queryCache.put(metadata, response.firstList());
return DONE;
}
@@ -141,26 +140,15 @@
if (query instanceof InvalidateListCacheQuery) {
InvalidateListCacheQuery invalidateQuery =
(InvalidateListCacheQuery) query;
- ObjectStore objectStore = ((DataContext)
actingContext).getObjectStore();
-
- int count = 0;
- synchronized (objectStore) {
- Iterator it =
objectStore.getCachedQueryResults().entrySet().iterator();
- while (it.hasNext()) {
- Map.Entry entry = (Map.Entry) it.next();
- if (invalidateQuery.matchesCacheKey((String)
entry.getKey())) {
- count++;
- it.remove();
- }
- }
- }
+ QueryCache queryCache = ((DataContext)
actingContext).getQueryCache();
+ queryCache.removeGroup(invalidateQuery.getCacheKeyPattern());
if (invalidateQuery.isCascade()) {
return !DONE;
}
else {
GenericResponse response = new GenericResponse();
- response.addUpdateCount(count);
+ response.addUpdateCount(1);
this.response = response;
return DONE;
}
Modified:
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/access/DataDomain.java
URL:
http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/access/DataDomain.java?rev=426241&r1=426240&r2=426241&view=diff
==============================================================================
---
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/access/DataDomain.java
(original)
+++
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/access/DataDomain.java
Thu Jul 27 14:08:12 2006
@@ -26,13 +26,12 @@
import java.util.Map;
import java.util.TreeMap;
-import org.apache.commons.collections.Transformer;
-import org.apache.commons.lang.builder.ToStringBuilder;
-import org.apache.log4j.Logger;
import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.DataChannel;
import org.apache.cayenne.ObjectContext;
import org.apache.cayenne.QueryResponse;
+import org.apache.cayenne.cache.MapQueryCacheFactory;
+import org.apache.cayenne.cache.QueryCacheFactory;
import org.apache.cayenne.event.EventManager;
import org.apache.cayenne.graph.CompoundDiff;
import org.apache.cayenne.graph.GraphDiff;
@@ -43,6 +42,9 @@
import org.apache.cayenne.query.Query;
import org.apache.cayenne.query.QueryChain;
import org.apache.cayenne.util.Util;
+import org.apache.commons.collections.Transformer;
+import org.apache.commons.lang.builder.ToStringBuilder;
+import org.apache.log4j.Logger;
/**
* DataDomain performs query routing functions in Cayenne. DataDomain creates
single data
@@ -76,6 +78,13 @@
*/
public static final String DATA_CONTEXT_FACTORY_PROPERTY =
"cayenne.DataDomain.dataContextFactory";
+ /**
+ * Defaines a property name for storing optional [EMAIL PROTECTED]
QueryCacheFactory}.
+ *
+ * @since 3.0
+ */
+ public static final String QUERY_CACHE_FACTORY_PROPERTY =
"cayenne.DataDomain.queryCacheFactory";
+
/** Stores mapping of data nodes to DataNode name keys. */
protected Map nodes = Collections.synchronizedMap(new TreeMap());
protected Map nodesByDataMapName = Collections.synchronizedMap(new
HashMap());
@@ -90,6 +99,7 @@
protected DataRowStore sharedSnapshotCache;
protected TransactionDelegate transactionDelegate;
protected DataContextFactory dataContextFactory;
+ protected QueryCacheFactory queryCacheFactory;
protected String name;
// these are initializable from properties...
@@ -202,6 +212,7 @@
.get(USING_EXTERNAL_TRANSACTIONS_PROPERTY);
Object dataContextFactory =
localMap.get(DATA_CONTEXT_FACTORY_PROPERTY);
+ Object queryCacheFactory = localMap.get(QUERY_CACHE_FACTORY_PROPERTY);
if (logObj.isDebugEnabled()) {
logObj.debug("DataDomain property "
@@ -220,6 +231,10 @@
+ DATA_CONTEXT_FACTORY_PROPERTY
+ " = "
+ dataContextFactory);
+ logObj.debug("DataDomain property "
+ + QUERY_CACHE_FACTORY_PROPERTY
+ + " = "
+ + queryCacheFactory);
}
// init ivars from properties
@@ -235,30 +250,48 @@
if (dataContextFactory != null
&& !Util.isEmptyString(dataContextFactory.toString())) {
- try {
- Class factoryClass = Class.forName(
- dataContextFactory.toString(),
- true,
- Thread.currentThread().getContextClassLoader());
-
- if (!DataContextFactory.class.isAssignableFrom(factoryClass)) {
- throw new CayenneRuntimeException(
- "Error loading DataContextFactory - factory class
does not implement 'DataContextFactory': "
- + factoryClass.getName());
- }
- this.dataContextFactory = (DataContextFactory)
factoryClass.newInstance();
- }
- catch (CayenneRuntimeException e) {
- throw e;
- }
- catch (Exception e) {
- throw new CayenneRuntimeException("Error loading
DataContextFactory: "
- + dataContextFactory, e);
- }
+ this.dataContextFactory = (DataContextFactory) createInstance(
+ dataContextFactory.toString(),
+ DataContextFactory.class);
}
else {
this.dataContextFactory = null;
}
+
+ if (queryCacheFactory != null
+ && !Util.isEmptyString(dataContextFactory.toString())) {
+ queryCacheFactory = (QueryCacheFactory)
createInstance(queryCacheFactory
+ .toString(), QueryCacheFactory.class);
+ }
+ else {
+ queryCacheFactory = null;
+ }
+ }
+
+ private Object createInstance(String className, Class
implementedInterface) {
+ Class aClass;
+ try {
+ aClass = Class.forName(className, true, Thread
+ .currentThread()
+ .getContextClassLoader());
+ }
+ catch (Exception e) {
+ throw new CayenneRuntimeException("Error loading '" + className +
"'", e);
+ }
+
+ if (!implementedInterface.isAssignableFrom(aClass)) {
+ throw new CayenneRuntimeException("Failed to load '"
+ + className
+ + "' - it is expected to implement "
+ + implementedInterface);
+ }
+
+ try {
+ return aClass.newInstance();
+ }
+ catch (Exception e) {
+ throw new CayenneRuntimeException("Error instantiating " +
className, e);
+ }
}
/**
@@ -817,5 +850,21 @@
public String toString() {
return new ToStringBuilder(this).append("name", name).toString();
+ }
+
+ /**
+ * Returns a non-null [EMAIL PROTECTED] QueryCacheFactory}.
+ *
+ * @since 3.0
+ */
+ public QueryCacheFactory getQueryCacheFactory() {
+ return queryCacheFactory != null ? queryCacheFactory : new
MapQueryCacheFactory();
+ }
+
+ /**
+ * @since 3.0
+ */
+ public void setQueryCacheFactory(QueryCacheFactory queryCacheFactory) {
+ this.queryCacheFactory = queryCacheFactory;
}
}
Modified:
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/access/ObjectStore.java
URL:
http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/access/ObjectStore.java?rev=426241&r1=426240&r2=426241&view=diff
==============================================================================
---
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/access/ObjectStore.java
(original)
+++
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/access/ObjectStore.java
Thu Jul 27 14:08:12 2006
@@ -44,9 +44,14 @@
import org.apache.cayenne.graph.NodeCreateOperation;
import org.apache.cayenne.graph.NodeDeleteOperation;
import org.apache.cayenne.graph.NodeDiff;
+import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.ObjEntity;
import org.apache.cayenne.map.ObjRelationship;
+import org.apache.cayenne.map.Procedure;
import org.apache.cayenne.query.ObjectIdQuery;
+import org.apache.cayenne.query.PrefetchTreeNode;
+import org.apache.cayenne.query.QueryMetadata;
/**
* ObjectStore stores objects using their ObjectId as a key. It works as a
dedicated
@@ -66,7 +71,6 @@
protected transient Map newObjectsMap;
protected Map objectMap = new HashMap();
- protected Map queryResultMap = new HashMap();
protected Map changes = new HashMap();
// a sequential id used to tag GraphDiffs so that they can later be sorted
in the
@@ -221,9 +225,12 @@
* result is a list and can possibly contain a large number of entries.
*
* @since 1.2
+ * @deprecated since 3.0. See [EMAIL PROTECTED]
DataContext#getQueryCache()}.
*/
public int cachedQueriesCount() {
- return queryResultMap.size();
+ return context != null && context.queryCache != null
+ ? context.queryCache.size()
+ : 0;
}
/**
@@ -589,27 +596,24 @@
* shared cache associated with the underlying DataRowStore.
*
* @since 1.1
+ *
+ * @deprecated since 3.0. See [EMAIL PROTECTED]
DataContext#getQueryCache()}.
*/
public synchronized List getCachedQueryResult(String name) {
- // results should have been stored as rows or objects when
- // they were originally cached... do no conversions here
- return (List) queryResultMap.get(name);
- }
-
- /**
- * @since 3.0
- */
- Map getCachedQueryResults() {
- return queryResultMap;
- }
+ return context != null && context.queryCache != null ?
context.queryCache
+ .get(new CacheQueryMetadata(name)) : null;
+ }
/**
* Caches a list of query results.
*
* @since 1.1
+ * @deprecated since 3.0. See [EMAIL PROTECTED]
DataContext#getQueryCache()}.
*/
public synchronized void cacheQueryResult(String name, List results) {
- queryResultMap.put(name, results);
+ if (context != null) {
+ context.getQueryCache().put(new CacheQueryMetadata(name), results);
+ }
}
/**
@@ -1174,6 +1178,67 @@
public void undo(GraphChangeHandler handler) {
throw new UnsupportedOperationException();
+ }
+ }
+
+ final class CacheQueryMetadata implements QueryMetadata {
+
+ private String cacheKey;
+
+ CacheQueryMetadata(String cacheKey) {
+ this.cacheKey = cacheKey;
+ }
+
+ public String getCacheKey() {
+ return cacheKey;
+ }
+
+ public String getCachePolicy() {
+ return null;
+ }
+
+ public DataMap getDataMap() {
+ return null;
+ }
+
+ public DbEntity getDbEntity() {
+ return null;
+ }
+
+ public int getFetchLimit() {
+ return 0;
+ }
+
+ public int getFetchStartIndex() {
+ return 0;
+ }
+
+ public ObjEntity getObjEntity() {
+ return null;
+ }
+
+ public int getPageSize() {
+ return 0;
+ }
+
+ public PrefetchTreeNode getPrefetchTree() {
+ return null;
+ }
+
+ public Procedure getProcedure() {
+ return null;
+ }
+
+ public boolean isFetchingDataRows() {
+ return false;
+ }
+
+ public boolean isRefreshingObjects() {
+ return false;
+ }
+
+ public boolean isResolvingInherited() {
+ return false;
}
}
}
Added:
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/cache/MapQueryCache.java
URL:
http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/cache/MapQueryCache.java?rev=426241&view=auto
==============================================================================
---
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/cache/MapQueryCache.java
(added)
+++
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/cache/MapQueryCache.java
Thu Jul 27 14:08:12 2006
@@ -0,0 +1,115 @@
+/*****************************************************************
+ * 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.io.Serializable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.query.QueryMetadata;
+import org.apache.commons.collections.map.LRUMap;
+
+/**
+ * A default implementation of the [EMAIL PROTECTED] QueryCache} interface
that stores data in a
+ * non-expiring LRUMap.
+ *
+ * @since 3.0
+ * @author Andrus Adamchik
+ */
+public class MapQueryCache implements QueryCache, Serializable {
+
+ public static final int DEFAULT_CACHE_SIZE = 2000;
+
+ protected Map map;
+
+ public MapQueryCache() {
+ this(DEFAULT_CACHE_SIZE);
+ }
+
+ public MapQueryCache(int maxSize) {
+ this.map = new LRUMap(maxSize);
+ }
+
+ public List get(QueryMetadata metadata) {
+ String key = metadata.getCacheKey();
+ if (key == null) {
+ return null;
+ }
+
+ CacheEntry entry;
+ synchronized (this) {
+ entry = (CacheEntry) map.get(key);
+ }
+
+ return (entry != null) ? entry.list : null;
+ }
+
+ public void put(QueryMetadata metadata, List results) {
+ String key = metadata.getCacheKey();
+ if (key != null) {
+
+ CacheEntry entry = new CacheEntry();
+ entry.list = results;
+
+ ObjEntity entity = metadata.getObjEntity();
+ if (entity != null) {
+ entry.entityName = entity.getName();
+ }
+
+ synchronized (this) {
+ map.put(key, entry);
+ }
+ }
+ }
+
+ public void remove(QueryMetadata metadata) {
+ String key = metadata.getCacheKey();
+ if (key != null) {
+ synchronized (this) {
+ map.remove(key);
+ }
+ }
+ }
+
+ public void removeGroup(String groupKey) {
+ if (groupKey != null) {
+ synchronized (this) {
+ Iterator it = map.values().iterator();
+ while (it.hasNext()) {
+ CacheEntry entry = (CacheEntry) it.next();
+ if (groupKey.equals(entry.entityName)) {
+ it.remove();
+ }
+ }
+ }
+ }
+ }
+
+ public int size() {
+ return map.size();
+ }
+
+ final class CacheEntry {
+
+ List list;
+ String entityName;
+ }
+}
Added:
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/cache/MapQueryCacheFactory.java
URL:
http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/cache/MapQueryCacheFactory.java?rev=426241&view=auto
==============================================================================
---
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/cache/MapQueryCacheFactory.java
(added)
+++
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/cache/MapQueryCacheFactory.java
Thu Jul 27 14:08:12 2006
@@ -0,0 +1,46 @@
+/*****************************************************************
+ * 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.Map;
+
+/**
+ * @since 3.0
+ * @author Andrus Adamchik
+ */
+public class MapQueryCacheFactory implements QueryCacheFactory {
+
+ public static final String CACHE_SIZE_PROPERTY =
"cayenne.MapQueryCacheFactory.cacheSize";
+
+ public QueryCache getQueryCache(Map properties) {
+ if(properties != null) {
+ Object size = properties.get(CACHE_SIZE_PROPERTY);
+ if(size != null) {
+ try {
+ return new
MapQueryCache(Integer.parseInt(size.toString()));
+ }
+ catch(NumberFormatException e) {
+ // ignore
+ }
+ }
+ }
+
+ return new MapQueryCache();
+ }
+}
Added:
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/cache/OSQueryCache.java
URL:
http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/cache/OSQueryCache.java?rev=426241&view=auto
==============================================================================
---
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/cache/OSQueryCache.java
(added)
+++
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/cache/OSQueryCache.java
Thu Jul 27 14:08:12 2006
@@ -0,0 +1,93 @@
+/*****************************************************************
+ * 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.List;
+
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.query.QueryMetadata;
+
+import com.opensymphony.oscache.base.NeedsRefreshException;
+import com.opensymphony.oscache.general.GeneralCacheAdministrator;
+
+/**
+ * A [EMAIL PROTECTED] QueryCache} implementation based on OpenSymphony
OSCache.
+ *
+ * @since 3.0
+ * @author Andrus Adamchik
+ */
+public class OSQueryCache implements QueryCache {
+
+ protected GeneralCacheAdministrator cache;
+ protected int refreshPeriod;
+ protected String cronExpression;
+
+ public OSQueryCache(int refreshPeriod, String cronExpression) {
+ this.cache = new GeneralCacheAdministrator();
+ this.refreshPeriod = refreshPeriod;
+ this.cronExpression = cronExpression;
+ }
+
+ public List get(QueryMetadata metadata) {
+ String key = metadata.getCacheKey();
+ if (key == null) {
+ return null;
+ }
+
+ try {
+ return (List) cache.getFromCache(key, refreshPeriod,
cronExpression);
+ }
+ catch (NeedsRefreshException e) {
+ cache.cancelUpdate(key);
+ return null;
+ }
+ }
+
+ public void put(QueryMetadata metadata, List results) {
+ String key = metadata.getCacheKey();
+ if (key != null) {
+
+ ObjEntity entity = metadata.getObjEntity();
+
+ String[] groups = entity != null ? new String[] {
+ entity.getName()
+ } : null;
+
+ cache.putInCache(key, results, groups);
+ }
+ }
+
+ public void remove(QueryMetadata metadata) {
+ String key = metadata.getCacheKey();
+ if (key != null) {
+
+ cache.removeEntry(key);
+ }
+ }
+
+ public void removeGroup(String groupKey) {
+ if (groupKey != null) {
+ cache.flushGroup(groupKey);
+ }
+ }
+
+ public int size() {
+ return cache.getCache().getSize();
+ }
+}
Added:
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/cache/OSQueryCacheFactory.java
URL:
http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/cache/OSQueryCacheFactory.java?rev=426241&view=auto
==============================================================================
---
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/cache/OSQueryCacheFactory.java
(added)
+++
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/cache/OSQueryCacheFactory.java
Thu Jul 27 14:08:12 2006
@@ -0,0 +1,32 @@
+/*****************************************************************
+ * 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.Map;
+
+/**
+ * @since 3.0
+ * @author Andrus Adamchik
+ */
+public class OSQueryCacheFactory implements QueryCacheFactory {
+
+ public QueryCache getQueryCache(Map properties) {
+ return null;
+ }
+}
Added:
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/cache/QueryCache.java
URL:
http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/cache/QueryCache.java?rev=426241&view=auto
==============================================================================
---
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/cache/QueryCache.java
(added)
+++
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/cache/QueryCache.java
Thu Jul 27 14:08:12 2006
@@ -0,0 +1,49 @@
+/*****************************************************************
+ * 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.List;
+
+import org.apache.cayenne.query.QueryMetadata;
+
+/**
+ * An interface that defines generic QueryCache.
+ *
+ * @author Andrus Adamchik
+ * @since 3.0
+ */
+public interface QueryCache {
+
+ List get(QueryMetadata metadata);
+
+ void put(QueryMetadata metadata, List results);
+
+ /**
+ * Removes a single entry from cache.
+ */
+ void remove(QueryMetadata metadata);
+
+ /**
+ * Removes a group of entries identified by group key. This may not be
supported by
+ * the implementation.
+ */
+ void removeGroup(String groupKey);
+
+ int size();
+}
Added:
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/cache/QueryCacheFactory.java
URL:
http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/cache/QueryCacheFactory.java?rev=426241&view=auto
==============================================================================
---
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/cache/QueryCacheFactory.java
(added)
+++
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/cayenne/java/org/apache/cayenne/cache/QueryCacheFactory.java
Thu Jul 27 14:08:12 2006
@@ -0,0 +1,35 @@
+/*****************************************************************
+ * 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.Map;
+
+/**
+ * Creates QueryCache.
+ *
+ * @author Andrus Adamchik
+ * @since 3.0
+ */
+public interface QueryCacheFactory {
+
+ /**
+ * Creates a new instance of the QueryCache, configuring it using provided
properties.
+ */
+ QueryCache getQueryCache(Map properties);
+}
Modified:
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/tests/java/org/apache/cayenne/access/DataContextNamedQueryCachingTst.java
URL:
http://svn.apache.org/viewvc/incubator/cayenne/main/trunk/cayenne/cayenne-java/src/tests/java/org/apache/cayenne/access/DataContextNamedQueryCachingTst.java?rev=426241&r1=426240&r2=426241&view=diff
==============================================================================
---
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/tests/java/org/apache/cayenne/access/DataContextNamedQueryCachingTst.java
(original)
+++
incubator/cayenne/main/trunk/cayenne/cayenne-java/src/tests/java/org/apache/cayenne/access/DataContextNamedQueryCachingTst.java
Thu Jul 27 14:08:12 2006
@@ -23,7 +23,9 @@
import java.util.List;
import org.apache.art.Artist;
+import org.apache.cayenne.query.MockQueryMetadata;
import org.apache.cayenne.query.NamedQuery;
+import org.apache.cayenne.query.QueryMetadata;
import org.apache.cayenne.query.SQLTemplate;
import org.apache.cayenne.unit.CayenneTestCase;
@@ -80,12 +82,17 @@
DataContext context = createDataContext();
- String cacheKey = "ParameterizedQueryWithLocalCache";
+ QueryMetadata cacheKey = new MockQueryMetadata() {
- assertNull(context.getObjectStore().getCachedQueryResult(cacheKey));
+ public String getCacheKey() {
+ return "ParameterizedQueryWithLocalCache";
+ }
+ };
+
+ assertNull(context.getQueryCache().get(cacheKey));
context.performQuery("ParameterizedQueryWithLocalCache", false);
- Object cached =
context.getObjectStore().getCachedQueryResult(cacheKey);
+ Object cached = context.getQueryCache().get(cacheKey);
assertNotNull(
"Failed to cache results of a NamedQuery that points to a
caching query",
@@ -94,14 +101,14 @@
// get from cache
context.performQuery("ParameterizedQueryWithLocalCache", false);
- assertSame(cached,
context.getObjectStore().getCachedQueryResult(cacheKey));
+ assertSame(cached, context.getQueryCache().get(cacheKey));
// refresh
List fetchedCached1 = context.performQuery(
"ParameterizedQueryWithLocalCache",
true);
- Object cached1 =
context.getObjectStore().getCachedQueryResult(cacheKey);
+ Object cached1 = context.getQueryCache().get(cacheKey);
assertNotNull(
"Failed to cache results of refreshing NamedQuery that points
to a caching query",
cached1);