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

org.mobicents.protocols.sctp.ManagementImpl Maven / Gradle / Ivy

The newest version!
/*
 * TeleStax, Open Source Cloud Communications  Copyright 2012. 
 * 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.mobicents.protocols.sctp;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.Selector;
import java.nio.channels.spi.SelectorProvider;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import javolution.text.TextBuilder;
import javolution.util.FastList;
import javolution.util.FastMap;
import javolution.xml.XMLObjectReader;
import javolution.xml.XMLObjectWriter;
import javolution.xml.stream.XMLStreamException;

import org.apache.log4j.Logger;
import org.mobicents.protocols.api.Association;
import org.mobicents.protocols.api.AssociationType;
import org.mobicents.protocols.api.CongestionListener;
import org.mobicents.protocols.api.IpChannelType;
import org.mobicents.protocols.api.Management;
import org.mobicents.protocols.api.ManagementEventListener;
import org.mobicents.protocols.api.Server;
import org.mobicents.protocols.api.ServerListener;
import org.mobicents.protocols.sctp.netty.NettySctpManagementImpl;

/**
 * @author amit bhayani
 * 
 */
public class ManagementImpl implements Management {

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

	private static final String SCTP_PERSIST_DIR_KEY = "sctp.persist.dir";
	private static final String USER_DIR_KEY = "user.dir";
	private static final String PERSIST_FILE_NAME = "sctp.xml";

	private static final String SERVERS = "servers";
	private static final String ASSOCIATIONS = "associations";
	
    private static final String CONNECT_DELAY_PROP = "connectdelay";
    private static final String SINGLE_THREAD_PROP = "singlethread";
    private static final String WORKER_THREADS_PROP = "workerthreads";

	private final TextBuilder persistFile = TextBuilder.newInstance();

	protected static final SctpXMLBinding binding = new SctpXMLBinding();
	protected static final String TAB_INDENT = "\t";
	private static final String CLASS_ATTRIBUTE = "type";

	private final String name;

	protected String persistDir = null;

	protected FastList servers = new FastList();
	protected AssociationMap associations = new AssociationMap();

	private FastList pendingChanges = new FastList();

	// Create a new selector
	private Selector socketSelector = null;

	private SelectorThread selectorThread = null;

	static final int DEFAULT_IO_THREADS = Runtime.getRuntime().availableProcessors() * 2;

	private int workerThreads = DEFAULT_IO_THREADS;

	private boolean singleThread = true;

	private int workerThreadCount = 0;

	// Maximum IO Errors tolerated by Socket. After this the Socket will be
	// closed and attempt will be made to open again
	private int maxIOErrors = 3;

	private int connectDelay = 5000;

	private int bufferSize = 8192;

	private ExecutorService[] executorServices = null;

	private FastList managementEventListeners = new FastList();

	private ServerListener serverListener = null;

	private volatile boolean started = false;

	public ManagementImpl(String name) throws IOException {
		this.name = name;
		binding.setClassAttribute(CLASS_ATTRIBUTE);
		binding.setAlias(ServerImpl.class, "server");
		binding.setAlias(AssociationImpl.class, "association");
		binding.setAlias(String.class, "string");
		this.socketSelector = SelectorProvider.provider().openSelector();
	}

	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}

	public String getPersistDir() {
		return persistDir;
	}

	public void setPersistDir(String persistDir) {
		this.persistDir = persistDir;
	}

	/**
	 * @return the connectDelay
	 */
	public int getConnectDelay() {
		return connectDelay;
	}

	/**
	 * @param connectDelay
	 *            the connectDelay to set
	 */
	public void setConnectDelay(int connectDelay) throws Exception {
        if (!this.started)
            throw new Exception("ConnectDelay parameter can be updated only when SCTP stack is running");

        this.connectDelay = connectDelay;

        this.store();
	}

	/**
	 * @return the workerThreads
	 */
	public int getWorkerThreads() {
		return workerThreads;
	}

	/**
	 * @param workerThreads
	 *            the workerThreads to set
	 */
	public void setWorkerThreads(int workerThreads) throws Exception {
        if (this.started)
            throw new Exception("WorkerThreads parameter can be updated only when SCTP stack is NOT running");

		if (workerThreads < 1) {
			workerThreads = DEFAULT_IO_THREADS;
		}
		this.workerThreads = workerThreads;

//		this.store();
	}

	/**
	 * @return the maxIOErrors
	 */
	public int getMaxIOErrors() {
		return maxIOErrors;
	}

	/**
	 * @param maxIOErrors
	 *            the maxIOErrors to set
	 */
	public void setMaxIOErrors(int maxIOErrors) {
		if (maxIOErrors < 1) {
			maxIOErrors = 1;
		}
		this.maxIOErrors = maxIOErrors;
	}

	/**
	 * @return the singleThread
	 */
	public boolean isSingleThread() {
		return singleThread;
	}

	/**
	 * @param singleThread
	 *            the singleThread to set
	 */
	public void setSingleThread(boolean singleThread) throws Exception {
        if (this.started)
            throw new Exception("SingleThread parameter can be updated only when SCTP stack is NOT running");

		this.singleThread = singleThread;

//		this.store();
	}

    @Override
    public int getBufferSize() {
        return bufferSize;
    }

    @Override
    public void setBufferSize(int bufferSize) throws Exception {
        if (this.started)
            throw new Exception("BufferSize parameter can be updated only when SCTP stack is NOT running");
        if (bufferSize < 1000 || bufferSize > 1000000)
            throw new Exception("BufferSize must be between 1000 and 1000000 bytes");

        this.bufferSize = bufferSize;
    }

	public ServerListener getServerListener() {
		return serverListener;
	}

	protected FastList getManagementEventListeners() {
		return managementEventListeners;
	}

	public void setServerListener(ServerListener serverListener) {
		this.serverListener = serverListener;
	}

	public void addManagementEventListener(ManagementEventListener listener) {
		synchronized (this) {
			if (this.managementEventListeners.contains(listener))
				return;

			FastList newManagementEventListeners = new FastList();
			newManagementEventListeners.addAll(this.managementEventListeners);
			newManagementEventListeners.add(listener);
			this.managementEventListeners = newManagementEventListeners;
		}
	}

	public void removeManagementEventListener(ManagementEventListener listener) {
		synchronized (this) {
			if (!this.managementEventListeners.contains(listener))
				return;

			FastList newManagementEventListeners = new FastList();
			newManagementEventListeners.addAll(this.managementEventListeners);
			newManagementEventListeners.remove(listener);
			this.managementEventListeners = newManagementEventListeners;
		}
	}

	public void start() throws Exception {

		if (this.started) {
			logger.warn(String.format("management=%s is already started", this.name));
			return;
		}

		synchronized (this) {
			this.persistFile.clear();

			if (persistDir != null) {
				this.persistFile.append(persistDir).append(File.separator).append(this.name).append("_").append(PERSIST_FILE_NAME);
			} else {
				persistFile.append(System.getProperty(SCTP_PERSIST_DIR_KEY, System.getProperty(USER_DIR_KEY))).append(File.separator).append(this.name)
						.append("_").append(PERSIST_FILE_NAME);
			}

			logger.info(String.format("SCTP configuration file path %s", persistFile.toString()));

			try {
				this.load();
			} catch (FileNotFoundException e) {
				logger.warn(String.format("Failed to load the SCTP configuration file. \n%s", e.getMessage()));
			}

			if (!this.singleThread) {
				// If not single thread model we create worker threads
				this.executorServices = new ExecutorService[this.workerThreads];
				for (int i = 0; i < this.workerThreads; i++) {
					this.executorServices[i] = Executors.newSingleThreadExecutor();
				}
			}
			this.selectorThread = new SelectorThread(this.socketSelector, this);
			this.selectorThread.setStarted(true);

			(new Thread(this.selectorThread)).start();

			this.started = true;

			if (logger.isInfoEnabled()) {
				logger.info(String.format("Started SCTP Management=%s WorkerThreads=%d SingleThread=%s", this.name,
						(this.singleThread ? 0 : this.workerThreads), this.singleThread));
			}

			for (ManagementEventListener lstr : managementEventListeners) {
				try {
					lstr.onServiceStarted();
				} catch (Throwable ee) {
					logger.error("Exception while invoking onServiceStarted", ee);
				}
			}
		}
	}

	public void stop() throws Exception {
		
		if (!this.started) {
			logger.warn(String.format("management=%s is already stopped", this.name));
			return;
		}

		for (ManagementEventListener lstr : managementEventListeners) {
			try {
				lstr.onServiceStopped();
			} catch (Throwable ee) {
				logger.error("Exception while invoking onServiceStopped", ee);
			}
		}

		// We store the original state first
		this.store();

		// Stop all associations
		FastMap associationsTemp = this.associations;
		for (FastMap.Entry n = associationsTemp.head(), end = associationsTemp.tail(); (n = n.getNext()) != end;) {
			Association associationTemp = n.getValue();
			if (associationTemp.isStarted()) {
				((AssociationImpl) associationTemp).stop();
			}
		}

		FastList tempServers = servers;
		for (FastList.Node n = tempServers.head(), end = tempServers.tail(); (n = n.getNext()) != end;) {
			Server serverTemp = n.getValue();
			if (serverTemp.isStarted()) {
				try {
					((ServerImpl) serverTemp).stop();
				} catch (Exception e) {
					logger.error(String.format("Exception while stopping the Server=%s", serverTemp.getName()), e);
				}
			}
		}

		if (this.executorServices != null) {
			for (int i = 0; i < this.executorServices.length; i++) {
				this.executorServices[i].shutdown();
			}
		}

		this.selectorThread.setStarted(false);
		this.socketSelector.wakeup(); // Wakeup selector so SelectorThread dies

		// waiting till stopping associations
		for (int i1 = 0; i1 < 20; i1++) {
			boolean assConnected = false;
			for (FastMap.Entry n = this.associations.head(), end = this.associations.tail(); (n = n.getNext()) != end;) {
				Association associationTemp = n.getValue();
				if (associationTemp.isConnected()) {
					assConnected = true;
					break;
				}
			}
			if (!assConnected)
				break;
			Thread.sleep(100);
		}

		// Graceful shutdown for each of Executors
		if (this.executorServices != null) {
			for (int i = 0; i < this.executorServices.length; i++) {
				if (!this.executorServices[i].isTerminated()) {
					if (logger.isInfoEnabled()) {
						logger.info("Waiting for worker thread to die gracefully ....");
					}
					try {
						this.executorServices[i].awaitTermination(5000, TimeUnit.MILLISECONDS);
					} catch (InterruptedException e) {
						// Do we care?
					}
				}
			}
		}

		this.started = false;
	}
	
	public boolean isStarted(){
		return this.started;
	}

	@SuppressWarnings("unchecked")
	public void load() throws FileNotFoundException {
		XMLObjectReader reader = null;
		try {
			reader = XMLObjectReader.newInstance(new FileInputStream(persistFile.toString()));
			reader.setBinding(binding);

            try {
                Integer vali = reader.read(CONNECT_DELAY_PROP, Integer.class);
                if (vali != null)
                    this.connectDelay = vali;
//                this.workerThreads = reader.read(WORKER_THREADS_PROP, Integer.class);
//                this.singleThread = reader.read(SINGLE_THREAD_PROP, Boolean.class);
                vali = reader.read(WORKER_THREADS_PROP, Integer.class);
                Boolean valb = reader.read(SINGLE_THREAD_PROP, Boolean.class);

                Double valTH1 = reader.read(NettySctpManagementImpl.CONG_CONTROL_DELAY_THRESHOLD_1, Double.class);
                Double valTH2 = reader.read(NettySctpManagementImpl.CONG_CONTROL_DELAY_THRESHOLD_2, Double.class);
                Double valTH3 = reader.read(NettySctpManagementImpl.CONG_CONTROL_DELAY_THRESHOLD_3, Double.class);
                Double valTB1 = reader
                        .read(NettySctpManagementImpl.CONG_CONTROL_BACK_TO_NORMAL_DELAY_THRESHOLD_1, Double.class);
                Double valTB2 = reader
                        .read(NettySctpManagementImpl.CONG_CONTROL_BACK_TO_NORMAL_DELAY_THRESHOLD_2, Double.class);
                Double valTB3 = reader
                        .read(NettySctpManagementImpl.CONG_CONTROL_BACK_TO_NORMAL_DELAY_THRESHOLD_3, Double.class);

                // TODO: revive this test when we introduce of parameters persistense 
//                Boolean valB = reader.read(NettySctpManagementImpl.OPTION_SCTP_DISABLE_FRAGMENTS, Boolean.class);
//                Integer valI = reader.read(NettySctpManagementImpl.OPTION_SCTP_FRAGMENT_INTERLEAVE, Integer.class);
//                Integer valI_In = reader.read(NettySctpManagementImpl.OPTION_SCTP_INIT_MAXSTREAMS_IN, Integer.class);
//                Integer valI_Out = reader.read(NettySctpManagementImpl.OPTION_SCTP_INIT_MAXSTREAMS_OUT, Integer.class);
//                valB = reader.read(NettySctpManagementImpl.OPTION_SCTP_NODELAY, Boolean.class);
//                valI = reader.read(NettySctpManagementImpl.OPTION_SO_SNDBUF, Integer.class);
//                valI = reader.read(NettySctpManagementImpl.OPTION_SO_RCVBUF, Integer.class);
//                valI = reader.read(NettySctpManagementImpl.OPTION_SO_LINGER, Integer.class);

            } catch (java.lang.NullPointerException npe) {
                // ignore.
                // For backward compatibility we can ignore if these values are not defined
            }			

			this.servers = reader.read(SERVERS, FastList.class);

			for (FastList.Node n = this.servers.head(), end = this.servers.tail(); (n = n.getNext()) != end;) {
				Server serverTemp = n.getValue();
				((ServerImpl) serverTemp).setManagement(this);
				if (serverTemp.isStarted()) {
					try {
						((ServerImpl) serverTemp).start();
					} catch (Exception e) {
						logger.error(String.format("Error while initiating Server=%s", serverTemp.getName()), e);
					}
				}
			}

			this.associations = reader.read(ASSOCIATIONS, AssociationMap.class);
			for (FastMap.Entry n = this.associations.head(), end = this.associations.tail(); (n = n.getNext()) != end;) {
				AssociationImpl associationTemp = (AssociationImpl) n.getValue();
				associationTemp.setManagement(this);
			}

		} catch (XMLStreamException ex) {
			// this.logger.info(
			// "Error while re-creating Linksets from persisted file", ex);
		}
	}

	public void store() {
		try {
			XMLObjectWriter writer = XMLObjectWriter.newInstance(new FileOutputStream(persistFile.toString()));
			writer.setBinding(binding);
			// Enables cross-references.
			// writer.setReferenceResolver(new XMLReferenceResolver());
			writer.setIndentation(TAB_INDENT);

            writer.write(this.connectDelay, CONNECT_DELAY_PROP, Integer.class);
//            writer.write(this.workerThreads, WORKER_THREADS_PROP, Integer.class);
//            writer.write(this.singleThread, SINGLE_THREAD_PROP, Boolean.class);

			writer.write(this.servers, SERVERS, FastList.class);
			writer.write(this.associations, ASSOCIATIONS, AssociationMap.class);

			writer.close();
		} catch (Exception e) {
			logger.error("Error while persisting the Rule state in file", e);
		}
	}

	public void removeAllResourses() throws Exception {

		synchronized (this) {
			if (!this.started) {
				throw new Exception(String.format("Management=%s not started", this.name));
			}

			if (this.associations.size() == 0 && this.servers.size() == 0)
				// no resources allocated - nothing to do
				return;

			if (logger.isInfoEnabled()) {
				logger.info(String.format("Removing allocated resources: Servers=%d, Associations=%d", this.servers.size(), this.associations.size()));
			}

			synchronized (this) {
				// Remove all associations
				ArrayList lst = new ArrayList();
				for (FastMap.Entry n = this.associations.head(), end = this.associations.tail(); (n = n.getNext()) != end;) {
					lst.add(n.getKey());
				}
				for (String n : lst) {
					this.stopAssociation(n);
					this.removeAssociation(n);
				}

				// Remove all servers
				lst.clear();
				for (FastList.Node n = this.servers.head(), end = this.servers.tail(); (n = n.getNext()) != end;) {
					lst.add(n.getValue().getName());
				}
				for (String n : lst) {
					this.stopServer(n);
					this.removeServer(n);
				}

				// We store the cleared state
				this.store();
			}

			for (ManagementEventListener lstr : managementEventListeners) {
				try {
					lstr.onRemoveAllResources();
				} catch (Throwable ee) {
					logger.error("Exception while invoking onRemoveAllResources", ee);
				}
			}
		}
	}

	public ServerImpl addServer(String serverName, String hostAddress, int port) throws Exception {
		return addServer(serverName, hostAddress, port, IpChannelType.SCTP, false, 0, null);
	}

	public Server addServer(String serverName, String hostAddress, int port, IpChannelType ipChannelType, String[] extraHostAddresses) throws Exception {
		return addServer(serverName, hostAddress, port, ipChannelType, false, 0, extraHostAddresses);
	}

	public ServerImpl addServer(String serverName, String hostAddress, int port, IpChannelType ipChannelType, boolean acceptAnonymousConnections,
			int maxConcurrentConnectionsCount, String[] extraHostAddresses) throws Exception {

		if (!this.started) {
			throw new Exception(String.format("Management=%s not started", this.name));
		}

		if (serverName == null) {
			throw new Exception("Server name cannot be null");
		}

		if (hostAddress == null) {
			throw new Exception("Server host address cannot be null");
		}

		if (port < 1) {
			throw new Exception("Server host port cannot be less than 1");
		}

		synchronized (this) {
			for (FastList.Node n = this.servers.head(), end = this.servers.tail(); (n = n.getNext()) != end;) {
				Server serverTemp = n.getValue();
				if (serverName.equals(serverTemp.getName())) {
					throw new Exception(String.format("Server name=%s already exist", serverName));
				}

				if (hostAddress.equals(serverTemp.getHostAddress()) && port == serverTemp.getHostport()) {
					throw new Exception(String.format("Server name=%s is already bound to %s:%d", serverTemp.getName(), serverTemp.getHostAddress(),
							serverTemp.getHostport()));
				}
			}

			ServerImpl server = new ServerImpl(serverName, hostAddress, port, ipChannelType, acceptAnonymousConnections, maxConcurrentConnectionsCount,
					extraHostAddresses);
			server.setManagement(this);

			FastList newServers = new FastList();
			newServers.addAll(this.servers);
			newServers.add(server);
			this.servers = newServers;
			// this.servers.add(server);

			this.store();

			for (ManagementEventListener lstr : managementEventListeners) {
				try {
					lstr.onServerAdded(server);
				} catch (Throwable ee) {
					logger.error("Exception while invoking onServerAdded", ee);
				}
			}

			if (logger.isInfoEnabled()) {
				logger.info(String.format("Created Server=%s", server.getName()));
			}

			return server;
		}
	}

	public void removeServer(String serverName) throws Exception {

		if (!this.started) {
			throw new Exception(String.format("Management=%s not started", this.name));
		}

		if (serverName == null) {
			throw new Exception("Server name cannot be null");
		}

		synchronized (this) {
			Server removeServer = null;
			for (FastList.Node n = this.servers.head(), end = this.servers.tail(); (n = n.getNext()) != end;) {
				ServerImpl serverTemp = (ServerImpl)n.getValue();

				if (serverName.equals(serverTemp.getName())) {
					if (serverTemp.isStarted()) {
						throw new Exception(String.format("Server=%s is started. Stop the server before removing", serverName));
					}
					
					if(serverTemp.anonymAssociations.size() !=0 || serverTemp.associations.size() != 0){
						throw new Exception(String.format("Server=%s has Associations. Remove all those Associations before removing Server", serverName));
					}
					removeServer = serverTemp;
					break;
				}
			}

			if (removeServer == null) {
				throw new Exception(String.format("No Server found with name=%s", serverName));
			}

			FastList newServers = new FastList();
			newServers.addAll(this.servers);
			newServers.remove(removeServer);
			this.servers = newServers;
			// this.servers.remove(removeServer);

			this.store();

			for (ManagementEventListener lstr : managementEventListeners) {
				try {
					lstr.onServerRemoved(removeServer);
				} catch (Throwable ee) {
					logger.error("Exception while invoking onServerRemoved", ee);
				}
			}
		}
	}

	public void startServer(String serverName) throws Exception {

		if (!this.started) {
			throw new Exception(String.format("Management=%s not started", this.name));
		}

		if (name == null) {
			throw new Exception("Server name cannot be null");
		}

		FastList tempServers = servers;
		for (FastList.Node n = tempServers.head(), end = tempServers.tail(); (n = n.getNext()) != end;) {
			Server serverTemp = n.getValue();

			if (serverName.equals(serverTemp.getName())) {
				if (serverTemp.isStarted()) {
					throw new Exception(String.format("Server=%s is already started", serverName));
				}
				((ServerImpl) serverTemp).start();
				this.store();
				return;
			}
		}

		throw new Exception(String.format("No Server foubd with name=%s", serverName));
	}

	public void stopServer(String serverName) throws Exception {

		if (!this.started) {
			throw new Exception(String.format("Management=%s not started", this.name));
		}

		if (serverName == null) {
			throw new Exception("Server name cannot be null");
		}

		FastList tempServers = servers;
		for (FastList.Node n = tempServers.head(), end = tempServers.tail(); (n = n.getNext()) != end;) {
			Server serverTemp = n.getValue();

			if (serverName.equals(serverTemp.getName())) {
				((ServerImpl) serverTemp).stop();
				this.store();
				return;
			}
		}

		throw new Exception(String.format("No Server found with name=%s", serverName));
	}

	public AssociationImpl addServerAssociation(String peerAddress, int peerPort, String serverName, String assocName) throws Exception {
		return addServerAssociation(peerAddress, peerPort, serverName, assocName, IpChannelType.SCTP);
	}

	public AssociationImpl addServerAssociation(String peerAddress, int peerPort, String serverName, String assocName, IpChannelType ipChannelType)
			throws Exception {

		if (!this.started) {
			throw new Exception(String.format("Management=%s not started", this.name));
		}

		if (peerAddress == null) {
			throw new Exception("Peer address cannot be null");
		}

		if (peerPort < 1) {
			throw new Exception("Peer port cannot be less than 1");
		}

		if (serverName == null) {
			throw new Exception("Server name cannot be null");
		}

		if (assocName == null) {
			throw new Exception("Association name cannot be null");
		}

		synchronized (this) {
			if (this.associations.get(assocName) != null) {
				throw new Exception(String.format("Already has association=%s", assocName));
			}

			Server server = null;

			for (FastList.Node n = this.servers.head(), end = this.servers.tail(); (n = n.getNext()) != end;) {
				Server serverTemp = n.getValue();
				if (serverTemp.getName().equals(serverName)) {
					server = serverTemp;
				}
			}

			if (server == null) {
				throw new Exception(String.format("No Server found for name=%s", serverName));
			}

			for (FastMap.Entry n = this.associations.head(), end = this.associations.tail(); (n = n.getNext()) != end;) {
				Association associationTemp = n.getValue();

				if (peerAddress.equals(associationTemp.getPeerAddress()) && associationTemp.getPeerPort() == peerPort) {
					throw new Exception(String.format("Already has association=%s with same peer address=%s and port=%d", associationTemp.getName(),
							peerAddress, peerPort));
				}
			}

			if (server.getIpChannelType() != ipChannelType)
				throw new Exception(String.format("Server and Accociation has different IP channel type"));

			AssociationImpl association = new AssociationImpl(peerAddress, peerPort, serverName, assocName, ipChannelType);
			association.setManagement(this);

			AssociationMap newAssociations = new AssociationMap();
			newAssociations.putAll(this.associations);
			newAssociations.put(assocName, association);
			this.associations = newAssociations;
			// this.associations.put(assocName, association);

			FastList newAssociations2 = new FastList();
			newAssociations2.addAll(((ServerImpl) server).associations);
			newAssociations2.add(assocName);
			((ServerImpl) server).associations = newAssociations2;
			// ((ServerImpl) server).associations.add(assocName);

			this.store();

			for (ManagementEventListener lstr : managementEventListeners) {
				try {
					lstr.onAssociationAdded(association);
				} catch (Throwable ee) {
					logger.error("Exception while invoking onAssociationAdded", ee);
				}
			}

			if (logger.isInfoEnabled()) {
				logger.info(String.format("Added Associoation=%s of type=%s", association.getName(), association.getAssociationType()));
			}

			return association;
		}
	}

	public AssociationImpl addAssociation(String hostAddress, int hostPort, String peerAddress, int peerPort, String assocName) throws Exception {
		return addAssociation(hostAddress, hostPort, peerAddress, peerPort, assocName, IpChannelType.SCTP, null);
	}

	public AssociationImpl addAssociation(String hostAddress, int hostPort, String peerAddress, int peerPort, String assocName, IpChannelType ipChannelType,
			String[] extraHostAddresses) throws Exception {

		if (!this.started) {
			throw new Exception(String.format("Management=%s not started", this.name));
		}

		if (hostAddress == null) {
			throw new Exception("Host address cannot be null");
		}

		if (hostPort < 0) {
			throw new Exception("Host port cannot be less than 0");
		}

		if (peerAddress == null) {
			throw new Exception("Peer address cannot be null");
		}

		if (peerPort < 1) {
			throw new Exception("Peer port cannot be less than 1");
		}

		if (assocName == null) {
			throw new Exception("Association name cannot be null");
		}

		synchronized (this) {
			for (FastMap.Entry n = this.associations.head(), end = this.associations.tail(); (n = n.getNext()) != end;) {
				Association associationTemp = n.getValue();

				if (assocName.equals(associationTemp.getName())) {
					throw new Exception(String.format("Already has association=%s", associationTemp.getName()));
				}

				if (peerAddress.equals(associationTemp.getPeerAddress()) && associationTemp.getPeerPort() == peerPort) {
					throw new Exception(String.format("Already has association=%s with same peer address=%s and port=%d", associationTemp.getName(),
							peerAddress, peerPort));
				}

				if (hostAddress.equals(associationTemp.getHostAddress()) && associationTemp.getHostPort() == hostPort) {
					throw new Exception(String.format("Already has association=%s with same host address=%s and port=%d", associationTemp.getName(),
							hostAddress, hostPort));
				}

			}

			AssociationImpl association = new AssociationImpl(hostAddress, hostPort, peerAddress, peerPort, assocName, ipChannelType, extraHostAddresses);
			association.setManagement(this);

			AssociationMap newAssociations = new AssociationMap();
			newAssociations.putAll(this.associations);
			newAssociations.put(assocName, association);
			this.associations = newAssociations;
			// associations.put(assocName, association);

			this.store();

			for (ManagementEventListener lstr : managementEventListeners) {
				try {
					lstr.onAssociationAdded(association);
				} catch (Throwable ee) {
					logger.error("Exception while invoking onAssociationAdded", ee);
				}
			}

			if (logger.isInfoEnabled()) {
				logger.info(String.format("Added Associoation=%s of type=%s", association.getName(), association.getAssociationType()));
			}

			return association;
		}
	}

	public Association getAssociation(String assocName) throws Exception {
		if (assocName == null) {
			throw new Exception("Association name cannot be null");
		}
		Association associationTemp = this.associations.get(assocName);

		if (associationTemp == null) {
			throw new Exception(String.format("No Association found for name=%s", assocName));
		}
		return associationTemp;
	}

	/**
	 * @return the associations
	 */
	public Map getAssociations() {
		Map routeTmp = new HashMap();
		routeTmp.putAll(this.associations);
		return routeTmp;
	}

	public void startAssociation(String assocName) throws Exception {
		if (!this.started) {
			throw new Exception(String.format("Management=%s not started", this.name));
		}

		if (assocName == null) {
			throw new Exception("Association name cannot be null");
		}

		Association associationTemp = this.associations.get(assocName);

		if (associationTemp == null) {
			throw new Exception(String.format("No Association found for name=%s", assocName));
		}

		if (associationTemp.isStarted()) {
			throw new Exception(String.format("Association=%s is already started", assocName));
		}

		((AssociationImpl) associationTemp).start();
		this.store();
	}

	public void stopAssociation(String assocName) throws Exception {
		if (!this.started) {
			throw new Exception(String.format("Management=%s not started", this.name));
		}

		if (assocName == null) {
			throw new Exception("Association name cannot be null");
		}

		Association association = this.associations.get(assocName);

		if (association == null) {
			throw new Exception(String.format("No Association found for name=%s", assocName));
		}

		((AssociationImpl) association).stop();
		this.store();
	}

	public void removeAssociation(String assocName) throws Exception {
		if (!this.started) {
			throw new Exception(String.format("Management=%s not started", this.name));
		}

		if (assocName == null) {
			throw new Exception("Association name cannot be null");
		}

		synchronized (this) {
			Association association = this.associations.get(assocName);

			if (association == null) {
				throw new Exception(String.format("No Association found for name=%s", assocName));
			}

			if (association.isStarted()) {
				throw new Exception(String.format("Association name=%s is started. Stop before removing", assocName));
			}

			AssociationMap newAssociations = new AssociationMap();
			newAssociations.putAll(this.associations);
			newAssociations.remove(assocName);
			this.associations = newAssociations;
			// this.associations.remove(assocName);

			if (((AssociationImpl) association).getAssociationType() == AssociationType.SERVER) {
				for (FastList.Node n = this.servers.head(), end = this.servers.tail(); (n = n.getNext()) != end;) {
					Server serverTemp = n.getValue();
					if (serverTemp.getName().equals(association.getServerName())) {
						FastList newAssociations2 = new FastList();
						newAssociations2.addAll(((ServerImpl) serverTemp).associations);
						newAssociations2.remove(assocName);
						((ServerImpl) serverTemp).associations = newAssociations2;
						// ((ServerImpl)
						// serverTemp).associations.remove(assocName);

						break;
					}
				}
			}

			this.store();

			for (ManagementEventListener lstr : managementEventListeners) {
				try {
					lstr.onAssociationRemoved(association);
				} catch (Throwable ee) {
					logger.error("Exception while invoking onAssociationRemoved", ee);
				}
			}
		}
	}

	/**
	 * @return the servers
	 */
	public List getServers() {
		return servers.unmodifiable();
	}

	/**
	 * @return the pendingChanges
	 */
	protected FastList getPendingChanges() {
		return pendingChanges;
	}

	/**
	 * @return the socketSelector
	 */
	protected Selector getSocketSelector() {
		return socketSelector;
	}

	protected void populateWorkerThread(int workerThreadTable[]) {
		for (int count = 0; count < workerThreadTable.length; count++) {
			if (this.workerThreadCount == this.workerThreads) {
				this.workerThreadCount = 0;
			}

			workerThreadTable[count] = this.workerThreadCount;
			this.workerThreadCount++;
		}
	}

	protected ExecutorService getExecutorService(int index) {
		return this.executorServices[index];
	}

    @Override
    public double getCongControl_DelayThreshold_1() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public double getCongControl_DelayThreshold_2() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public double getCongControl_DelayThreshold_3() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public void setCongControl_DelayThreshold_1(double val) throws Exception {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void setCongControl_DelayThreshold_2(double val) throws Exception {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void setCongControl_DelayThreshold_3(double val) throws Exception {
        // TODO Auto-generated method stub
        
    }

    @Override
    public double getCongControl_BackToNormalDelayThreshold_1() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public double getCongControl_BackToNormalDelayThreshold_2() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public double getCongControl_BackToNormalDelayThreshold_3() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public void setCongControl_BackToNormalDelayThreshold_1(double val) throws Exception {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void setCongControl_BackToNormalDelayThreshold_2(double val) throws Exception {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void setCongControl_BackToNormalDelayThreshold_3(double val) throws Exception {
        // TODO Auto-generated method stub
        
    }

    @Override
    public Boolean getOptionSctpDisableFragments() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void setOptionSctpDisableFragments(Boolean optionSctpDisableFragments) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public Integer getOptionSctpFragmentInterleave() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void setOptionSctpFragmentInterleave(Integer optionSctpFragmentInterleave) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public Boolean getOptionSctpNodelay() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void setOptionSctpNodelay(Boolean optionSctpNodelay) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public Integer getOptionSoSndbuf() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void setOptionSoSndbuf(Integer optionSoSndbuf) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public Integer getOptionSoRcvbuf() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void setOptionSoRcvbuf(Integer optionSoRcvbuf) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public Integer getOptionSoLinger() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void setOptionSoLinger(Integer optionSoLinger) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public Integer getOptionSctpInitMaxstreams_MaxOutStreams() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Integer getOptionSctpInitMaxstreams_MaxInStreams() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void setOptionSctpInitMaxstreams_MaxOutStreams(Integer maxOutStreams) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void setOptionSctpInitMaxstreams_MaxInStreams(Integer maxInStreams) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void addCongestionListener(CongestionListener listener) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void removeCongestionListener(CongestionListener listener) {
        // TODO Auto-generated method stub
        
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy