wink-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From b...@apache.org
Subject svn commit: r816253 - in /incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal: handlers/FindRootResourceHandler.java registry/ResourceRegistry.java
Date Thu, 17 Sep 2009 16:08:17 GMT
Author: bluk
Date: Thu Sep 17 16:08:17 2009
New Revision: 816253

URL: http://svn.apache.org/viewvc?rev=816253&view=rev
Log:
Performance improvement to FindRootResourceHandler

See [WINK-189]

Modified:
    incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/handlers/FindRootResourceHandler.java
    incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/registry/ResourceRegistry.java

Modified: incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/handlers/FindRootResourceHandler.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/handlers/FindRootResourceHandler.java?rev=816253&r1=816252&r2=816253&view=diff
==============================================================================
--- incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/handlers/FindRootResourceHandler.java
(original)
+++ incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/handlers/FindRootResourceHandler.java
Thu Sep 17 16:08:17 2009
@@ -20,7 +20,6 @@
 
 package org.apache.wink.server.internal.handlers;
 
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Properties;
 
@@ -28,13 +27,13 @@
 import javax.ws.rs.core.PathSegment;
 import javax.ws.rs.core.Response;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.apache.wink.server.handlers.HandlersChain;
 import org.apache.wink.server.handlers.MessageContext;
 import org.apache.wink.server.handlers.RequestHandler;
 import org.apache.wink.server.internal.registry.ResourceInstance;
 import org.apache.wink.server.internal.registry.ResourceRegistry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class FindRootResourceHandler implements RequestHandler {
 
@@ -54,7 +53,13 @@
         String strippedPath = buildPathForMatching(segments);
 
         // get a list of root resources that can handle the request
-        List<ResourceInstance> matchedResources = registry.getMatchingRootResources(strippedPath);
+
+        // JAX-RS specification requires to search only the first matching
+        // resource,
+        // but the continued search behavior is to continue searching in all
+        // matching resources
+        List<ResourceInstance> matchedResources =
+            registry.getMatchingRootResources(strippedPath, isContinuedSearchPolicy);
         if (matchedResources.size() == 0) {
             logger.debug("No resource found matching {}", context.getUriInfo().getPath(false));
             SearchResult result =
@@ -63,23 +68,8 @@
             return;
         }
 
-        // JAX-RS specification requires to search only the first matching
-        // resource,
-        // but the continued search behavior is to continue searching in all
-        // matching resources
-        List<ResourceInstance> searchableResources = new LinkedList<ResourceInstance>();
-        if (!isContinuedSearchPolicy) {
-            // strict behavior - search only in the first matched root resource,
-            // as per the JAX-RS
-            // specification
-            searchableResources.add(matchedResources.get(0));
-        } else {
-            // continued search behavior - search in all matched resources
-            searchableResources.addAll(matchedResources);
-        }
-
         // search through all the matched resources (or just the first one)
-        for (ResourceInstance resource : searchableResources) {
+        for (ResourceInstance resource : matchedResources) {
             // save the matched variables, resource and uri
             SearchResult result = new SearchResult(resource, context.getUriInfo());
             context.setAttribute(SearchResult.class, result);

Modified: incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/registry/ResourceRegistry.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/registry/ResourceRegistry.java?rev=816253&r1=816252&r2=816253&view=diff
==============================================================================
--- incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/registry/ResourceRegistry.java
(original)
+++ incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/registry/ResourceRegistry.java
Thu Sep 17 16:08:17 2009
@@ -22,6 +22,7 @@
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
@@ -48,6 +49,8 @@
 import org.apache.wink.common.internal.uritemplate.UriTemplateMatcher;
 import org.apache.wink.common.internal.uritemplate.UriTemplateProcessor;
 import org.apache.wink.common.internal.utils.MediaTypeUtils;
+import org.apache.wink.common.internal.utils.SimpleMap;
+import org.apache.wink.common.internal.utils.SoftConcurrentMap;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -57,16 +60,21 @@
  */
 public class ResourceRegistry {
 
-    private static final Logger        logger = LoggerFactory.getLogger(ResourceRegistry.class);
+    private static final Logger                                   logger             =
+                                                                                        
LoggerFactory
+                                                                                        
    .getLogger(ResourceRegistry.class);
 
-    private List<ResourceRecord>       rootResources;
-    private boolean                    dirty;
+    private List<ResourceRecord>                                  rootResources;
+    private boolean                                               dirty;
 
-    private ResourceRecordFactory      resourceRecordsFactory;
+    private ResourceRecordFactory                                 resourceRecordsFactory;
 
-    private Lock                       readersLock;
-    private Lock                       writersLock;
-    private final ApplicationValidator applicationValidator;
+    private Lock                                                  readersLock;
+    private Lock                                                  writersLock;
+    private final ApplicationValidator                            applicationValidator;
+
+    private Map<Boolean, SimpleMap<String, List<ResourceRecord>>> uriToResourceCache
=
+                                                                                        
new HashMap<Boolean, SimpleMap<String, List<ResourceRecord>>>();
 
     public ResourceRegistry(LifecycleManagersRegistry factoryRegistry,
                             ApplicationValidator applicationValidator) {
@@ -77,6 +85,9 @@
         ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
         readersLock = readWriteLock.readLock();
         writersLock = readWriteLock.writeLock();
+        uriToResourceCache.put(Boolean.TRUE, new SoftConcurrentMap<String, List<ResourceRecord>>());
+        uriToResourceCache
+            .put(Boolean.FALSE, new SoftConcurrentMap<String, List<ResourceRecord>>());
     }
 
     /**
@@ -185,8 +196,13 @@
      * @return unmodifiable list of all the root resource records
      */
     public List<ResourceRecord> getRecords() {
-        assertSorted();
-        return Collections.unmodifiableList(rootResources);
+        readersLock.lock();
+        try {
+            assertSorted();
+            return Collections.unmodifiableList(rootResources);
+        } finally {
+            readersLock.unlock();
+        }
     }
 
     public Set<String> getOptions(ResourceInstance resource) {
@@ -216,17 +232,14 @@
      * Verify that the root resources list is sorted
      */
     private void assertSorted() {
-        readersLock.lock();
-        try {
-            if (dirty) {
-                // we use the reverse-order comparator because the sort method
-                // will sort the elements in ascending order, but we want
-                // them sorted in descending order
-                Collections.sort(rootResources, Collections.reverseOrder());
-                dirty = false;
-            }
-        } finally {
-            readersLock.unlock();
+        if (dirty) {
+            // we use the reverse-order comparator because the sort method
+            // will sort the elements in ascending order, but we want
+            // them sorted in descending order
+            Collections.sort(rootResources, Collections.reverseOrder());
+            uriToResourceCache.get(Boolean.TRUE).clear();
+            uriToResourceCache.get(Boolean.FALSE).clear();
+            dirty = false;
         }
     }
 
@@ -237,21 +250,55 @@
      * @return
      */
     public List<ResourceInstance> getMatchingRootResources(String uri) {
-        assertSorted();
+        return getMatchingRootResources(uri, true);
+    }
+
+    /**
+     * Get a list of all the root resources that match the request.
+     * 
+     * @param context
+     * @return
+     */
+    public List<ResourceInstance> getMatchingRootResources(String uri,
+                                                           boolean isContinuedSearchPolicy)
{
         List<ResourceInstance> found = new ArrayList<ResourceInstance>();
         uri = UriTemplateProcessor.normalizeUri(uri);
 
         readersLock.lock();
         try {
+            assertSorted();
+            List<ResourceRecord> previousMatched = null;
+            /*
+             * the previous matches are cached so if a previous URI used is
+             * still in the cache, this will find the resources that matched
+             * skipping the expensive UriTemplateMatcher.matches()
+             */
+            previousMatched = uriToResourceCache.get(isContinuedSearchPolicy).get(uri);
+            if (previousMatched != null) {
+                for (ResourceRecord record : previousMatched) {
+                    UriTemplateMatcher matcher = record.getTemplateProcessor().matcher();
+                    if (matcher.matches(uri)) {
+                        found.add(new ResourceInstance(record, matcher));
+                    }
+                }
+                return found;
+            }
+            previousMatched = new ArrayList<ResourceRecord>();
+
             // the list of root resource records is already sorted
             for (ResourceRecord record : rootResources) {
                 UriTemplateMatcher matcher = record.getTemplateProcessor().matcher();
                 if (matcher.matches(uri)) {
                     if (matcher.isExactMatch() || record.hasSubResources()) {
+                        previousMatched.add(record);
                         found.add(new ResourceInstance(record, matcher));
+                        if (!isContinuedSearchPolicy) {
+                            break;
+                        }
                     }
                 }
             }
+            uriToResourceCache.get(isContinuedSearchPolicy).put(uri, previousMatched);
         } finally {
             readersLock.unlock();
         }



Mime
View raw message