Author: doogie
Date: Thu Mar 11 18:59:34 2010
New Revision: 921990

URL: http://svn.apache.org/viewvc?rev=921990&view=rev
Log:
Fix bad caching.  Previously, any call to getDelegator() would *always*
walk the entire classpath, trying to find all implementations of
DelegatorFactory.  This was fixed by moving the cache higher up.

In detail, the entity caching system only stored a String delegator
name.  It would then try to find the appropriate delegator to match that
name.  However, during a custom importer, the caching system was being
exercised very heavily, so DelegatorFactory.getDelegator() was being
called in a very tight loop.  Since the delegator instances were not
being cached at the high level, this caused a *big* slowdown; basically,
a 15 minute importer was taking over 2 hours, and was no near finishing.
This was because UtilObject.getObjectFromFactory would end up walking
the entire classpath, finding every jar, looking at every zip entry, to
try and find the appropriate file in META-INF/services.

Modified:
    ofbiz/trunk/framework/entity/src/org/ofbiz/entity/DelegatorFactory.java
    ofbiz/trunk/framework/entity/src/org/ofbiz/entity/DelegatorFactoryImpl.java
    ofbiz/trunk/framework/entity/src/org/ofbiz/entity/GenericDelegator.java

Modified: 
ofbiz/trunk/framework/entity/src/org/ofbiz/entity/DelegatorFactory.java
URL: 
http://svn.apache.org/viewvc/ofbiz/trunk/framework/entity/src/org/ofbiz/entity/DelegatorFactory.java?rev=921990&r1=921989&r2=921990&view=diff
==============================================================================
--- ofbiz/trunk/framework/entity/src/org/ofbiz/entity/DelegatorFactory.java 
(original)
+++ ofbiz/trunk/framework/entity/src/org/ofbiz/entity/DelegatorFactory.java Thu 
Mar 11 18:59:34 2010
@@ -18,6 +18,8 @@
  */
 package org.ofbiz.entity;
 
+import java.util.concurrent.ConcurrentHashMap;
+
 import org.ofbiz.base.util.Debug;
 import org.ofbiz.base.util.Factory;
 import org.ofbiz.base.util.UtilObject;
@@ -25,13 +27,29 @@ import org.ofbiz.base.util.UtilObject;
 /** <code>Delegator</code> factory abstract class. */
 public abstract class DelegatorFactory implements Factory<Delegator, String> {
     public static final String module = DelegatorFactoryImpl.class.getName();
+    private static final ConcurrentHashMap<String, Delegator> delegatorCache = 
new ConcurrentHashMap<String, Delegator>();
 
     public static Delegator getDelegator(String delegatorName) {
-        try {
-            return UtilObject.getObjectFromFactory(DelegatorFactory.class, 
delegatorName);
-        } catch (ClassNotFoundException e) {
-            Debug.logError(e, module);
+        if (delegatorName == null) {
+            delegatorName = "default";
+            //Debug.logWarning(new Exception("Location where getting delegator 
with null name"), "Got a getGenericDelegator call with a null delegatorName, 
assuming default for the name.", module);
         }
-        return null;
+        do {
+            Delegator delegator = delegatorCache.get(delegatorName);
+
+            if (delegator != null) {
+                // setup the Entity ECA Handler
+                delegator.initEntityEcaHandler();
+                //Debug.logInfo("got delegator(" + delegatorName + ") from 
cache", module);
+                return delegator;
+            }
+            try {
+                delegator = 
UtilObject.getObjectFromFactory(DelegatorFactory.class, delegatorName);
+            } catch (ClassNotFoundException e) {
+                Debug.logError(e, module);
+            }
+            //Debug.logInfo("putting delegator(" + delegatorName + ") into 
cache", module);
+            delegatorCache.putIfAbsent(delegatorName, delegator);
+        } while (true);
     }
 }

Modified: 
ofbiz/trunk/framework/entity/src/org/ofbiz/entity/DelegatorFactoryImpl.java
URL: 
http://svn.apache.org/viewvc/ofbiz/trunk/framework/entity/src/org/ofbiz/entity/DelegatorFactoryImpl.java?rev=921990&r1=921989&r2=921990&view=diff
==============================================================================
--- ofbiz/trunk/framework/entity/src/org/ofbiz/entity/DelegatorFactoryImpl.java 
(original)
+++ ofbiz/trunk/framework/entity/src/org/ofbiz/entity/DelegatorFactoryImpl.java 
Thu Mar 11 18:59:34 2010
@@ -27,32 +27,13 @@ public class DelegatorFactoryImpl extend
     public static final String module = DelegatorFactoryImpl.class.getName();
 
     public Delegator getInstance(String delegatorName) {
-        if (delegatorName == null) {
-            delegatorName = "default";
-            Debug.logWarning(new Exception("Location where getting delegator 
with null name"), "Got a getGenericDelegator call with a null delegatorName, 
assuming default for the name.", module);
+        if (Debug.infoOn()) Debug.logInfo("Creating new delegator [" + 
delegatorName + "] (" + Thread.currentThread().getName() + ")", module);
+        //Debug.logInfo(new Exception(), "Showing stack where new delegator is 
being created...", module);
+        try {
+            return new GenericDelegator(delegatorName);
+        } catch (GenericEntityException e) {
+            Debug.logError(e, "Error creating delegator", module);
+            return null;
         }
-        GenericDelegator delegator = 
GenericDelegator.delegatorCache.get(delegatorName);
-        if (delegator == null) {
-            synchronized (GenericDelegator.delegatorCache) {
-                // must check if null again as one of the blocked threads can 
still enter
-                delegator = GenericDelegator.delegatorCache.get(delegatorName);
-                if (delegator == null) {
-                    if (Debug.infoOn()) Debug.logInfo("Creating new delegator 
[" + delegatorName + "] (" + Thread.currentThread().getName() + ")", module);
-                    //Debug.logInfo(new Exception(), "Showing stack where new 
delegator is being created...", module);
-                    try {
-                        delegator = new GenericDelegator(delegatorName);
-                    } catch (GenericEntityException e) {
-                        Debug.logError(e, "Error creating delegator", module);
-                    }
-                    if (delegator != null) {
-                        GenericDelegator.delegatorCache.put(delegatorName, 
delegator);
-                    } else {
-                        Debug.logError("Could not create delegator with name " 
+ delegatorName + ", constructor failed (got null value) not sure why/how.", 
module);
-                    }
-                }
-            }
-        }
-        return delegator;
     }
-
 }

Modified: 
ofbiz/trunk/framework/entity/src/org/ofbiz/entity/GenericDelegator.java
URL: 
http://svn.apache.org/viewvc/ofbiz/trunk/framework/entity/src/org/ofbiz/entity/GenericDelegator.java?rev=921990&r1=921989&r2=921990&view=diff
==============================================================================
--- ofbiz/trunk/framework/entity/src/org/ofbiz/entity/GenericDelegator.java 
(original)
+++ ofbiz/trunk/framework/entity/src/org/ofbiz/entity/GenericDelegator.java Thu 
Mar 11 18:59:34 2010
@@ -95,9 +95,6 @@ public class GenericDelegator implements
     /** This flag is only here for lower level technical testing, it shouldn't 
be user configurable (or at least I don't think so yet); when true all 
operations without a transaction will be wrapped in one; seems to be necessary 
for some (all?) XA aware connection pools, and should improve overall stability 
and consistency */
     public static final boolean alwaysUseTransaction = true;
 
-    /** the delegatorCache will now be a HashMap, allowing reload of 
definitions,
-     * but the delegator will always be the same object for the given name */
-    public static Map<String, GenericDelegator> delegatorCache = 
FastMap.newInstance();
     protected String delegatorName = null;
     protected DelegatorInfo delegatorInfo = null;
 
@@ -274,8 +271,6 @@ public class GenericDelegator implements
         }
 
         // NOTE: doing some things before the ECAs and such to make sure it is 
in place just in case it is used in a service engine startup thing or something
-        // put the delegator in the master Map by its name
-        GenericDelegator.delegatorCache.put(delegatorName, this);
 
         // setup the crypto class
         this.crypto = new EntityCrypto(this);
@@ -306,15 +301,15 @@ public class GenericDelegator implements
         } else {
             Debug.logInfo("Distributed Cache Clear System disabled for 
delegator [" + delegatorName + "]", module);
         }
-
-        // setup the Entity ECA Handler
-        initEntityEcaHandler();
     }
 
     /* (non-Javadoc)
      * @see org.ofbiz.entity.Delegator#initEntityEcaHandler()
      */
-    public void initEntityEcaHandler() {
+    public synchronized void initEntityEcaHandler() {
+        if (!getDelegatorInfo().useEntityEca || this.entityEcaHandler != null) 
{
+            return;
+        }
         if (getDelegatorInfo().useEntityEca) {
             ClassLoader loader = 
Thread.currentThread().getContextClassLoader();
             // initialize the entity eca handler


Reply via email to