summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCaspar De Groot2010-01-06 06:47:50 (EST)
committerCaspar De Groot2010-01-06 06:47:50 (EST)
commit7a4162227fcbb24404cd79cd8ac7f00f684feffb (patch)
tree59b554d4b826677a8cd55acd452965cbe1213ca4
parenta07837e5b1a420823850f1ec05817e0b8232eca5 (diff)
downloadcdo-7a4162227fcbb24404cd79cd8ac7f00f684feffb.zip
cdo-7a4162227fcbb24404cd79cd8ac7f00f684feffb.tar.gz
cdo-7a4162227fcbb24404cd79cd8ac7f00f684feffb.tar.bz2
[296100] [DB] AbstractMappingStrategy.createClassMapping can be invoked concurrently
https://bugs.eclipse.org/bugs/show_bug.cgi?id=296100
-rw-r--r--plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/AbstractMappingStrategy.java32
1 files changed, 22 insertions, 10 deletions
diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/AbstractMappingStrategy.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/AbstractMappingStrategy.java
index 9c7541e..477c5e1 100644
--- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/AbstractMappingStrategy.java
+++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/AbstractMappingStrategy.java
@@ -59,6 +59,8 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
/**
* This abstract base class implements those methods which are most likely common to most mapping strategies. It can be
@@ -84,11 +86,11 @@ public abstract class AbstractMappingStrategy extends Lifecycle implements IMapp
private Map<String, String> properties;
- private Map<EClass, IClassMapping> classMappings;
+ private ConcurrentMap<EClass, IClassMapping> classMappings;
public AbstractMappingStrategy()
{
- classMappings = new HashMap<EClass, IClassMapping>();
+ classMappings = new ConcurrentHashMap<EClass, IClassMapping>();
}
// -- property related methods -----------------------------------------
@@ -346,7 +348,7 @@ public abstract class AbstractMappingStrategy extends Lifecycle implements IMapp
if (!(eClass.isInterface() || eClass.isAbstract()))
{
String mapping = DBAnnotation.TABLE_MAPPING.getValue(eClass);
-
+
// TODO Maybe we should explicitly report unknown values of the annotation
if (mapping == null || !mapping.equalsIgnoreCase(DBAnnotation.TABLE_MAPPING_NONE))
{
@@ -400,16 +402,26 @@ public abstract class AbstractMappingStrategy extends Lifecycle implements IMapp
public final IClassMapping getClassMapping(EClass eClass)
{
+ // Try without synchronization first; this will almost always succeed, so it avoids the
+ // performance penalty of syncing in the majority of cases
IClassMapping result = classMappings.get(eClass);
- if (result != null)
+ if (result == null)
{
- return result;
- }
- else
- {
- // create class mapping on demand ...
- return createClassMapping(eClass);
+ // Synchronize on the classMappings to prevent concurrent invocations of createClassMapping
+ // (Synchronizing on the eClass allows for more concurrency, but is risky because application
+ // code may be syncing on the eClass also.)
+ synchronized (classMappings)
+ {
+ // Check again, because other thread may have just added the mapping
+ result = classMappings.get(eClass);
+ if (result == null)
+ {
+ result = createClassMapping(eClass);
+ }
+ }
}
+
+ return result;
}
public ITypeMapping createValueMapping(EStructuralFeature feature)