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