All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jdiameter.server.impl.MutablePeerTableImpl Maven / Gradle / Ivy

There is a newer version: 2.0.5
Show newest version
/*
 * TeleStax, Open Source Cloud Communications
 * Copyright 2011-2014, TeleStax Inc. and individual contributors
 * by the @authors tag.
 *
 * This program is free software: you can redistribute it and/or modify
 * under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation; either version 3 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see 
 *
 * This file incorporates work covered by the following copyright and
 * permission notice:
 *
 *   JBoss, Home of Professional Open Source
 *   Copyright 2007-2011, Red Hat, Inc. and individual contributors
 *   by the @authors tag. See the copyright.txt in the distribution for a
 *   full listing of individual contributors.
 *
 *   This is free software; you can redistribute it and/or modify it
 *   under the terms of the GNU Lesser General Public License as
 *   published by the Free Software Foundation; either version 2.1 of
 *   the License, or (at your option) any later version.
 *
 *   This software is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 *   Lesser General Public License for more details.
 *
 *   You should have received a copy of the GNU Lesser General Public
 *   License along with this software; if not, write to the Free
 *   Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 *   02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

package org.jdiameter.server.impl;

import static org.jdiameter.client.impl.helpers.Parameters.*;
import static org.jdiameter.common.api.concurrent.IConcurrentFactory.ScheduledExecServices.*;
import static org.jdiameter.server.impl.helpers.Parameters.*;

import java.io.IOException;
import java.net.InetAddress;
import java.net.URISyntaxException;
import java.net.UnknownServiceException;
import java.util.Collection;
import java.util.HashSet;
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.CopyOnWriteArraySet;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import org.jdiameter.api.Avp;
import org.jdiameter.api.AvpDataException;
import org.jdiameter.api.Configuration;
import org.jdiameter.api.ConfigurationListener;
import org.jdiameter.api.DisconnectCause;
import org.jdiameter.api.IllegalDiameterStateException;
import org.jdiameter.api.InternalException;
import org.jdiameter.api.Message;
import org.jdiameter.api.MetaData;
import org.jdiameter.api.MutableConfiguration;
import org.jdiameter.api.MutablePeerTable;
import org.jdiameter.api.Network;
import org.jdiameter.api.Peer;
import org.jdiameter.api.PeerState;
import org.jdiameter.api.PeerTableListener;
import org.jdiameter.api.Realm;
import org.jdiameter.api.Statistic;
import org.jdiameter.api.URI;
import org.jdiameter.client.api.IContainer;
import org.jdiameter.client.api.IMessage;
import org.jdiameter.client.api.ISessionFactory;
import org.jdiameter.client.api.StackState;
import org.jdiameter.client.api.controller.IRealm;
import org.jdiameter.client.api.fsm.EventTypes;
import org.jdiameter.client.api.io.IConnection;
import org.jdiameter.client.api.io.IConnectionListener;
import org.jdiameter.client.api.io.TransportException;
import org.jdiameter.client.api.parser.IMessageParser;
import org.jdiameter.client.impl.controller.PeerTableImpl;
import org.jdiameter.common.api.concurrent.IConcurrentFactory;
import org.jdiameter.common.api.statistic.IStatisticManager;
import org.jdiameter.server.api.IFsmFactory;
import org.jdiameter.server.api.IMutablePeerTable;
import org.jdiameter.server.api.INetwork;
import org.jdiameter.server.api.IOverloadManager;
import org.jdiameter.server.api.IPeer;
import org.jdiameter.server.api.io.INetworkConnectionListener;
import org.jdiameter.server.api.io.INetworkGuard;
import org.jdiameter.server.api.io.ITransportLayerFactory;
import org.jdiameter.server.impl.helpers.EmptyConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author [email protected]
 * @author  Alexandre Mendonca 
 * @author  Bartosz Baranowski 
 */
@SuppressWarnings("all") //3rd party lib
public class MutablePeerTableImpl extends PeerTableImpl implements IMutablePeerTable, ConfigurationListener {

    private static final Logger logger = LoggerFactory.getLogger(MutablePeerTableImpl.class);

    private static final int CONN_INVALIDATE_PERIOD = 60000;
    private static final int MAX_PEER_TABLE_SIZE = 10000;

    protected Configuration config;
    protected ISessionFactory sessionFactory;
    protected IFsmFactory fsmFactory;
    protected ITransportLayerFactory transportFactory;
    protected IMessageParser parser;
    protected org.jdiameter.server.api.IRouter router;

    // Duplicate handling -------------------------------------------------------
    protected boolean duplicateProtection = false;
    protected int duplicateSize;
    protected long duplicateTimer;
    protected ScheduledExecutorService duplicationScheduler = null;
    protected ScheduledFuture duplicationHandler = null;
    protected ConcurrentHashMap storageAnswers = new ConcurrentHashMap();

    protected boolean isAcceptUndefinedPeer = false;

    // Connections handling -----------------------------------------------------
    private ConcurrentHashMap incConnections;
    private ScheduledExecutorService connScheduler;
    private ScheduledFuture connHandler;

    // Network management -------------------------------------------------------
    protected INetworkGuard networkGuard;
    protected INetwork network;
    protected Set predefinedPeerTable;

    // Overload handling --------------------------------------------------------
    protected IOverloadManager ovrManager;
    protected ScheduledExecutorService overloadScheduler = null;
    protected ScheduledFuture overloadHandler = null;
    protected PeerTableListener peerTableListener = null;
    protected IStatisticManager statisticFactory;

    private IContainer stack;

    protected class StorageEntry {

        private String duplicationKey;
        private long time = System.currentTimeMillis();
        private IMessage answer;

        public StorageEntry(IMessage message) {
            answer = message;
            // duplicationKey = message.getDuplicationKey(); doesn't work because it's answer
            String[] originInfo = router.getRequestRouteInfo(answer);
            duplicationKey = message.getDuplicationKey(originInfo[0], message.getEndToEndIdentifier());
        }

        public IMessage getMessage() {
            return answer;
        }

        public long getTime() {
            return time;
        }

        public String getDuplicationKey() {
            return duplicationKey;
        }
    }

    public MutablePeerTableImpl(Configuration config, MetaData metaData, IContainer stack,
            org.jdiameter.server.api.IRouter router,
            ISessionFactory sessionFactory, IFsmFactory fsmFactory, ITransportLayerFactory trFactory,
            IMessageParser parser, INetwork network, IOverloadManager ovrManager,
            IStatisticManager statisticFactory, IConcurrentFactory concurrentFactory) {
        logger.debug("MutablePeerTableImpl is being created");
        this.metaData = metaData;
        this.config = config;
        this.router = router;
        this.sessionFactory = sessionFactory;
        this.statisticFactory = statisticFactory;
        this.concurrentFactory = concurrentFactory;
        this.fsmFactory = fsmFactory;
        this.transportFactory = trFactory;
        this.parser = parser;
        this.network = network;
        this.ovrManager = ovrManager;
        this.network.setPeerManager(this);
        this.stack = stack;
        this.isAcceptUndefinedPeer = config.getBooleanValue(AcceptUndefinedPeer.ordinal(), false);
        this.duplicateProtection = config.getBooleanValue(DuplicateProtection.ordinal(),
                (Boolean) DuplicateProtection.defValue());
        if (this.duplicateProtection) {
            this.duplicateTimer = config.getLongValue(DuplicateTimer.ordinal(), (Long) DuplicateTimer.defValue());
            this.duplicateSize = config.getIntValue(DuplicateSize.ordinal(), (Integer) DuplicateSize.defValue());
        }
        logger.debug("Duplicate Protection Configuration: Enabled? {}, Timer: {}, Size: {}",
                new Object[] { this.duplicateProtection, this.duplicateTimer, this.duplicateSize });
        if (predefinedPeerTable == null) {
            predefinedPeerTable = new CopyOnWriteArraySet();
        }
        if (config instanceof MutableConfiguration) {
            ((MutableConfiguration) config).addChangeListener(this);
        }

        logger.debug("MutablePeerTableImpl is starting initialisation by calling init on super class");
        init(stack, router, config, metaData, fsmFactory, transportFactory, statisticFactory, concurrentFactory, parser);
        logger.debug("MutablePeerTableImpl has finished initialisation");
    }

    @Override
    protected Peer createPeer(int rating, String uri, String ip, String portRange, MetaData metaData,
            Configuration globalConfig,
            Configuration peerConfig, org.jdiameter.client.api.fsm.IFsmFactory fsmFactory,
            org.jdiameter.client.api.io.ITransportLayerFactory transportFactory,
            IStatisticManager statisticFactory, IConcurrentFactory concurrentFactory,
            IMessageParser parser) throws InternalException, TransportException, URISyntaxException, UnknownServiceException {
        logger.debug("Creating Peer for URI [{}]", uri);
        if (predefinedPeerTable == null) {
            logger.debug("Creating new empty predefined peer table");
            predefinedPeerTable = new CopyOnWriteArraySet();
        }
        logger.debug("Adding URI [{}] to predefinedPeerTable", uri);
        predefinedPeerTable.add(new URI(uri).getFQDN());
        if (peerConfig.getBooleanValue(PeerAttemptConnection.ordinal(), false)) {
            logger.debug(
                    "Peer at URI [{}] is configured to attempt a connection (acting as a client) and a new peer instance will be created and returned",
                    uri);
            return newPeerInstance(rating, new URI(uri), ip, portRange, true, null,
                    metaData, globalConfig, peerConfig, (IFsmFactory) fsmFactory,
                    (ITransportLayerFactory) transportFactory, parser, statisticFactory, concurrentFactory);
        } else {
            logger.debug(
                    "Peer at URI [{}] is configured to NOT attempt a connection (i.e. acting as a server) and null will be returned",
                    uri);
            return null;
        }
    }

    protected IPeer newPeerInstance(int rating, URI uri, String ip, String portRange, boolean attCnn, IConnection connection,
            MetaData metaData, Configuration globalConfig, Configuration peerConfig, IFsmFactory fsmFactory,
            ITransportLayerFactory transportFactory, IMessageParser parser,
            IStatisticManager statisticFactory, IConcurrentFactory concurrentFactory)
            throws URISyntaxException, UnknownServiceException, InternalException, TransportException {
        logger.debug("Creating and returning a new Peer Instance for URI [{}].", uri);
        return new org.jdiameter.server.impl.PeerImpl(
                rating, uri, ip, portRange, attCnn, connection,
                this, (org.jdiameter.server.api.IMetaData) metaData, globalConfig, peerConfig, sessionFactory,
                fsmFactory, transportFactory, statisticFactory, concurrentFactory, parser, network, ovrManager,
                sessionDatasource);
    }

    @Override
    public void setPeerTableListener(PeerTableListener peerTableListener) {
        this.peerTableListener = peerTableListener;
    }

    @Override
    public boolean elementChanged(int i, Object data) {
        Configuration newConf = (Configuration) data;
        stopTimeOut = newConf.getLongValue(StopTimeOut.ordinal(), (Long) StopTimeOut.defValue());
        duplicateTimer = newConf.getLongValue(DuplicateTimer.ordinal(), (Long) DuplicateTimer.defValue());
        isAcceptUndefinedPeer = newConf.getBooleanValue(AcceptUndefinedPeer.ordinal(), false);
        return true;
    }

    public boolean isDuplicateProtection() {
        return duplicateProtection;
    }

    @Override
    public void start() throws IllegalDiameterStateException, IOException { // TODO: use parent method
        logger.debug("Starting MutablePeerTableImpl. Starting router, overload scheduler, connection check timer, etc.");
        router.start();
        // Start overload manager
        overloadScheduler = concurrentFactory.getScheduledExecutorService(PeerOverloadTimer.name());

        Runnable overloadTask = new Runnable() {
            @Override
            public void run() {
                if (ovrManager != null) {
                    for (Peer p : peerTable.values()) {
                        ((IPeer) p).notifyOvrManager(ovrManager);
                    }
                }
            }
        };
        overloadHandler = overloadScheduler.scheduleAtFixedRate(overloadTask, 0, 1, TimeUnit.SECONDS);
        // Start duplication protection procedure
        if (duplicateProtection) {
            duplicationScheduler = concurrentFactory.getScheduledExecutorService(DuplicationMessageTimer.name());
            Runnable duplicateTask = new Runnable() {
                @Override
                public void run() {
                    long now = System.currentTimeMillis();
                    if (logger.isDebugEnabled()) {
                        logger.debug(
                                "Running Duplicate Cleaning Task. Duplicate Storage size is: {}. Removing entries with time <= '{}'",
                                storageAnswers.size(), now - duplicateTimer);
                    }
                    for (StorageEntry s : storageAnswers.values()) {
                        if (s != null && s.getTime() + duplicateTimer <= now) {
                            if (logger.isTraceEnabled()) {
                                logger.trace("Duplicate Cleaning Task - Removing Entry with key '{}' and time '{}'",
                                        s.getDuplicationKey(), s.getTime());
                            }
                            storageAnswers.remove(s.getDuplicationKey());
                        } else {
                            if (logger.isTraceEnabled()) {
                                logger.trace("Duplicate Cleaning Task - Skipping Entry with key '{}' and time '{}'",
                                        s.getDuplicationKey(), s.getTime());
                            }
                        }
                    }
                    if (logger.isDebugEnabled()) {
                        logger.debug(
                                "Completed Duplicate Cleaning Task. New Duplicate Storage size is: {}. Total task runtime: {}ms",
                                storageAnswers.size(), System.currentTimeMillis() - now);
                    }
                }
            };
            duplicationHandler = duplicationScheduler.scheduleAtFixedRate(duplicateTask, duplicateTimer, duplicateTimer,
                    TimeUnit.MILLISECONDS);
        }
        //
        connScheduler = concurrentFactory.getScheduledExecutorService(ConnectionTimer.name());
        Runnable connectionCheckTask = new Runnable() {
            @Override
            public void run() {
                Map connections = getIncConnections();
                for (IConnection connection : connections.values()) {
                    if (System.currentTimeMillis() - connection.getCreatedTime() >= CONN_INVALIDATE_PERIOD) {
                        logger.debug("External connection released by timeout [{}]", connection.getKey());
                        try {
                            connection.remAllConnectionListener();
                            connection.release();
                        } catch (IOException e) {
                            logger.debug("Unable to release connection", e);
                        }
                        connections.remove(connection.getKey());
                    }
                }
            }
        };
        connHandler = connScheduler.scheduleAtFixedRate(connectionCheckTask, CONN_INVALIDATE_PERIOD, CONN_INVALIDATE_PERIOD,
                TimeUnit.MILLISECONDS);
        // Start server socket
        try {
            logger.debug("Creating network guard");
            networkGuard = createNetworkGuard(transportFactory);
        } catch (TransportException e) {
            // We want the root cause, that's what matters to us...
            Throwable t = e;
            while (t.getCause() != null) {
                t = t.getCause();
            }
            Peer p = stack.getMetaData().getLocalPeer();
            String ips = "";
            for (InetAddress ip : p.getIPAddresses()) {
                ips += " " + ip.getHostAddress() + ":" + p.getUri().getPort();
            }
            logger.error("Unable to create server socket for LocalPeer '{}' at{} ({}).",
                    new Object[] { p.getUri().getFQDN(), ips, t.getMessage() });
            logger.debug("Unable to create server socket", e);
        }
        // Connect to predefined peers
        for (Peer p : peerTable.values()) {
            try {
                if (((IPeer) p).isAttemptConnection()) {
                    p.connect();
                }
            } catch (Exception e) {
                logger.warn("Unable to start connect procedure for peer [" + p + "]", e);
            }
        }
        isStarted = true;
    }

    public Set getPredefinedPeerTable() {
        return predefinedPeerTable;
    }

    public ConcurrentHashMap getIncConnections() {
        if (incConnections == null) {
            incConnections = new ConcurrentHashMap();
        }

        return incConnections;
    }

    private final Object regLock = new Object();

    private INetworkGuard createNetworkGuard(final ITransportLayerFactory transportFactory) throws TransportException {
        return transportFactory.createNetworkGuard(
                metaData.getLocalPeer().getIPAddresses(),
                metaData.getLocalPeer().getUri().getPort(),
                new INetworkConnectionListener() {
                    @Override
                    public void newNetworkConnection(final IConnection connection) {
                        //PCB added logging
                        logger.debug("newNetworkConnection. connection [{}]", connection.getKey());
                        synchronized (regLock) {
                            final IConnectionListener listener = new IConnectionListener() {
                                @Override
                                public void connectionOpened(String connKey) {
                                    logger.debug("Connection [{}] opened", connKey);
                                }

                                @Override
                                @SuppressWarnings("unchecked")
                                public void connectionClosed(String connKey, List notSended) {
                                    logger.debug("Connection [{}] closed", connKey);
                                    unregister(true);
                                }

                                @Override
                                public void messageReceived(String connKey, IMessage message) {
                                    logger.debug("Message [{}] received to peer [{}]", message, connKey);
                                    if (message.isRequest()
                                            && message.getCommandCode() == Message.CAPABILITIES_EXCHANGE_REQUEST) {
                                        connection.remConnectionListener(this);
                                        IPeer peer = null;
                                        String host;
                                        try {
                                            host = message.getAvps().getAvp(Avp.ORIGIN_HOST).getDiameterIdentity();
                                            logger.debug("Origin-Host in new received message is [{}]", host);
                                        } catch (AvpDataException e) {
                                            logger.warn("Unable to retrieve find Origin-Host AVP in CER", e);
                                            unregister(true);
                                            return;
                                        }
                                        String realm;
                                        try {
                                            realm = message.getAvps().getAvp(Avp.ORIGIN_REALM).getDiameterIdentity();
                                            logger.debug("Origin-Realm in new received message is [{}]", realm);
                                        } catch (AvpDataException e) {
                                            logger.warn("Unable to retrieve find Origin-Realm AVP in CER", e);
                                            unregister(true);
                                            return;
                                        }

                                        boolean foundInPredefinedTable = false;
                                        // find into predefined table
                                        for (String fqdn : predefinedPeerTable) {
                                            if (logger.isDebugEnabled()) {
                                                logger.debug("Checking against entry in predefinedPeerTable with FQDN [{}]",
                                                        fqdn);
                                            }
                                            if (fqdn.equals(host)) {
                                                if (logger.isDebugEnabled()) {
                                                    logger.debug("{} == {}", fqdn, host);
                                                }
                                                peer = (IPeer) peerTable.get(fqdn);
                                                foundInPredefinedTable = true; // found but not init
                                                break;
                                            } else {
                                                if (logger.isDebugEnabled()) {
                                                    logger.debug("{} != {}", fqdn, host);
                                                }
                                            }
                                        }
                                        // find in peer table for peer already connected to server but not removed
                                        if (peer == null) {
                                            logger.debug(
                                                    "Peer with FQDN [{}] was not found in predefined peer table. Checking at (previously) connected peers table",
                                                    host);
                                            peer = (IPeer) peerTable.get(host);
                                            if (peer != null) {
                                                logger.debug("Got peer for FQDN [{}]. Is connection open ? {}.", host,
                                                        peer.hasValidConnection());
                                            } else {
                                                logger.debug("Still haven't found peer for FQDN [{}]", host);
                                            }
                                        }

                                        if (peer != null) {
                                            //FIXME: define procedure when 'peer.getRealm() != realm'
                                            logger.debug("Add [{}] connection to peer [{}]", connection, peer);
                                            peer.addIncomingConnection(connection);
                                            try {
                                                logger.debug("Handle [{}] message on peer [{}]", message, peer);
                                                peer.handleMessage(
                                                        message.isRequest() ? EventTypes.CER_EVENT : EventTypes.CER_EVENT,
                                                        message, connKey);
                                            } catch (Exception e) {
                                                logger.debug("Unable to process CER message", e);
                                            }
                                        } else {
                                            if (isAcceptUndefinedPeer || foundInPredefinedTable) {
                                                try {
                                                    int port = connection.getRemotePort();

                                                    boolean hostAsUri = config.getBooleanValue(UseUriAsFqdn.ordinal(),
                                                            (Boolean) UseUriAsFqdn.defValue());
                                                    URI uri;
                                                    if (hostAsUri || host.startsWith("aaa://")) {
                                                        uri = new URI(host);
                                                    } else {
                                                        uri = new URI("aaa://" + host + ":" + port);
                                                    }

                                                    peer = newPeerInstance(0, uri,
                                                            connection.getRemoteAddress().getHostAddress(), null, false,
                                                            connection,
                                                            metaData, config, null, fsmFactory, transportFactory, parser,
                                                            statisticFactory, concurrentFactory);
                                                    logger.debug("Created new peer instance [{}] and adding to peer table",
                                                            peer);
                                                    peer.setRealm(realm);

                                                    Collection realms = router.getRealmTable().getRealms(realm);
                                                    for (Realm r : realms) {
                                                        if (r.getName().equals(realm)) {
                                                            logger.debug(
                                                                    "Found the realm [{}] for the new peer [{}], adding it to it",
                                                                    realm, peer);
                                                            ((IRealm) r).addPeerName(host);
                                                        }
                                                    }

                                                    appendPeerToPeerTable(peer);
                                                    logger.debug("Handle [{}] message on peer [{}]", message, peer);
                                                    peer.handleMessage(
                                                            message.isRequest() ? EventTypes.CER_EVENT : EventTypes.CER_EVENT,
                                                            message, connKey);
                                                } catch (Exception e) {
                                                    logger.warn("Unable to create peer", e);
                                                    unregister(true);
                                                }
                                            } else {
                                                logger.info("Skip anonymous connection [{}]", connection);
                                                unregister(true);
                                            }
                                        }
                                    } else {
                                        logger.debug("Unknown message [{}] by connection [{}]", message, connKey);
                                        unregister(true);
                                    }
                                }

                                @Override
                                public void internalError(String connKey, IMessage message, TransportException cause) {
                                    logger.debug("Connection [{}] internalError [{}]", connKey, cause);
                                    unregister(true);
                                }

                                public void unregister(boolean release) {
                                    getIncConnections().remove(connection.getKey());
                                    connection.remConnectionListener(this);
                                    if (release && connection.isConnected()) {
                                        try {
                                            connection.release();
                                        } catch (IOException e) {
                                            logger.debug("Unable to release connection [{}]", connection);
                                        }
                                    }
                                }
                            };
                            //PCB added logging
                            String connKey = connection.getKey();
                            getIncConnections().put(connection.getKey(), connection);
                            logger.debug("Inserted connection [{}] into IncConnections", connKey);

                            connection.addConnectionListener(listener);
                            logger.debug("Added listener [{}] to connection [{}]", listener, connKey);
                        }
                    }
                });
    }

    private void appendPeerToPeerTable(IPeer peer) {
        logger.debug("Adding Peer[{}] to PeerTable with size {}", peer, peerTable.size());

        // Cleaning up if we are at max capacity...
        if (peerTable.size() == MAX_PEER_TABLE_SIZE) {
            for (String k : peerTable.keySet()) {
                Peer p = peerTable.get(k);
                if (p != null && p.getState(PeerState.class) == PeerState.DOWN) {
                    peerTable.remove(k, p);
                }
            }
        }

        peerTable.put(peer.getUri().getFQDN(), peer);
        if (peerTableListener != null) {
            peerTableListener.peerAccepted(peer);
        }
    }

    @Override
    public void stopping(int disconnectCause) {
        super.stopping(disconnectCause);
        if (networkGuard != null) {
            networkGuard.destroy();
            networkGuard = null;
        }
        //
        if (overloadScheduler != null) {
            concurrentFactory.shutdownNow(overloadScheduler);
            overloadScheduler = null;
            overloadHandler.cancel(true);
            overloadHandler = null;
        }
        //
        if (duplicationScheduler != null) {
            concurrentFactory.shutdownNow(duplicationScheduler);
            duplicationScheduler = null;
        }
        if (duplicationHandler != null) {
            duplicationHandler.cancel(true);
            duplicationHandler = null;
        }
        //
        if (connScheduler != null) {
            concurrentFactory.shutdownNow(connScheduler);
            connScheduler = null;
        }
        if (connHandler != null) {
            connHandler.cancel(true);
            connHandler = null;
        }
        //remove incoming data
        storageAnswers.clear();

        // Clear dynamic peers from peertable
        Iterator it = super.peerTable.keySet().iterator();
        while (it.hasNext()) {
            String fqdn = it.next();
            if (this.predefinedPeerTable.contains(fqdn)) {
                continue;
            } else {
                it.remove();
            }
        }

    }

    @Override
    public Peer addPeer(URI peerURI, String realm, boolean connecting) {
        //TODO: add sKey here, now it adds peer to all realms.
        //TODO: better, separate addPeer from realm!
        try {
            Configuration peerConfig = null;
            Configuration[] peers = config.getChildren(PeerTable.ordinal());
            // find peer config
            for (Configuration c : peers) {
                if (peerURI.getFQDN().equals(c.getStringValue(PeerName.ordinal(), ""))) {
                    peerConfig = c;
                    break;
                }
            }
            if (peerConfig == null) {
                peerConfig = new EmptyConfiguration(false).add(PeerAttemptConnection, connecting);
            }
            IPeer peer = (IPeer) createPeer(0, peerURI.toString(), null, null, metaData, config, peerConfig, fsmFactory,
                    transportFactory, statisticFactory, concurrentFactory, parser);
            if (peer == null) {
                return null;
            }
            peer.setRealm(realm);
            appendPeerToPeerTable(peer);
            boolean found = false;

            Collection realms = this.router.getRealmTable().getRealms(realm);
            for (Realm r : realms) {
                if (r.getName().equals(realm)) {
                    ((IRealm) r).addPeerName(peerURI.toString());
                    found = true;
                    break;
                }
            }
            if (!found) {
                throw new IllegalArgumentException("Incorrect realm name");
            }
            if (StackState.STARTED.equals(stack.getState()) && connecting) {
                peer.connect();
            }
            return peer;
        } catch (Exception e) {
            logger.debug("Unable to add peer", e);
            return null;
        }
    }

    public Set getAllRealms() {
        return new HashSet(router.getRealmTable().getRealms());
    }

    @Override
    public Peer removePeer(String host) {
        try {
            String fqdn = null;
            for (String f : peerTable.keySet()) {
                if (f.equals(host)) {
                    fqdn = f;
                    peerTable.get(fqdn).disconnect(DisconnectCause.BUSY);
                }
            }
            if (fqdn != null) {
                predefinedPeerTable.remove(fqdn);
                Peer removedPeer = peerTable.remove(fqdn);
                if (peerTableListener != null) {
                    peerTableListener.peerRemoved(removedPeer);
                }

                return removedPeer;
            } else {
                return null;
            }
        } catch (Exception e) {
            logger.debug("Unable to remove peer", e);
            return null;
        }
    }

    @Override
    public Statistic getStatistic(String name) {
        for (Peer p : peerTable.values()) {
            if (p.getUri().getFQDN().equals(name)) {
                return ((IPeer) p).getStatistic();
            }
        }
        return null;
    }

    @Override
    public IMessage isDuplicate(IMessage request) {
        String key = request.getDuplicationKey();
        if (key != null && storageAnswers != null) {
            StorageEntry entry = storageAnswers.get(key);
            return entry != null ? (IMessage) entry.getMessage().clone() : null;
        }
        return null;
    }

    @Override
    public void saveToDuplicate(String key, IMessage answer) {
        if (storageAnswers != null && storageAnswers.size() < duplicateSize) {
            if (key != null) {
                StorageEntry se = new StorageEntry((IMessage) answer.clone());
                if (logger.isTraceEnabled()) {
                    logger.trace("Duplicate Protection - Inserting Entry with key '{}' and time '{}'", key, se.getTime());
                }
                storageAnswers.put(key, se);
            }
        }
    }

    @Override
    public ISessionFactory getSessionFactory() {
        return sessionFactory;
    }

    @Override
    public boolean isWrapperFor(Class aClass) throws InternalException {
        boolean isWrapp = super.isWrapperFor(aClass);

        return aClass == MutablePeerTable.class || aClass == Network.class || isWrapp;
    }

    @Override
    public  T unwrap(Class aClass) throws InternalException {
        if (aClass == MutablePeerTable.class) {
            return assembler.getComponentInstance(aClass);
        }
        if (aClass == Network.class) {
            return assembler.getComponentInstance(aClass);
        }
        return null;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy