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