/* * 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.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; import java.util.concurrent.ConcurrentHashMap; import org.opendaylight.usc.manager.UscRouteBrokerService; import org.opendaylight.usc.manager.cluster.UscRemoteChannelIdentifier; import org.opendaylight.usc.manager.cluster.message.UscRemoteChannelEventMessage; import org.opendaylight.usc.manager.monitor.evt.UscChannelCloseEvent; import org.opendaylight.usc.manager.monitor.evt.UscChannelCreateEvent; import org.opendaylight.usc.plugin.model.UscChannel; import org.opendaylight.usc.plugin.model.UscChannelImpl; import org.opendaylight.usc.plugin.model.UscDevice; import org.opendaylight.usc.util.UscServiceUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.annotations.VisibleForTesting; /** * This class manages the collection of connections (channels) that are * currently established to this controller node. */ public class UscConnectionManager { private static final Logger log = LoggerFactory.getLogger(UscConnectionManager.class); private final UscPlugin plugin; private UscRouteBrokerService brokerService = null; /** * Map from host name to agentChannel */ private final ConcurrentHashMap<UscDevice, UscChannelImpl> connections = new ConcurrentHashMap<>(); protected UscConnectionManager(UscPlugin plugin) { this.plugin = plugin; brokerService = UscServiceUtils.getService(UscRouteBrokerService.class); } public UscChannelImpl getConnection(UscDevice device, UscChannel.ChannelType type) throws Exception { UscChannelImpl connection = connections.get(device); log.trace("device is" + device + ",type is " + type + ",Connections is " + connections); if (connection == null) { /* * Channel channel = null; try { channel = * plugin.connectToAgent(device); }catch(Exception e) { * log.warn(e.getMessage()); channel = * plugin.connectToDeviceDirectly(device); } * * return addConnection(device, channel, false, type); */ return addConnection(device, plugin.connectToAgent(device), false, type); } else { return connection; } } protected UscChannelImpl addConnection(final UscDevice device, final Channel channel, final boolean isCallHome, final UscChannel.ChannelType type) { // standard idiom for double-checked locking UscChannelImpl connection = connections.get(device); if (connection == null) { final UscChannelImpl newConnection = new UscChannelImpl(plugin, device, channel, isCallHome, type); connection = connections.putIfAbsent(device, newConnection); if (connection == null) { channel.closeFuture().addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { removeConnection(newConnection); log.trace("agentChannel for device " + device + " closed"); } }); if (brokerService != null) { UscRemoteChannelIdentifier remoteChannel = new UscRemoteChannelIdentifier(newConnection.getDevice() .getInetAddress(), newConnection.getType()); brokerService.broadcastMessage(new UscRemoteChannelEventMessage(remoteChannel, UscRemoteChannelEventMessage.ChannelEventType.CREATE)); } else { log.warn("Broker service is null, can't send broadcast for adding channel message(" + newConnection.getDevice().getInetAddress() + ")!"); } plugin.sendEvent(new UscChannelCreateEvent(newConnection)); connection = newConnection; } else { // previous entry exists; put failed; close the new channel channel.close(); } } return connection; } public boolean removeConnection(UscChannelImpl connection) { // don't re-close the connection here since we should only reach this // point after the connection has been closed boolean isRemoved = connections.remove(connection.getDevice(), connection); if (isRemoved) { connection.removeAllSessions(); plugin.sendEvent(new UscChannelCloseEvent(connection)); } return isRemoved; } @VisibleForTesting public int getConnectionCount() { return connections.size(); } @VisibleForTesting public int getSessionCount() { return connections.values().stream().mapToInt(UscChannelImpl::getSessionCount).sum(); } @Override public String toString() { return connections.toString(); } }