You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2017/11/07 09:27:46 UTC

[sling-org-apache-sling-discovery-commons] 11/16: SLING-6836 : Use Timer instead of scheduler for delayed execution

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

rombert pushed a commit to annotated tag org.apache.sling.discovery.commons-1.0.20
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-discovery-commons.git

commit d7dbd3c412d53ab7b1e424996f55eb8d44538e98
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Mon May 8 05:19:54 2017 +0000

    SLING-6836 : Use Timer instead of scheduler for delayed execution
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/bundles/extensions/discovery/commons@1794284 13f79535-47bb-0310-9956-ffa450edef68
---
 .../commons/InitDelayingTopologyEventListener.java | 119 ++++++++++++++-------
 .../sling/discovery/commons/package-info.java      |   4 +-
 .../TestInitDelayingTopologyEventListener.java     |  36 ++-----
 3 files changed, 93 insertions(+), 66 deletions(-)

diff --git a/src/main/java/org/apache/sling/discovery/commons/InitDelayingTopologyEventListener.java b/src/main/java/org/apache/sling/discovery/commons/InitDelayingTopologyEventListener.java
index 4014f80..8d59027 100644
--- a/src/main/java/org/apache/sling/discovery/commons/InitDelayingTopologyEventListener.java
+++ b/src/main/java/org/apache/sling/discovery/commons/InitDelayingTopologyEventListener.java
@@ -18,7 +18,8 @@
  */
 package org.apache.sling.discovery.commons;
 
-import java.sql.Date;
+import java.util.Timer;
+import java.util.TimerTask;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.sling.commons.scheduler.Scheduler;
@@ -42,7 +43,7 @@ import org.slf4j.LoggerFactory;
  *      (as the discovery API says the first event received is an INIT event).
  *      </li>
  *  <li>if the last event received was not a CHANGING event
- *      (ie it was an INIT, CHANGED or PROPERTIES), then 
+ *      (ie it was an INIT, CHANGED or PROPERTIES), then
  *      as soon as the startup time passes this facade will simulate
  *      an INIT event
  *      (again, as the discovery API says the first event received is an INIT event)
@@ -67,32 +68,37 @@ public class InitDelayingTopologyEventListener implements TopologyEventListener
     private final AtomicBoolean active = new AtomicBoolean(false);
 
     /** flag indicating whether we're still delaying or not **/
-    private boolean delaying = true;
-    
+    private volatile boolean delaying = true;
+
     /** the last pending delayed event - we only have to keep the last event to support all different cases **/
-    private TopologyEvent pendingDelayedEvent = null;
+    private volatile TopologyEvent pendingDelayedEvent;
 
-    /** 
+    /**
      * Creates a new init-delaying listener with the given delay, delegate and scheduler.
      * <p>
      * For properly disposing the caller should use the dispose method!
+     * @param startupDelay The startup delay in seconds
+     * @param delegate The topology event listener
      * @see #dispose()
      */
-    public InitDelayingTopologyEventListener(final long startupDelay, final TopologyEventListener delegate, final Scheduler scheduler) {
-        this(startupDelay, delegate, scheduler, null);
+    public InitDelayingTopologyEventListener(final long startupDelay,
+            final TopologyEventListener delegate) {
+        this(startupDelay, delegate, (Logger)null);
     }
 
     /**
      * Creates a new init-delaying listener with the given delay, delegate, scheduler and optinoal logger.
      * <p>
      * For properly disposing the caller should use the dispose method!
+     * @param startupDelay The startup delay in seconds
+     * @param delegate The topology event listener
+     * @param loggerOrNull Optional logger instance
      * @see #dispose()
      */
-    public InitDelayingTopologyEventListener(final long startupDelay, final TopologyEventListener delegate, 
-            final Scheduler scheduler, final Logger loggerOrNull) {
-        if ( scheduler == null ) {
-            throw new IllegalArgumentException("scheduler must not be null");
-        }
+    public InitDelayingTopologyEventListener(final long startupDelay,
+            final TopologyEventListener delegate,
+            final Logger loggerOrNull) {
+
         if ( delegate == null ) {
             throw new IllegalArgumentException("delegate must not be null");
         }
@@ -106,13 +112,13 @@ public class InitDelayingTopologyEventListener implements TopologyEventListener
             this.logger = LoggerFactory.getLogger(this.getClass());
         }
         final Runnable r = new Runnable() {
-            
+
             @Override
             public void run() {
                 if (InitDelayingTopologyEventListener.this.active.get()) {
                     // only call afterStartupDelay if we're active
                     // (to avoid this call if disposed in the meantime)
-                    
+
                     // and since after disposing this listener is no longer
                     // used - ie it is a throw-away - you can create
                     // such a listener on each activate and dispose it on
@@ -123,20 +129,59 @@ public class InitDelayingTopologyEventListener implements TopologyEventListener
                 }
             }
         };
-        
+
         // mark this listener as active
         this.active.set(true);
 
-        // schedule me if you can
-        if ( !scheduler.schedule(r, scheduler.AT(new Date(System.currentTimeMillis() + startupDelay * 1000))) ) {
-            // if for whatever reason scheduling doesn't work, let's run now
-            logger.warn("activate: could not schedule startupDelay handler with scheduler ({}) - "
-                    + "thus starting ({}) immediately", scheduler, delegate);
-            r.run();
-        }
+        // schedule me
+        final Timer timer = new Timer();
+        final TimerTask task = new TimerTask() {
+
+            @Override
+            public void run() {
+                r.run();
+            }
+        };
+        timer.schedule(task, startupDelay * 1000);
         // SLING-5560 : at this point either r is invoked immediately or scheduled after the delay
     }
-    
+
+    /**
+     * Creates a new init-delaying listener with the given delay, delegate and scheduler.
+     * <p>
+     * For properly disposing the caller should use the dispose method!
+     * @param startupDelay The startup delay in seconds
+     * @param delegate The topology event listener
+     * @param scheduler Scheduler to schedule the delay (not used)
+     * @see #dispose()
+     * @deprecated Use {@link InitDelayingTopologyEventListener#InitDelayingTopologyEventListener(long, TopologyEventListener)
+     */
+    @Deprecated
+    public InitDelayingTopologyEventListener(final long startupDelay,
+            final TopologyEventListener delegate,
+            final Scheduler scheduler) {
+        this(startupDelay, delegate, scheduler, null);
+    }
+
+    /**
+     * Creates a new init-delaying listener with the given delay, delegate, scheduler and optinoal logger.
+     * <p>
+     * For properly disposing the caller should use the dispose method!
+     * @param startupDelay The startup delay in seconds
+     * @param delegate The topology event listener
+     * @param scheduler Scheduler to schedule the delay (not used)
+     * @param loggerOrNull Optional logger instance
+     * @see #dispose()
+     * @deprecated Use {@link InitDelayingTopologyEventListener#InitDelayingTopologyEventListener(long, TopologyEventListener, Logger)
+     */
+    @Deprecated
+    public InitDelayingTopologyEventListener(final long startupDelay,
+            final TopologyEventListener delegate,
+            final Scheduler scheduler,
+            final Logger loggerOrNull) {
+        this(startupDelay, delegate, loggerOrNull);
+    }
+
     @Override
     public void handleTopologyEvent(TopologyEvent event) {
         synchronized ( syncObj ) {
@@ -146,7 +191,7 @@ public class InitDelayingTopologyEventListener implements TopologyEventListener
                 // event
                 this.logger.debug("handleTopologyEvent: delaying processing of received topology event (startup delay active) {}", event);
                 this.pendingDelayedEvent = event;
-                
+
                 // and we're delaying - so stop processing now and return
                 return;
             } else if ( this.pendingDelayedEvent != null ) {
@@ -157,7 +202,7 @@ public class InitDelayingTopologyEventListener implements TopologyEventListener
                 // in afterStartupDelay).
                 // which means that we must now convert the new event into an INIT
                 // to ensure our code gets an INIT first thing
-                
+
                 // paranoia check:
                 if ( event.getType() == Type.TOPOLOGY_CHANGING ) {
                     // this should never happen - but if it does, rinse and repeat
@@ -180,14 +225,14 @@ public class InitDelayingTopologyEventListener implements TopologyEventListener
         // no delaying applicable - call delegate
         this.delegate.handleTopologyEvent(event);
     }
-    
+
     /**
      * Marks this listener as no longer active - ensures that it doesn't call the delegate
      * via any potentially pending scheduler callback.
      * <p>
      * Note that after dispose you can *still* call handleTopologyEvent and the events
-     * are passed to the delegate - but those are expected to be 'late' events and not 
-     * really part of the normal game. Hence, the caller must also ensure that the 
+     * are passed to the delegate - but those are expected to be 'late' events and not
+     * really part of the normal game. Hence, the caller must also ensure that the
      * handleTopologyEvent method isn't called anymore (which typically is automatically
      * guaranteed since the caller is typically an osgi service that gets unregistered anyway)
      */
@@ -204,7 +249,7 @@ public class InitDelayingTopologyEventListener implements TopologyEventListener
         synchronized ( this.syncObj ) {
             // stop any future delaying
             this.delaying = false;
-            
+
             if ( this.pendingDelayedEvent == null ) {
                 // if no event received while we delayed,
                 // then we don't have to do anything later
@@ -214,25 +259,25 @@ public class InitDelayingTopologyEventListener implements TopologyEventListener
                 // if the last delayed event was CHANGING
                 // then we must convert the next upcoming CHANGED, PROPERTIES
                 // into an INIT
-                
+
                 // and the way this is done in this class is by leving this
                 // event sit in this.pendingDelayedEvent, for grabs in handleTopologyEvent later
                 this.logger.debug("afterStartupDelay: startup delay passed, pending delayed event was CHANGING. "
                         + "Waiting for next stable topology event");
             } else {
                 // otherwise the last delayed event was either an INIT, CHANGED or PROPERTIES
-                // - but in any case we definitely never 
+                // - but in any case we definitely never
                 // processed any INIT - and our code expects an INIT
                 // as the first event ever..
-                
+
                 // so we now convert the event into an INIT
-                final TopologyEvent artificialInitEvent = 
+                final TopologyEvent artificialInitEvent =
                         new TopologyEvent(Type.TOPOLOGY_INIT, null, this.pendingDelayedEvent.getNewView());
-                
+
                 this.logger.debug("afterStartupDelay: startup delay passed, last pending delayed event was stable ({}). "
-                        + "Simulating an INIT event with that view: {}", this.pendingDelayedEvent, artificialInitEvent); 
+                        + "Simulating an INIT event with that view: {}", this.pendingDelayedEvent, artificialInitEvent);
                 this.pendingDelayedEvent = null;
-                
+
                 // call the delegate.
                 // we must do this call in the synchronized block
                 // to ensure any concurrent new event waits properly
diff --git a/src/main/java/org/apache/sling/discovery/commons/package-info.java b/src/main/java/org/apache/sling/discovery/commons/package-info.java
index 427fb1a..81c665b 100644
--- a/src/main/java/org/apache/sling/discovery/commons/package-info.java
+++ b/src/main/java/org/apache/sling/discovery/commons/package-info.java
@@ -20,9 +20,9 @@
 /**
  * Provides commons utility for users for the Discovery API.
  *
- * @version 1.0.0
+ * @version 1.2.0
  */
-@Version("1.1.0")
+@Version("1.2.0")
 package org.apache.sling.discovery.commons;
 
 import aQute.bnd.annotation.Version;
diff --git a/src/test/java/org/apache/sling/discovery/commons/TestInitDelayingTopologyEventListener.java b/src/test/java/org/apache/sling/discovery/commons/TestInitDelayingTopologyEventListener.java
index 8f224da..f49233f 100644
--- a/src/test/java/org/apache/sling/discovery/commons/TestInitDelayingTopologyEventListener.java
+++ b/src/test/java/org/apache/sling/discovery/commons/TestInitDelayingTopologyEventListener.java
@@ -45,13 +45,13 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public class TestInitDelayingTopologyEventListener {
-    
+
     private final Logger logger = LoggerFactory.getLogger(this.getClass());
-    
+
     class TestListener implements TopologyEventListener {
 
         private List<TopologyEvent> events = new LinkedList<TopologyEvent>();
-        
+
         @Override
         public void handleTopologyEvent(TopologyEvent event) {
             synchronized(events) {
@@ -59,7 +59,7 @@ public class TestInitDelayingTopologyEventListener {
                 events.notifyAll();
             }
         }
-        
+
         public List<TopologyEvent> getEvents() {
             synchronized(events) {
                 return events;
@@ -213,7 +213,7 @@ public class TestInitDelayingTopologyEventListener {
     @Test
     public void testConstructor() throws Exception {
         final TopologyEventListener delegate = new TopologyEventListener() {
-            
+
             @Override
             public void handleTopologyEvent(TopologyEvent event) {
                 // nothing here atm
@@ -239,12 +239,6 @@ public class TestInitDelayingTopologyEventListener {
             // ok
         }
         try{
-            new InitDelayingTopologyEventListener(1, delegate, null);
-            fail("should complain");
-        } catch(IllegalArgumentException re) {
-            // ok
-        }
-        try{
             new InitDelayingTopologyEventListener(-1, delegate, scheduler, null);
             fail("should complain");
         } catch(IllegalArgumentException re) {
@@ -263,12 +257,6 @@ public class TestInitDelayingTopologyEventListener {
             // ok
         }
         try{
-            new InitDelayingTopologyEventListener(1, delegate, null, null);
-            fail("should complain");
-        } catch(IllegalArgumentException re) {
-            // ok
-        }
-        try{
             new InitDelayingTopologyEventListener(-1, delegate, scheduler, logger);
             fail("should complain");
         } catch(IllegalArgumentException re) {
@@ -286,14 +274,8 @@ public class TestInitDelayingTopologyEventListener {
         } catch(IllegalArgumentException re) {
             // ok
         }
-        try{
-            new InitDelayingTopologyEventListener(1, delegate, null, logger);
-            fail("should complain");
-        } catch(IllegalArgumentException re) {
-            // ok
-        }
     }
-    
+
     private TopologyView createView(boolean current) {
         final TopologyView view = Mockito.mock(TopologyView.class);
         Mockito.when(view.isCurrent()).thenReturn(current);
@@ -331,7 +313,7 @@ public class TestInitDelayingTopologyEventListener {
             }
         }
     }
-    
+
     @Test
     public void testDisposing() throws Exception {
         final TestListener delegate = new TestListener();
@@ -347,7 +329,7 @@ public class TestInitDelayingTopologyEventListener {
         delegate.assureEventCnt(1, 1000);
         delegate.assureEventCnt(1, 500);
     }
-    
+
     @Test
     public void testNoEvents() throws Exception {
         final TestListener delegate = new TestListener();
@@ -355,7 +337,7 @@ public class TestInitDelayingTopologyEventListener {
         InitDelayingTopologyEventListener listener = new InitDelayingTopologyEventListener(1, delegate, scheduler, logger);
         // no events:
         delegate.assureEventCnt(0, 1500);
-        
+
         // then the first init is passed through
         listener.handleTopologyEvent(createEvent(Type.TOPOLOGY_INIT));
         delegate.waitForEventCnt(1, 5000);

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.