/******************************************************************************* * gMix open source project - https://svs.informatik.uni-hamburg.de/gmix/ * Copyright (C) 2014 SVS * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. *******************************************************************************/ package staticContent.evaluation.loadGenerator.fixedSchedule; import java.io.BufferedOutputStream; import java.io.IOException; import java.security.SecureRandom; import java.util.Arrays; import java.util.concurrent.TimeUnit; import org.apache.commons.math.random.RandomDataImpl; import staticContent.evaluation.loadGenerator.ClientTrafficScheduleWriter; import staticContent.evaluation.loadGenerator.applicationLevelTraffic.requestReply.ALRR_BasicWriter; import staticContent.evaluation.loadGenerator.applicationLevelTraffic.requestReply.ALRR_ClientWrapper; import staticContent.evaluation.loadGenerator.applicationLevelTraffic.requestReply.ALRR_ReplyReceiver; import staticContent.evaluation.loadGenerator.applicationLevelTraffic.requestReply.ApplicationLevelMessage; import staticContent.evaluation.loadGenerator.randomVariable.FakeRandom; import staticContent.evaluation.loadGenerator.randomVariable.RandomVariable; import staticContent.evaluation.loadGenerator.scheduler.ScheduleTarget; import staticContent.evaluation.loadGenerator.scheduler.Scheduler; import staticContent.framework.AnonNode; import staticContent.framework.config.Settings; import staticContent.framework.launcher.ToolName; import staticContent.framework.routing.RoutingMode; import staticContent.framework.socket.socketInterfaces.AnonSocketOptions.CommunicationDirection; public class ALM_FS_Poisson implements ClientTrafficScheduleWriter<ApplicationLevelMessage> { private Settings settings; private ScheduleTarget<ApplicationLevelMessage> scheduleTarget; private ALRR_ClientWrapper[] clientsArray; private long experimentStart; // in nanosec private long startOfPeriod; // in nanosec private AnonNode client; private ALRR_ReplyReceiver replyReceiver; private RandomVariable REQUEST_PAYLOAD_SIZE; private RandomVariable REPLY_PAYLOAD_SIZE; private RandomVariable AVG_SENDS_PER_PERIOD; private long PULSE_LENGTH; // in ns private RandomVariable REPLY_DELAY; // in seconds private RandomDataImpl randomDataImpl; private SecureRandom random; public ALM_FS_Poisson(AL_FixedScheduleLoadGenerator owner) { this.settings = owner.getSettings(); this.experimentStart = owner.getScheduler().now() + TimeUnit.SECONDS.toNanos(2); this.startOfPeriod = experimentStart; int numberOfClients = settings.getPropertyAsInt("AL-POISSON-NUMBER_OF_CLIENTS"); String str_avgSendsPerPulse = settings.getProperty("AL-POISSON-AVERAGE_SEND_OPERATIONS_PER_PULSE"); if (RandomVariable.isRandomVariable(str_avgSendsPerPulse)) { this.AVG_SENDS_PER_PERIOD = RandomVariable.createRandomVariable(str_avgSendsPerPulse); } else { float float_avgSendsPerPulse = Float.parseFloat(str_avgSendsPerPulse); float_avgSendsPerPulse = float_avgSendsPerPulse * (float)numberOfClients; if (float_avgSendsPerPulse < 1f) this.AVG_SENDS_PER_PERIOD = new FakeRandom(1); else this.AVG_SENDS_PER_PERIOD = new FakeRandom(Math.round(float_avgSendsPerPulse)); } String str_ReplyDelay = settings.getProperty("AL-POISSON-REPLY_DELAY"); if (RandomVariable.isRandomVariable(str_ReplyDelay)) this.REPLY_DELAY = RandomVariable.createRandomVariable(str_ReplyDelay); else this.REPLY_DELAY = new FakeRandom(Double.parseDouble(str_ReplyDelay)); this.PULSE_LENGTH = (long) (settings.getPropertyAsFloat("AL-POISSON-PULSE_LENGTH")*1000000000f); this.random = new SecureRandom(); this.randomDataImpl = new RandomDataImpl(); this.randomDataImpl.reSeed(this.random.nextLong()); System.out.println("LOAD_GENERATOR: start at " +experimentStart); // create client owner.getLoadGenerator().commandLineParameters.gMixTool = ToolName.CLIENT; this.client = new AnonNode(owner.getLoadGenerator().commandLineParameters); this.scheduleTarget = new ALRR_BasicWriter(this, client.IS_DUPLEX); // determine number of clients and lines; create ClientWrapper objects etc this.clientsArray = new ALRR_ClientWrapper[numberOfClients]; CommunicationDirection cm = client.IS_DUPLEX ? CommunicationDirection.DUPLEX : CommunicationDirection.SIMPLEX_SENDER; int port = settings.getPropertyAsInt("SERVICE_PORT1"); System.out.println("LOAD_GENERATOR: connecting clients..."); for (int i=0; i<numberOfClients; i++) { clientsArray[i] = new ALRR_ClientWrapper(i); clientsArray[i].socket = client.createStreamSocket(cm, client.ROUTING_MODE != RoutingMode.GLOBAL_ROUTING); try { clientsArray[i].socket.connect(port); clientsArray[i].outputStream = new BufferedOutputStream(clientsArray[i].socket.getOutputStream()); if (client.IS_DUPLEX) clientsArray[i].inputStream = clientsArray[i].socket.getInputStream(); } catch (IOException e) { e.printStackTrace(); } } String str_requestPayloadSize = settings.getProperty("AL-POISSON-REQUEST_PAYLOAD_SIZE"); if (RandomVariable.isRandomVariable(str_requestPayloadSize)) { this.REQUEST_PAYLOAD_SIZE = RandomVariable.createRandomVariable(str_requestPayloadSize); } else { if (str_requestPayloadSize.equalsIgnoreCase("AUTO")) this.REQUEST_PAYLOAD_SIZE = new FakeRandom(clientsArray[0].socket.getMTU()); else this.REQUEST_PAYLOAD_SIZE = new FakeRandom(Integer.parseInt(str_requestPayloadSize)); } String str_replyPayloadSize = settings.getProperty("AL-POISSON-REPLY_PAYLOAD_SIZE"); if (RandomVariable.isRandomVariable(str_replyPayloadSize)) { this.REPLY_PAYLOAD_SIZE = RandomVariable.createRandomVariable(str_replyPayloadSize); } else { if (str_replyPayloadSize.equalsIgnoreCase("AUTO")) this.REPLY_PAYLOAD_SIZE = new FakeRandom(clientsArray[0].socket.getMTU()); else this.REPLY_PAYLOAD_SIZE = new FakeRandom(Integer.parseInt(str_replyPayloadSize)); } if (client.IS_DUPLEX) { this.replyReceiver = new ALRR_ReplyReceiver(clientsArray, settings); //this.replyReceiver.registerObserver(this); this.replyReceiver.start(); } } @Override public boolean scheduleRecords(int numberOfRecords, Scheduler<ApplicationLevelMessage> scheduler) { int periods = (int) (numberOfRecords / AVG_SENDS_PER_PERIOD.drawIntSample()); if (periods == 0) periods = 1; int ctr = 0; ApplicationLevelMessage currentEntry; for (int j=0; j<periods; j++) { // for each period long requestsInThisPeriod = randomDataImpl.nextPoisson(AVG_SENDS_PER_PERIOD.drawIntSample()); long[] delays = new long[(int) requestsInThisPeriod]; for (int l=0; l<delays.length; l++) // distribute delays at (uniform) random (for this period) delays[l] = (long) (random.nextDouble() * PULSE_LENGTH); Arrays.sort(delays); for (int l=0; l<delays.length; l++) { ctr++; // choose client to send this request at (uniform) random: int clientId = (int) Math.round(random.nextDouble() * (double)(clientsArray.length-1)); currentEntry = new ApplicationLevelMessage( ((float)delays[l]/1000000000f), clientId, clientId, REQUEST_PAYLOAD_SIZE.drawIntSample(), REPLY_PAYLOAD_SIZE.drawIntSample(), (float) REPLY_DELAY.drawDoubleSample() ); long timeToSend = startOfPeriod + delays[l]; currentEntry.setPlanedSendTime(timeToSend); scheduler.executeAt( currentEntry.getPlanedSendTime(), scheduleTarget, currentEntry ); } startOfPeriod += PULSE_LENGTH; } System.out.println("ALM_Poisson: scheduled " +ctr +" requests"); return true; } @Override public ALRR_ClientWrapper getClientWrapper(int identifier) { return clientsArray[identifier]; } }