/* * Copyright (c) 2015 Huawei, 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.usc.plugin; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; import io.netty.channel.local.LocalChannel; import java.util.Collection; import java.util.concurrent.ConcurrentHashMap; import org.opendaylight.usc.manager.monitor.evt.UscSessionCloseEvent; import org.opendaylight.usc.manager.monitor.evt.UscSessionCreateEvent; import org.opendaylight.usc.plugin.model.UscSession; import org.opendaylight.usc.plugin.model.UscSessionImpl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.annotations.VisibleForTesting; /** * This class manages the collection of client sessions that are currently * established to this controller node. */ public abstract class UscSessionManager { private static final Logger log = LoggerFactory.getLogger(UscSessionManager.class); private final UscPlugin plugin; /** * One session manager is created per connection, so the session IDs here * are unique */ private final ConcurrentHashMap<Integer, UscSessionImpl> sessions = new ConcurrentHashMap<>(); protected UscSessionManager(UscPlugin plugin) { this.plugin = plugin; } /** * Add a session (channel) to this session manager. * * @param port * @param channel * @return */ public UscSessionImpl addSession(int port, LocalChannel channel) { // generate unique session ID for this agent // valid session ID range is 1 to 65535 // always assign in sequential order for ease of testing for (int sessionId = 1; sessionId <= Character.MAX_VALUE; ++sessionId) { // standard idiom for double-checked locking if (!sessions.containsKey(sessionId)) { final UscSessionImpl session = createSession(sessionId, port, channel); if (sessions.putIfAbsent(sessionId, session) == null) { final int sId = sessionId; channel.closeFuture().addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { removeSession(sId); log.trace("serverChannel for session " + sId + " closed"); } }); plugin.sendEvent(new UscSessionCreateEvent(session)); return session; } } } throw new RuntimeException("out of available session IDs"); } /** * Remove all sessions from this manager. */ public void removeAllSessions() { sessions.keySet().stream().forEach(this::removeSession); } public UscSession removeSession(int sessionId) { UscSessionImpl session = sessions.remove(sessionId); if (session != null) { plugin.sendEvent(new UscSessionCloseEvent(session)); } return session; } /** * Get the session information corresponding to a session ID. * * @param sessionId * @return */ public UscSessionImpl getSession(int sessionId) { return sessions.get(sessionId); } /** * * @return return all sessions */ public Collection<UscSessionImpl> getAllSessions() { return sessions.values(); } @VisibleForTesting public int getSessionCount() { return sessions.size(); } protected abstract UscSessionImpl createSession(int sessionId, int port, LocalChannel channel); }