001/******************************************************************************* 002 * Copyright (c) 2016 Pablo Pavon Mariņo. 003 * All rights reserved. This program and the accompanying materials 004 * are made available under the terms of the GNU Lesser Public License v2.1 005 * which accompanies this distribution, and is available at 006 * http://www.gnu.org/licenses/lgpl.html 007 ******************************************************************************/ 008 009 010 011 012 013 014 015 016package com.net2plan.examples.ocnbook.onlineSim; 017 018import java.text.SimpleDateFormat; 019import java.util.Calendar; 020import java.util.HashSet; 021import java.util.LinkedList; 022import java.util.List; 023import java.util.Map; 024import java.util.Random; 025import java.util.Set; 026 027import cern.colt.matrix.tdouble.DoubleFactory1D; 028import cern.colt.matrix.tdouble.DoubleMatrix1D; 029import cern.jet.random.tdouble.Exponential; 030 031import com.net2plan.interfaces.networkDesign.Demand; 032import com.net2plan.interfaces.networkDesign.Link; 033import com.net2plan.interfaces.networkDesign.Net2PlanException; 034import com.net2plan.interfaces.networkDesign.NetPlan; 035import com.net2plan.interfaces.networkDesign.NetworkLayer; 036import com.net2plan.interfaces.networkDesign.Node; 037import com.net2plan.interfaces.networkDesign.SharedRiskGroup; 038import com.net2plan.interfaces.simulation.IEventGenerator; 039import com.net2plan.interfaces.simulation.SimEvent; 040import com.net2plan.libraries.SRGUtils; 041import com.net2plan.libraries.TrafficMatrixGenerationModels; 042import com.net2plan.utils.InputParameter; 043import com.net2plan.utils.Pair; 044import com.net2plan.utils.RandomUtils; 045import com.net2plan.utils.Triple; 046 047/** 048 * Generates events to a technology-agnostic network, consisting of connection requests/releases and failures and repairs. 049 * 050 * The events generated targeted to the event processor module (e.g. {@code Online_evProc_generalProcessor}) are: 051 * <ul> 052 * <li>SimEvent.RouteAdd: To add a route to the network, associated to a given demand (the demand is seen as a source of connection requests).</li> 053 * <li>SimEvent.RouteRemove: If the processor successfully creates a Route object, as a reaction to the RouteAdd event, then a RouteRemove event will be sent to the processor, to release the resources when the connection holding time ends. In the incremental model, route remove events are never sent</li> 054 * <li>SimEvent.DemandModify: Sends this event to ask the processor to modify the offered traffic of a demand (recall that generators cannot modify the NetPlan object). The demand offered traffic is the average traffic of connection requests created. This generator changes it to be able to simulate fast and slow traffic fluctuations.</li> 055 * <li>SimEvent.NodesAndLinksChangeFailureState: Sends these events to the processor, representing network failures and repairs to react to.</li> 056 * </ul> 057 * 058 * The average rate of connection requests sent can change along time using fast and/or slow fluctuations. Fast fluctuations are intended to reflect typical short time-scale 059 * traffic variations, while slow fluctuation are more suitable for representing multihour (slow) traffic fluctuations (e.g. night vs day traffic). 060 * 061 * In the long-run simulations, connections have a finite holding time, so route add and route remove events can be sent. 062 * With the incremental model, connections are never released, and the traffic only increases. This can be used e.g. in studies that search for the moment in 063 * which the network needs an upgrade, since its capacity is exhausted. 064 * 065 * @net2plan.keywords CAC (Connection-Admission-Control), Network recovery: protection, Network recovery: restoration 066 * @net2plan.ocnbooksections Section 3.3.3, Exercise 3.7, Exercise 3.8 067 * @net2plan.inputParameters 068 * @author Pablo Pavon-Marino 069 */ 070public class Online_evGen_generalGenerator extends IEventGenerator 071{ 072 private final static String DATE_FORMAT = "MM/dd/YY HH:mm:ss"; 073 074 private InputParameter _fail_failureModel = new InputParameter ("_fail_failureModel", "#select# perBidirectionalLinkBundle none SRGfromNetPlan perNode perLink perDirectionalLinkBundle" , "Failure model selection: SRGfromNetPlan, perNode, perLink, perDirectionalLinkBundle, perBidirectionalLinkBundle"); 075 private InputParameter _tfFast_fluctuationType = new InputParameter ("_tfFast_fluctuationType", "#select# none random-truncated-gaussian" , ""); 076 private InputParameter _trafficType = new InputParameter ("_trafficType", "#select# non-connection-based connection-based-longrun connection-based-incremental " , ""); 077 private InputParameter _tfSlow_fluctuationType = new InputParameter ("_tfSlow_fluctuationType", "#select# none time-zone-based" , ""); 078 private InputParameter cac_arrivalsPattern = new InputParameter ("cac_arrivalsPattern", "#select# deterministic random-exponential-arrivals-deterministic-duration random-exponential-arrivals-and-duration" , ""); 079 private InputParameter trafficLayerId = new InputParameter ("trafficLayerId", (long) -1 , "Layer containing traffic demands (-1 means default layer)"); 080 private InputParameter randomSeed = new InputParameter ("randomSeed", (long) 1 , "Seed for the random generator (-1 means random)"); 081 private InputParameter cac_avHoldingTimeHours = new InputParameter ("cac_avHoldingTimeHours", (double) 1 , "Default average connection duration (in seconds)" , 0 , false , Double.MAX_VALUE , true); 082 private InputParameter cac_defaultConnectionSizeTrafficUnits = new InputParameter ("cac_defaultConnectionSizeTrafficUnits", (double) 1 , "Default requested traffic volume per connection" , 0 , false , Double.MAX_VALUE , true); 083 private InputParameter tfFast_timeBetweenDemandFluctuationsHours = new InputParameter ("tfFast_timeBetweenDemandFluctuationsHours", (double) 0.1 , "Average time between two changes of demand offered traffic in a demand (demands behave independently)" , 0 , false , Double.MAX_VALUE , true); 084 private InputParameter tfFast_fluctuationCoefficientOfVariation = new InputParameter ("tfFast_fluctuationCoefficientOfVariation", (double) 1.0 , "Average time between two changes of demand offered traffic in a demand (demands behave independently)" , 0 , false , Double.MAX_VALUE , true); 085 private InputParameter tfFast_maximumFluctuationRelativeFactor = new InputParameter ("tfFast_maximumFluctuationRelativeFactor", (double) 1.0 , "The fluctuation of a demand cannot exceed this percentage from the media" , 0 , true , Double.MAX_VALUE , true); 086 private InputParameter tfSlow_startDate = new InputParameter ("tfSlow_startDate", new SimpleDateFormat(DATE_FORMAT).format(Calendar.getInstance().getTime()) , "Initial date and time of the simulation"); 087 private InputParameter tfSlow_timeBetweenDemandFluctuationsHours = new InputParameter ("tfSlow_timeBetweenDemandFluctuationsHours", (double) 1.0 , "Average time between two changes of demand offered traffic in a demand (demands behave independently)" , 0 , false , Double.MAX_VALUE , true); 088 private InputParameter tfSlow_defaultTimezone = new InputParameter ("tfSlow_defaultTimezone", (int) 0 , "Default timezone with respect to UTC (in range [-12, 12])" , -12 , 12); 089 private InputParameter fail_defaultMTTFInHours = new InputParameter ("fail_defaultMTTFInHours", (double) 10 , "Default value for Mean Time To Fail (hours) (unused when failureModel=SRGfromNetPlan)" , 0 , false , Double.MAX_VALUE , true); 090 private InputParameter fail_defaultMTTRInHours = new InputParameter ("fail_defaultMTTRInHours", (double) 12 , "Default value for Mean Time To Repair (hours) (unused when failureModel=SRGfromNetPlan)" , 0 , false , Double.MAX_VALUE , true); 091 private InputParameter fail_statisticalPattern = new InputParameter ("fail_statisticalPattern", "#select# exponential-iid" , "Type of failure and repair statistical pattern"); 092 093 /* demands and links do not change the number (maybe capacity, offered traffic...) */ 094 private Random rng; 095 private DoubleMatrix1D cac_avHoldingTimeSeconds_d , cac_connectionSize_d; 096 private DoubleMatrix1D currentTheoreticalOfferedTraffic_d; 097 private boolean cac_auxIATDeterministic , cac_auxIATExponential , cac_auxDurationDeterministic , cac_auxDurationExponential , cac_auxIncremental; 098 private boolean isCac; 099 private boolean tfFast_auxRandomGaussian; 100 private DoubleMatrix1D initialOfferedTraffic_d; // the offered traffic is the sum of the two 101 private DoubleMatrix1D slowChangingOfferedTraffic_d; // the offered traffic is the sum of the two 102 private DoubleMatrix1D tfSlow_timeZones_n; 103 private Calendar tfSlow_calendar; 104 private double tfSlow_simTimeOfLastCalendarUpdate; 105 private boolean tfSlow_auxTimeZoneBased; 106 private Set<Pair<SimEvent.RouteAdd,Double>> cacIncremental_potentiallyBlockedRouteRequests; 107 108 private Set<SharedRiskGroup> fail_currentlyFailedSRGs; 109 110 public Online_evGen_generalGenerator () { super (); } 111 112 @Override 113 public String getDescription() 114 { 115 return "Generates events to a technology-agnostic network, consisting of connection requests/releases and failures and repairs."; 116 } 117 118 @Override 119 public List<Triple<String, String, String>> getParameters() 120 { 121 /* Returns the parameter information for all the InputParameter objects defined in this object (uses Java reflection) */ 122 return InputParameter.getInformationAllInputParameterFieldsOfObject(this , "com.net2plan.examples.ocnbook.onlineSim.Online_evGen_generalGenerator"); 123 } 124 125 @Override 126 public void initialize(NetPlan initialNetPlan, Map<String, String> algorithmParameters, Map<String, String> simulationParameters, Map<String, String> net2planParameters) 127 { 128 /* Initialize all InputParameter objects defined in this object (this uses Java reflection) */ 129 InputParameter.initializeAllInputParameterFieldsOfObject(this , "com.net2plan.examples.ocnbook.onlineSim.Online_evGen_generalGenerator" , algorithmParameters); 130 131 NetworkLayer trafficLayer = trafficLayerId.getLong () == -1? initialNetPlan.getNetworkLayerDefault () : initialNetPlan.getNetworkLayerFromId(trafficLayerId.getLong ()); 132 if (trafficLayer == null) throw new Net2PlanException ("Unknown layer id"); 133 final int D = initialNetPlan.getNumberOfDemands(trafficLayer); 134 final int N = initialNetPlan.getNumberOfNodes (); 135 if (D == 0) throw new Net2PlanException("No demands were defined in the original design"); 136 137 if (randomSeed.getLong () == -1) randomSeed.initialize((long) RandomUtils.random(0, Long.MAX_VALUE - 1)); 138 this.rng = new Random(randomSeed.getLong ()); 139 this.initialOfferedTraffic_d = initialNetPlan.getVectorDemandOfferedTraffic(trafficLayer); 140 this.currentTheoreticalOfferedTraffic_d = initialNetPlan.getVectorDemandOfferedTraffic(trafficLayer); 141 this.isCac = (_trafficType.getString ().equalsIgnoreCase("connection-based-longrun") || _trafficType.getString ().equalsIgnoreCase("connection-based-incremental")); 142 /* Initialize CAC if applicable */ 143 if (isCac) 144 { 145 this.cac_auxIATDeterministic = cac_arrivalsPattern.getString ().equalsIgnoreCase("deterministic"); 146 this.cac_auxIATExponential = cac_arrivalsPattern.getString ().equalsIgnoreCase("random-exponential-arrivals-deterministic-duration") || cac_arrivalsPattern.getString ().equalsIgnoreCase("random-exponential-arrivals-and-duration"); 147 this.cac_auxDurationDeterministic = cac_arrivalsPattern.getString ().equalsIgnoreCase("deterministic") || cac_arrivalsPattern.getString ().equalsIgnoreCase("random-exponential-arrivals-deterministic-duration"); 148 this.cac_auxDurationExponential = cac_arrivalsPattern.getString ().equalsIgnoreCase("random-exponential-arrivals-and-duration"); 149 this.cac_auxIncremental = _trafficType.getString ().equalsIgnoreCase("connection-based-incremental"); 150 this.cac_avHoldingTimeSeconds_d = DoubleFactory1D.dense.make (D , 0); 151 this.cac_connectionSize_d = DoubleFactory1D.dense.make (D , 0); 152 this.cacIncremental_potentiallyBlockedRouteRequests = cac_auxIncremental? new HashSet<Pair<SimEvent.RouteAdd,Double>> () : null; 153 for (Demand originalDemand : initialNetPlan.getDemands(trafficLayer)) 154 { 155 final int d = originalDemand.getIndex(); 156 final double connectionSize = (originalDemand.getAttribute("connectionSize") != null)? Double.parseDouble(originalDemand.getAttribute("connectionSize")) : cac_defaultConnectionSizeTrafficUnits.getDouble(); 157 final double holdingTimeSeconds = (originalDemand.getAttribute("holdingTime") != null)? Double.parseDouble(originalDemand.getAttribute("holdingTime")) : cac_avHoldingTimeHours.getDouble() * 3600; 158 final double avIATSeconds = connectionSize * holdingTimeSeconds / currentTheoreticalOfferedTraffic_d.get(d); 159 final double nextInterArrivalTimeSeconds = cac_auxIATDeterministic? avIATSeconds : cac_auxIATExponential? Exponential.staticNextDouble(1/avIATSeconds) : -1; 160 cac_avHoldingTimeSeconds_d.set (d,holdingTimeSeconds); 161 cac_connectionSize_d.set (d,connectionSize); 162 scheduleEvent(new SimEvent(nextInterArrivalTimeSeconds, SimEvent.DestinationModule.EVENT_GENERATOR , -1 , new GenerateConnectionRequest(originalDemand))); 163 } 164 } 165 166 /* Initialize fast changing traffic */ 167 this.tfFast_auxRandomGaussian = false; 168 if (_tfFast_fluctuationType.getString ().equalsIgnoreCase("random-truncated-gaussian")) 169 { 170 this.tfFast_auxRandomGaussian = true; 171 for (Demand originalDemand : initialNetPlan.getDemands(trafficLayer)) 172 scheduleEvent(new SimEvent(0, SimEvent.DestinationModule.EVENT_GENERATOR , -1 , new GenerateDemandOfferedTrafficFastFluctuation(originalDemand))); 173 } 174 175 /* Initialize slow changing traffic */ 176 this.slowChangingOfferedTraffic_d = initialNetPlan.getVectorDemandOfferedTraffic(trafficLayer); // the offered traffic is the sum of the two 177 if (_tfSlow_fluctuationType.getString ().equalsIgnoreCase("time-zone-based")) 178 { 179 this.tfSlow_auxTimeZoneBased = true; 180 this.tfSlow_calendar = Calendar.getInstance(); 181 try { this.tfSlow_calendar.setTime(new SimpleDateFormat(DATE_FORMAT).parse(tfSlow_startDate.getString())); } catch (Exception e) { e.printStackTrace(); throw new Net2PlanException ("Error parsing the date"); } 182 this.tfSlow_simTimeOfLastCalendarUpdate = 0; 183 tfSlow_timeZones_n = DoubleFactory1D.dense.make (N , tfSlow_defaultTimezone.getInt()); 184 for(Node node : initialNetPlan.getNodes ()) 185 { 186 if (node.getAttribute("timezone") == null) continue; 187 double timezone = Double.parseDouble(node.getAttribute("timezone")); 188 if (timezone < -12 || timezone > 12) throw new Net2PlanException(String.format("Timezone for node %d must be in range [-12, 12]", node.getIndex ())); 189 tfSlow_timeZones_n.set(node.getIndex (), timezone); 190 } 191 for (Demand demand : initialNetPlan.getDemands(trafficLayer)) 192 scheduleEvent(new SimEvent(0.0, SimEvent.DestinationModule.EVENT_GENERATOR , -1 , new GenerateDemandOfferedTrafficSlowFluctuation(demand))); 193 } 194 195 /* Initialize slow changing traffic */ 196 if (!_fail_failureModel.getString ().equalsIgnoreCase("none")) 197 { 198 this.fail_currentlyFailedSRGs = new HashSet<SharedRiskGroup> (); 199 if (!fail_statisticalPattern.getString ().equalsIgnoreCase("exponential-iid")) throw new Net2PlanException ("Unknown failure statisitical pattern"); 200 switch (_fail_failureModel.getString ()) 201 { 202 case "SRGfromNetPlan": 203 break; 204 case "perNode": 205 SRGUtils.configureSRGs(initialNetPlan, fail_defaultMTTFInHours.getDouble(), fail_defaultMTTRInHours.getDouble(), SRGUtils.SharedRiskModel.PER_NODE, true); 206 break; 207 case "perLink": 208 SRGUtils.configureSRGs(initialNetPlan, fail_defaultMTTFInHours.getDouble(), fail_defaultMTTRInHours.getDouble(), SRGUtils.SharedRiskModel.PER_LINK, true); 209 break; 210 case "perDirectionalLinkBundle": 211 SRGUtils.configureSRGs(initialNetPlan, fail_defaultMTTFInHours.getDouble(), fail_defaultMTTRInHours.getDouble(), SRGUtils.SharedRiskModel.PER_DIRECTIONAL_LINK_BUNDLE, true); 212 break; 213 case "perBidirectionalLinkBundle": 214 SRGUtils.configureSRGs(initialNetPlan, fail_defaultMTTFInHours.getDouble(), fail_defaultMTTRInHours.getDouble(), SRGUtils.SharedRiskModel.PER_BIDIRECTIONAL_LINK_BUNDLE, true); 215 break; 216 default: 217 throw new Net2PlanException("Failure model not valid. Please, check algorithm parameters description"); 218 } 219 if (initialNetPlan.getNumberOfSRGs() == 0) throw new Net2PlanException("No SRGs were defined"); 220 for (SharedRiskGroup srg : initialNetPlan.getSRGs()) 221 { 222 final double nextEvent = Exponential.staticNextDouble(1 / srg.getMeanTimeToFailInHours()); 223// System.out.println ("nextEvent: " + nextEvent +", srg.getMeanTimeToFailInHours(): " + srg.getMeanTimeToFailInHours()); 224 scheduleEvent(new SimEvent(nextEvent , SimEvent.DestinationModule.EVENT_GENERATOR , -1 , new GenerateFailureSRG(srg))); 225 } 226 } 227 228 229 } 230 231 @Override 232 public void processEvent(NetPlan currentNetPlan, SimEvent event) 233 { 234 final double simTime = event.getEventTime(); 235 Object eventObject = event.getEventObject(); 236 237 /* if a connection could not be setup, end simulation in the incremental simulation mode */ 238 if (this.cac_auxIncremental) 239 { 240 for (Pair<SimEvent.RouteAdd,Double> ev : new LinkedList<Pair<SimEvent.RouteAdd,Double>> (this.cacIncremental_potentiallyBlockedRouteRequests)) 241 { 242 if (ev.getFirst().routeAddedToFillByProcessor != null) 243 cacIncremental_potentiallyBlockedRouteRequests.remove(ev); 244 else if (ev.getSecond() < simTime) endSimulation(); // not assigned route, and it is in the past => end simulation in the incremental mode 245 } 246 } 247 248 if (eventObject instanceof GenerateConnectionRequest) 249 { 250 final GenerateConnectionRequest connectionRequest = (GenerateConnectionRequest) eventObject; 251 final Demand demand = connectionRequest.demand; 252 final int d = demand.getIndex (); 253 final double h_d = currentTheoreticalOfferedTraffic_d.get(d); // same traffic units as connection size 254 final double avHoldingTimeSeconds = cac_avHoldingTimeSeconds_d.get(d); 255 final double connectionSize = cac_connectionSize_d.get (d); 256 final double avIATSeconds = connectionSize * avHoldingTimeSeconds / h_d; 257 final double nextHoldingTimeSeconds = cac_auxDurationDeterministic? avHoldingTimeSeconds : cac_auxDurationExponential? Exponential.staticNextDouble(1/avHoldingTimeSeconds) : -1; 258 final double nextInterArrivalTimeSeconds = cac_auxIATDeterministic? avIATSeconds : cac_auxIATExponential? Exponential.staticNextDouble(1/avIATSeconds) : -1; 259 260 /* Events to the processor. RouteAdd, and if not incremental mode, route remove */ 261 SimEvent.RouteAdd routeInfo_add = new SimEvent.RouteAdd(demand , null , connectionSize , connectionSize); 262 scheduleEvent(new SimEvent (simTime, SimEvent.DestinationModule.EVENT_PROCESSOR , -1 , routeInfo_add)); 263 if (cac_auxIncremental) 264 this.cacIncremental_potentiallyBlockedRouteRequests.add (Pair.of(routeInfo_add,simTime)); // to check later if it was blocked 265 else 266 scheduleEvent(new SimEvent(simTime + nextHoldingTimeSeconds, SimEvent.DestinationModule.EVENT_GENERATOR , -1 , new GenerateConnectionRelease(routeInfo_add))); 267 268 /* Event for me: new connection */ 269 scheduleEvent(new SimEvent(simTime + nextInterArrivalTimeSeconds, SimEvent.DestinationModule.EVENT_GENERATOR , -1 , new GenerateConnectionRequest(demand))); 270 } 271 if (eventObject instanceof GenerateConnectionRelease) 272 { 273 final GenerateConnectionRelease releaseEvent = (GenerateConnectionRelease) eventObject; 274// SimEvent.DemandModify demandOfferedTrafficUpdate = new SimEvent.DemandModify(releaseEvent.routeAddEvent.demand , -releaseEvent.routeAddEvent.carriedTraffic , true); 275// scheduleEvent(new SimEvent (simTime, SimEvent.DestinationModule.EVENT_PROCESSOR , -1 , demandOfferedTrafficUpdate)); 276 if (releaseEvent.routeAddEvent.routeAddedToFillByProcessor != null) 277 { 278 SimEvent.RouteRemove routeInfo_remove = new SimEvent.RouteRemove(releaseEvent.routeAddEvent.routeAddedToFillByProcessor); 279 scheduleEvent(new SimEvent (simTime , SimEvent.DestinationModule.EVENT_PROCESSOR , -1 , routeInfo_remove)); 280 } 281 } 282 else if (eventObject instanceof GenerateDemandOfferedTrafficFastFluctuation) 283 { 284 final GenerateDemandOfferedTrafficFastFluctuation trafficFluctuation = (GenerateDemandOfferedTrafficFastFluctuation) eventObject; 285 final Demand demand = trafficFluctuation.demand; 286 final int d = demand.getIndex (); 287 final double slowChangingTrafficPart = slowChangingOfferedTraffic_d.get(d); 288 if (tfFast_auxRandomGaussian) 289 { 290 double newFastTrafficVariation = rng.nextGaussian() * tfFast_fluctuationCoefficientOfVariation.getDouble() * slowChangingTrafficPart; 291 newFastTrafficVariation = Math.max (newFastTrafficVariation , slowChangingTrafficPart * (1 - tfFast_maximumFluctuationRelativeFactor.getDouble())); 292 newFastTrafficVariation = Math.min (newFastTrafficVariation , slowChangingTrafficPart * (1 + tfFast_maximumFluctuationRelativeFactor.getDouble())); 293 currentTheoreticalOfferedTraffic_d.set (d , slowChangingTrafficPart + newFastTrafficVariation); 294 if (!isCac) // inform the processor with a demand modified only if it is NOT cac. In CAC the sent events are the routes only, and the algorithms update the offered traffic according to it 295 { 296 System.out.println ("GeneralGenerator (FAST FLUCT): Sending the event... demand: " + demand + ", Offered (ABSOLUTE) " + (slowChangingTrafficPart + newFastTrafficVariation) + " = slow (" +slowChangingTrafficPart + ") + fast ("+ newFastTrafficVariation + ")"); 297 SimEvent.DemandModify modifyEvent = new SimEvent.DemandModify(demand , Math.max (0 , slowChangingTrafficPart + newFastTrafficVariation) , false); 298 scheduleEvent(new SimEvent (simTime, SimEvent.DestinationModule.EVENT_PROCESSOR , -1 , modifyEvent)); 299 } 300 } 301 else if (_tfFast_fluctuationType.getString ().equalsIgnoreCase("none")) 302 { 303 throw new RuntimeException ("Bad"); 304 } 305 else throw new Net2PlanException ("Unknow fast traffic fluctuation type: " + _tfFast_fluctuationType.getString ()); 306 /* Send event to me for the next fast change */ 307 scheduleEvent(new SimEvent(simTime + tfFast_timeBetweenDemandFluctuationsHours.getDouble()*3600 , SimEvent.DestinationModule.EVENT_GENERATOR , -1 , new GenerateDemandOfferedTrafficFastFluctuation(demand))); 308 } 309 else if (eventObject instanceof GenerateDemandOfferedTrafficSlowFluctuation) 310 { 311 final GenerateDemandOfferedTrafficSlowFluctuation trafficFluctuation = (GenerateDemandOfferedTrafficSlowFluctuation) eventObject; 312 final Demand demand = trafficFluctuation.demand; 313 final int d = demand.getIndex (); 314 final double currentSlowHd = slowChangingOfferedTraffic_d.get(d); 315 final double currentHd = currentTheoreticalOfferedTraffic_d.get(d); 316 if (tfSlow_auxTimeZoneBased) 317 { 318 /* Send event to processor with the demand change */ 319 tfSlow_calendar.add(Calendar.MILLISECOND, (int) ((simTime - tfSlow_simTimeOfLastCalendarUpdate) * 1000)); 320 final int hours = tfSlow_calendar.get(Calendar.HOUR_OF_DAY); 321 final int minutes = tfSlow_calendar.get(Calendar.MINUTE); 322 final int seconds = tfSlow_calendar.get(Calendar.SECOND); 323 final int weekday = tfSlow_calendar.get(Calendar.DAY_OF_WEEK); 324 final double UTC = hours + (double) minutes / 60 + (double) seconds / 3600; 325 final double peakTrafficFactor = weekday == Calendar.SATURDAY || weekday == Calendar.SUNDAY ? 0.5 : 1; 326 final double activityOriginNode = TrafficMatrixGenerationModels.activityFactor(UTC, tfSlow_timeZones_n.get(demand.getIngressNode().getIndex ()), 0.3, peakTrafficFactor); 327 final double activityDestinationNode = TrafficMatrixGenerationModels.activityFactor(UTC, tfSlow_timeZones_n.get(demand.getEgressNode().getIndex ()), 0.3, peakTrafficFactor); 328 final double activityFactorNodePair = Math.max (0 , (activityOriginNode + activityDestinationNode) / 2); 329 final double newSlowFluctuationTraffic = initialOfferedTraffic_d.get(d) * activityFactorNodePair; 330 final double currentFastFluctuationTraffic = currentHd - currentSlowHd; 331 this.currentTheoreticalOfferedTraffic_d.set (d , newSlowFluctuationTraffic + currentFastFluctuationTraffic); 332 System.out.println ("GeneralGenerator (SLOW FLUCT): Sending the event... demand: " + demand + ", Offered (ABSOLUTE) " + Math.max (0 , newSlowFluctuationTraffic + currentFastFluctuationTraffic) + " = slow (" + newSlowFluctuationTraffic + ") + fast ("+ currentFastFluctuationTraffic+ "), old slow: " + this.slowChangingOfferedTraffic_d.get(d)); 333 this.slowChangingOfferedTraffic_d.set (d , newSlowFluctuationTraffic); 334 if (!isCac) // inform the processor with a demand modified only if it is NOT cac. In CAC the sent events are the routes only, and the algorithms update the offered traffic according to it 335 { 336 SimEvent.DemandModify modifyEvent = new SimEvent.DemandModify(demand , Math.max (0 , newSlowFluctuationTraffic + currentFastFluctuationTraffic), false); 337 scheduleEvent(new SimEvent (simTime, SimEvent.DestinationModule.EVENT_PROCESSOR , -1 , modifyEvent)); 338 } 339 tfSlow_simTimeOfLastCalendarUpdate = simTime; 340 } 341 else throw new Net2PlanException ("Unknow fast traffic fluctuation type: " + _tfFast_fluctuationType.getString ()); 342 /* Send event to me for the next fast change */ 343 scheduleEvent(new SimEvent(simTime + tfSlow_timeBetweenDemandFluctuationsHours.getDouble()*3600 , SimEvent.DestinationModule.EVENT_GENERATOR , -1 , new GenerateDemandOfferedTrafficSlowFluctuation(demand))); 344 } 345 else if (eventObject instanceof GenerateFailureSRG) 346 { 347 final GenerateFailureSRG srgEvent = (GenerateFailureSRG) eventObject; 348 final SharedRiskGroup srg = srgEvent.srg; 349 350 /* Send event of appropriate failures to the processor (only links and nodes changing its state) */ 351 Set<Node> nodesUpToDown = new HashSet<Node> (currentNetPlan.getNodesUp()); nodesUpToDown.retainAll(srg.getNodes()); 352 Set<Link> linksUpToDown = new HashSet<Link> (currentNetPlan.getLinksUpAllLayers()); linksUpToDown.retainAll(srg.getLinks()); 353 if (!nodesUpToDown.isEmpty() || !linksUpToDown.isEmpty()) 354 { 355 SimEvent.NodesAndLinksChangeFailureState failEvent = new SimEvent.NodesAndLinksChangeFailureState (null , nodesUpToDown , null , linksUpToDown); 356 scheduleEvent(new SimEvent(simTime , SimEvent.DestinationModule.EVENT_PROCESSOR , -1 , failEvent)); 357 } 358 /* Send repair event to myself */ 359 scheduleEvent(new SimEvent(simTime + Exponential.staticNextDouble(1 / srg.getMeanTimeToRepairInHours()) , SimEvent.DestinationModule.EVENT_GENERATOR , -1 , new GenerateRepairSRG(srg))); 360 361 fail_currentlyFailedSRGs.add (srg); 362 } 363 else if (eventObject instanceof GenerateRepairSRG) 364 { 365 final GenerateRepairSRG srgEvent = (GenerateRepairSRG) eventObject; 366 final SharedRiskGroup srg = srgEvent.srg; 367 368 /* Send event of appropriate repairs to the processor (only links and nodes changing its state) */ 369 fail_currentlyFailedSRGs.remove (srg); 370 Set<Node> nodesDownAfterRepair = new HashSet<Node> (); 371 Set<Link> linksDownAfterRepair = new HashSet<Link> (); 372 for (SharedRiskGroup srgStillFailed : fail_currentlyFailedSRGs) 373 { 374 nodesDownAfterRepair.addAll (srgStillFailed.getNodes()); 375 linksDownAfterRepair.addAll (srgStillFailed.getLinks()); 376 } 377 Set<Node> nodesDownToUp = new HashSet<Node> (currentNetPlan.getNodesDown()); nodesDownToUp.removeAll (nodesDownAfterRepair); 378 Set<Link> linksDownToUp = new HashSet<Link> (currentNetPlan.getLinksDownAllLayers()); linksDownToUp.removeAll (linksDownAfterRepair); 379 380 if (!nodesDownToUp.isEmpty() || !linksDownToUp.isEmpty()) 381 { 382 SimEvent.NodesAndLinksChangeFailureState repairEvent = new SimEvent.NodesAndLinksChangeFailureState (nodesDownToUp , null , linksDownToUp , null); 383 scheduleEvent(new SimEvent(simTime , SimEvent.DestinationModule.EVENT_PROCESSOR , -1 , repairEvent)); 384 } 385 /* Send repair event to myself */ 386 scheduleEvent(new SimEvent(simTime + Exponential.staticNextDouble(1 / srg.getMeanTimeToFailInHours()) , SimEvent.DestinationModule.EVENT_GENERATOR , -1 , new GenerateFailureSRG(srg))); 387 } 388 } 389 390 391 private static class GenerateConnectionRequest 392 { 393 public final Demand demand; 394 public GenerateConnectionRequest(Demand demand) { this.demand = demand; } 395 @Override 396 public String toString() { return "Generate connection request for demand " + demand.getId (); } 397 } 398 private static class GenerateConnectionRelease 399 { 400 public final SimEvent.RouteAdd routeAddEvent; 401 public GenerateConnectionRelease(SimEvent.RouteAdd routeAddEvent) { this.routeAddEvent = routeAddEvent; } 402 @Override 403 public String toString() { return "Generate connection release for demand " + routeAddEvent.demand.getId (); } 404 } 405 private static class GenerateDemandOfferedTrafficFastFluctuation 406 { 407 public final Demand demand; 408 public GenerateDemandOfferedTrafficFastFluctuation(Demand demand) { this.demand= demand; } 409 @Override 410 public String toString() { return "Generate fast fluctuation of offered traffic of demand " + demand.getId () ; } 411 } 412 private static class GenerateDemandOfferedTrafficSlowFluctuation 413 { 414 public final Demand demand; 415 public GenerateDemandOfferedTrafficSlowFluctuation(Demand demand) { this.demand= demand; } 416 @Override 417 public String toString() { return "Generate slow fluctuation of offered traffic of demand " + demand.getId () ; } 418 } 419 private static class GenerateFailureSRG 420 { 421 public final SharedRiskGroup srg; 422 public GenerateFailureSRG(SharedRiskGroup srg) { this.srg = srg; } 423 @Override 424 public String toString() { return "Generate failure in SRG " + srg.getId () ; } 425 } 426 private static class GenerateRepairSRG 427 { 428 public final SharedRiskGroup srg; 429 public GenerateRepairSRG(SharedRiskGroup srg) { this.srg = srg; } 430 @Override 431 public String toString() { return "Generate repair event in SRG " + srg.getId () ; } 432 } 433 434}