Author: desruisseaux
Date: Mon Jan 7 08:42:48 2013
New Revision: 1429706
URL: http://svn.apache.org/viewvc?rev=1429706&view=rev
Log:
Centralize the shutdown logic in a new Shutdown class, to be registered to the
JVM in a future version.
Added:
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/Shutdown.java
(with props)
Modified:
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/DaemonThread.java
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/DelayedExecutor.java
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/OSGiActivator.java
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/Supervisor.java
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/SupervisorMBean.java
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/Threads.java
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
Modified:
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/DaemonThread.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/DaemonThread.java?rev=1429706&r1=1429705&r2=1429706&view=diff
==============================================================================
---
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/DaemonThread.java
(original)
+++
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/DaemonThread.java
Mon Jan 7 08:42:48 2013
@@ -99,6 +99,18 @@ abstract class DaemonThread extends Thre
public abstract void run();
/**
+ * Returns {@code true} if this thread seems to be blocked for a time long
enough for suspecting
+ * a problem. The default implementation always returns {@code false}.
Subclasses are encouraged
+ * to provide some problem detection mechanism here if they can. For
example if the head of a
+ * queue seems to be never removed, then maybe the process consuming that
queue is blocked.
+ *
+ * @return {@code true} if this thread seems to be stalled.
+ */
+ protected boolean isStalled() {
+ return false;
+ }
+
+ /**
* Returns {@code true} if this daemon thread shall terminate.
* This happen at shutdown time.
*
@@ -137,26 +149,24 @@ abstract class DaemonThread extends Thre
}
/**
- * Returns the names of dead threads, or {@code null} if none. The
returned list should
- * always be null. A non-empty list would be a symptom for a severe
problem, probably
+ * Returns the list of stalled or dead threads, or {@code null} if none.
The returned list
+ * should always be null. A non-empty list would be a symptom for a severe
problem, probably
* requiring an application reboot.
*
* <p><strong>This method is for internal use by Apache SIS only.</strong>
* Users should never invoke this method explicitely.</p>
*
* @param thread The first thread in the chain of threads to verify.
- * @return The name of dead threads, or {@code null} if none.
- *
- * @see Threads#listDeadThreads()
+ * @return The list of stalled or dead threads, or {@code null} if none.
*/
- static List<String> listDeadThreads(DaemonThread thread) {
- List<String> list = null;
+ static List<Thread> listStalledThreads(DaemonThread thread) {
+ List<Thread> list = null;
while (thread != null) {
- if (!thread.isAlive()) {
+ if (!thread.isAlive() || thread.isStalled()) {
if (list == null) {
list = new ArrayList<>();
}
- list.add(thread.getName());
+ list.add(thread);
}
thread = thread.previous;
}
Modified:
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/DelayedExecutor.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/DelayedExecutor.java?rev=1429706&r1=1429705&r2=1429706&view=diff
==============================================================================
---
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/DelayedExecutor.java
(original)
+++
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/DelayedExecutor.java
Mon Jan 7 08:42:48 2013
@@ -16,6 +16,7 @@
*/
package org.apache.sis.internal.util;
+import java.util.concurrent.TimeUnit;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.BlockingQueue;
import org.apache.sis.util.logging.Logging;
@@ -182,4 +183,28 @@ public final class DelayedExecutor exten
}
// Do not log anything at this point, since the loggers may be
shutdown now.
}
+
+ /**
+ * Returns {@code true} if this thread seems to be stalled. This method
checks the head
+ * of the queue. If the delay for that head has expired and the head is
not removed in
+ * the next 5 seconds, then we will presume that the thread is stalled or
dead.
+ */
+ @Override
+ protected boolean isStalled() {
+ final DelayedRunnable waiting = QUEUE.peek();
+ if (waiting != null && waiting.getDelay(TimeUnit.NANOSECONDS) <= 0)
try {
+ for (int i=0; i<50; i++) {
+ if (!isAlive()) break;
+ Thread.sleep(100);
+ if (QUEUE.peek() != waiting) {
+ return false;
+ }
+ }
+ return true;
+ } catch (InterruptedException e) {
+ // Someone doesn't want to let us wait. Since we didn't had the
time to
+ // determine if the thread is stalled, conservatively return
'false'.
+ }
+ return false;
+ }
}
Modified:
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/OSGiActivator.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/OSGiActivator.java?rev=1429706&r1=1429705&r2=1429706&view=diff
==============================================================================
---
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/OSGiActivator.java
(original)
+++
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/OSGiActivator.java
Mon Jan 7 08:42:48 2013
@@ -51,15 +51,10 @@ public final class OSGiActivator impleme
* This method shutdowns the {@code sis-utility} threads.
*
* @param context The execution context of the bundle being stopped.
- * @throws InterruptedException If an other thread invoked {@link
#interrupt()} while
- * we were waiting for the {@code sis-utility} threads to die.
* @throws JMException If an error occurred during unregistration of the
supervisor MBean.
*/
@Override
- public void stop(final BundleContext context) throws InterruptedException,
JMException {
- Threads.shutdown(4000);
- if (Supervisor.ENABLED) {
- Supervisor.unregister();
- }
+ public void stop(final BundleContext context) throws JMException {
+ Shutdown.stop(getClass());
}
}
Added:
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/Shutdown.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/Shutdown.java?rev=1429706&view=auto
==============================================================================
---
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/Shutdown.java
(added)
+++
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/Shutdown.java
Mon Jan 7 08:42:48 2013
@@ -0,0 +1,77 @@
+/*
+ * 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.sis.internal.util;
+
+import javax.management.JMException;
+import org.apache.sis.util.logging.Logging;
+
+
+/**
+ * A central place where to manage SIS shutdown process.
+ * For now this class is not yet registered as a shutdown hock,
+ * but it will be in a future version.
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ * @since 0.3
+ * @version 0.3
+ * @module
+ */
+public final class Shutdown {
+ /**
+ * Do not allow instantiation of this class.
+ */
+ private Shutdown() {
+ }
+
+ /**
+ * Shutdowns the {@code sis-utility} threads and unregister the supervisor
MBean.
+ *
+ * @param caller The class invoking this method, to be used only for
logging purpose,
+ * or {@code null} if the logging system is not available anymore
(i.e. the JVM
+ * itself is shutting down).
+ * @throws JMException If an error occurred during unregistration of the
supervisor MBean.
+ */
+ public static void stop(final Class<?> caller) throws JMException {
+ /*
+ * Unregister the MBean before to stop the threads, in order to avoid
false alerts
+ * in the superviror 'warnings()' method. Failure to unregister the
MBean is worth
+ * to report, but we will do that only after we completed the other
shutdown steps.
+ */
+ JMException exception = null;
+ if (Supervisor.ENABLED) try {
+ Supervisor.unregister();
+ } catch (JMException deferred) {
+ exception = deferred;
+ }
+ /*
+ * Following is usually fast, but may potentially take a little while.
+ * If an other thread invoked Thread.interrupt() while we were waiting
+ * for the threads to terminate, maybe not all threads have terminated
+ * but continue the shutdown process anyway.
+ */
+ try {
+ Threads.shutdown(System.nanoTime() + 4000);
+ } catch (InterruptedException e) {
+ if (caller != null) {
+ Logging.unexpectedException(caller, "stop", e);
+ }
+ }
+ if (exception != null) {
+ throw exception;
+ }
+ }
+}
Propchange:
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/Shutdown.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/Shutdown.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified:
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/Supervisor.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/Supervisor.java?rev=1429706&r1=1429705&r2=1429706&view=diff
==============================================================================
---
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/Supervisor.java
(original)
+++
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/Supervisor.java
Mon Jan 7 08:42:48 2013
@@ -199,13 +199,21 @@ public final class Supervisor extends St
* {@inheritDoc}
*/
@Override
- public List<String> warnings() {
- final List<String> warnings = Threads.listDeadThreads();
- if (warnings != null) {
- final Errors resources = Errors.getResources(locale);
- for (int i=warnings.size(); --i>=0;) {
- warnings.set(i, resources.getString(Errors.Keys.DeadThread_1,
warnings.get(i)));
- }
+ public String[] warnings() {
+ final DaemonThread lastCreatedDaemon;
+ synchronized (Threads.class) {
+ lastCreatedDaemon = Threads.lastCreatedDaemon;
+ }
+ final List<Thread> threads =
DaemonThread.listStalledThreads(lastCreatedDaemon);
+ if (threads == null) {
+ return null;
+ }
+ final String[] warnings = new String[threads.size()];
+ final Errors resources = Errors.getResources(locale);
+ for (int i=0; i<warnings.length; i++) {
+ final Thread thread = threads.get(i);
+ warnings[i] = resources.getString(thread.isAlive() ?
+ Errors.Keys.StalledThread_1 : Errors.Keys.DeadThread_1,
thread.getName());
}
return warnings;
}
Modified:
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/SupervisorMBean.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/SupervisorMBean.java?rev=1429706&r1=1429705&r2=1429706&view=diff
==============================================================================
---
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/SupervisorMBean.java
(original)
+++
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/SupervisorMBean.java
Mon Jan 7 08:42:48 2013
@@ -16,7 +16,6 @@
*/
package org.apache.sis.internal.util;
-import java.util.List;
import org.apache.sis.util.collection.TreeTable;
@@ -46,5 +45,5 @@ public interface SupervisorMBean {
*
* @return A description of a problems in the library, or {@code null} if
none.
*/
- List<String> warnings();
+ String[] warnings();
}
Modified:
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/Threads.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/Threads.java?rev=1429706&r1=1429705&r2=1429706&view=diff
==============================================================================
---
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/Threads.java
(original)
+++
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/util/Threads.java
Mon Jan 7 08:42:48 2013
@@ -16,7 +16,6 @@
*/
package org.apache.sis.internal.util;
-import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ExecutorService;
import org.apache.sis.util.Static;
@@ -131,15 +130,4 @@ final class Threads extends Static {
}
DaemonThread.killAll(lastCreatedDaemon, stopWaitingAt);
}
-
- /**
- * Returns the names of dead threads, or {@code null} if none. The
returned list should
- * always be null. A non-empty list would be a symptom for a severe
problem, probably
- * requiring an application reboot.
- *
- * @return The name of dead threads, or {@code null} if none.
- */
- static synchronized List<String> listDeadThreads() {
- return DaemonThread.listDeadThreads(lastCreatedDaemon);
- }
}
Modified:
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java?rev=1429706&r1=1429705&r2=1429706&view=diff
==============================================================================
---
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
(original)
+++
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
Mon Jan 7 08:42:48 2013
@@ -309,6 +309,11 @@ public final class Errors extends Indexe
public static final int RequireDecimalSeparator = 33;
/**
+ * Thread â{0}â seems stalled.
+ */
+ public static final int StalledThread_1 = 63;
+
+ /**
* Unexpected change in â{0}â.
*/
public static final int UnexpectedChange_1 = 56;
Modified:
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties?rev=1429706&r1=1429705&r2=1429706&view=diff
==============================================================================
---
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
(original)
+++
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
Mon Jan 7 08:42:48 2013
@@ -74,6 +74,7 @@ NullArgument_1 = Argume
OddArrayLength_1 = Array length is {0}, while we expected an
even length.
RecursiveCreateCallForKey_1 = Recursive call while creating an object for
the \u201c{0}\u201d key.
RequireDecimalSeparator = A decimal separator is required.
+StalledThread_1 = Thread \u201c{0}\u201d seems stalled.
UnexpectedChange_1 = Unexpected change in \u2018{0}\u2019.
UnexpectedEndOfString_1 = More characters were expected at the end of
\u201c{0}\u201d.
UnmodifiableAffineTransform = This affine transform is unmodifiable.
Modified:
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties?rev=1429706&r1=1429705&r2=1429706&view=diff
==============================================================================
---
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
(original)
+++
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
Mon Jan 7 08:42:48 2013
@@ -63,6 +63,7 @@ NullArgument_1 = L\u201
OddArrayLength_1 = La longueur du tableau est {0}, alors
qu\u2019on attendait une longueur paire.
RecursiveCreateCallForKey_1 = Appel r\u00e9cursif lors de la cr\u00e9ation
d\u2019un objet pour la cl\u00e9 \u201c{0}\u201d.
RequireDecimalSeparator = Un s\u00e9parateur d\u00e9cimal est requis.
+StalledThread_1 = La t\u00e2che \u201c{0}\u201d semble
bloqu\u00e9e.
UnexpectedChange_1 = Changement inattendu dans \u2018{0}\u2019.
UnexpectedEndOfString_1 = D\u2019autres caract\u00e8res \u00e9taient
attendus \u00e0 la fin du texte \u201c{0}\u201d.
UnmodifiableAffineTransform = Cette transformation affine n\u2019est pas
modifiable.