package es.tid.pce.computingEngine;
import es.tid.pce.computingEngine.algorithms.ComputingAlgorithmManager;
import es.tid.pce.computingEngine.algorithms.ComputingAlgorithmManagerSSON;
import es.tid.pce.computingEngine.algorithms.multiLayer.OperationsCounter;
import es.tid.pce.pcep.constructs.Request;
import es.tid.pce.pcep.constructs.SVECConstruct;
import es.tid.pce.pcep.messages.PCEPInitiate;
import es.tid.pce.pcep.messages.PCEPMessageTypes;
import es.tid.pce.pcep.messages.PCEPRequest;
import es.tid.pce.pcep.objects.ObjectiveFunction;
import es.tid.pce.pcep.objects.RequestParameters;
import es.tid.pce.pcep.objects.tlvs.MaxRequestTimeTLV;
import es.tid.pce.server.ParentPCERequestManager;
import es.tid.pce.server.communicationpce.CollaborationPCESessionManager;
import es.tid.pce.server.wson.ReservationManager;
import es.tid.tedb.DomainTEDB;
import es.tid.tedb.TEDB;
import java.io.DataOutputStream;
import java.net.Inet4Address;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The Request Dispatcher receives the PCEP Request messages and distribute the
* individual requests in the computing threads. It creates Computing request,
* which contain the list of Request objects that need to be computed jointly, together
* with its associated. SVEC object. In case of individual requests, the ComputingRequest
* just contains a single Request.
* If not all the requests referred in the SVEC
* @author Oscar Gonzalez de Dios (ogondio@tid.es)
*
*/
public class RequestDispatcher {
/**
* Number of processing threads
*/
private final int nThreads;
/**
* Array of RequestProcessor Threads
*/
private final RequestProcessorThread[] threads;
private Lock numOPsLock;
/**
* The logger
*/
private Logger log;
/**
* For synchronized requests, to temporary store the requests until all the requests arrive
*/
private Hashtable<Long,ComputingRequest> pendingRequestList;
/**
* Queue to add path computing requests.
* This queue is read by the request processor threads.
*/
private LinkedBlockingQueue<ComputingRequest> pathComputingRequestQueue;
/**
* Queue to insert path computing requests that failed.
*/
private LinkedBlockingQueue<ComputingRequest> pathComputingRequestRetryQueue;
/*
* Constructor
* @param nThreads
* @param ted
* @param cpcerm
* @param analyzeRequestTime
*/
public RequestDispatcher(int nThreads,TEDB ted,ParentPCERequestManager cpcerm, boolean analyzeRequestTime)
{
log=LoggerFactory.getLogger("PCEServer");
this.nThreads = nThreads;
pathComputingRequestQueue = new LinkedBlockingQueue<ComputingRequest>();
pathComputingRequestRetryQueue= new LinkedBlockingQueue<ComputingRequest>();
pendingRequestList=new Hashtable<Long,ComputingRequest>();
threads = new RequestProcessorThread[nThreads];
numOPsLock = new ReentrantLock();
for (int i=0; i<this.nThreads; i++) {
log.info("Starting Request Processor Thread");
threads[i] = new RequestProcessorThread(pathComputingRequestQueue,ted,cpcerm,pathComputingRequestRetryQueue,analyzeRequestTime);
threads[i].setPriority(Thread.MAX_PRIORITY);
threads[i].start();
}
}
/**
* Constructor
* @param nThreads #thread
* @param ted database
* @param cpcerm requestmanager
* @param analyzeRequestTime boolean
* @param intraTEDBs internal tedbs
*/
public RequestDispatcher(int nThreads,TEDB ted,ParentPCERequestManager cpcerm, boolean analyzeRequestTime,Hashtable<String,TEDB> intraTEDBs)
{
log=LoggerFactory.getLogger("PCEServer");
this.nThreads = nThreads;
pathComputingRequestQueue = new LinkedBlockingQueue<ComputingRequest>();
pathComputingRequestRetryQueue= new LinkedBlockingQueue<ComputingRequest>();
pendingRequestList=new Hashtable<Long,ComputingRequest>();
threads = new RequestProcessorThread[nThreads];
numOPsLock = new ReentrantLock();
for (int i=0; i<this.nThreads; i++) {
log.info("Starting Request Processor Thread");
threads[i] = new RequestProcessorThread(pathComputingRequestQueue,ted,cpcerm,pathComputingRequestRetryQueue,analyzeRequestTime, intraTEDBs);
threads[i].setPriority(Thread.MAX_PRIORITY);
threads[i].start();
}
}
public RequestDispatcher(int nThreads,TEDB ted,ParentPCERequestManager cpcerm, boolean analyzeRequestTime, boolean useMaxReqTime, ReservationManager reservationManager)
{
log=LoggerFactory.getLogger("PCEServer");
this.nThreads = nThreads;
pathComputingRequestQueue = new LinkedBlockingQueue<ComputingRequest>();
pathComputingRequestRetryQueue= new LinkedBlockingQueue<ComputingRequest>();
pendingRequestList=new Hashtable<Long,ComputingRequest>();
threads = new RequestProcessorThread[nThreads];
for (int i=0; i<this.nThreads; i++) {
//log.info("TEEED:: "+ted.printTopology());
log.info("1. Starting Request Processor Thread!");
threads[i] = new RequestProcessorThread(pathComputingRequestQueue,ted,cpcerm,pathComputingRequestRetryQueue,analyzeRequestTime,useMaxReqTime, reservationManager);
threads[i].setPriority(Thread.MAX_PRIORITY);
threads[i].start();
}
}
public RequestDispatcher(int nThreads,TEDB ted,ParentPCERequestManager cpcerm, boolean analyzeRequestTime, boolean useMaxReqTime, ReservationManager reservationManager, OperationsCounter OPcounter, boolean isMult)
{
log=LoggerFactory.getLogger("PCEServer");
this.nThreads = nThreads;
pathComputingRequestQueue = new LinkedBlockingQueue<ComputingRequest>();
pathComputingRequestRetryQueue= new LinkedBlockingQueue<ComputingRequest>();
pendingRequestList=new Hashtable<Long,ComputingRequest>();
threads = new RequestProcessorThread[nThreads];
for (int i=0; i<this.nThreads; i++) {
log.info("Starting Request Processor Thread!");
threads[i] = new RequestProcessorThread(pathComputingRequestQueue,ted,cpcerm,pathComputingRequestRetryQueue,analyzeRequestTime,useMaxReqTime, reservationManager, OPcounter, isMult);
threads[i].setPriority(Thread.MAX_PRIORITY);
threads[i].start();
}
}
public RequestDispatcher(int nThreads,TEDB ted,ParentPCERequestManager cpcerm, boolean analyzeRequestTime,CollaborationPCESessionManager collaborationPCESessionManager)
{
log=LoggerFactory.getLogger("PCEServer");
this.nThreads = nThreads;
pathComputingRequestQueue = new LinkedBlockingQueue<ComputingRequest>();
pathComputingRequestRetryQueue= new LinkedBlockingQueue<ComputingRequest>();
pendingRequestList=new Hashtable<Long,ComputingRequest>();
threads = new RequestProcessorThread[nThreads];
for (int i=0; i<this.nThreads; i++) {
log.info("Starting Request Processor Thread!");
threads[i] = new RequestProcessorThread(pathComputingRequestQueue,ted,cpcerm,pathComputingRequestRetryQueue,analyzeRequestTime, collaborationPCESessionManager);
threads[i].setPriority(Thread.MAX_PRIORITY);
threads[i].start();
}
}
public RequestDispatcher(int nThreads,TEDB ted,ParentPCERequestManager cpcerm, boolean analyzeRequestTime, boolean useMaxReqTime, ReservationManager reservationManager,CollaborationPCESessionManager collaborationPCESessionManager)
{
log=LoggerFactory.getLogger("PCEServer");
this.nThreads = nThreads;
pathComputingRequestQueue = new LinkedBlockingQueue<ComputingRequest>();
pathComputingRequestRetryQueue= new LinkedBlockingQueue<ComputingRequest>();
pendingRequestList=new Hashtable<Long,ComputingRequest>();
threads = new RequestProcessorThread[nThreads];
for (int i=0; i<this.nThreads; i++) {
log.info("Starting Request Processor Thread!");
threads[i] = new RequestProcessorThread(pathComputingRequestQueue,ted,cpcerm,pathComputingRequestRetryQueue,analyzeRequestTime,useMaxReqTime, reservationManager,collaborationPCESessionManager);
threads[i].setPriority(Thread.MAX_PRIORITY);
threads[i].start();
}
}
public void registerAlgorithm(AlgorithmRule rule, ComputingAlgorithmManager algortithmManager ){
for (int i=0; i<this.nThreads; i++) {
log.info("Registering algorithm im processor");
threads[i].registerAlgorithm(rule,algortithmManager);
}
}
public void registerAlgorithmSSON(AlgorithmRule rule, ComputingAlgorithmManagerSSON algortithmManager ){
for (int i=0; i<this.nThreads; i++) {
log.info("Registering algorithm im processor");
threads[i].registerAlgorithmSSON(rule,algortithmManager);
}
}
public void dispathRequests(PCEPRequest reqMessage, DataOutputStream out){
dispathRequests(reqMessage, out,null);
}
public void dispathRequests(PCEPInitiate iniMessage, DataOutputStream out)
{
log.info("Dispatching Request from Initiate message!");
ComputingRequest cr=new ComputingRequest();
cr.setOut(out);
LinkedList<Request> requestList = new LinkedList<Request>();
Request req = new Request();
ObjectiveFunction of=new ObjectiveFunction();//FIXME: FIRE!!!
of.setOFcode(1002);
req.setObjectiveFunction(of);
req.setEndPoints(iniMessage.getPcepIntiatedLSPList().get(0).getEndPoint());
req.setBandwidth(iniMessage.getPcepIntiatedLSPList().get(0).getBandwidth());
RequestParameters reqparams=new RequestParameters();
reqparams.setRequestID(iniMessage.getPcepIntiatedLSPList().get(0).getLsp().getLspId());
req.setRequestParameters(reqparams);
requestList.add(req);
cr.setRequestList(requestList);
cr.setTimeStampNs(System.nanoTime());
cr.setMaxTimeInPCE(120000);
cr.getEcodingType(PCEPMessageTypes.MESSAGE_INITIATE);
pathComputingRequestQueue.add(cr);
}
public void dispathRequests(PCEPInitiate iniMessage, DataOutputStream out, Inet4Address remotePCEId)
{
log.info("Dispatching Initiate message");
ComputingRequest cr=new ComputingRequest();
cr.setOut(out);
LinkedList<Request> requestList = new LinkedList<Request>();
Request req = new Request();
ObjectiveFunction of=new ObjectiveFunction();//FIXME: FIRE!!!
of.setOFcode(1002);
req.setObjectiveFunction(of);
req.setEndPoints(iniMessage.getPcepIntiatedLSPList().get(0).getEndPoint());
req.setBandwidth(iniMessage.getPcepIntiatedLSPList().get(0).getBandwidth());
RequestParameters reqparams=new RequestParameters();
reqparams.setRequestID(iniMessage.getPcepIntiatedLSPList().get(0).getLsp().getLspId());
req.setRequestParameters(reqparams);
requestList.add(req);
cr.setIniLSP(iniMessage.getPcepIntiatedLSPList().get(0));
cr.setRequestList(requestList);
cr.setTimeStampNs(System.nanoTime());
cr.setMaxTimeInPCE(120000);
cr.getEcodingType(PCEPMessageTypes.MESSAGE_INITIATE);
pathComputingRequestQueue.add(cr);
}
public void dispathRequests(PCEPRequest reqMessage, DataOutputStream out, Inet4Address remotePCEId){
if (out==null){
log.error("OUT ESTA A NULL!!!!");
}
//Obtain the request list
LinkedList<Request> reqList=reqMessage.getRequestList();
log.debug("There are "+reqMessage.getRequestList().size()+" requests");
//If there are request to sincronize...
if (reqMessage.getSvecList().size()!=0){
log.debug("SVEC is present!");
int numRequests=0;
Hashtable<Long,Request> hashReqList=new Hashtable<Long,Request>();
for (int i=0;i<reqList.size();++i){
hashReqList.put(new Long(reqList.get(i).getRequestParameters().getRequestID()), reqList.get(i));
}
log.debug("TAM DE hashReqList ES "+hashReqList.size());
for (int i=0;i<reqMessage.getSvecList().size();++i){
log.debug("SVEC begins");
SVECConstruct svecc=reqMessage.getSvecList().get(i);
if (svecc.getSvec().getRequestIDlist().size()!=0){
ComputingRequest cr=new ComputingRequest();
cr.setRequestList(new LinkedList<Request>());
cr.setOut(out);
cr.setSvec(svecc);
ArrayList<Long> reqIDlist=reqMessage.getSvecList().get(i).getSvec().getRequestIDlist();
for (int j=0;j<reqIDlist.size();++j){
long reqId=reqIDlist.get(j);
Request req=hashReqList.remove(reqId);
if (req!=null){
cr.getRequestList().add(req);
numRequests=numRequests+1;
}
else {
pendingRequestList.put(reqId, cr);
}
}
pathComputingRequestQueue.add(cr);
}
}
if (hashReqList.size()!=0){
Enumeration<Request> enumReq=hashReqList.elements();
while(enumReq.hasMoreElements()){
ComputingRequest cr=new ComputingRequest();
cr.setOut(out);
LinkedList<Request> req=new LinkedList<Request>();
req.add(enumReq.nextElement());
cr.setRequestList(req);
pathComputingRequestQueue.add(cr);
}
}
}
else {
if (reqMessage.getRequestList().size()==1){
log.info("Dispatching Request!");
ComputingRequest cr=new ComputingRequest();
cr.setOut(out);
if (remotePCEId!=null){
cr.setRemotePCEId(remotePCEId);
}
cr.setRequestList(reqMessage.getRequestList());
cr.setTimeStampNs(System.nanoTime());
if(reqMessage.getMonitoring()!=null){
cr.setMonitoring(reqMessage.getMonitoring());
}
if(reqMessage.getPccReqId()!=null){
cr.setPccReqId(reqMessage.getPccReqId());
}
MaxRequestTimeTLV reqTLV=reqMessage.getRequestList().getFirst().getRequestParameters().getMaxRequestTimeTLV();
if (reqTLV!=null){
cr.setMaxTimeInPCE(reqTLV.getMaxRequestTime());
}else{
cr.setMaxTimeInPCE(120000);
}
pathComputingRequestQueue.add(cr);
}
else {
log.info("The number of requests is "+reqMessage.getRequestList().size());
for (int i=0;i<reqMessage.getRequestList().size();i++){
log.info("Dispatching Request "+i+"th request");
ComputingRequest cr=new ComputingRequest();
cr.setOut(out);
LinkedList<Request> requestList=new LinkedList<Request>();
requestList.add(reqMessage.getRequestList().get(i));
cr.setRequestList(requestList);
pathComputingRequestQueue.add(cr);
}
}
}
}
public RequestProcessorThread[] getThreads() {
return threads;
}
/*
* Insert a computing request in the retry Queue
*/
public void addComputingRequestToRetryQueue(ComputingRequest compreq){
pathComputingRequestRetryQueue.add(compreq);
}
/*
* Move all the elements in the retry queue to the
* computing request queue in the same order
*/
public synchronized void moveRetryQueueToComputingRequestQueue(){
int numRetryReq=pathComputingRequestRetryQueue.size();
for(int i=0;i<numRetryReq;++i){
try {
pathComputingRequestQueue.add(pathComputingRequestRetryQueue.take());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public int queueSize(){
return pathComputingRequestQueue.size() ;
}
public int retryQueueSize(){
return pathComputingRequestRetryQueue.size() ;
}
}