/** * This file is part of Path Computation Element Emulator (PCEE). * * PCEE is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * PCEE 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with PCEE. If not, see <http://www.gnu.org/licenses/>. */ package com.pcee.architecture.computationmodule; import java.util.HashMap; import java.util.concurrent.LinkedBlockingQueue; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.pcee.architecture.ModuleEnum; import com.pcee.architecture.ModuleManagement; import com.pcee.architecture.computationmodule.ted.TopologyInformation; import com.pcee.architecture.computationmodule.threadpool.ThreadPool; import com.pcee.protocol.message.PCEPMessage; import com.pcee.protocol.message.objectframe.impl.erosubobjects.PCEPAddress; import com.pcee.protocol.response.PCEPResponseFrame; import com.pcee.protocol.response.PCEPResponseFrameFactory; /** * * @author Marek Drogon * @author Mohit Chamania */ public class ComputationModuleImpl extends ComputationModule { private static Logger logger = LoggerFactory.getLogger(ComputationModuleImpl.class); // Management Object used to forward communications between the different // modules private ModuleManagement lm; // Thread Pool Implementation to compute incoming requests private ThreadPool threadPool; // Used by the ThreadPool class to initialize the given amount of Threads private int computationThreads; // Thread-safe queue to store requests to be used by the thread pool private LinkedBlockingQueue<PCEPMessage> requestQueue; //HashMap for keeping track of requests made to remote peers and the associated worker tasks private HashMap <String, LinkedBlockingQueue<PCEPMessage>> remotePeerResponseAssociationHashMap; /** * Default Constructor * * @param layerManagement */ public ComputationModuleImpl(ModuleManagement layerManagement) { lm = layerManagement; computationThreads = 5; start(); } public ComputationModuleImpl(ModuleManagement layerManagement, int computationThreads) { lm = layerManagement; this.computationThreads = computationThreads; start(); } public void stop(boolean graceful) { logger.info("Stopping Computation Module, graceful=" + (graceful?"true":"false")); if (graceful) { //Include code for graceful stop } else { threadPool.stop(); requestQueue.clear(); TopologyInformation.closeInstance(); } } public void start() { //Initialize the topology to import the definition from file and start the thread to listen for topology updates TopologyInformation.getInstance(); //Innitialize the map that will record the responses coming from remote peers remotePeerResponseAssociationHashMap = new HashMap<String, LinkedBlockingQueue<PCEPMessage>>(); // Initialize a new request Queue requestQueue = new LinkedBlockingQueue<PCEPMessage>(); // Initialize the thread pool used for computing requests threadPool = new ThreadPool(lm, computationThreads, requestQueue); } public void closeConnection(PCEPAddress address) { // TODO Auto-generated method stub // Explicit removal of requests from closed connections not implemented } public void registerConnection(PCEPAddress address, boolean connected, boolean connectionInitialized, boolean forceClient) { // TODO Auto-generated method stub // Explicit registration of connections not implemented } public void receiveMessage(PCEPMessage message, ModuleEnum sourceLayer) { logger.debug("Entering: receiveMessage(PCEPMessage message)"); logger.debug("| message: " + message.contentInformation()); logger.debug("| sourceLayer: " + sourceLayer); switch (sourceLayer) { case SESSION_MODULE: //If message is a path computation request process message if (message.getMessageHeader().getTypeDecimalValue()==3) requestQueue.add(message); else if (message.getMessageHeader().getTypeDecimalValue()==4) //Path computation response received from another PCE server /// needs to be sent to a worker in the computataion module processResponseFromRemotePeer(message); break; default: logger.info("Error in receiveMessage(PCEPMessage message, LayerEnum targetLayer)"); logger.info("Wrong sourceLayer"); break; } } private String getKeyForRemotePeerAssociation(PCEPAddress address, String requestID) { return address.getIPv4Address(true) + "-" + requestID; } public synchronized boolean isValidRequestToRemotePeer(PCEPAddress address, String requestID){ //If the particular combination of remote PCE peer and request ID already exist do not make a new association String key = getKeyForRemotePeerAssociation(address, requestID); if (remotePeerResponseAssociationHashMap.containsKey(key)) return false; return true; } public synchronized void registerRequestToRemotePeer(PCEPAddress address, String requestID, LinkedBlockingQueue<PCEPMessage> queue){ if (isValidRequestToRemotePeer(address, requestID)) { String key = getKeyForRemotePeerAssociation(address, requestID); remotePeerResponseAssociationHashMap.put(key, queue); } else logger.info("registerRequestToRemotePeer: Not a valid request"); } //Function to implement a mechanism where a response from another server (hierarchical or PCE peer) is sent to the correct worker task protected synchronized void processResponseFromRemotePeer(PCEPMessage message) { PCEPAddress address = message.getAddress(); //Message is of type PCEP Response PCEPResponseFrame responseFrame = PCEPResponseFrameFactory .getPathComputationResponseFrame(message); String requestID = Integer.toString(responseFrame.getRequestID()); String key = getKeyForRemotePeerAssociation(address, requestID); if (remotePeerResponseAssociationHashMap.containsKey(key)) { logger.info("Path Computation Response Received by the computation Module, adding to queue from worker task"); remotePeerResponseAssociationHashMap.get(key).add(message); remotePeerResponseAssociationHashMap.remove(key); } else { logger.info("Response for Peer-requestID combnation that is not registered with the computation module"); } } public void sendMessage(PCEPMessage message, ModuleEnum targetLayer) { switch (targetLayer) { case NETWORK_MODULE: // undefined break; case SESSION_MODULE: lm.getSessionModule().receiveMessage(message, ModuleEnum.COMPUTATION_MODULE); break; case COMPUTATION_MODULE: // undefined break; case CLIENT_MODULE: // Not possible break; default: logger.info("Error in sendMessage(PCEPMessage message, LayerEnum targetLayer)"); logger.info("Wrong target Layer"); break; } } }