Eliminate GlobalNetconfSshScheduledExecutor 06/110006/4
authorRobert Varga <robert.varga@pantheon.tech>
Fri, 26 Jan 2024 00:48:52 +0000 (01:48 +0100)
committerRobert Varga <nite@hq.sk>
Fri, 26 Jan 2024 12:08:39 +0000 (12:08 +0000)
The only thing this executor is used is for ietf-monitoring listener
updates for netconf-server.

Rather than having a tuneable threadpool, just acknowledge the fact we
need a single thread for this task and manage it internally
NetconfMonitoringServiceImpl if possible.

JIRA: NETCONF-1232
Change-Id: I081947c28981442777ea8bc91a77df01641d23fe
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
apps/netconf-nb/src/main/java/org/opendaylight/netconf/northbound/DefaultNetconfMonitoringService.java
apps/netconf-nb/src/main/java/org/opendaylight/netconf/northbound/OSGiNetconfServer.java
netconf/netconf-config/src/main/java/org/opendaylight/netconf/config/Configuration.java
netconf/netconf-config/src/main/java/org/opendaylight/netconf/config/GlobalNetconfConfiguration.java
netconf/netconf-config/src/main/java/org/opendaylight/netconf/config/GlobalNetconfSshScheduledExecutor.java [deleted file]
netconf/netconf-config/src/main/java/org/opendaylight/netconf/config/GlobalNetconfThreadFactory.java
protocol/netconf-server/src/main/java/org/opendaylight/netconf/server/osgi/NetconfMonitoringServiceImpl.java

index b4af03671bc5b61ddfb20844adc3302aa847d98d..787e8aad9968017c48e88a7b9b502de40085c1b8 100644 (file)
@@ -9,8 +9,10 @@ package org.opendaylight.netconf.northbound;
 
 import static java.util.Objects.requireNonNull;
 
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
 import java.util.Map;
-import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
 import org.opendaylight.netconf.server.api.monitoring.NetconfMonitoringService;
 import org.opendaylight.netconf.server.api.operations.NetconfOperationServiceFactory;
 import org.opendaylight.netconf.server.osgi.NetconfMonitoringServiceImpl;
@@ -22,14 +24,20 @@ import org.osgi.service.component.annotations.Deactivate;
 public final class DefaultNetconfMonitoringService extends NetconfMonitoringServiceImpl {
     static final String FACTORY_NAME = "org.opendaylight.netconf.impl.mdsal.DefaultNetconfMonitoringService";
 
+    private static final ThreadFactory THREAD_FACTORY = new ThreadFactoryBuilder()
+        .setNameFormat("netconf-server-monitoring-%d")
+        .setDaemon(true)
+        .build();
     private static final String OP_PROVIDER_PROP = ".opProvider";
-    private static final String THREAD_POOL_PROP = ".threadPool";
     private static final String UPDATE_INTERVAL_PROP = ".updateInterval";
 
+    private DefaultNetconfMonitoringService(final NetconfOperationServiceFactory opProvider, final long periodSeconds) {
+        super(opProvider, THREAD_FACTORY, periodSeconds, TimeUnit.SECONDS);
+    }
+
     @Activate
     public DefaultNetconfMonitoringService(final Map<String, ?> properties) {
-        super(OSGiNetconfServer.extractProp(properties, OP_PROVIDER_PROP, NetconfOperationServiceFactory.class),
-            OSGiNetconfServer.extractProp(properties, THREAD_POOL_PROP, ScheduledExecutorService.class),
+        this(OSGiNetconfServer.extractProp(properties, OP_PROVIDER_PROP, NetconfOperationServiceFactory.class),
             OSGiNetconfServer.extractProp(properties, UPDATE_INTERVAL_PROP, Long.class));
     }
 
@@ -39,12 +47,10 @@ public final class DefaultNetconfMonitoringService extends NetconfMonitoringServ
         super.close();
     }
 
-    static Map<String, ?> props(final NetconfOperationServiceFactory opProvider,
-            final ScheduledExecutorService threadPool, final long updateInterval) {
+    static Map<String, ?> props(final NetconfOperationServiceFactory opProvider, final long updateInterval) {
         return Map.of(
             "type", "netconf-server-monitoring",
             OP_PROVIDER_PROP, requireNonNull(opProvider),
-            THREAD_POOL_PROP, requireNonNull(threadPool),
             UPDATE_INTERVAL_PROP, updateInterval);
     }
 }
index 6f193cf3f12c99c2ad39a2995708e7d25bb98ddd..ee6271593eb2df923be15b38e70bae8040e2aee1 100644 (file)
@@ -12,7 +12,6 @@ import static java.util.Objects.requireNonNull;
 
 import io.netty.util.Timer;
 import java.util.Map;
-import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
 import org.opendaylight.netconf.server.NetconfServerSessionNegotiatorFactory;
 import org.opendaylight.netconf.server.ServerTransportInitializer;
 import org.opendaylight.netconf.server.api.SessionIdProvider;
@@ -50,15 +49,12 @@ public final class OSGiNetconfServer {
             final ComponentFactory<DefaultNetconfMonitoringService> monitoringFactory,
             @Reference(target = "(type=mapper-aggregator-registry)")
             final NetconfOperationServiceFactory mapperAggregatorRegistry,
-            @Reference(target = "(type=global-netconf-ssh-scheduled-executor)")
-            final ScheduledThreadPool sshScheduledExecutor,
             @Reference(target = "(type=global-timer)") final Timer timer,
             @Reference final SessionIdProvider sessionIdProvider,
             final Configuration configuration) {
         mappers.onAddNetconfOperationServiceFactory(mapperAggregatorRegistry);
         monitoring = monitoringFactory.newInstance(FrameworkUtil.asDictionary(DefaultNetconfMonitoringService.props(
-            mapperAggregatorRegistry, sshScheduledExecutor.getExecutor(),
-            configuration.monitoring$_$update$_$interval())));
+            mapperAggregatorRegistry, configuration.monitoring$_$update$_$interval())));
         serverTransportInitializer = new ServerTransportInitializer(NetconfServerSessionNegotiatorFactory.builder()
             .setTimer(timer)
             .setAggregatedOpService(mappers)
index fbe7be79ee9210b35a98f5199fc4703cfed868a7..144fac35501577f1b2b5a74157cc40a2f154702c 100644 (file)
@@ -25,7 +25,4 @@ public @interface Configuration {
     @AttributeDefinition(min = "0")
     long keep$_$alive$_$millis$_$flexible$_$thread$_$pool()
         default GlobalNetconfProcessingExecutor.DEFAULT_KEEPALIVE_MILLIS;
-    @AttributeDefinition(min = "1")
-    int max$_$thread$_$count$_$scheduled$_$thread$_$pool()
-        default GlobalNetconfSshScheduledExecutor.DEFAULT_MAX_THREAD_COUNT;
 }
index 0d0bfd4dd504701a7b78ae0a7da62fdc17f375e0..de2c608bbf7e5e12f14b8ef7bcb8139d4aa06635 100644 (file)
@@ -33,29 +33,21 @@ public final class GlobalNetconfConfiguration {
     private static final Logger LOG = LoggerFactory.getLogger(GlobalNetconfConfiguration.class);
 
     private final ComponentFactory<GlobalNetconfProcessingExecutor> processingFactory;
-    private final ComponentFactory<GlobalNetconfSshScheduledExecutor> sshScheduledFactory;
 
     private GlobalNetconfThreadFactory threadFactory;
     private ComponentInstance<GlobalNetconfProcessingExecutor> processingExecutor;
     private Map<String, ?> processingProps;
-    private ComponentInstance<GlobalNetconfSshScheduledExecutor> sshScheduledExecutor;
-    private Map<String, ?> sshScheduledProps;
 
     @Activate
     public GlobalNetconfConfiguration(
             @Reference(target = "(component.factory=" + GlobalNetconfProcessingExecutor.FACTORY_NAME + ")")
             final ComponentFactory<GlobalNetconfProcessingExecutor> processingFactory,
-            @Reference(target = "(component.factory=" + GlobalNetconfSshScheduledExecutor.FACTORY_NAME + ")")
-            final ComponentFactory<GlobalNetconfSshScheduledExecutor> sshScheduledFactory,
             final Configuration configuration) {
         this.processingFactory = requireNonNull(processingFactory);
-        this.sshScheduledFactory = requireNonNull(sshScheduledFactory);
 
         threadFactory = new GlobalNetconfThreadFactory(configuration.name$_$prefix());
         processingProps = GlobalNetconfProcessingExecutor.props(threadFactory, configuration);
         processingExecutor = processingFactory.newInstance(FrameworkUtil.asDictionary(processingProps));
-        sshScheduledProps = GlobalNetconfSshScheduledExecutor.props(threadFactory, configuration);
-        sshScheduledExecutor = sshScheduledFactory.newInstance(FrameworkUtil.asDictionary(sshScheduledProps));
         LOG.info("Global NETCONF configuration pools started");
     }
 
@@ -65,7 +57,6 @@ public final class GlobalNetconfConfiguration {
         if (!threadFactory.getNamePrefix().equals(newNamePrefix)) {
             threadFactory = new GlobalNetconfThreadFactory(newNamePrefix);
             processingProps = null;
-            sshScheduledProps = null;
             LOG.debug("Forcing restart of all executors");
         }
 
@@ -80,14 +71,6 @@ public final class GlobalNetconfConfiguration {
             LOG.debug("Processing executor restarted with {}", processingProps);
         }
 
-        final var newSshScheduledProps = GlobalNetconfSshScheduledExecutor.props(threadFactory, configuration);
-        if (!newSshScheduledProps.equals(sshScheduledProps)) {
-            sshScheduledProps = newSshScheduledProps;
-            toDispose.add(sshScheduledExecutor);
-            sshScheduledExecutor = sshScheduledFactory.newInstance(FrameworkUtil.asDictionary(sshScheduledProps));
-            LOG.debug("Scheduled executor restarted with {}", sshScheduledProps);
-        }
-
         toDispose.forEach(ComponentInstance::dispose);
     }
 
@@ -95,8 +78,6 @@ public final class GlobalNetconfConfiguration {
     void deactivate() {
         processingExecutor.dispose();
         processingExecutor = null;
-        sshScheduledExecutor.dispose();
-        sshScheduledExecutor = null;
         threadFactory = null;
         LOG.info("Global NETCONF configuration pools stopped");
     }
diff --git a/netconf/netconf-config/src/main/java/org/opendaylight/netconf/config/GlobalNetconfSshScheduledExecutor.java b/netconf/netconf-config/src/main/java/org/opendaylight/netconf/config/GlobalNetconfSshScheduledExecutor.java
deleted file mode 100644 (file)
index 29e0bfc..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2023 PANTHEON.tech, s.r.o. 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.netconf.config;
-
-import static java.util.Objects.requireNonNull;
-
-import java.util.Map;
-import javax.annotation.PreDestroy;
-import javax.inject.Inject;
-import javax.inject.Singleton;
-import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
-import org.opendaylight.controller.config.threadpool.util.ScheduledThreadPoolWrapper;
-import org.osgi.service.component.annotations.Activate;
-import org.osgi.service.component.annotations.Component;
-import org.osgi.service.component.annotations.Deactivate;
-
-@Singleton
-@Component(factory = GlobalNetconfSshScheduledExecutor.FACTORY_NAME, service = ScheduledThreadPool.class)
-public final class GlobalNetconfSshScheduledExecutor extends ScheduledThreadPoolWrapper {
-    public static final String OSGI_TYPE = "global-netconf-ssh-scheduled-executor";
-    public static final int DEFAULT_MAX_THREAD_COUNT = 8;
-
-    // OSGi DS Component Factory name
-    static final String FACTORY_NAME = "org.opendaylight.netconf.config.GlobalNetconfSshScheduledExecutor";
-
-    private static final String PROP_MAX_THREAD_COUNT = ".maxThreadCount";
-    private static final String PROP_THREAD_FACTORY = ".threadFactory";
-
-    public GlobalNetconfSshScheduledExecutor(final GlobalNetconfThreadFactory threadFactory, final int maxThreadCount) {
-        super(maxThreadCount, threadFactory);
-    }
-
-    @Inject
-    public GlobalNetconfSshScheduledExecutor(final GlobalNetconfThreadFactory threadFactory) {
-        this(threadFactory, DEFAULT_MAX_THREAD_COUNT);
-    }
-
-    @Activate
-    public GlobalNetconfSshScheduledExecutor(final Map<String, ?> properties) {
-        this(GlobalNetconfConfiguration.extractProp(properties, PROP_THREAD_FACTORY, GlobalNetconfThreadFactory.class),
-            GlobalNetconfConfiguration.extractProp(properties, PROP_MAX_THREAD_COUNT, Integer.class));
-    }
-
-    @Override
-    @PreDestroy
-    @Deactivate
-    public void close() {
-        super.close();
-    }
-
-    static Map<String, ?> props(final GlobalNetconfThreadFactory threadFactory, final Configuration configuration) {
-        return Map.of(
-            "type", OSGI_TYPE,
-            PROP_MAX_THREAD_COUNT, configuration.max$_$thread$_$count$_$scheduled$_$thread$_$pool(),
-            PROP_THREAD_FACTORY, requireNonNull(threadFactory));
-    }
-}
index 1c06140cedc4db802d378a45fb2eee0ebf6079c3..4cf467278183c7708ecbdad60a2715e09aeca17d 100644 (file)
@@ -12,8 +12,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.opendaylight.controller.config.threadpool.util.NamingThreadPoolFactory;
 
 /**
- * Shared {@link NamingThreadPoolFactory} for {@link GlobalNetconfProcessingExecutor} and
- * {@link GlobalNetconfSshScheduledExecutor}.
+ * Shared {@link NamingThreadPoolFactory} for {@link GlobalNetconfProcessingExecutor}.
  */
 @NonNullByDefault
 public final class GlobalNetconfThreadFactory extends NamingThreadPoolFactory {
index e0bddc78220a9fd90fcb0174c3dfa0fddd74111f..8fb2c53f204556bf4437fa3e194f151d3b8f1ad0 100644 (file)
@@ -10,7 +10,9 @@ package org.opendaylight.netconf.server.osgi;
 import static java.util.Objects.requireNonNull;
 
 import java.util.Optional;
+import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.TimeUnit;
 import org.opendaylight.netconf.server.api.monitoring.NetconfMonitoringService;
 import org.opendaylight.netconf.server.api.monitoring.SessionListener;
@@ -24,17 +26,33 @@ import org.opendaylight.yangtools.concepts.Registration;
 public class NetconfMonitoringServiceImpl implements NetconfMonitoringService, AutoCloseable {
     private final NetconfCapabilityMonitoringService capabilityMonitoring;
     private final NetconfSessionMonitoringService sessionMonitoring;
+    private final ScheduledExecutorService executorService;
 
     private NetconfMonitoringServiceImpl(final NetconfOperationServiceFactory opProvider,
             final NetconfSessionMonitoringService sessionMonitoring) {
         capabilityMonitoring = new NetconfCapabilityMonitoringService(opProvider);
         this.sessionMonitoring = requireNonNull(sessionMonitoring);
+        executorService = null;
     }
 
     public NetconfMonitoringServiceImpl(final NetconfOperationServiceFactory opProvider) {
         this(opProvider, new NetconfSessionMonitoringService.WithoutUpdates());
     }
 
+    public NetconfMonitoringServiceImpl(final NetconfOperationServiceFactory opProvider,
+            final ThreadFactory threadFactory, final long period, final TimeUnit timeUnit) {
+        capabilityMonitoring = new NetconfCapabilityMonitoringService(opProvider);
+        if (period > 0) {
+            executorService = Executors.unconfigurableScheduledExecutorService(
+                // Note: 0 core pool size, as we want to shut the thread down when we do not have listeners
+                Executors.newScheduledThreadPool(0, threadFactory));
+            sessionMonitoring = new NetconfSessionMonitoringService.WithUpdates(executorService, period, timeUnit);
+        } else {
+            executorService = null;
+            sessionMonitoring = new NetconfSessionMonitoringService.WithoutUpdates();
+        }
+    }
+
     public NetconfMonitoringServiceImpl(final NetconfOperationServiceFactory opProvider,
             final ScheduledExecutorService threadPool, final long periodSeconds) {
         this(opProvider, periodSeconds > 0
@@ -85,5 +103,8 @@ public class NetconfMonitoringServiceImpl implements NetconfMonitoringService, A
     public void close() {
         capabilityMonitoring.close();
         sessionMonitoring.close();
+        if (executorService != null) {
+            executorService.shutdown();
+        }
     }
 }