OPENJPA-437

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@615316 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Patrick Linskey 2008-01-25 19:41:47 +00:00
parent d4454e5a1f
commit 2a45dc5929
1 changed files with 16 additions and 11 deletions

View File

@ -97,6 +97,7 @@ public abstract class AbstractBrokerFactory
// that we can re-load them for each new broker // that we can re-load them for each new broker
private transient Collection _pcClassNames = null; private transient Collection _pcClassNames = null;
private transient Collection _pcClassLoaders = null; private transient Collection _pcClassLoaders = null;
private transient boolean _persistentTypesLoaded = false;
// lifecycle listeners to pass to each broker // lifecycle listeners to pass to each broker
private transient Map _lifecycleListeners = null; private transient Map _lifecycleListeners = null;
@ -256,28 +257,31 @@ public abstract class AbstractBrokerFactory
/** /**
* Load the configured persistent classes list. Performed automatically * Load the configured persistent classes list. Performed automatically
* whenever a broker is created. * whenever a broker is created.
*
* This method is synchronized due to the possible creation of new brokers
* (entity managers) by multiple threads (clients). The two data structures
* used by this method (_pcClassNames and _pcClassLoaders) are not thread
* safe and this was an easy, efficient solution (OPENJPA-437).
*/ */
private synchronized void loadPersistentTypes(ClassLoader envLoader) { private void loadPersistentTypes(ClassLoader envLoader) {
// no listed persistent types? // if we've loaded the persistent types and the class name list
if (_pcClassNames != null && _pcClassNames.isEmpty()) // is empty, then we can simply return. Note that there is a
// potential threading scenario in which _persistentTypesLoaded is
// false when read, but the work to populate _pcClassNames has
// already been done. This is ok; _pcClassNames can tolerate
// concurrent access, so the worst case is that the list is
// persistent type data is processed multiple times, which this
// algorithm takes into account.
if (_persistentTypesLoaded && _pcClassNames.isEmpty())
return; return;
// cache persistent type names if not already // cache persistent type names if not already
ClassLoader loader = _conf.getClassResolverInstance(). ClassLoader loader = _conf.getClassResolverInstance().
getClassLoader(getClass(), envLoader); getClassLoader(getClass(), envLoader);
Collection toRedefine = new ArrayList(); Collection toRedefine = new ArrayList();
if (_pcClassNames == null) { if (!_persistentTypesLoaded) {
Collection clss = _conf.getMetaDataRepositoryInstance(). Collection clss = _conf.getMetaDataRepositoryInstance().
loadPersistentTypes(false, loader); loadPersistentTypes(false, loader);
if (clss.isEmpty()) if (clss.isEmpty())
_pcClassNames = Collections.EMPTY_LIST; _pcClassNames = Collections.EMPTY_SET;
else { else {
_pcClassNames = new ArrayList(clss.size()); _pcClassNames = new ConcurrentReferenceHashSet(
ConcurrentReferenceHashSet.HARD);
for (Iterator itr = clss.iterator(); itr.hasNext();) { for (Iterator itr = clss.iterator(); itr.hasNext();) {
Class cls = (Class) itr.next(); Class cls = (Class) itr.next();
_pcClassNames.add(cls.getName()); _pcClassNames.add(cls.getName());
@ -286,6 +290,7 @@ public abstract class AbstractBrokerFactory
} }
_pcClassLoaders.add(loader); _pcClassLoaders.add(loader);
} }
_persistentTypesLoaded = true;
} else { } else {
// reload with this loader // reload with this loader
if (_pcClassLoaders.add(loader)) { if (_pcClassLoaders.add(loader)) {