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

org.restcomm.protocols.ss7.m3ua.impl.M3UAManagementImpl Maven / Gradle / Ivy

/*
 * 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.restcomm.protocols.ss7.m3ua.impl;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
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.Management;
import org.restcomm.protocols.ss7.m3ua.As;
import org.restcomm.protocols.ss7.m3ua.Asp;
import org.restcomm.protocols.ss7.m3ua.AspFactory;
import org.restcomm.protocols.ss7.m3ua.ExchangeType;
import org.restcomm.protocols.ss7.m3ua.Functionality;
import org.restcomm.protocols.ss7.m3ua.IPSPType;
import org.restcomm.protocols.ss7.m3ua.M3UACounterProvider;
import org.restcomm.protocols.ss7.m3ua.RouteAs;
import org.restcomm.protocols.ss7.m3ua.impl.fsm.FSM;
import org.restcomm.protocols.ss7.m3ua.impl.message.MessageFactoryImpl;
import org.restcomm.protocols.ss7.m3ua.impl.oam.M3UAOAMMessages;
import org.restcomm.protocols.ss7.m3ua.impl.parameter.ParameterFactoryImpl;
import org.restcomm.protocols.ss7.m3ua.impl.scheduler.M3UAScheduler;
import org.restcomm.protocols.ss7.m3ua.message.MessageClass;
import org.restcomm.protocols.ss7.m3ua.message.MessageFactory;
import org.restcomm.protocols.ss7.m3ua.message.MessageType;
import org.restcomm.protocols.ss7.m3ua.message.transfer.PayloadData;
import org.restcomm.protocols.ss7.m3ua.parameter.NetworkAppearance;
import org.restcomm.protocols.ss7.m3ua.parameter.ParameterFactory;
import org.restcomm.protocols.ss7.m3ua.parameter.ProtocolData;
import org.restcomm.protocols.ss7.m3ua.parameter.RoutingContext;
import org.restcomm.protocols.ss7.m3ua.parameter.TrafficModeType;
import org.restcomm.protocols.ss7.mtp.Mtp3EndCongestionPrimitive;
import org.restcomm.protocols.ss7.mtp.Mtp3PausePrimitive;
import org.restcomm.protocols.ss7.mtp.Mtp3ResumePrimitive;
import org.restcomm.protocols.ss7.mtp.Mtp3StatusPrimitive;
import org.restcomm.protocols.ss7.mtp.Mtp3TransferPrimitive;
import org.restcomm.protocols.ss7.mtp.Mtp3UserPartBaseImpl;
import org.restcomm.protocols.ss7.mtp.RoutingLabelFormat;
import org.restcomm.protocols.ss7.m3ua.M3UAManagement;
import org.restcomm.protocols.ss7.m3ua.M3UAManagementEventListener;
import org.restcomm.protocols.ss7.ss7ext.Ss7ExtInterface;

/**
 * @author amit bhayani
 */
public class M3UAManagementImpl extends Mtp3UserPartBaseImpl implements M3UAManagement {
    private static final Logger logger = Logger.getLogger(M3UAManagementImpl.class);
    private static final String AS_LIST = "asList";
    private static final String ASP_FACTORY_LIST = "aspFactoryList";
    private static final String DPC_VS_AS_LIST = "route";

    private static final String MAX_AS_FOR_ROUTE_PROP = "maxasforroute";
    private static final String MAX_SEQUENCE_NUMBER_PROP = "maxsequencenumber";
    private static final String HEART_BEAT_TIME_PROP = "heartbeattime";
    private static final String STATISTICS_ENABLED = "statisticsenabled";
    private static final String ROUTING_KEY_MANAGEMENT_ENABLED = "routingkeymanagementenabled";

    private static final String M3UA_PERSIST_DIR_KEY = "m3ua.persist.dir";
    private static final String USER_DIR_KEY = "user.dir";
    private static final String PERSIST_FILE_NAME = "m3ua1.xml";

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

    protected static final int MAX_SEQUENCE_NUMBER = 256;

    protected FastList appServers = new FastList();
    protected FastList aspfactories = new FastList();

    protected M3UAScheduler m3uaScheduler = new M3UAScheduler();
    protected M3UACounterProviderImpl m3uaCounterProvider;

    private final TextBuilder persistFile = TextBuilder.newInstance();

    private final String name;

    private String persistDir = null;

    protected ParameterFactory parameterFactory = new ParameterFactoryImpl();
    protected MessageFactory messageFactory = new MessageFactoryImpl();

    protected Management transportManagement = null;
    protected boolean sctpLibNettySupport = false;

    protected ScheduledExecutorService fsmTicker;

    protected int maxAsForRoute = 2;

    protected int timeBetweenHeartbeat = 10000; // 10 sec default

    private M3UARouteManagement routeManagement = null;

    private boolean statisticsEnabled = false;
    private boolean routingKeyManagementEnabled = false;

    protected FastList managementEventListeners = new FastList();

    /**
     * Maximum sequence number received from SCCTP user. If SCCTP users sends seq number greater than max, packet will be
     * dropped and error message will be logged
     */
    private int maxSequenceNumber = MAX_SEQUENCE_NUMBER;

    public M3UAManagementImpl(String name, String productName, Ss7ExtInterface ss7ExtInterface) {
        super(productName, ss7ExtInterface);
        this.name = name;
        binding.setClassAttribute(CLASS_ATTRIBUTE);
        binding.setAlias(AspFactoryImpl.class, "aspFactory");
        binding.setAlias(AsImpl.class, "as");
        binding.setAlias(AspImpl.class, "asp");

        this.routeManagement = new M3UARouteManagement(this);
        this.m3uaCounterProvider = new M3UACounterProviderImpl(this);

    }

    public String getName() {
        return name;
    }

    public int getMaxSequenceNumber() {
        return maxSequenceNumber;
    }

    /**
     * Set the maximum SLS that can be used by SCTP. Internally SLS vs SCTP Stream Sequence Number is maintained. Stream Seq
     * Number 0 is for management.
     *
     * @param maxSls the maxSls to set
     */
    public void setMaxSequenceNumber(int maxSequenceNumber) throws Exception {
        if (this.isStarted)
            throw new Exception("MaxSequenceNumber parameter can be updated only when M3UA stack is NOT running");

        if (maxSequenceNumber < 1) {
            maxSequenceNumber = 1;
        } else if (maxSequenceNumber > MAX_SEQUENCE_NUMBER) {
            maxSequenceNumber = MAX_SEQUENCE_NUMBER;
        }
        this.maxSequenceNumber = maxSequenceNumber;
    }

    public String getPersistDir() {
        return persistDir;
    }

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

    public int getMaxAsForRoute() {
        return maxAsForRoute;
    }

    public void setMaxAsForRoute(int maxAsForRoute) throws Exception {
        if (this.isStarted)
            throw new Exception("MaxAsForRoute parameter can be updated only when M3UA stack is NOT running");

        if (maxAsForRoute < 1) {
            maxAsForRoute = 1;
        } else if (maxAsForRoute > 4) {
            maxAsForRoute = 4;
        }

        this.maxAsForRoute = maxAsForRoute;
    }

    public int getHeartbeatTime() {
        return this.timeBetweenHeartbeat;
    }

    public void setHeartbeatTime(int timeBetweenHeartbeat) throws Exception {
        if (!this.isStarted)
            throw new Exception("HeartbeatTime parameter can be updated only when M3UA stack is running");

        if (timeBetweenHeartbeat < 1000) {
            // minimum 1 sec is reasonable?
            timeBetweenHeartbeat = 1000;
        }

        this.timeBetweenHeartbeat = timeBetweenHeartbeat;

        this.store();
    }

    @Override
    public void setUseLsbForLinksetSelection(boolean useLsbForLinksetSelection) throws Exception {
        if (!this.isStarted)
            throw new Exception("UseLsbForLinksetSelection parameter can be updated only when M3UA stack is running");

        super.setUseLsbForLinksetSelection(useLsbForLinksetSelection);

        this.store();
    }

    @Override
    public void setRoutingLabelFormat(RoutingLabelFormat routingLabelFormat) throws Exception {
        if (this.isStarted)
            throw new Exception("RoutingLabelFormat parameter can be updated only when M3UA stack is NOT running");

        super.setRoutingLabelFormat(routingLabelFormat);
    }

    @Override
    public void setDeliveryMessageThreadCount(int deliveryMessageThreadCount) throws Exception {
        if (this.isStarted)
            throw new Exception("DeliveryMessageThreadCount parameter can be updated only when M3UA stack is NOT running");

        super.setDeliveryMessageThreadCount(deliveryMessageThreadCount);
    }

    @Override
    public String getRoutingLabelFormatStr() {
        return super.getRoutingLabelFormat().toString();
    }

    public Management getTransportManagement() {
        return transportManagement;
    }

    public void setTransportManagement(Management transportManagement) {
        this.transportManagement = transportManagement;
        if (transportManagement != null && transportManagement.getClass().getSimpleName().contains("Netty"))
            sctpLibNettySupport = true;
    }

    public boolean isSctpLibNettySupport() {
        return sctpLibNettySupport;
    }

    public void start() throws Exception {

        if (this.transportManagement == null) {
            throw new NullPointerException("TransportManagement is null");
        }

        if (maxAsForRoute < 1 || maxAsForRoute > 4) {
            throw new Exception("Max AS for a route can be minimum 1 or maximum 4");
        }

        super.start();

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

        binding.setM3uaManagement(this);

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

        fsmTicker = Executors.newSingleThreadScheduledExecutor();
        fsmTicker.scheduleAtFixedRate(m3uaScheduler, 500, 500, TimeUnit.MILLISECONDS);

        for (FastList.Node n = this.managementEventListeners.head(), end = this.managementEventListeners
                .tail(); (n = n.getNext()) != end;) {
            M3UAManagementEventListener m3uaManagementEventListener = n.getValue();
            try {
                m3uaManagementEventListener.onServiceStarted();
            } catch (Throwable ee) {
                logger.error("Exception while invoking M3UAManagementEventListener.onServiceStarted", ee);
            }
        }

        logger.info("Started M3UAManagement");
    }

    private void preparePersistFile() {
        if (this.persistFile.length() > 0)
            return;

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

    public void stop() throws Exception {

        for (FastList.Node n = this.managementEventListeners.head(), end = this.managementEventListeners
                .tail(); (n = n.getNext()) != end;) {
            M3UAManagementEventListener m3uaManagementEventListener = n.getValue();
            try {
                m3uaManagementEventListener.onServiceStopped();
            } catch (Throwable ee) {
                logger.error("Exception while invoking onServiceStopped", ee);
            }
        }

        this.store();

        this.stopFactories();
        super.stop();

        fsmTicker.shutdown();
    }

    @Override
    public boolean isStarted() {
        return this.isStarted;
    }

    @Override
    public void addM3UAManagementEventListener(M3UAManagementEventListener m3uaManagementEventListener) {
        synchronized (this) {
            if (this.managementEventListeners.contains(m3uaManagementEventListener))
                return;

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

    @Override
    public void removeM3UAManagementEventListener(M3UAManagementEventListener m3uaManagementEventListener) {
        synchronized (this) {
            if (!this.managementEventListeners.contains(m3uaManagementEventListener))
                return;

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

    public List getAppServers() {
        FastList appServersTmp = new FastList();
        appServersTmp.addAll(this.appServers);
        return appServersTmp;
    }

    public List getAspfactories() {
        FastList aspfactoriesTmpe = new FastList();
        aspfactoriesTmpe.addAll(this.aspfactories);
        return aspfactoriesTmpe;
    }

    public Map getRoute() {
        Map routeTmp = new HashMap();
        routeTmp.putAll(this.routeManagement.route);
        return routeTmp;
    }

    protected As getAs(String asName) {
        for (FastList.Node n = appServers.head(), end = appServers.tail(); (n = n.getNext()) != end;) {
            As as = n.getValue();
            if (as.getName().equals(asName)) {
                return as;
            }
        }
        return null;
    }

    /**
     * 

* Create new {@link AsImpl} *

*

* Command is m3ua as create mode ipspType rc * traffic-mode min-asp network-appearance *

*

* where mode is optional, by default SE. ipspType should be specified if type is IPSP. rc is optional and traffi-mode is * also optional, default is Loadshare *

* * @param args * @return * @throws Exception */ public As createAs(String asName, Functionality functionality, ExchangeType exchangeType, IPSPType ipspType, RoutingContext rc, TrafficModeType trafficMode, int minAspActiveForLoadbalance, NetworkAppearance na) throws Exception { As as = this.getAs(asName); if (as != null) { throw new Exception(String.format(M3UAOAMMessages.CREATE_AS_FAIL_NAME_EXIST, asName)); } // TODO check if RC is already taken? if (exchangeType == null) { exchangeType = ExchangeType.SE; } if (functionality == Functionality.IPSP && ipspType == null) { ipspType = IPSPType.CLIENT; } as = new AsImpl(asName, rc, trafficMode, minAspActiveForLoadbalance, functionality, exchangeType, ipspType, na); ((AsImpl) as).setM3UAManagement(this); FSM localFSM = ((AsImpl) as).getLocalFSM(); this.m3uaScheduler.execute(localFSM); FSM peerFSM = ((AsImpl) as).getPeerFSM(); this.m3uaScheduler.execute(peerFSM); appServers.add(as); this.store(); for (FastList.Node n = this.managementEventListeners.head(), end = this.managementEventListeners .tail(); (n = n.getNext()) != end;) { M3UAManagementEventListener m3uaManagementEventListener = n.getValue(); try { m3uaManagementEventListener.onAsCreated(as); } catch (Throwable ee) { logger.error("Exception while invoking onAsCreated", ee); } } return as; } public AsImpl destroyAs(String asName) throws Exception { AsImpl as = (AsImpl) this.getAs(asName); if (as == null) { throw new Exception(String.format(M3UAOAMMessages.NO_AS_FOUND, asName)); } if (as.appServerProcs.size() != 0) { throw new Exception(String.format(M3UAOAMMessages.DESTROY_AS_FAILED_ASP_ASSIGNED, asName)); } for (FastMap.Entry e = this.routeManagement.route.head(), end = this.routeManagement.route.tail(); (e = e .getNext()) != end;) { RouteAsImpl asList = e.getValue(); if(asList.hasAs(as)){ throw new Exception(String.format(M3UAOAMMessages.AS_USED_IN_ROUTE_ERROR, asName, e.getKey())); } } FSM asLocalFSM = as.getLocalFSM(); if (asLocalFSM != null) { asLocalFSM.cancel(); } FSM asPeerFSM = as.getPeerFSM(); if (asPeerFSM != null) { asPeerFSM.cancel(); } appServers.remove(as); this.store(); for (FastList.Node n = this.managementEventListeners.head(), end = this.managementEventListeners .tail(); (n = n.getNext()) != end;) { M3UAManagementEventListener m3uaManagementEventListener = n.getValue(); try { m3uaManagementEventListener.onAsDestroyed(as); } catch (Throwable ee) { logger.error("Exception while invoking onAsDestroyed", ee); } } return as; } /** * Create new {@link AspFactoryImpl} without passing optional aspid and heartbeat is false * * @param aspName * @param associationName * @return * @throws Exception */ public AspFactory createAspFactory(String aspName, String associationName) throws Exception { return this.createAspFactory(aspName, associationName, false); } /** * Create new {@link AspFactoryImpl} without passing optional aspid * * @param aspName * @param associationName * @return * @throws Exception */ public AspFactory createAspFactory(String aspName, String associationName, boolean isHeartBeatEnabled) throws Exception { long aspid = 0L; boolean regenerateFlag = true; while (regenerateFlag) { aspid = AspFactoryImpl.generateId(); if (aspfactories.size() == 0) { // Special case where this is first Asp added break; } for (FastList.Node n = aspfactories.head(), end = aspfactories.tail(); (n = n.getNext()) != end;) { AspFactoryImpl aspFactoryImpl = (AspFactoryImpl) n.getValue(); if (aspid == aspFactoryImpl.getAspid().getAspId()) { regenerateFlag = true; break; } else { regenerateFlag = false; } }// for }// while return this.createAspFactory(aspName, associationName, aspid, isHeartBeatEnabled); } /** *

* Create new {@link AspFactoryImpl} *

*

* Command is m3ua asp create aspid heartbeat *

*

* asp-name and sctp-association is mandatory where as aspid is optional. If aspid is not passed, next available aspid wil * be used *

* * @param aspName * @param associationName * @param aspid * @return * @throws Exception */ public AspFactory createAspFactory(String aspName, String associationName, long aspid, boolean isHeartBeatEnabled) throws Exception { AspFactoryImpl factory = this.getAspFactory(aspName); if (factory != null) { throw new Exception(String.format(M3UAOAMMessages.CREATE_ASP_FAIL_NAME_EXIST, aspName)); } Association association = this.transportManagement.getAssociation(associationName); if (association == null) { throw new Exception(String.format(M3UAOAMMessages.NO_ASSOCIATION_FOUND, associationName)); } if (association.isStarted()) { throw new Exception(String.format(M3UAOAMMessages.ASSOCIATION_IS_STARTED, associationName)); } if (association.getAssociationListener() != null) { throw new Exception(String.format(M3UAOAMMessages.ASSOCIATION_IS_ASSOCIATED, associationName)); } for (FastList.Node n = aspfactories.head(), end = aspfactories.tail(); (n = n.getNext()) != end;) { AspFactoryImpl aspFactoryImpl = (AspFactoryImpl) n.getValue(); if (aspid == aspFactoryImpl.getAspid().getAspId()) { throw new Exception(String.format(M3UAOAMMessages.ASP_ID_TAKEN, aspid)); } } factory = new AspFactoryImpl(aspName, this.getMaxSequenceNumber(), aspid, isHeartBeatEnabled); factory.setM3UAManagement(this); factory.setAssociation(association); factory.setTransportManagement(this.transportManagement); aspfactories.add(factory); this.store(); for (FastList.Node n = this.managementEventListeners.head(), end = this.managementEventListeners .tail(); (n = n.getNext()) != end;) { M3UAManagementEventListener m3uaManagementEventListener = n.getValue(); try { m3uaManagementEventListener.onAspFactoryCreated(factory); } catch (Throwable ee) { logger.error("Exception while invoking onAspFactoryCreated", ee); } } return factory; } public AspFactoryImpl destroyAspFactory(String aspName) throws Exception { AspFactoryImpl aspFactroy = this.getAspFactory(aspName); if (aspFactroy == null) { throw new Exception(String.format(M3UAOAMMessages.NO_ASP_FOUND, aspName)); } if (aspFactroy.aspList.size() != 0) { throw new Exception("Asp are still assigned to As. Unassign all"); } aspFactroy.unsetAssociation(); this.aspfactories.remove(aspFactroy); this.store(); for (FastList.Node n = this.managementEventListeners.head(), end = this.managementEventListeners .tail(); (n = n.getNext()) != end;) { M3UAManagementEventListener m3uaManagementEventListener = n.getValue(); try { m3uaManagementEventListener.onAspFactoryDestroyed(aspFactroy); } catch (Throwable ee) { logger.error("Exception while invoking onAspFactoryDestroyed", ee); } } return aspFactroy; } /** * Associate {@link AspImpl} to {@link AsImpl} * * @param asName * @param aspName * @return * @throws Exception */ public AspImpl assignAspToAs(String asName, String aspName) throws Exception { // check ASP and AS exist with given name AsImpl asImpl = (AsImpl) this.getAs(asName); if (asImpl == null) { throw new Exception(String.format(M3UAOAMMessages.NO_AS_FOUND, asName)); } AspFactoryImpl aspFactroy = this.getAspFactory(aspName); if (aspFactroy == null) { throw new Exception(String.format(M3UAOAMMessages.NO_ASP_FOUND, aspName)); } // If ASP already assigned to AS we don't want to re-assign for (FastList.Node n = asImpl.appServerProcs.head(), end = asImpl.appServerProcs.tail(); (n = n.getNext()) != end;) { AspImpl aspImpl = (AspImpl) n.getValue(); if (aspImpl.getName().equals(aspName)) { throw new Exception(String.format(M3UAOAMMessages.ADD_ASP_TO_AS_FAIL_ALREADY_ASSIGNED_TO_THIS_AS, aspName, asName)); } } FastList aspImpls = aspFactroy.aspList; // Checks for RoutingContext. We know that for null RC there will always // be a single ASP assigned to AS and ASP cannot be shared if (asImpl.getRoutingContext() == null) { // If AS has Null RC, this should be the first assignment of ASP to // AS if (aspImpls.size() != 0) { throw new Exception(String.format(M3UAOAMMessages.ADD_ASP_TO_AS_FAIL_ALREADY_ASSIGNED_TO_OTHER_AS, aspName, asName)); } } else if (aspImpls.size() > 0) { // RoutingContext is not null, make sure there is no ASP that is // assigned to AS with null RC Asp asp = aspImpls.get(0); if (asp != null && asp.getAs().getRoutingContext() == null) { throw new Exception(String.format(M3UAOAMMessages.ADD_ASP_TO_AS_FAIL_ALREADY_ASSIGNED_TO_OTHER_AS_WITH_NULL_RC, aspName, asName)); } } if (aspFactroy.getFunctionality() != null && aspFactroy.getFunctionality() != asImpl.getFunctionality()) { throw new Exception(String.format(M3UAOAMMessages.ADD_ASP_TO_AS_FAIL_ALREADY_ASSIGNED_TO_OTHER_AS_TYPE, aspName, asName, aspFactroy.getFunctionality())); } if (aspFactroy.getExchangeType() != null && aspFactroy.getExchangeType() != asImpl.getExchangeType()) { throw new Exception(String.format(M3UAOAMMessages.ADD_ASP_TO_AS_FAIL_ALREADY_ASSIGNED_TO_OTHER_AS_EXCHANGETYPE, aspName, asName, aspFactroy.getExchangeType())); } if (aspFactroy.getIpspType() != null && aspFactroy.getIpspType() != asImpl.getIpspType()) { throw new Exception(String.format(M3UAOAMMessages.ADD_ASP_TO_AS_FAIL_ALREADY_ASSIGNED_TO_OTHER_IPSP_TYPE, aspName, asName, aspFactroy.getIpspType())); } aspFactroy.setExchangeType(asImpl.getExchangeType()); aspFactroy.setFunctionality(asImpl.getFunctionality()); aspFactroy.setIpspType(asImpl.getIpspType()); AspImpl aspImpl = aspFactroy.createAsp(); FSM aspLocalFSM = aspImpl.getLocalFSM(); m3uaScheduler.execute(aspLocalFSM); FSM aspPeerFSM = aspImpl.getPeerFSM(); m3uaScheduler.execute(aspPeerFSM); asImpl.addAppServerProcess(aspImpl); this.store(); for (FastList.Node n = this.managementEventListeners.head(), end = this.managementEventListeners .tail(); (n = n.getNext()) != end;) { M3UAManagementEventListener m3uaManagementEventListener = n.getValue(); try { m3uaManagementEventListener.onAspAssignedToAs(asImpl, aspImpl); } catch (Throwable ee) { logger.error("Exception while invoking onAspAssignedToAs", ee); } } return aspImpl; } public Asp unassignAspFromAs(String asName, String aspName) throws Exception { // check ASP and AS exist with given name AsImpl asImpl = (AsImpl) this.getAs(asName); if (asImpl == null) { throw new Exception(String.format(M3UAOAMMessages.NO_AS_FOUND, asName)); } AspImpl aspImpl = asImpl.removeAppServerProcess(aspName); aspImpl.getAspFactory().destroyAsp(aspImpl); this.store(); for (FastList.Node n = this.managementEventListeners.head(), end = this.managementEventListeners .tail(); (n = n.getNext()) != end;) { M3UAManagementEventListener m3uaManagementEventListener = n.getValue(); try { m3uaManagementEventListener.onAspUnassignedFromAs(asImpl, aspImpl); } catch (Throwable ee) { logger.error("Exception while invoking onAspUnassignedFromAs", ee); } } return aspImpl; } /** * This method should be called by management to start the ASP * * @param aspName The name of the ASP to be started * @throws Exception */ public void startAsp(String aspName) throws Exception { AspFactoryImpl aspFactoryImpl = this.getAspFactory(aspName); if (aspFactoryImpl == null) { throw new Exception(String.format(M3UAOAMMessages.NO_ASP_FOUND, aspName)); } if (aspFactoryImpl.getStatus()) { throw new Exception(String.format(M3UAOAMMessages.ASP_ALREADY_STARTED, aspName)); } if (aspFactoryImpl.aspList.size() == 0) { throw new Exception(String.format(M3UAOAMMessages.ASP_NOT_ASSIGNED_TO_AS, aspName)); } aspFactoryImpl.start(); this.store(); for (FastList.Node n = this.managementEventListeners.head(), end = this.managementEventListeners .tail(); (n = n.getNext()) != end;) { M3UAManagementEventListener m3uaManagementEventListener = n.getValue(); try { m3uaManagementEventListener.onAspFactoryStarted(aspFactoryImpl); } catch (Throwable ee) { logger.error("Exception while invoking onAspFactoryStarted", ee); } } } /** * This method should be called by management to stop the ASP * * @param aspName The name of the ASP to be stopped * @throws Exception */ public void stopAsp(String aspName) throws Exception { this.doStopAsp(aspName, true); } private void doStopAsp(String aspName, boolean needStore) throws Exception { AspFactoryImpl aspFactoryImpl = this.getAspFactory(aspName); if (aspFactoryImpl == null) { throw new Exception(String.format(M3UAOAMMessages.NO_ASP_FOUND, aspName)); } if (!aspFactoryImpl.getStatus()) { throw new Exception(String.format(M3UAOAMMessages.ASP_ALREADY_STOPPED, aspName)); } aspFactoryImpl.stop(); if (needStore) this.store(); // TODO : Should calling // m3uaManagementEventListener.onAspFactoryStopped() be before actual // stop of aspFactory? The problem is ASP_DOWN and AS_INACTIV callbacks // are before AspFactoryStopped. Is it ok? for (FastList.Node n = this.managementEventListeners.head(), end = this.managementEventListeners .tail(); (n = n.getNext()) != end;) { M3UAManagementEventListener m3uaManagementEventListener = n.getValue(); try { m3uaManagementEventListener.onAspFactoryStopped(aspFactoryImpl); } catch (Throwable ee) { logger.error("Exception while invoking onAspFactoryStopped", ee); } } } public void addRoute(int dpc, int opc, int si, String asName) throws Exception { this.routeManagement.addRoute(dpc, opc, si, asName, TrafficModeType.Loadshare); } public void addRoute(int dpc, int opc, int si, String asName, int trafficModeType) throws Exception { this.routeManagement.addRoute(dpc, opc, si, asName, trafficModeType); } public void removeRoute(int dpc, int opc, int si, String asName) throws Exception { this.routeManagement.removeRoute(dpc, opc, si, asName); } public void removeAllResourses() throws Exception { if (!this.isStarted) { throw new Exception(String.format("Management=%s not started", this.name)); } if (this.appServers.size() == 0 && this.aspfactories.size() == 0) // no resources allocated - nothing to do return; if (logger.isInfoEnabled()) { logger.info(String.format("Removing allocated resources: AppServers=%d, AspFactories=%d", this.appServers.size(), this.aspfactories.size())); } this.stopFactories(); // Remove routes this.routeManagement.removeAllResourses(); // Unassign asp from as FastMap> lstAsAsp = new FastMap>(); for (As as : this.appServers) { AsImpl asImpl = (AsImpl) as; FastList lstAsps = new FastList(); for (FastList.Node n = asImpl.appServerProcs.head(), end = asImpl.appServerProcs.tail(); (n = n.getNext()) != end;) { AspImpl aspImpl = (AspImpl) n.getValue(); lstAsps.add(aspImpl.getName()); } lstAsAsp.put(asImpl.getName(), lstAsps); } for (FastMap.Entry> e = lstAsAsp.head(), end = lstAsAsp.tail(); (e = e.getNext()) != end;) { String asName = e.getKey(); FastList lstAsps = e.getValue(); for (FastList.Node n = lstAsps.head(), end1 = lstAsps.tail(); (n = n.getNext()) != end1;) { String aspName = n.getValue(); this.unassignAspFromAs(asName, aspName); } } // Remove all AspFactories ArrayList lstAspFactory = new ArrayList(); for (AspFactory aspFact : this.aspfactories) { lstAspFactory.add(aspFact); } for (AspFactory aspFact : lstAspFactory) { this.destroyAspFactory(aspFact.getName()); } // Remove all AppServers ArrayList lst = new ArrayList(); for (As asImpl : this.appServers) { lst.add(asImpl.getName()); } for (String n : lst) { this.destroyAs(n); } // We store the cleared state this.store(); for (FastList.Node n = this.managementEventListeners.head(), end = this.managementEventListeners .tail(); (n = n.getNext()) != end;) { M3UAManagementEventListener m3uaManagementEventListener = n.getValue(); try { m3uaManagementEventListener.onRemoveAllResources(); } catch (Throwable ee) { logger.error("Exception while invoking onRemoveAllResources", ee); } } } private void stopFactories() throws Exception { // Stopping asp factories boolean someFactoriesIsStopped = false; for (AspFactory aspFact : this.aspfactories) { AspFactoryImpl aspFactImpl = (AspFactoryImpl) aspFact; if (aspFactImpl.started) { someFactoriesIsStopped = true; this.doStopAsp(aspFact.getName(), false); } } // waiting 5 seconds till stopping factories if (someFactoriesIsStopped) { for (int step = 1; step < 50; step++) { boolean allStopped = true; for (AspFactory aspFact : this.aspfactories) { if (aspFact.getAssociation() != null && aspFact.getAssociation().isConnected()) { allStopped = false; break; } } if (allStopped) break; Thread.sleep(100); } } } public void sendTransferMessageToLocalUser(Mtp3TransferPrimitive msg, int seqControl) { super.sendTransferMessageToLocalUser(msg, seqControl); } public void sendPauseMessageToLocalUser(Mtp3PausePrimitive msg) { super.sendPauseMessageToLocalUser(msg); } public void sendResumeMessageToLocalUser(Mtp3ResumePrimitive msg) { super.sendResumeMessageToLocalUser(msg); } public void sendStatusMessageToLocalUser(Mtp3StatusPrimitive msg) { super.sendStatusMessageToLocalUser(msg); } public void sendEndCongestionMessageToLocalUser(Mtp3EndCongestionPrimitive msg) { super.sendEndCongestionMessageToLocalUser(msg); } private AspFactoryImpl getAspFactory(String aspName) { for (FastList.Node n = aspfactories.head(), end = aspfactories.tail(); (n = n.getNext()) != end;) { AspFactoryImpl aspFactoryImpl = (AspFactoryImpl) n.getValue(); if (aspFactoryImpl.getName().equals(aspName)) { return aspFactoryImpl; } } return null; } /** * Persist */ public void store() { // TODO : Should we keep reference to Objects rather than recreating // everytime? try { this.preparePersistFile(); 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.timeBetweenHeartbeat, HEART_BEAT_TIME_PROP, Integer.class); writer.write(this.statisticsEnabled, STATISTICS_ENABLED, Boolean.class); writer.write(this.routingKeyManagementEnabled, ROUTING_KEY_MANAGEMENT_ENABLED, Boolean.class); writer.write(this.isUseLsbForLinksetSelection(), USE_LSB_FOR_LINKSET_SELECTION, Boolean.class); writer.write(aspfactories, ASP_FACTORY_LIST, FastList.class); writer.write(appServers, AS_LIST, FastList.class); writer.write(this.routeManagement.route, DPC_VS_AS_LIST, RouteMap.class); writer.close(); } catch (Exception e) { logger.error("Error while persisting the Rule state in file", e); } } /** * Load and create LinkSets and Link from persisted file * * @throws Exception */ public void load() throws FileNotFoundException { XMLObjectReader reader = null; try { this.preparePersistFile(); File f = new File(persistFile.toString()); if (f.exists()) { // we have V2 config loadVer2(persistFile.toString()); } else { String s1 = persistFile.toString().replace("1.xml", ".xml"); f = new File(s1); if (f.exists()) { loadVer1(s1); } this.store(); f.delete(); } } catch (XMLStreamException ex) { logger.error(String.format("Failed to load the M3UA configuration file. \n%s", ex.getMessage())); } catch (FileNotFoundException e) { logger.warn(String.format("Failed to load the M3UA configuration file. \n%s", e.getMessage())); } catch (IOException e) { logger.error(String.format("Failed to load the M3UA configuration file. \n%s", e.getMessage())); } } protected void loadActualData(XMLObjectReader reader ) throws XMLStreamException, IOException{ try { Integer vali = reader.read(MAX_SEQUENCE_NUMBER_PROP, Integer.class); vali = reader.read(MAX_AS_FOR_ROUTE_PROP, Integer.class); this.timeBetweenHeartbeat = reader.read(HEART_BEAT_TIME_PROP, Integer.class); this.statisticsEnabled = reader.read(STATISTICS_ENABLED, Boolean.class); this.routingKeyManagementEnabled = reader.read(ROUTING_KEY_MANAGEMENT_ENABLED, Boolean.class); } catch (java.lang.Exception e) { // ignore. // For backward compatibility we can ignore if these values are not defined logger.error("Errro while reading attribute", e); } String vals = reader.read(ROUTING_LABEL_FORMAT, String.class); // we do not store it - for backup compatibility Boolean valb = reader.read(USE_LSB_FOR_LINKSET_SELECTION, Boolean.class); if (valb != null) { try { super.setUseLsbForLinksetSelection(valb); } catch (Exception e) { } } aspfactories = reader.read(ASP_FACTORY_LIST, FastList.class); appServers = reader.read(AS_LIST, FastList.class); this.routeManagement.route = reader.read(DPC_VS_AS_LIST, RouteMap.class); this.routeManagement.reset(); // Create Asp's and assign to each of the AS. Schedule the FSM's for (FastList.Node n = appServers.head(), end = appServers.tail(); (n = n.getNext()) != end;) { AsImpl asImpl = (AsImpl) n.getValue(); asImpl.setM3UAManagement(this); FSM asLocalFSM = asImpl.getLocalFSM(); m3uaScheduler.execute(asLocalFSM); FSM asPeerFSM = asImpl.getPeerFSM(); m3uaScheduler.execute(asPeerFSM); // All the Asp's for this As added in temp list FastList tempAsp = new FastList(); tempAsp.addAll(asImpl.appServerProcs); // Claer Asp's from this As asImpl.appServerProcs.clear(); for (FastList.Node n1 = tempAsp.head(), end1 = tempAsp.tail(); (n1 = n1.getNext()) != end1;) { AspImpl aspImpl = (AspImpl) n1.getValue(); try { // Now let the Asp's be created from respective // AspFactory and added to As this.assignAspToAs(asImpl.getName(), aspImpl.getName()); } catch (Exception e) { logger.error("Error while assigning Asp to As on loading from xml file", e); } } } // Set the transportManagement for (FastList.Node n = aspfactories.head(), end = aspfactories.tail(); (n = n.getNext()) != end;) { AspFactoryImpl factory = (AspFactoryImpl) n.getValue(); factory.setTransportManagement(this.transportManagement); factory.setM3UAManagement(this); try { factory.setAssociation(this.transportManagement.getAssociation(factory.associationName)); } catch (Throwable e1) { logger.error(String.format("Error setting Assciation=%s for the AspFactory=%s while loading from XML", factory.associationName, factory.getName()), e1); } if (factory.getStatus()) { try { factory.start(); } catch (Exception e) { logger.error(String.format("Error starting the AspFactory=%s while loading from XML", factory.getName()), e); } } } } private void loadVer1(String fn) throws XMLStreamException, IOException{ BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(fn))); StringBuilder sb = new StringBuilder(); while (true) { String s1 = br.readLine(); if (s1 == null) break; sb.append(s1); sb.append("\n"); } br.close(); String s2 = sb.toString(); s2 = s2.replace("




© 2015 - 2025 Weber Informatics LLC | Privacy Policy