%>>>eventDispatcherMainLoop
%
%This function is in charge of the simulation. eventDispatcherMainLoop is
%the engine of the simulator. It controls an event list, being the only
%module capable of adding and removing events from the list. The list contains
%just two types of events: new flow arrival and existing flow termination.
%Moreover, it updates this structure in every event cycle according to the
%actions planned by the Planning algorithm.
%>>>The inputs are:
%
% 1) maxSimulationTime: is the total time of simulation.
%
% 2) transitoryTime: is the time it takes the simulation to get a
% stationary state that lets us get valid statistics. After that time,
% the counters and the statistics are reseted.
%
% 3) physicalTopologyFile: is a string containing the Physical Topology
% File (*.phys) name used.
%
% 4) generator: is a string containing the generator name used to generate
% the flows.
%
% 5) generatorParameters: parameters of the generator what are taken from
% the guide aplication (Average flow rate (Gbps) Average flow duration (s)
% Flag truncated exponential (0=not truncated, 1=truncated)).
%
% 6) algorithmMethod: is a string containing the algorithm name used to
% make decisions about planning the net.
%
% 7) algorithmParameters: is a string containing the parameters of the
% algorithm what are taken from the guide aplication.
%
% 8) batchSimulationFlag: is a flag to show if it is a batch simulation. When
% its value is '1', it is a batch simulation and then this function will
% be able to be used without the guide application. If its value is '0',
% it is not a batch simulation and then we will be using the guide
% application.
%
% 9) handles: is a structure containing handles of components in GUI using
% tags as fieldnames, e.g. handles.figure1, handles.slider2. This
% structure is created at GUI startup using GUIHANDLES and stored in
% the figure's application data using GUIDATA. A copy of the structure
% is passed to each callback. You can store additional information in
% this structure at GUI startup, and you can change the structure
% during callbacks. Call guidata(h, handles) after changing your
% copy to replace the stored original so that subsequent callbacks see
% the updates. Type "help guihandles" and "help guidata" for more
% information.
%
%
%>>>The outputs are:
%
% 1) dynStatistics: is a structure containing the temporal average of the
% statistics calculated.
%
function [dynStatistics] = eventDispatcherMainLoop (maxSimulationTime , transitoryTime , physicalTopologyFile,...
batchSimulationFlag,handles)
if batchSimulationFlag == 0
load_global_Dynamic;
global netState;
global simTime;
global dynStatistics;
end
if batchSimulationFlag == 1
simulationState = 1;
end
%%%%%%%%%%%%%%% VARIABLES INITIALIZATION %%%%%%%%%%%%%%%%%%
fullpathname=[pwd '\data\physicalTopologies\' physicalTopologyFile];
[metadata, phys, netState] = io_readXML(fullpathname);
simTime = 0;
transitoryFlag=0;
currentGeneratorState=-1;
numberOfGeneratedFlows=0;
numberOfLinks=phys.M;
numberOfNodes=phys.N;
netState = struct ('flowRoutingMatrix' , [] , 'lightpathRoutingMatrix' , [] , 'lightpathTable' , [] , 'flowTable' , [] , 'numberOfOccupiedTWCs' , zeros(numberOfNodes,1),'numberOfOccupiedTxs' , zeros(numberOfNodes,1),'numberOfOccupiedRxs' , zeros(numberOfNodes,1));
global dynStatistics
dynStatistics = struct ('maxNrUsedTransmittersPerNode' , zeros (1,numberOfNodes) , 'minNrUsedTransmittersPerNode' , inf * ones (1,numberOfNodes) , ...
'NrUsedTransmittersPerNode' , 0 , 'NrUsedReceiversPerNode' , 0 , 'NrUsedWavelengthsPerFiber' , zeros(1,numberOfLinks) , ...
'NrUsedPhysHops' , 0 , 'linkTraffic' , 0 , 'offeredTraffic' , 0 ,'carriedPhysTraffic' , 0 ,'carriedVirtTraffic' , 0 , ...
'averPhysicalHops' , 0 , 'averVirtualHops' , 0 , 'singleHopTraffic' , 0 , 'networkCongestion' , 0 , ...
'totalNrOfUsedWavelengths' , 0 , 'maximumLinkLoadinNrLightpaths' , 0 ,'messagePropagationDelay' , 0 ,'totalNrOfUsedConverters' , 0 , ...
'NrUsedConvertersPerNode' , 0 , 'averNrUsedConverPerLP' , 0 , ...
'maxNrUsedReceiversPerNode' , zeros (1,numberOfNodes) , 'minNrUsedReceiversPerNode' , inf * ones (1,numberOfNodes) , ...
'maxNrUsedWavelengthsPerFiber' , zeros (1,numberOfLinks) , 'minNrUsedWavelengthsPerFiber' , inf * ones (1,numberOfLinks) , ...
'averageNrUsedPhysHops' , 0 , 'maxAverNrUsedPhysHops' , 0 , 'minAverNrUsedPhysHops' , inf , 'maxlinkTraffic' , zeros (1,numberOfLinks) , ...
'minlinkTraffic' , inf * ones (1,numberOfLinks) , 'maxofferedTraffic' , 0 , 'minofferedTraffic' , inf , 'maxcarriedPhysTraffic' , 0 , ...
'mincarriedPhysTraffic' , inf , 'maxcarriedVirtTraffic' , 0 , 'mincarriedVirtTraffic' , inf , 'maxaverPhysicalHops' , 0 , 'minaverPhysicalHops' , inf , ...
'maxaverVirtualHops' , 0 , 'minaverVirtualHops' , inf , 'maxsingleHopTraffic' , 0 , 'minsingleHopTraffic' , inf , 'maxnetworkCongestion' , 0 , ...
'minnetworkCongestion' , inf , 'maxtotalNrOfUsedWavelengths' , 0 , 'mintotalNrOfUsedWavelengths' , inf , 'maxmaximumLinkLoadinNrLightpaths' , 0 , ...
'minmaximumLinkLoadinNrLightpaths' , inf , 'maxmessagePropagationDelay' , 0 , 'minmessagePropagationDelay' , inf , 'maxtotalNrOfUsedConverters' , 0 , ...
'mintotalNrOfUsedConverters' , inf , 'maxNrUsedConvertersPerNode' , zeros (1,numberOfNodes) , 'minNrUsedConvertersPerNode' , inf * ones (1,numberOfNodes) , ...
'carriedFlows' , 0 , 'lostFlows' , 0 , 'lostTraffic' , 0 , 'carriedTraffic' , 0 , 'blockingProbability' , 0 , 'percentOfBlockedTraffic' , 0 , 'elapsedTime' , 0);
%%%%%%%%%% Global Variables Initialization %%%%%%%
global availableWavelengthsPerLinkTable;
global availableTWCsPerNode;
global availableTxPerNode;
global availableRxPerNode;
availableWavelengthsPerLinkTable=[];
availableTWCsPerNode=[];
availableTxPerNode=[];
availableRxPerNode=[];
global firstTime;
firstTime= [];
global generatorListOfPendingEvents;
generatorListOfPendingEvents=[];
global averageRate
averageRate=[];
global averageDuration
averageDuration=[];
global IAT;
IAT=[];
global truncatedExponentialFlag;
truncatedExponentialFlag=[];
%listOfPendingEvents is a matrix where each row save at the first column
%the type of the event, at the second column the time of the event and at
%the third column the ID of the flow.
listOfPendingEvents=[];
%Add the first arravied event to the list of pending events starting at
%simulation time 0 and with ID 1.
[timeToNextEvent , flowPropertiesNotUsed,exitFlagGenerator,exitMsgGenerator] = feval(generator ,generatorParameters,simTime,netState,phys);
%EXIT FLAG FROM DESIGN PROCESS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if(exitFlagGenerator==-1)||(exitFlagGenerator==-2)
if (exitFlagGenerator==-1)
errordlg(exitMsgGenerator,'Design Failed','modal')
end
%Updating buttons state
set(handles.pushbutton5,'Enable','on');
set(handles.pushbutton14,'Enable','off');
set(handles.pushbutton7,'Enable','off');
set(handles.pushbutton8,'Enable','off');
set(handles.pushbutton9,'Enable','off');
set(handles.pushbutton10,'Enable','off');
set(handles.pushbutton20,'Enable','off');
%Updating simulation state
set(handles.pushbutton7,'UserData',4);
return
end
listOfPendingEvents=addEventToListOfPendingEvents (0 , timeToNextEvent , -1 , listOfPendingEvents);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%Beginning of principal loop%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
while (true)
if batchSimulationFlag==0
simulationState=get(handles.pushbutton7, 'UserData');
end
%At first, check the simulation state.
switch simulationState
case 0 %Continue
simulationState_continue;
pause(0.001)
case 1 %Normal Execution
%If the simulation is with refresh, then the results are updated.
if batchSimulationFlag==0
if(get(handles.checkbox1,'Value') == get(handles.checkbox1,'Max'))
GUIResultsInformation; %Updating edits.
else
%Updating edits from Results Information
set(handles.edit9,'String','');
set(handles.edit14,'String','');
set(handles.edit15,'String','');
set(handles.edit16,'String','');
end
pause(0.0000000001)
end
case 2 %Stop
simulationState_stop;
%Waiting for a change of simulation state.
waitfor(handles.pushbutton7,'UserData');
case 3 %Step
simulationState_step;
pause(0.001)
continue
case 4 %End Simulation
if batchSimulationFlag==0
%Updating state buttons
set(handles.pushbutton5,'Enable','on');
set(handles.pushbutton14,'Enable','off');
set(handles.pushbutton7,'Enable','off');
set(handles.pushbutton8,'Enable','off');
set(handles.pushbutton9,'Enable','off');
set(handles.pushbutton10,'Enable','off');
set(handles.pushbutton20,'Enable','off');
set(handles.pushbutton16,'Enable','on');
%Updating input parameters
set(handles.popupmenu11,'Enable','on');
set(handles.popupmenu12,'Enable','on');
set(handles.popupmenu1,'Enable','on');
set(handles.popupmenu2,'Enable','on');
set(handles.popupmenu3,'Enable','on');
set(handles.edit11,'Enable','on');
set(handles.edit12,'Enable','on');
set(handles.edit13,'Enable','on');
set(handles.edit17,'Enable','on');
%Updating simulation state
set(handles.pushbutton7,'UserData',4);
%Show Results
GUIShowResults;
end
pause(0.001)
break; % para el while del bucle principal
otherwise %Error
error('It isnt a legal value for simulationState')
end
if simulationState==4 %If Simulation State is EndSimulation, then we stop the loop.
break;
end
%Take the first event in the list of pending events and simulation time is updated.
[eventType , eventTime , serialNumOfThisFlow] = nextPendingEvent(listOfPendingEvents);
lastSimTime=simTime;
simTime = eventTime;
%When we get at maximum simulation time, we stop the simulation, show
%the results and initialize the variables.
if (simTime > maxSimulationTime && simulationState~=4)
if batchSimulationFlag==0
GUIResultsInformation;
%Updating buttons state
set(handles.pushbutton5,'Enable','on');
set(handles.pushbutton14,'Enable','off');
set(handles.pushbutton7,'Enable','off');
set(handles.pushbutton8,'Enable','off');
set(handles.pushbutton9,'Enable','off');
set(handles.pushbutton10,'Enable','off');
set(handles.pushbutton20,'Enable','off');
set(handles.pushbutton16,'Enable','on');
%Updating simulation state
set(handles.pushbutton7,'UserData',4);
%Updating input parameters
set(handles.popupmenu11,'Enable','on');
set(handles.popupmenu12,'Enable','on');
set(handles.popupmenu1,'Enable','on');
set(handles.popupmenu2,'Enable','on');
set(handles.popupmenu3,'Enable','on');
set(handles.edit11,'Enable','on');
set(handles.edit12,'Enable','on');
set(handles.edit13,'Enable','on');
set(handles.edit17,'Enable','on');
%Show Results
GUIShowResults;
end
pause(0.001)
break; % para el while del bucle principal
end
switch eventType %Distinguish the two types of events
case 0 %When it is an ARRIVED event:
[timeToNextEvent , flowProperties,exitFlagGenerator,exitMsgGenerator] = feval(generator ,generatorParameters,simTime,netState,phys);
flowProperties.flowSerialNumber = numberOfGeneratedFlows;
flowProperties.flowSetUpTime = -1;
numberOfGeneratedFlows = numberOfGeneratedFlows + 1;
[actions,infoWhatHappenedWithTheFlow,exitFlagAlgorithm,exitMsgAlgorithm] =feval(algorithmMethod,0,netState,phys,simTime, algorithmParameters,flowProperties);
%EXIT FLAG FROM DESIGN PROCESS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if(exitFlagAlgorithm==-1)
errordlg(exitMsgAlgorithm,'Design Failed','modal')
%Updating buttons state
set(handles.pushbutton5,'Enable','on');
set(handles.pushbutton14,'Enable','off');
set(handles.pushbutton7,'Enable','off');
set(handles.pushbutton8,'Enable','off');
set(handles.pushbutton9,'Enable','off');
set(handles.pushbutton10,'Enable','off');
set(handles.pushbutton20,'Enable','off');
%Updating simulation state
set(handles.pushbutton7,'UserData',4);
break;
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
for actionNumber=1:size(actions)
actionToDo=actions{actionNumber};
[netState]=processAction(actionToDo, netState,phys,simTime);
end
switch infoWhatHappenedWithTheFlow
case 0 %If infoWhatHappenedWithTheFlow is 0, then the flow has been CARRIED.
%The event is deleted from the list of pending events.
[listOfPendingEvents,currentSerialNum]=removeTopPendingEvent(listOfPendingEvents);
%Add its end event of the carried flow to the list of pending events.
listOfPendingEvents=addEventToListOfPendingEvents (1 , simTime + flowProperties.flowDuration ,flowProperties.flowSerialNumber,listOfPendingEvents);
%Updating variables
dynStatistics.carriedFlows=dynStatistics.carriedFlows+1;
dynStatistics.carriedTraffic=dynStatistics.carriedTraffic+flowProperties.flowAverageRate;
case 1 %If infoWhatHappenedWithTheFlow is 1, then the flow has been LOST.
%The event is deleted from the list of pending events.
listOfPendingEvents=removeTopPendingEvent(listOfPendingEvents);
%Updating variables
dynStatistics.lostFlows=dynStatistics.lostFlows+1;
dynStatistics.lostTraffic=dynStatistics.lostTraffic+flowProperties.flowAverageRate;
otherwise
error('infoWhatHappenedWithTheFlow isnt any legal value');
end
%When there is an arrived event, add a new arrived event to the
%list of pending events.
listOfPendingEvents=addEventToListOfPendingEvents (0 , simTime + timeToNextEvent , -1 ,listOfPendingEvents) ;
case 1 %When it is an END event:
flowProperties = struct('flowDuration',[],'flowAverageRate',[],'pairIngressEgress',[],'flowPriority',[],'flowSerialNumber',serialNumOfThisFlow,'flowSetUpTime',[]);
flowId=find(netState.flowTable(:,1)==serialNumOfThisFlow);
flowProperties.pairIngressEgress=netState.flowTable(flowId,2:3);
flowProperties.flowAverageRate=netState.flowTable(flowId,4);
flowProperties.flowSetUpTime=netState.flowTable(flowId,5);
flowProperties.flowDuration=netState.flowTable(flowId,6);
[actions,infoWhatHappenedWithTheFlow,exitFlag,exitMsg] = feval(algorithmMethod,1,netState,phys,simTime, algorithmParameters,flowProperties);
for actionNumber=1:size(actions)
actionToDo=actions{actionNumber};
[netState]=processAction(actionToDo, netState,phys,simTime);
end
%the actions returned by the algorithm should include the flow removal
%The end event is deleted from the list of pending events.
listOfPendingEvents=removeTopPendingEvent(listOfPendingEvents);
otherwise
error('eventType isnt any legal value');
end
%If we have got the transitory time, then we initialize the stadistics variables.
if(simTime>transitoryTime & lastSimTime<transitoryTime)
clear dynStatistics;
dynStatistics = struct ('maxNrUsedTransmittersPerNode' , zeros (1,numberOfNodes) , 'minNrUsedTransmittersPerNode' , inf * ones (1,numberOfNodes) , ...
'NrUsedTransmittersPerNode' , 0 , 'NrUsedReceiversPerNode' , 0 , 'NrUsedWavelengthsPerFiber' , zeros(1,numberOfLinks) , ...
'NrUsedPhysHops' , 0 , 'linkTraffic' , 0 , 'offeredTraffic' , 0 ,'carriedPhysTraffic' , 0 ,'carriedVirtTraffic' , 0 , ...
'averPhysicalHops' , 0 , 'averVirtualHops' , 0 , 'singleHopTraffic' , 0 , 'networkCongestion' , 0 , ...
'totalNrOfUsedWavelengths' , 0 , 'maximumLinkLoadinNrLightpaths' , 0 ,'messagePropagationDelay' , 0 ,'totalNrOfUsedConverters' , 0 , ...
'NrUsedConvertersPerNode' , 0 , 'averNrUsedConverPerLP' , 0 , ...
'maxNrUsedReceiversPerNode' , zeros (1,numberOfNodes) , 'minNrUsedReceiversPerNode' , inf * ones (1,numberOfNodes) , ...
'maxNrUsedWavelengthsPerFiber' , zeros (1,numberOfLinks) , 'minNrUsedWavelengthsPerFiber' , inf * ones (1,numberOfLinks) , ...
'averageNrUsedPhysHops' , 0 , 'maxAverNrUsedPhysHops' , 0 , 'minAverNrUsedPhysHops' , inf , 'maxlinkTraffic' , zeros (1,numberOfLinks) , ...
'minlinkTraffic' , inf * ones (1,numberOfLinks) , 'maxofferedTraffic' , 0 , 'minofferedTraffic' , inf , 'maxcarriedPhysTraffic' , 0 , ...
'mincarriedPhysTraffic' , inf , 'maxcarriedVirtTraffic' , 0 , 'mincarriedVirtTraffic' , inf , 'maxaverPhysicalHops' , 0 , 'minaverPhysicalHops' , inf , ...
'maxaverVirtualHops' , 0 , 'minaverVirtualHops' , inf , 'maxsingleHopTraffic' , 0 , 'minsingleHopTraffic' , inf , 'maxnetworkCongestion' , 0 , ...
'minnetworkCongestion' , inf , 'maxtotalNrOfUsedWavelengths' , 0 , 'mintotalNrOfUsedWavelengths' , inf , 'maxmaximumLinkLoadinNrLightpaths' , 0 , ...
'minmaximumLinkLoadinNrLightpaths' , inf , 'maxmessagePropagationDelay' , 0 , 'minmessagePropagationDelay' , inf , 'maxtotalNrOfUsedConverters' , 0 , ...
'mintotalNrOfUsedConverters' , inf , 'maxNrUsedConvertersPerNode' , zeros (1,numberOfNodes) , 'minNrUsedConvertersPerNode' , inf * ones (1,numberOfNodes) , ...
'carriedFlows' , 0 , 'lostFlows' , 0 , 'lostTraffic' , 0 , 'carriedTraffic' , 0 , 'blockingProbability' , 0 , 'percentOfBlockedTraffic' , 0 , 'elapsedTime' , 0);
end
%Calculate dynamic net metrics
dynStatistics = acumulateDynamicNetMetrics (dynStatistics , simTime , lastSimTime , netState , phys,1);
end
[dynStatistics] = calculateDynamicNetMetrics (dynStatistics);