2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netconf.server.osgi;
10 import static java.util.Objects.requireNonNull;
12 import com.google.common.collect.ImmutableList;
13 import java.util.HashSet;
15 import java.util.concurrent.ScheduledExecutorService;
16 import java.util.concurrent.ScheduledFuture;
17 import java.util.concurrent.TimeUnit;
18 import java.util.stream.Collectors;
19 import org.checkerframework.checker.lock.qual.Holding;
20 import org.opendaylight.netconf.server.api.monitoring.NetconfManagementSession;
21 import org.opendaylight.netconf.server.api.monitoring.NetconfMonitoringService;
22 import org.opendaylight.netconf.server.api.monitoring.SessionEvent;
23 import org.opendaylight.netconf.server.api.monitoring.SessionListener;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Sessions;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.SessionsBuilder;
26 import org.opendaylight.yangtools.concepts.AbstractRegistration;
27 import org.opendaylight.yangtools.concepts.Registration;
28 import org.opendaylight.yangtools.yang.binding.util.BindingMap;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
33 * This class implements {@link SessionListener} to receive updates about Netconf sessions. Instance notifies its
34 * listeners about session start and end. It also publishes on regular interval list of sessions,
35 * where events like rpc or notification happened.
37 abstract sealed class NetconfSessionMonitoringService implements SessionListener, AutoCloseable {
38 static final class WithoutUpdates extends NetconfSessionMonitoringService {
40 LOG.info("/netconf-state/sessions will not be updated.");
54 static final class WithUpdates extends NetconfSessionMonitoringService {
55 private final ScheduledExecutorService executor;
56 private final long period;
57 private final TimeUnit timeUnit;
59 private ScheduledFuture<?> task;
61 WithUpdates(final ScheduledExecutorService executor, final long period, final TimeUnit timeUnit) {
62 this.executor = requireNonNull(executor);
64 this.timeUnit = requireNonNull(timeUnit);
65 LOG.info("/netconf-state/sessions will be updated every {} {}.", period, timeUnit);
71 task = executor.scheduleAtFixedRate(this::updateSessionStats, period, period, timeUnit);
84 private static final Logger LOG = LoggerFactory.getLogger(NetconfSessionMonitoringService.class);
86 private final Set<NetconfManagementSession> sessions = new HashSet<>();
87 private final Set<NetconfManagementSession> changedSessions = new HashSet<>();
88 private final Set<NetconfMonitoringService.SessionsListener> listeners = new HashSet<>();
90 synchronized Sessions getSessions() {
91 return new SessionsBuilder()
92 .setSession(BindingMap.of(
93 sessions.stream().map(NetconfManagementSession::toManagementSession).collect(Collectors.toList())))
98 public final synchronized void onSessionUp(final NetconfManagementSession session) {
99 LOG.debug("Session {} up", session);
100 if (!sessions.add(session)) {
101 throw new IllegalStateException("Session " + session + " was already added");
104 final var mgmt = session.toManagementSession();
105 for (var listener : listeners) {
106 listener.onSessionStarted(mgmt);
111 public final synchronized void onSessionDown(final NetconfManagementSession session) {
112 LOG.debug("Session {} down", session);
113 if (!sessions.remove(session)) {
114 throw new IllegalStateException("Session " + session + " not present");
116 changedSessions.remove(session);
118 final var mgmt = session.toManagementSession();
119 for (var listener : listeners) {
120 listener.onSessionEnded(mgmt);
125 public final synchronized void onSessionEvent(final SessionEvent event) {
126 changedSessions.add(event.getSession());
129 final synchronized Registration registerListener(final NetconfMonitoringService.SessionsListener listener) {
130 listeners.add(listener);
132 return new AbstractRegistration() {
134 protected void removeRegistration() {
135 listeners.remove(listener);
141 public final synchronized void close() {
148 abstract void startTask();
151 abstract void stopTask();
153 final synchronized void updateSessionStats() {
154 if (!changedSessions.isEmpty()) {
155 final var updatedSessions = changedSessions.stream()
156 .map(NetconfManagementSession::toManagementSession)
157 .collect(ImmutableList.toImmutableList());
158 changedSessions.clear();
160 for (var listener : listeners) {
161 listener.onSessionsUpdated(updatedSessions);