You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by st...@apache.org on 2006/12/15 17:14:53 UTC

svn commit: r487589 - /jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java

Author: stefan
Date: Fri Dec 15 08:14:53 2006
New Revision: 487589

URL: http://svn.apache.org/viewvc?view=rev&rev=487589
Log:
reduced potential lock contention

Modified:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java?view=diff&rev=487589&r1=487588&r2=487589
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java Fri Dec 15 08:14:53 2006
@@ -48,6 +48,8 @@
 import java.util.Set;
 import java.util.Stack;
 
+import EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap;
+
 /**
  * A <code>NodeTypeRegistry</code> ...
  */
@@ -77,15 +79,15 @@
     private final EffectiveNodeTypeCache entCache;
 
     // map of node type names and node type definitions
-    private final HashMap registeredNTDefs;
+    private final ConcurrentReaderHashMap registeredNTDefs;
 
     // definition of the root node
     private final NodeDef rootNodeDef;
 
     // map of id's and property definitions
-    private final HashMap propDefs;
+    private final ConcurrentReaderHashMap propDefs;
     // map of id's and node definitions
-    private final HashMap nodeDefs;
+    private final ConcurrentReaderHashMap nodeDefs;
 
     /**
      * namespace registry for resolving prefixes and namespace URI's;
@@ -125,7 +127,7 @@
      *
      * @return the names of all registered node types.
      */
-    public synchronized QName[] getRegisteredNodeTypes() {
+    public QName[] getRegisteredNodeTypes() {
         return (QName[]) registeredNTDefs.keySet().toArray(new QName[registeredNTDefs.size()]);
     }
 
@@ -299,7 +301,7 @@
      * @throws RepositoryException if another error occurs.
      * @see #unregisterNodeTypes(Collection)
      */
-    public synchronized void unregisterNodeType(QName ntName)
+    public void unregisterNodeType(QName ntName)
             throws NoSuchNodeTypeException, RepositoryException {
         HashSet ntNames = new HashSet();
         ntNames.add(ntName);
@@ -387,7 +389,7 @@
      * @return
      * @throws NoSuchNodeTypeException
      */
-    public synchronized EffectiveNodeType getEffectiveNodeType(QName ntName)
+    public EffectiveNodeType getEffectiveNodeType(QName ntName)
             throws NoSuchNodeTypeException {
         return getEffectiveNodeType(ntName, entCache, registeredNTDefs);
     }
@@ -398,7 +400,7 @@
      * @throws NodeTypeConflictException
      * @throws NoSuchNodeTypeException
      */
-    public synchronized EffectiveNodeType getEffectiveNodeType(QName[] ntNames)
+    public EffectiveNodeType getEffectiveNodeType(QName[] ntNames)
             throws NodeTypeConflictException, NoSuchNodeTypeException {
         return getEffectiveNodeType(ntNames, entCache, registeredNTDefs);
     }
@@ -411,7 +413,7 @@
      * @return a set of node type <code>QName</code>s
      * @throws NoSuchNodeTypeException
      */
-    public synchronized Set getDependentNodeTypes(QName nodeTypeName)
+    public Set getDependentNodeTypes(QName nodeTypeName)
             throws NoSuchNodeTypeException {
         if (!registeredNTDefs.containsKey(nodeTypeName)) {
             throw new NoSuchNodeTypeException(nodeTypeName.toString());
@@ -440,12 +442,12 @@
      * @throws NoSuchNodeTypeException if a node type with the given name
      *                                 does not exist
      */
-    public synchronized NodeTypeDef getNodeTypeDef(QName nodeTypeName)
+    public NodeTypeDef getNodeTypeDef(QName nodeTypeName)
             throws NoSuchNodeTypeException {
-        if (!registeredNTDefs.containsKey(nodeTypeName)) {
+        NodeTypeDef def = (NodeTypeDef) registeredNTDefs.get(nodeTypeName);
+        if (def == null) {
             throw new NoSuchNodeTypeException(nodeTypeName.toString());
         }
-        NodeTypeDef def = (NodeTypeDef) registeredNTDefs.get(nodeTypeName);
         // return clone to make sure nobody messes around with the 'live' definition
         return (NodeTypeDef) def.clone();
     }
@@ -455,17 +457,16 @@
      * @return <code>true</code> if the specified node type is registered;
      *         <code>false</code> otherwise.
      */
-    public synchronized boolean isRegistered(QName nodeTypeName) {
+    public boolean isRegistered(QName nodeTypeName) {
         return registeredNTDefs.containsKey(nodeTypeName);
     }
 
-
     /**
      * @param nodeTypeName
      * @return <code>true</code> if the specified node type is built-in;
      *         <code>false</code> otherwise.
      */
-    public synchronized boolean isBuiltIn(QName nodeTypeName) {
+    public boolean isBuiltIn(QName nodeTypeName) {
         return builtInNTDefs.contains(nodeTypeName);
     }
 
@@ -643,9 +644,9 @@
         }
 
         entCache = new EffectiveNodeTypeCache();
-        registeredNTDefs = new HashMap();
-        propDefs = new HashMap();
-        nodeDefs = new HashMap();
+        registeredNTDefs = new ConcurrentReaderHashMap();
+        propDefs = new ConcurrentReaderHashMap();
+        nodeDefs = new ConcurrentReaderHashMap();
 
         // setup definition of root node
         rootNodeDef = createRootNodeDef();
@@ -918,8 +919,8 @@
      *                                 could not be resolved.
      */
     static EffectiveNodeType getEffectiveNodeType(QName ntName,
-                                                         EffectiveNodeTypeCache entCache,
-                                                         Map ntdCache)
+                                                  EffectiveNodeTypeCache entCache,
+                                                  Map ntdCache)
             throws NoSuchNodeTypeException {
         // 1. check if effective node type has already been built
         EffectiveNodeType ent = entCache.get(new QName[]{ntName});
@@ -928,22 +929,24 @@
         }
 
         // 2. make sure we've got the definition of the specified node type
-        if (!ntdCache.containsKey(ntName)) {
+        NodeTypeDef ntd = (NodeTypeDef) ntdCache.get(ntName);
+        if (ntd == null) {
             throw new NoSuchNodeTypeException(ntName.toString());
         }
 
         // 3. build effective node type
-        try {
-            NodeTypeDef ntd = (NodeTypeDef) ntdCache.get(ntName);
-            ent = EffectiveNodeType.create(ntd, entCache, ntdCache);
-            // store new effective node type
-            entCache.put(ent);
-            return ent;
-        } catch (NodeTypeConflictException ntce) {
-            // should never get here as all known node types should be valid!
-            String msg = "internal error: encountered invalid registered node type " + ntName;
-            log.debug(msg);
-            throw new NoSuchNodeTypeException(msg, ntce);
+        synchronized (entCache) {
+            try {
+                ent = EffectiveNodeType.create(ntd, entCache, ntdCache);
+                // store new effective node type
+                entCache.put(ent);
+                return ent;
+            } catch (NodeTypeConflictException ntce) {
+                // should never get here as all known node types should be valid!
+                String msg = "internal error: encountered invalid registered node type " + ntName;
+                log.debug(msg);
+                throw new NoSuchNodeTypeException(msg, ntce);
+            }
         }
     }
 
@@ -961,8 +964,8 @@
      *                                 could not be resolved.
      */
     static EffectiveNodeType getEffectiveNodeType(QName[] ntNames,
-                                                         EffectiveNodeTypeCache entCache,
-                                                         Map ntdCache)
+                                                  EffectiveNodeTypeCache entCache,
+                                                  Map ntdCache)
             throws NodeTypeConflictException, NoSuchNodeTypeException {
 
         EffectiveNodeTypeCache.WeightedKey key =
@@ -982,72 +985,73 @@
 
         // 3. build aggregate
         EffectiveNodeType result = null;
-
-        // build list of 'best' existing sub-aggregates
-        ArrayList tmpResults = new ArrayList();
-        while (key.getNames().length > 0) {
-            // check if we've already built this aggregate
-            if (entCache.contains(key)) {
-                tmpResults.add(entCache.get(key));
-                // subtract the result from the temporary key
-                // (which is 'empty' now)
-                key = key.subtract(key);
-                break;
-            }
-            /**
-             * walk list of existing aggregates sorted by 'weight' of
-             * aggregate (i.e. the cost of building it)
-             */
-            boolean foundSubResult = false;
-            Iterator iter = entCache.keyIterator();
-            while (iter.hasNext()) {
-                EffectiveNodeTypeCache.WeightedKey k =
-                        (EffectiveNodeTypeCache.WeightedKey) iter.next();
-                /**
-                 * check if the existing aggregate is a 'subset' of the one
-                 * we're looking for
-                 */
-                if (key.contains(k)) {
-                    tmpResults.add(entCache.get(k));
+        synchronized (entCache) {
+            // build list of 'best' existing sub-aggregates
+            ArrayList tmpResults = new ArrayList();
+            while (key.getNames().length > 0) {
+                // check if we've already built this aggregate
+                if (entCache.contains(key)) {
+                    tmpResults.add(entCache.get(key));
                     // subtract the result from the temporary key
-                    key = key.subtract(k);
-                    foundSubResult = true;
+                    // (which is 'empty' now)
+                    key = key.subtract(key);
                     break;
                 }
-            }
-            if (!foundSubResult) {
                 /**
-                 * no matching sub-aggregates found:
-                 * build aggregate of remaining node types through iteration
+                 * walk list of existing aggregates sorted by 'weight' of
+                 * aggregate (i.e. the cost of building it)
                  */
-                QName[] remainder = key.getNames();
-                for (int i = 0; i < remainder.length; i++) {
-                    NodeTypeDef ntd = (NodeTypeDef) ntdCache.get(remainder[i]);
-                    EffectiveNodeType ent =
-                            EffectiveNodeType.create(ntd, entCache, ntdCache);
-                    // store new effective node type
-                    entCache.put(ent);
-                    if (result == null) {
-                        result = ent;
-                    } else {
-                        result = result.merge(ent);
-                        // store intermediate result (sub-aggregate)
-                        entCache.put(result);
+                boolean foundSubResult = false;
+                Iterator iter = entCache.keyIterator();
+                while (iter.hasNext()) {
+                    EffectiveNodeTypeCache.WeightedKey k =
+                            (EffectiveNodeTypeCache.WeightedKey) iter.next();
+                    /**
+                     * check if the existing aggregate is a 'subset' of the one
+                     * we're looking for
+                     */
+                    if (key.contains(k)) {
+                        tmpResults.add(entCache.get(k));
+                        // subtract the result from the temporary key
+                        key = key.subtract(k);
+                        foundSubResult = true;
+                        break;
                     }
                 }
-                // add aggregate of remaining node types to result list
-                tmpResults.add(result);
-                break;
+                if (!foundSubResult) {
+                    /**
+                     * no matching sub-aggregates found:
+                     * build aggregate of remaining node types through iteration
+                     */
+                    QName[] remainder = key.getNames();
+                    for (int i = 0; i < remainder.length; i++) {
+                        NodeTypeDef ntd = (NodeTypeDef) ntdCache.get(remainder[i]);
+                        EffectiveNodeType ent =
+                                EffectiveNodeType.create(ntd, entCache, ntdCache);
+                        // store new effective node type
+                        entCache.put(ent);
+                        if (result == null) {
+                            result = ent;
+                        } else {
+                            result = result.merge(ent);
+                            // store intermediate result (sub-aggregate)
+                            entCache.put(result);
+                        }
+                    }
+                    // add aggregate of remaining node types to result list
+                    tmpResults.add(result);
+                    break;
+                }
             }
-        }
-        // merge the sub-aggregates into new effective node type
-        for (int i = 0; i < tmpResults.size(); i++) {
-            if (result == null) {
-                result = (EffectiveNodeType) tmpResults.get(i);
-            } else {
-                result = result.merge((EffectiveNodeType) tmpResults.get(i));
-                // store intermediate result
-                entCache.put(result);
+            // merge the sub-aggregates into new effective node type
+            for (int i = 0; i < tmpResults.size(); i++) {
+                if (result == null) {
+                    result = (EffectiveNodeType) tmpResults.get(i);
+                } else {
+                    result = result.merge((EffectiveNodeType) tmpResults.get(i));
+                    // store intermediate result
+                    entCache.put(result);
+                }
             }
         }
         // we're done
@@ -1055,8 +1059,8 @@
     }
 
     static void checkForCircularInheritance(QName[] supertypes,
-                                     Stack inheritanceChain,
-                                     Map ntDefCache)
+                                            Stack inheritanceChain,
+                                            Map ntDefCache)
             throws InvalidNodeTypeDefException, RepositoryException {
         for (int i = 0; i < supertypes.length; i++) {
             QName nt = supertypes[i];