org.opendaylight.usc.UscChannelServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.opendaylight.usc.UscChannelServiceImpl.java

Source

/*
 * 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;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.local.LocalChannel;
import io.netty.channel.local.LocalEventLoopGroup;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.util.AttributeKey;

import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Future;

import org.opendaylight.usc.manager.UscManagerService;
import org.opendaylight.usc.manager.UscTopologyService;
import org.opendaylight.usc.manager.api.UscShardService;
import org.opendaylight.usc.plugin.UscPlugin;
import org.opendaylight.usc.plugin.model.UscChannelImpl;
import org.opendaylight.usc.util.UscServiceUtils;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.usc.channel.rev150101.AddChannelInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.usc.channel.rev150101.AddChannelOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.usc.channel.rev150101.AddChannelOutputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.usc.channel.rev150101.RemoveChannelInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.usc.channel.rev150101.RemoveChannelOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.usc.channel.rev150101.RemoveChannelOutputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.usc.channel.rev150101.RemoveSessionInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.usc.channel.rev150101.RemoveSessionOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.usc.channel.rev150101.RemoveSessionOutputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.usc.channel.rev150101.UscChannelService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.usc.channel.rev150101.ViewChannelInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.usc.channel.rev150101.ViewChannelOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.usc.channel.rev150101.ViewChannelOutputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.usc.channel.rev150101.view.channel.output.Topology;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.usc.channel.rev150101.view.channel.output.TopologyBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.usc.channel.rev150101.view.channel.output.TopologyKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.usc.channel.rev150101.SendMessageInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.usc.channel.rev150101.SendMessageOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.usc.channel.rev150101.SendMessageOutputBuilder;
import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Implementation of the YANG RPCs defined in module usc. Service provides rpc
 * for viewing the usc topology.
 */
public class UscChannelServiceImpl implements UscChannelService {
    private static final Logger LOG = LoggerFactory.getLogger(UscChannelServiceImpl.class);
    @SuppressWarnings("rawtypes")
    private UscShardService shardService;
    private UscTopologyService topoService;
    public static final AttributeKey<String> CLIENT_KEY = AttributeKey.valueOf("client_key");
    private ConcurrentMap<String, Channel> connectList = new ConcurrentHashMap<String, Channel>();
    private ConcurrentMap<String, EventLoopGroup> groupList = new ConcurrentHashMap<String, EventLoopGroup>();

    /**
     * Create a UscService and initialize the Shard Service
     */
    public UscChannelServiceImpl() {
        shardService = UscServiceUtils.getService(UscShardService.class);
        if (shardService == null) {
            LOG.error("Failed to get UscShardService!");
        }
        topoService = UscServiceUtils.getService(UscTopologyService.class);
    }

    /**
     * Implements rpc call for viewing the usc topology.
     */

    @Override
    public Future<RpcResult<AddChannelOutput>> addChannel(AddChannelInput input) {
        String hostname = input.getChannel().getHostname();
        int port = input.getChannel().getPort();
        AddChannelOutputBuilder builder = new AddChannelOutputBuilder();
        boolean isTcp = input.getChannel().isTcp();
        String result = connectDevice(hostname, port, isTcp, input.getChannel().isRemote());
        builder.setResult(result);
        return RpcResultBuilder.success(builder.build()).buildFuture();
    }

    private String connectDevice(String hostname, int port, boolean isTcp, boolean remote) {
        Bootstrap clientBootStrap = getNewBootstrap();
        InetSocketAddress address = new InetSocketAddress(hostname, port);
        try {
            UscPlugin plugin = null;
            if (isTcp)
                plugin = UscManagerService.getInstance().getPluginTcp();
            else
                plugin = UscManagerService.getInstance().getPluginUdp();

            Channel clientChannel = plugin.connect(clientBootStrap, address, remote).sync().channel();
            clientChannel.attr(CLIENT_KEY).set(hostname + ":" + port + isTcp);
            connectList.put(hostname + ":" + port + isTcp, clientChannel);
            groupList.put(hostname + ":" + port + isTcp, clientBootStrap.group());
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return "Failed to Connect device(" + hostname + ":" + port + ")!error is " + e.getMessage();
        }
        return "Succeed to connect device(" + hostname + ":" + port + ")!";
    }

    private Bootstrap getNewBootstrap() {
        Bootstrap ret = new Bootstrap();
        EventLoopGroup localGroup = new LocalEventLoopGroup();

        // set up client bootstrap
        ret.group(localGroup);
        ret.channel(LocalChannel.class);
        ret.handler(new ChannelInitializer<LocalChannel>() {
            @Override
            public void initChannel(LocalChannel ch) throws Exception {
                ChannelPipeline p = ch.pipeline();
                p.addLast(new LoggingHandler("Manager Test 1", LogLevel.TRACE));
            }
        });
        return ret;
    }

    private void closeConnect(EventLoopGroup localGroup) {
        localGroup.shutdownGracefully();

        // allow some time for all ports to close;
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    @Override
    public Future<RpcResult<RemoveChannelOutput>> removeChannel(RemoveChannelInput input) {
        String hostname = input.getChannel().getHostname();
        boolean isTcp = input.getChannel().isTcp();

        LOG.debug("Beginning of removeChannel: connectList is " + connectList + "; groupList is " + groupList);
        Iterator it = connectList.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<String, Channel> item = (Map.Entry<String, Channel>) it.next();
            String connectionName = item.getKey();
            if (connectionName.contains(hostname) && connectionName.contains(Boolean.toString(isTcp))) {
                Channel clientChannel = connectList.get(connectionName);
                clientChannel.close();
                it.remove();
            }
        }

        it = groupList.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<String, EventLoopGroup> item = (Map.Entry<String, EventLoopGroup>) it.next();
            String groupName = item.getKey();
            if (groupName.contains(hostname) && groupName.contains(Boolean.toString(isTcp))) {
                EventLoopGroup group = item.getValue();
                closeConnect(group);
                it.remove();
            }
        }

        UscPlugin plugin = null;
        if (isTcp)
            plugin = UscManagerService.getInstance().getPluginTcp();
        else
            plugin = UscManagerService.getInstance().getPluginUdp();

        String result = "Failed to remove channel(" + hostname + ": " + isTcp + ")!";
        InetSocketAddress address = new InetSocketAddress(hostname, 9999);
        UscChannelImpl channelImpl = plugin.retrieveChannelImpl(address);
        if (channelImpl != null) {
            LOG.info("address is" + address + ", Channel is " + channelImpl.getChannel());
            channelImpl.getChannel().close();
            result = "Succeed to remove channel(" + hostname + ": " + isTcp + ")!";
        }

        LOG.debug("End of removeChannel: connectList is " + connectList + "; groupList is " + groupList);

        RemoveChannelOutputBuilder builder = new RemoveChannelOutputBuilder();
        builder.setResult(result);
        return RpcResultBuilder.success(builder.build()).buildFuture();
    }

    @Override
    public Future<RpcResult<RemoveSessionOutput>> removeSession(RemoveSessionInput input) {
        String hostname = input.getChannel().getHostname();
        int port = input.getChannel().getPort();
        boolean isTcp = input.getChannel().isTcp();

        LOG.debug("Beginning of removeSession: connectList is " + connectList + "; groupList is " + groupList);
        Channel clientChannel = connectList.get(hostname + ":" + port + isTcp);
        EventLoopGroup group = groupList.get(hostname + ":" + port + isTcp);
        String result = "";
        LOG.info("connectList number is " + connectList.size());

        if (clientChannel == null) {
            result = "Failed to remove channel(" + hostname + ":" + port + ")!";
        } else {
            // plugin.closeAgentInternalConnection(clientChannel);
            closeConnect(group);
            clientChannel.close();
            connectList.remove(hostname + ":" + port + isTcp);
            groupList.remove(hostname + ":" + port + isTcp);

            result = "Succeed to remove session (" + hostname + ":" + port + ")!";
        }

        LOG.debug("End of removeSession: connectList is " + connectList + "; groupList is " + groupList);
        RemoveSessionOutputBuilder builder = new RemoveSessionOutputBuilder();
        builder.setResult(result);
        return RpcResultBuilder.success(builder.build()).buildFuture();
    }

    @SuppressWarnings("unchecked")
    @Override
    public Future<RpcResult<ViewChannelOutput>> viewChannel(ViewChannelInput input) {
        if (topoService == null || shardService == null) {
            LOG.error("USC Topology Service is not initialized, currently can't process this rpc request.");
            return (Future<RpcResult<ViewChannelOutput>>) RpcResultBuilder.failed()
                    .withError(ErrorType.RPC, "Internal error,For details please see the log.").build();
        }

        // Build Output
        // there only one whole topology
        org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.usc.channel.rev150101.usc.topology.Topology topo = topoService
                .getWholeUscTopology();
        if (topo == null) {
            return (Future<RpcResult<ViewChannelOutput>>) RpcResultBuilder.failed()
                    .withError(ErrorType.RPC, "Internal error,For details please see the log.").build();
        }
        ViewChannelOutputBuilder outputBuilder = new ViewChannelOutputBuilder();
        TopologyBuilder topoBuilder = new TopologyBuilder();
        TopologyKey topoKey = new TopologyKey(topo.getTopologyId());
        Topology outputTopo = topoBuilder.setChannel(topo.getChannel()).setKey(topoKey).setNode(topo.getNode())
                .setTopologyId(topo.getTopologyId()).build();
        List<Topology> outputTopologyList = new ArrayList<Topology>();
        outputTopologyList.add(outputTopo);
        outputBuilder.setTopology(outputTopologyList);
        ViewChannelOutput output = outputBuilder.build();
        // Return Results
        return RpcResultBuilder.success(output).buildFuture();
    }

    @Override
    public Future<RpcResult<SendMessageOutput>> sendMessage(SendMessageInput input) {
        String hostname = input.getChannel().getHostname();
        int port = input.getChannel().getPort();
        boolean isTcp = input.getChannel().isTcp();

        Channel clientChannel = connectList.get(hostname + ":" + port + isTcp);
        String result = "";
        //        outputConnectList();
        ByteBuf payload = Unpooled.buffer(10000);
        payload.writeBytes(input.getChannel().getContent().getBytes());
        if (clientChannel == null) {
            result = "Failed to send request to device(" + hostname + ":" + port + "), since it is not found!";
        } else {
            clientChannel.writeAndFlush(payload);
            result = "Succeed to send request to device(" + hostname + ":" + port + "),content is "
                    + input.getChannel().getContent();
        }
        SendMessageOutputBuilder builder = new SendMessageOutputBuilder();
        builder.setResult(result);
        return RpcResultBuilder.success(builder.build()).buildFuture();
    }
}