You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by cz...@apache.org on 2020/01/16 13:56:20 UTC

[sling-org-apache-sling-engine] branch master updated: SLING-9006 : Remove contention on sling request listener manager

This is an automated email from the ASF dual-hosted git repository.

cziegeler pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-engine.git


The following commit(s) were added to refs/heads/master by this push:
     new 6684b10  SLING-9006 : Remove contention on sling request listener manager
6684b10 is described below

commit 6684b10e5dfdc8476857159762f31743006ab79f
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Thu Jan 16 14:54:29 2020 +0100

    SLING-9006 : Remove contention on sling request listener manager
---
 .../apache/sling/engine/impl/SlingMainServlet.java | 25 +++++-------
 .../engine/impl/helper/RequestListenerManager.java | 47 +++++++++++++++-------
 2 files changed, 43 insertions(+), 29 deletions(-)

diff --git a/src/main/java/org/apache/sling/engine/impl/SlingMainServlet.java b/src/main/java/org/apache/sling/engine/impl/SlingMainServlet.java
index 5f94c31..7451c76 100644
--- a/src/main/java/org/apache/sling/engine/impl/SlingMainServlet.java
+++ b/src/main/java/org/apache/sling/engine/impl/SlingMainServlet.java
@@ -61,6 +61,7 @@ import org.osgi.service.component.annotations.Modified;
 import org.osgi.service.component.annotations.Reference;
 import org.osgi.service.component.annotations.ReferenceCardinality;
 import org.osgi.service.component.annotations.ReferencePolicy;
+import org.osgi.service.component.annotations.ReferencePolicyOption;
 import org.osgi.service.component.propertytypes.ServiceDescription;
 import org.osgi.service.component.propertytypes.ServiceVendor;
 import org.osgi.service.http.context.ServletContextHelper;
@@ -139,6 +140,9 @@ public class SlingMainServlet extends GenericServlet {
     @Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
     private volatile AdapterManager adapterManager;
 
+    @Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY)
+    private volatile RequestListenerManager requestListenerManager;
+
     private BundleContext bundleContext;
 
     /** default log */
@@ -183,8 +187,6 @@ public class SlingMainServlet extends GenericServlet {
      */
     private volatile String serverInfo = PRODUCT_NAME;
 
-    private volatile RequestListenerManager requestListenerManager;
-
     private volatile boolean allowTrace;
 
     // new properties
@@ -227,7 +229,10 @@ public class SlingMainServlet extends GenericServlet {
             // set the thread name according to the request
             String threadName = setThreadName(request);
 
-            requestListenerManager.sendEvent( request, SlingRequestEvent.EventType.EVENT_INIT );
+            final RequestListenerManager localRLM = requestListenerManager;
+            if (localRLM != null) {
+                localRLM.sendEvent(request, SlingRequestEvent.EventType.EVENT_INIT);
+            }
 
             ResourceResolver resolver = null;
             try {
@@ -269,7 +274,9 @@ public class SlingMainServlet extends GenericServlet {
                     resolver.close();
                 }
 
-                requestListenerManager.sendEvent( request, SlingRequestEvent.EventType.EVENT_DESTROY );
+                if (localRLM != null) {
+                    localRLM.sendEvent(request, SlingRequestEvent.EventType.EVENT_DESTROY);
+                }
 
                 // reset the thread name
                 if (threadName != null) {
@@ -497,9 +504,6 @@ public class SlingMainServlet extends GenericServlet {
                     filterManager.open();
                     requestProcessor.setFilterManager(filterManager);
 
-                    // initialize requestListenerManager
-                    requestListenerManager = new RequestListenerManager(bundleContext, slingServletContext);
-
                     try {
                         Dictionary<String, String> mbeanProps = new Hashtable<>();
                         mbeanProps.put("jmx.objectname", "org.apache.sling:type=engine,service=RequestProcessor");
@@ -547,13 +551,6 @@ public class SlingMainServlet extends GenericServlet {
             this.servletRegistration = null;
         }
 
-        // dispose of request listener manager after unregistering the servlet
-        // to prevent a potential NPE in the service method
-        if ( this.requestListenerManager != null ) {
-            this.requestListenerManager.dispose();
-            this.requestListenerManager = null;
-        }
-
         // reset the sling main servlet reference (help GC and be nice)
         RequestData.setSlingMainServlet(null);
 
diff --git a/src/main/java/org/apache/sling/engine/impl/helper/RequestListenerManager.java b/src/main/java/org/apache/sling/engine/impl/helper/RequestListenerManager.java
index 96a9174..4cd3fd0 100644
--- a/src/main/java/org/apache/sling/engine/impl/helper/RequestListenerManager.java
+++ b/src/main/java/org/apache/sling/engine/impl/helper/RequestListenerManager.java
@@ -18,38 +18,55 @@
  */
 package org.apache.sling.engine.impl.helper;
 
+import java.util.List;
+
 import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletRequest;
 
 import org.apache.sling.api.request.SlingRequestEvent;
 import org.apache.sling.api.request.SlingRequestListener;
-import org.osgi.framework.BundleContext;
-import org.osgi.util.tracker.ServiceTracker;
+import org.apache.sling.engine.impl.SlingMainServlet;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.FieldOption;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicy;
+import org.osgi.service.component.propertytypes.ServiceDescription;
+import org.osgi.service.component.propertytypes.ServiceVendor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
+@Component(service = RequestListenerManager.class)
+@ServiceDescription("Request listener manager")
+@ServiceVendor("The Apache Software Foundation")
 public class RequestListenerManager  {
 
-    private final ServiceTracker serviceTracker;
-
     private final ServletContext servletContext;
 
-	public RequestListenerManager( final BundleContext context, final ServletContext servletContext ) {
-		serviceTracker = new ServiceTracker( context, SlingRequestListener.SERVICE_NAME, null );
-		serviceTracker.open();
+    private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+    @Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC, fieldOption = FieldOption.REPLACE)
+    private volatile List<SlingRequestListener> listeners;
+
+    @Activate
+    public RequestListenerManager(@Reference(target = "(name=" + SlingMainServlet.SERVLET_CONTEXT_NAME
+            + ")") final ServletContext servletContext) {
 		this.servletContext = servletContext;
 	}
 
 	public void sendEvent ( final HttpServletRequest request,
 	        final SlingRequestEvent.EventType type) {
-		final Object[] services = serviceTracker.getServices();
-		if ( services != null && services.length > 0 ) {
+        final List<SlingRequestListener> local = listeners;
+        if (local != null && !local.isEmpty()) {
 		    final SlingRequestEvent event = new SlingRequestEvent(this.servletContext, request, type);
-			for ( final Object service : services ) {
-				( (SlingRequestListener) service ).onEvent( event );
+            for (final SlingRequestListener service : local) {
+                try {
+                    service.onEvent(event);
+                } catch (final Throwable t) {
+                    logger.error("Error invoking sling request listener " + service + " : " + t.getMessage(), t);
+                }
 			}
 		}
 	}
-
-	public void dispose() {
-	    this.serviceTracker.close();
-	}
 }