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 2013/06/22 19:23:56 UTC
svn commit: r1495760 - in
/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map:
DefaultMappingCache.java EntityResolver.java MappingCache.java
ProxiedMappingCache.java
Author: aadamchik
Date: Sat Jun 22 17:23:55 2013
New Revision: 1495760
URL: http://svn.apache.org/r1495760
Log:
CAY-1789 Lock-free EntityResolver
adding a proxy wrapper for lazy initialization
Added:
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/DefaultMappingCache.java
- copied, changed from r1495759, cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/MappingCache.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ProxiedMappingCache.java
Modified:
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/EntityResolver.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/MappingCache.java
Copied: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/DefaultMappingCache.java (from r1495759, cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/MappingCache.java)
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/DefaultMappingCache.java?p2=cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/DefaultMappingCache.java&p1=cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/MappingCache.java&r1=1495759&r2=1495760&rev=1495760&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/MappingCache.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/DefaultMappingCache.java Sat Jun 22 17:23:55 2013
@@ -30,11 +30,11 @@ import org.apache.commons.logging.LogFac
/**
* @since 3.2
*/
-class MappingCache {
+class DefaultMappingCache implements MappingCache {
private static final ObjEntity OBJ_DUPLICATE_MARKER = new ObjEntity();
- protected static final Log logger = LogFactory.getLog(MappingCache.class);
+ protected static final Log logger = LogFactory.getLog(DefaultMappingCache.class);
protected Map<String, Query> queryCache;
protected Map<String, Embeddable> embeddableCache;
@@ -44,7 +44,7 @@ class MappingCache {
protected Map<String, Procedure> procedureCache;
protected Map<String, EntityInheritanceTree> entityInheritanceCache;
- MappingCache(Collection<DataMap> maps) {
+ DefaultMappingCache(Collection<DataMap> maps) {
this.embeddableCache = new HashMap<String, Embeddable>();
this.queryCache = new HashMap<String, Query>();
this.dbEntityCache = new HashMap<String, DbEntity>();
@@ -163,35 +163,35 @@ class MappingCache {
return "^cl^" + className;
}
- Embeddable getEmbeddable(String className) {
+ public Embeddable getEmbeddable(String className) {
return embeddableCache.get(className);
}
- SQLResult getResult(String name) {
+ public SQLResult getResult(String name) {
return resultsCache.get(name);
}
- EntityInheritanceTree getInheritanceTree(String entityName) {
+ public EntityInheritanceTree getInheritanceTree(String entityName) {
return entityInheritanceCache.get(entityName);
}
- Procedure getProcedure(String procedureName) {
+ public Procedure getProcedure(String procedureName) {
return procedureCache.get(procedureName);
}
- Query getQuery(String queryName) {
+ public Query getQuery(String queryName) {
return queryCache.get(queryName);
}
- DbEntity getDbEntity(String name) {
+ public DbEntity getDbEntity(String name) {
return dbEntityCache.get(name);
}
- ObjEntity getObjEntity(Class<?> entityClass) {
+ public ObjEntity getObjEntity(Class<?> entityClass) {
return getObjEntity(classKey(entityClass.getName()));
}
- ObjEntity getObjEntity(String name) {
+ public ObjEntity getObjEntity(String name) {
ObjEntity entity = objEntityCache.get(name);
if (entity == OBJ_DUPLICATE_MARKER) {
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/EntityResolver.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/EntityResolver.java?rev=1495760&r1=1495759&r2=1495760&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/EntityResolver.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/EntityResolver.java Sat Jun 22 17:23:55 2013
@@ -60,7 +60,7 @@ public class EntityResolver implements M
protected boolean indexedByClass;
protected Collection<DataMap> maps;
- protected transient MappingCache entityCache;
+ protected transient MappingCache mappingCache;
protected EntityResolver clientEntityResolver;
// must be transient, as resolver may get deserialized in another VM, and
@@ -379,24 +379,24 @@ public class EntityResolver implements M
}
public DbEntity getDbEntity(String name) {
- DbEntity result = entityCache.getDbEntity(name);
+ DbEntity result = mappingCache.getDbEntity(name);
if (result == null) {
// reconstruct cache just in case some of the datamaps
// have changed and now contain the required information
refreshMappingCache();
- result = entityCache.getDbEntity(name);
+ result = mappingCache.getDbEntity(name);
}
return result;
}
public ObjEntity getObjEntity(String name) {
- ObjEntity result = entityCache.getObjEntity(name);
+ ObjEntity result = mappingCache.getObjEntity(name);
if (result == null) {
// reconstruct cache just in case some of the datamaps
// have changed and now contain the required information
refreshMappingCache();
- result = entityCache.getObjEntity(name);
+ result = mappingCache.getObjEntity(name);
}
return result;
@@ -414,13 +414,13 @@ public class EntityResolver implements M
* @since 3.0
*/
public Embeddable getEmbeddable(String className) {
- Embeddable result = entityCache.getEmbeddable(className);
+ Embeddable result = mappingCache.getEmbeddable(className);
if (result == null) {
// reconstruct cache just in case some of the datamaps
// have changed and now contain the required information
refreshMappingCache();
- result = entityCache.getEmbeddable(className);
+ result = mappingCache.getEmbeddable(className);
}
return result;
@@ -430,13 +430,13 @@ public class EntityResolver implements M
* @since 3.0
*/
public SQLResult getResult(String name) {
- SQLResult result = entityCache.getResult(name);
+ SQLResult result = mappingCache.getResult(name);
if (result == null) {
// reconstruct cache just in case some of the datamaps
// have changed and now contain the required information
refreshMappingCache();
- result = entityCache.getResult(name);
+ result = mappingCache.getResult(name);
}
return result;
@@ -481,7 +481,14 @@ public class EntityResolver implements M
* @since 3.2
*/
public void refreshMappingCache() {
- entityCache = new MappingCache(maps);
+ mappingCache = new ProxiedMappingCache() {
+
+ @Override
+ protected MappingCache createDelegate() {
+ return new DefaultMappingCache(maps);
+ }
+ };
+
clientEntityResolver = null;
}
@@ -525,7 +532,7 @@ public class EntityResolver implements M
*/
public EntityInheritanceTree lookupInheritanceTree(String entityName) {
- EntityInheritanceTree tree = entityCache.getInheritanceTree(entityName);
+ EntityInheritanceTree tree = mappingCache.getInheritanceTree(entityName);
if (tree == null) {
// since we keep inheritance trees for all entities, null means
@@ -534,7 +541,7 @@ public class EntityResolver implements M
// rebuild cache just in case some of the datamaps
// have changed and now contain the required information
refreshMappingCache();
- tree = entityCache.getInheritanceTree(entityName);
+ tree = mappingCache.getInheritanceTree(entityName);
}
return tree;
@@ -548,12 +555,12 @@ public class EntityResolver implements M
* specifier
*/
public ObjEntity lookupObjEntity(Class<?> aClass) {
- ObjEntity result = entityCache.getObjEntity(aClass);
+ ObjEntity result = mappingCache.getObjEntity(aClass);
if (result == null) {
// reconstruct cache just in case some of the datamaps
// have changed and now contain the required information
refreshMappingCache();
- result = entityCache.getObjEntity(aClass);
+ result = mappingCache.getObjEntity(aClass);
}
return result;
@@ -588,12 +595,12 @@ public class EntityResolver implements M
public Procedure lookupProcedure(String procedureName) {
- Procedure result = entityCache.getProcedure(procedureName);
+ Procedure result = mappingCache.getProcedure(procedureName);
if (result == null) {
// reconstruct cache just in case some of the datamaps
// have changed and now contain the required information
refreshMappingCache();
- result = entityCache.getProcedure(procedureName);
+ result = mappingCache.getProcedure(procedureName);
}
return result;
@@ -603,13 +610,13 @@ public class EntityResolver implements M
* Returns a named query or null if no query exists for a given name.
*/
public Query lookupQuery(String name) {
- Query result = entityCache.getQuery(name);
+ Query result = mappingCache.getQuery(name);
if (result == null) {
// reconstruct cache just in case some of the datamaps
// have changed and now contain the required information
refreshMappingCache();
- result = entityCache.getQuery(name);
+ result = mappingCache.getQuery(name);
}
return result;
}
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/MappingCache.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/MappingCache.java?rev=1495760&r1=1495759&r2=1495760&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/MappingCache.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/MappingCache.java Sat Jun 22 17:23:55 2013
@@ -18,187 +18,23 @@
****************************************************************/
package org.apache.cayenne.map;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.query.Query;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-/**
- * @since 3.2
- */
-class MappingCache {
-
- private static final ObjEntity OBJ_DUPLICATE_MARKER = new ObjEntity();
-
- protected static final Log logger = LogFactory.getLog(MappingCache.class);
-
- protected Map<String, Query> queryCache;
- protected Map<String, Embeddable> embeddableCache;
- protected Map<String, SQLResult> resultsCache;
- protected Map<String, DbEntity> dbEntityCache;
- protected Map<String, ObjEntity> objEntityCache;
- protected Map<String, Procedure> procedureCache;
- protected Map<String, EntityInheritanceTree> entityInheritanceCache;
-
- MappingCache(Collection<DataMap> maps) {
- this.embeddableCache = new HashMap<String, Embeddable>();
- this.queryCache = new HashMap<String, Query>();
- this.dbEntityCache = new HashMap<String, DbEntity>();
- this.objEntityCache = new HashMap<String, ObjEntity>();
- this.procedureCache = new HashMap<String, Procedure>();
- this.entityInheritanceCache = new HashMap<String, EntityInheritanceTree>();
- this.resultsCache = new HashMap<String, SQLResult>();
-
- index(maps);
- }
-
- private void index(Collection<DataMap> maps) {
-
- // index DbEntities separately and before ObjEntities to avoid infinite
- // loops when looking up DbEntities during ObjEntity index op
-
- for (DataMap map : maps) {
- for (DbEntity de : map.getDbEntities()) {
- dbEntityCache.put(de.getName(), de);
- }
- }
-
- for (DataMap map : maps) {
-
- // index ObjEntities
- for (ObjEntity oe : map.getObjEntities()) {
-
- // index by name
- objEntityCache.put(oe.getName(), oe);
-
- // index by class.. use class name as a key to avoid class
- // loading here...
- String className = oe.getJavaClassName();
- if (className == null) {
- continue;
- }
-
- String classKey = classKey(className);
-
- // allow duplicates, but put a special marker indicating
- // that this entity can't be looked up by class
- Object existing = objEntityCache.get(classKey);
- if (existing != null) {
-
- if (existing != OBJ_DUPLICATE_MARKER) {
- objEntityCache.put(classKey, OBJ_DUPLICATE_MARKER);
- }
- } else {
- objEntityCache.put(classKey, oe);
- }
- }
-
- // index stored procedures
- for (Procedure proc : map.getProcedures()) {
- procedureCache.put(proc.getName(), proc);
- }
-
- // index embeddables
- embeddableCache.putAll(map.getEmbeddableMap());
-
- // index queries
- for (Query query : map.getQueries()) {
- String name = query.getName();
- Object existingQuery = queryCache.put(name, query);
-
- if (existingQuery != null && query != existingQuery) {
- throw new CayenneRuntimeException("More than one Query for name" + name);
- }
- }
- }
-
- // restart the map iterator to index inheritance
- for (DataMap map : maps) {
-
- // index ObjEntity inheritance
- for (ObjEntity oe : map.getObjEntities()) {
-
- // build inheritance tree
- EntityInheritanceTree node = entityInheritanceCache.get(oe.getName());
- if (node == null) {
- node = new EntityInheritanceTree(oe);
- entityInheritanceCache.put(oe.getName(), node);
- }
-
- String superOEName = oe.getSuperEntityName();
- if (superOEName != null) {
- EntityInheritanceTree superNode = entityInheritanceCache.get(superOEName);
-
- if (superNode == null) {
- // do direct entity lookup to avoid recursive cache
- // rebuild
- ObjEntity superOE = objEntityCache.get(superOEName);
- if (superOE != null) {
- superNode = new EntityInheritanceTree(superOE);
- entityInheritanceCache.put(superOEName, superNode);
- } else {
- // bad mapping? Or most likely some classloader
- // issue
- logger.warn("No super entity mapping for '" + superOEName + "'");
- continue;
- }
- }
-
- superNode.addChildNode(node);
- }
- }
- }
- }
-
- /**
- * Generates a map key for the object class.
- */
- private String classKey(String className) {
- // need to ensure that there is no conflict with entity names... I guess
- // such prefix is enough to guarantee that:
- return "^cl^" + className;
- }
-
- Embeddable getEmbeddable(String className) {
- return embeddableCache.get(className);
- }
-
- SQLResult getResult(String name) {
- return resultsCache.get(name);
- }
-
- EntityInheritanceTree getInheritanceTree(String entityName) {
- return entityInheritanceCache.get(entityName);
- }
-
- Procedure getProcedure(String procedureName) {
- return procedureCache.get(procedureName);
- }
-
- Query getQuery(String queryName) {
- return queryCache.get(queryName);
- }
-
- DbEntity getDbEntity(String name) {
- return dbEntityCache.get(name);
- }
-
- ObjEntity getObjEntity(Class<?> entityClass) {
- return getObjEntity(classKey(entityClass.getName()));
- }
-
- ObjEntity getObjEntity(String name) {
- ObjEntity entity = objEntityCache.get(name);
-
- if (entity == OBJ_DUPLICATE_MARKER) {
- throw new CayenneRuntimeException("Can't perform lookup. There is more than one ObjEntity mapped to "
- + name);
- }
+interface MappingCache {
+
+ Embeddable getEmbeddable(String className);
+
+ SQLResult getResult(String name);
+
+ EntityInheritanceTree getInheritanceTree(String entityName);
+
+ Procedure getProcedure(String procedureName);
+
+ Query getQuery(String queryName);
+
+ DbEntity getDbEntity(String name);
+
+ ObjEntity getObjEntity(Class<?> entityClass);
- return entity;
- }
+ ObjEntity getObjEntity(String name);
}
Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ProxiedMappingCache.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ProxiedMappingCache.java?rev=1495760&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ProxiedMappingCache.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ProxiedMappingCache.java Sat Jun 22 17:23:55 2013
@@ -0,0 +1,78 @@
+/*****************************************************************
+ * 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.map;
+
+import org.apache.cayenne.query.Query;
+
+/**
+ * A proxy for lazy on-demand initialization of the mapping cache.
+ */
+abstract class ProxiedMappingCache implements MappingCache {
+
+ private volatile MappingCache delegate;
+
+ MappingCache getDelegate() {
+
+ if (delegate == null) {
+
+ synchronized (this) {
+ if (delegate == null) {
+ delegate = createDelegate();
+ }
+ }
+ }
+
+ return delegate;
+ }
+
+ protected abstract MappingCache createDelegate();
+
+ public Embeddable getEmbeddable(String className) {
+ return getDelegate().getEmbeddable(className);
+ }
+
+ public SQLResult getResult(String name) {
+ return getDelegate().getResult(name);
+ }
+
+ public EntityInheritanceTree getInheritanceTree(String entityName) {
+ return getDelegate().getInheritanceTree(entityName);
+ }
+
+ public Procedure getProcedure(String procedureName) {
+ return getDelegate().getProcedure(procedureName);
+ }
+
+ public Query getQuery(String queryName) {
+ return getDelegate().getQuery(queryName);
+ }
+
+ public DbEntity getDbEntity(String name) {
+ return getDelegate().getDbEntity(name);
+ }
+
+ public ObjEntity getObjEntity(Class<?> entityClass) {
+ return getDelegate().getObjEntity(entityClass);
+ }
+
+ public ObjEntity getObjEntity(String name) {
+ return getDelegate().getObjEntity(name);
+ }
+
+}