You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by mr...@apache.org on 2008/03/19 12:22:21 UTC

svn commit: r638790 - in /jackrabbit/trunk/jackrabbit-jcr-commons/src: main/java/org/apache/jackrabbit/util/Timer.java test/java/org/apache/jackrabbit/util/TestAll.java test/java/org/apache/jackrabbit/util/TimerTest.java

Author: mreutegg
Date: Wed Mar 19 04:22:11 2008
New Revision: 638790

URL: http://svn.apache.org/viewvc?rev=638790&view=rev
Log:
JCR-1486: Introduce Timer idle time

Added:
    jackrabbit/trunk/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/util/TimerTest.java   (with props)
Modified:
    jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/Timer.java
    jackrabbit/trunk/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/util/TestAll.java

Modified: jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/Timer.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/Timer.java?rev=638790&r1=638789&r2=638790&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/Timer.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/Timer.java Wed Mar 19 04:22:11 2008
@@ -21,11 +21,22 @@
 /**
  * <code>Timer</code> wraps the standard Java {@link java.util.Timer} class
  * and implements a guaranteed shutdown of the background thread running
- * in the <code>Timer</code> instance.
+ * in the <code>Timer</code> instance after a certain {@link #IDLE_TIME}.
  */
 public class Timer {
 
     /**
+     * Idle time in milliseconds. When a timer instance is idle for this amount
+     * of time the underlying timer is canceled.
+     */
+    static final int IDLE_TIME = 3 * 1000;
+
+    /**
+     * The interval at which the idle checker task runs.
+     */
+    static final int CHECKER_INTERVAL = 1000;
+
+    /**
      * The timer implementation we us internally.
      */
     private java.util.Timer delegatee;
@@ -44,6 +55,11 @@
     private int numScheduledTasks = 0;
 
     /**
+     * The time when the last task was scheduled.
+     */
+    private long lastTaskScheduled;
+
+    /**
      * Creates a new <code>Timer</code> instance.
      *
      * @param isDeamon if <code>true</code> the background thread wil run as
@@ -75,10 +91,15 @@
         synchronized (this) {
             if (delegatee == null) {
                 delegatee = new java.util.Timer(runAsDeamon);
+                // run idle checker every second
+                Task idleChecker = new IdleCheckerTask();
+                idleChecker.setTimer(this);
+                delegatee.schedule(idleChecker, IDLE_TIME, CHECKER_INTERVAL);
             }
             delegatee.schedule(task, delay, period);
             task.setTimer(this);
             numScheduledTasks++;
+            lastTaskScheduled = System.currentTimeMillis();
         }
     }
 
@@ -107,14 +128,21 @@
     }
 
     /**
+     * @return <code>true</code> if this timer has a running backround thread
+     *         for scheduled tasks. This method is only for test purposes.
+     */
+    boolean isRunning() {
+        synchronized (this) {
+            return delegatee != null;
+        }
+    }
+
+    /**
      * Notifies this <code>Timer</code> that a task has been canceled.
      */
     private void taskCanceled() {
         synchronized (this) {
-            if (--numScheduledTasks == 0) {
-                delegatee.cancel();
-                delegatee = null;
-            }
+            --numScheduledTasks;
         }
     }
 
@@ -147,6 +175,23 @@
                 timer = null;
             }
             return super.cancel();
+        }
+    }
+
+    /**
+     * Checks if the enclosing timer had been idle for at least
+     * {@link Timer#IDLE_TIME} and cancels it in that case.
+     */
+    private class IdleCheckerTask extends Task {
+
+        public void run() {
+            synchronized (Timer.this) {
+                if (numScheduledTasks == 0 &&
+                        System.currentTimeMillis() > lastTaskScheduled + IDLE_TIME) {
+                    delegatee.cancel();
+                    delegatee = null;
+                }
+            }
         }
     }
 }

Modified: jackrabbit/trunk/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/util/TestAll.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/util/TestAll.java?rev=638790&r1=638789&r2=638790&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/util/TestAll.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/util/TestAll.java Wed Mar 19 04:22:11 2008
@@ -38,6 +38,7 @@
         suite.addTestSuite(ISO9075Test.class);
         suite.addTestSuite(TextTest.class);
         suite.addTestSuite(UUIDTest.class);
+        suite.addTestSuite(TimerTest.class);
 
         return suite;
     }

Added: jackrabbit/trunk/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/util/TimerTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/util/TimerTest.java?rev=638790&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/util/TimerTest.java (added)
+++ jackrabbit/trunk/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/util/TimerTest.java Wed Mar 19 04:22:11 2008
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.util;
+
+import junit.framework.TestCase;
+
+/**
+ * <code>TimerTest</code> checks if the internal thread of a timer is stopped
+ * after {@link Timer#IDLE_TIME} elapsed.
+ */
+public class TimerTest extends TestCase {
+
+    private Timer timer;
+
+    private DummyTask task;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        timer = new Timer(true);
+        task = new DummyTask();
+    }
+
+    protected void tearDown() throws Exception {
+        timer.cancel();
+        super.tearDown();
+    }
+
+    public void testInitiallyNotRunning() {
+        assertTrue("Timer must not be running without a scheduled task", !timer.isRunning());
+    }
+
+    public void testIsRunning() {
+        timer.schedule(task, 0, Integer.MAX_VALUE);
+        assertTrue("Timer must be running with a scheduled task", timer.isRunning());
+    }
+
+    public void testLongDelay() throws InterruptedException {
+        int testDelay = Timer.IDLE_TIME + 1000;
+        timer.schedule(task, testDelay, Integer.MAX_VALUE);
+        Thread.sleep(testDelay);
+        assertTrue("Timer must be running with a scheduled task", timer.isRunning());
+    }
+
+    public void testIdle() throws InterruptedException {
+        timer.schedule(task, 0, Integer.MAX_VALUE);
+        task.waitUntilRun();
+        task.cancel();
+        assertTrue("Timer must be running while idle", timer.isRunning());
+        Thread.sleep(Timer.IDLE_TIME + 2 * Timer.CHECKER_INTERVAL);
+        assertTrue("Timer must not be running after idle time elapsed", !timer.isRunning());
+    }
+
+    private static class DummyTask extends Timer.Task {
+
+        private boolean run = false;
+
+        public void run() {
+            synchronized (this) {
+                run = true;
+                notifyAll();
+            }
+        }
+
+        public void waitUntilRun() throws InterruptedException {
+            synchronized (this) {
+                while (!run) {
+                    wait();
+                }
+            }
+        }
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/util/TimerTest.java
------------------------------------------------------------------------------
    svn:eol-style = native