io.udvi.amqp.mq.transport.connection.CAMQPConnectionManager.java Source code

Java tutorial

Introduction

Here is the source code for io.udvi.amqp.mq.transport.connection.CAMQPConnectionManager.java

Source

/**
 * Copyright 2013 Suresh Reddy Guntaka
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * You may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package io.udvi.amqp.mq.transport.connection;

import io.udvi.amqp.mq.transport.session.CAMQPSessionManager;
import io.udvi.amqp.mq.transport.utils.CAMQPThreadFactory;

import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

/**
 * Manages outstanding AMQP connections
 * @author tejdas
 *
 */
public final class CAMQPConnectionManager {
    private static final Logger log = Logger.getLogger(CAMQPConnectionManager.class);

    private static volatile CAMQPConnectionObserver connectionObserver = null;

    private static volatile String containerId = null;

    private static final AtomicBoolean shutdownInProgress = new AtomicBoolean(false);

    private static final ConcurrentMap<CAMQPConnectionKey, CAMQPConnection> openConnections = new ConcurrentHashMap<>();

    private static final Object shutdownLock = new Object();

    private static final ScheduledExecutorService connectionHeartbeatScheduler = Executors.newScheduledThreadPool(
            CAMQPConnectionConstants.DEFAULT_HEARTBEAT_PROCESSOR_THREAD_COUNT,
            new CAMQPThreadFactory("UdviMQConnectionHeartbeatProcessor"));

    static ScheduledExecutorService getConnectionHeartbeatScheduler() {
        return connectionHeartbeatScheduler;
    }

    public synchronized static void initialize(String containerId) {
        if (CAMQPConnectionManager.containerId == null) {
            String hostName = "localhost";
            try {
                InetAddress localMachine = InetAddress.getLocalHost();
                hostName = localMachine.getHostAddress();
                log.debug("hostName: " + hostName);
            } catch (java.net.UnknownHostException uhe) {
                String errorMessage = "Caught UnknownHostException while resolving canonicalHostName: "
                        + uhe.getMessage();
                log.error(errorMessage);
                throw new CAMQPConnectionException(errorMessage);
            }
            CAMQPConnectionManager.containerId = String.format("%s@%s", containerId, hostName);
            log.info("Initialized UdviMQ endpoint ID: " + CAMQPConnectionManager.containerId);
            System.out.println("Initialized UdviMQ endpoint ID: " + CAMQPConnectionManager.containerId);
        } else {
            throw new IllegalStateException("CAMQPConnectionManager already initialized: containerId: "
                    + CAMQPConnectionManager.containerId);
        }
    }

    /*
     * Used only by CAMQP functional tests
     */
    public static CAMQPConnection getCAMQPConnection(String targetContainerId) {
        Collection<CAMQPConnectionKey> keys = openConnections.keySet();
        for (CAMQPConnectionKey key : keys) {
            if (StringUtils.equalsIgnoreCase(key.getRemoteContainerId(), targetContainerId)) {
                return openConnections.get(key);
            }
        }
        return null;
    }

    /*
     * Used only for functional tests
     */
    public static CAMQPConnection getAnyCAMQPConnection(String targetContainerId) {
        return getCAMQPConnection(targetContainerId);
    }

    public static void registerConnectionObserver(CAMQPConnectionObserver connectionAcceptor) {
        CAMQPConnectionManager.connectionObserver = connectionAcceptor;
    }

    public static String getContainerId() {
        return containerId;
    }

    static Collection<String> listConnections() {
        Collection<String> connectionList = new ArrayList<>();
        Set<CAMQPConnectionKey> keys = openConnections.keySet();
        for (CAMQPConnectionKey k : keys) {
            connectionList.add(k.toString());
        }
        return connectionList;
    }

    static void connectionClosed(CAMQPConnectionKey key) {
        connectionClosedInternal(key);
        CAMQPSessionManager.connectionClosed(key);
    }

    static void connectionAborted(CAMQPConnectionKey key) {
        CAMQPConnection abortedConnection = connectionClosedInternal(key);
        if (abortedConnection != null) {
            abortedConnection.aborted();
        }
        CAMQPSessionManager.connectionClosed(key);
    }

    private static CAMQPConnection connectionClosedInternal(CAMQPConnectionKey key) {
        CAMQPConnection connection = openConnections.remove(key);
        if (shutdownInProgress.get()) {
            synchronized (shutdownLock) {
                if (openConnections.size() == 0) {
                    shutdownLock.notifyAll();
                }
            }
        }
        return connection;
    }

    static void connectionCreated(CAMQPConnectionKey key, CAMQPConnection connection) {
        connectionCreatedInternal(key, connection);
    }

    private static void connectionCreatedInternal(CAMQPConnectionKey key, CAMQPConnection connection) {
        if (shutdownInProgress.get()) {
            log.error(
                    "Shutdown is already in progress: cannot add CAMQPConnection to ConnectionManager's openConnectionsList");
            return; // TODO handle error
        }
        openConnections.put(key, connection);
    }

    static void connectionAccepted(CAMQPConnectionStateActor stateActor, CAMQPConnectionKey key) {
        CAMQPConnection amqpConnection = new CAMQPConnection(stateActor);
        connectionCreatedInternal(key, amqpConnection);
    }

    public static void connectionCloseInitiatedByRemotePeer(CAMQPConnectionKey key) {
        if (connectionObserver != null) {
            CAMQPConnection connection = openConnections.get(key);
            if (connection != null) {
                connectionObserver.connectionCloseInitiatedByRemotePeer(connection);
            } else {
                log.warn("Connection not found in the openConnections list: " + key.toString());
            }
        }
    }

    public static void shutdown() {
        if (!shutdownInProgress.compareAndSet(false, true)) {
            return;
        }

        Collection<CAMQPConnectionKey> connectionKeys = openConnections.keySet();
        for (CAMQPConnectionKey connectionKey : connectionKeys) {
            CAMQPConnection connection = openConnections.get(connectionKey);
            if (connection != null) {
                connection.closeAsync();
            }
        }
        try {
            synchronized (shutdownLock) {
                while (openConnections.size() > 0) {
                    shutdownLock.wait();
                }
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        connectionHeartbeatScheduler.shutdown();
        try {
            connectionHeartbeatScheduler.awaitTermination(300, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }

        log.info("Shutdown UdviMQ endpoint ID: " + containerId);
        System.out.println("Shutdown UdviMQ endpoint ID: " + containerId);
    }
}