Listener base classes should not throw exception if close()'d 57/57257/2
authorMichael Vorburger <vorburger@redhat.com>
Wed, 17 May 2017 10:36:46 +0000 (12:36 +0200)
committerFaseela K <faseela.k@ericsson.com>
Sat, 10 Jun 2017 05:32:28 +0000 (05:32 +0000)
for AsyncClusteredDataTreeChangeListenerBase and
AsyncDataTreeChangeListenerBase, by introducing a new
ShutdownLoggingExecutorService infra util. related to -1 discussion in
https://git.opendaylight.org/gerrit/#/c/57004/

This is an alternative proposal to the ShutdownLoggingExecutorService
idea from https://git.opendaylight.org/gerrit/#/c/57156/

Change-Id: I5884a188fb5ea3581f99cc559acb158ed370ed7b
Signed-off-by: Michael Vorburger <vorburger@redhat.com>
mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/datastoreutils/AsyncClusteredDataTreeChangeListenerBase.java
mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/datastoreutils/AsyncDataTreeChangeListenerBase.java
mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/infra/LoggingRejectedExecutionHandler.java [new file with mode: 0644]

index 37a73f67e6a9903177ce3ca08c648074c74ccf64..67df09b6455aa68517f3a444de8e0d8739359df1 100644 (file)
@@ -21,6 +21,7 @@ import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.genius.infra.LoggingRejectedExecutionHandler;
 import org.opendaylight.genius.utils.SuperTypeUtil;
 import org.opendaylight.infrautils.utils.concurrent.ThreadFactoryProvider;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
@@ -52,7 +53,8 @@ public abstract class AsyncClusteredDataTreeChangeListenerBase
             ThreadFactoryProvider.builder()
                 .namePrefix("AsyncClusteredDataTreeChangeListenerBase-DataTreeChangeHandler")
                 .logger(LOG)
-                .build().get());
+                .build().get(),
+            new LoggingRejectedExecutionHandler());
 
     protected final Class<T> clazz;
 
index a8248e5ae1b71dd58397057c60a4c85606a5b075..7c011af0507e98b8b72147dad8964609fb79134b 100644 (file)
@@ -21,6 +21,7 @@ import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.genius.infra.LoggingRejectedExecutionHandler;
 import org.opendaylight.genius.utils.SuperTypeUtil;
 import org.opendaylight.infrautils.utils.concurrent.ThreadFactoryProvider;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
@@ -51,7 +52,8 @@ public abstract class AsyncDataTreeChangeListenerBase<T extends DataObject, K ex
             ThreadFactoryProvider.builder()
                 .namePrefix("AsyncDataTreeChangeListenerBase-DataTreeChangeHandler")
                 .logger(LOG)
-                .build().get());
+                .build().get(),
+            new LoggingRejectedExecutionHandler());
 
     protected final Class<T> clazz;
 
diff --git a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/infra/LoggingRejectedExecutionHandler.java b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/genius/infra/LoggingRejectedExecutionHandler.java
new file mode 100644 (file)
index 0000000..9589ace
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2017 Red Hat, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.genius.infra;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.RejectedExecutionHandler;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.ThreadPoolExecutor.AbortPolicy;
+import java.util.concurrent.ThreadPoolExecutor.DiscardPolicy;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A {@link RejectedExecutionHandler} which logs
+ * instead of throwing an exception (like e.g. {@link ThreadPoolExecutor}'s default
+ * {@link AbortPolicy} does) or just completely silently ignores the execute
+ * (like e.g. {@link DiscardPolicy} does).
+ *
+ * <p>This logs an ERROR level message (because typically that's a real problem),
+ * unless the {@link ExecutorService#isShutdown()} - then it logs only an INFO level message
+ * (because typically that's "just" a shutdown ordering issue, and not a real problem).
+ *
+ * @author Michael Vorburger.ch
+ */
+public class LoggingRejectedExecutionHandler implements RejectedExecutionHandler {
+
+    // TODO This utility could eventually be moved to org.opendaylight.infrautils.utils.concurrent
+
+    private static final Logger LOG = LoggerFactory.getLogger(LoggingRejectedExecutionHandler.class);
+
+    @Override
+    public void rejectedExecution(Runnable runnable, ThreadPoolExecutor executor) {
+        if (executor.isShutdown() || executor.isTerminating() || executor.isTerminated()) {
+            LOG.info("rejectedExecution, but OK as ExecutorService is terminating or shutdown; "
+                    + "executor: {}, runnable: {}", executor, runnable);
+        } else {
+            LOG.error("rejectedExecution (BUT ExecutorService is NOT terminating or shutdown, so that's a PROBLEM); "
+                    + "executor: {}, runnable: {}", executor, runnable);
+        }
+    }
+
+}