/*******************************************************************************
* 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.mixPacketLevelTraffic;
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.fixedSchedule.MPL_FixedScheduleLoadGenerator;
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 MPL_FS_Poisson implements ClientTrafficScheduleWriter<MPL_ClientWrapper> {
private Settings settings;
private ScheduleTarget<MPL_ClientWrapper> scheduleTarget;
private MPL_ClientWrapper[] clientsArray;
private long experimentStart; // in nanosec
private long startOfPeriod; // in nanosec
private AnonNode client;
private MPL_ReplyReceiver replyReceiver;
private RandomVariable AVG_SENDS_PER_PERIOD;
private long PULSE_LENGTH; // in ns
private RandomDataImpl randomDataImpl;
private SecureRandom random;
public MPL_FS_Poisson(MPL_FixedScheduleLoadGenerator owner) {
this.settings = owner.getSettings();
this.experimentStart = owner.getScheduler().now() + TimeUnit.SECONDS.toNanos(2);
this.startOfPeriod = experimentStart;
int numberOfClients = settings.getPropertyAsInt("MPL-POISSON-NUMBER_OF_CLIENTS");
String str_avgSendsPerPulse = settings.getProperty("MPL-POISSON-AVERAGE_PACKETS_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));
}
this.PULSE_LENGTH = (long) (settings.getPropertyAsFloat("MPL-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);
int dstPort = settings.getPropertyAsInt("SERVICE_PORT1");
this.scheduleTarget = new MPL_BasicWriter(this, client.IS_DUPLEX, dstPort);
// determine number of clients and lines; create ClientWrapper objects etc
this.clientsArray = new MPL_ClientWrapper[numberOfClients];
CommunicationDirection cm = client.IS_DUPLEX ? CommunicationDirection.DUPLEX : CommunicationDirection.SIMPLEX_SENDER;
for (int i=0; i<numberOfClients; i++) {
clientsArray[i] = new MPL_ClientWrapper(i);
clientsArray[i].socket = client.createDatagramSocket(cm, true, true, client.ROUTING_MODE != RoutingMode.GLOBAL_ROUTING);
}
if (client.IS_DUPLEX) {
this.replyReceiver = new MPL_ReplyReceiver(clientsArray, settings);
//this.replyReceiver.registerObserver(this);
this.replyReceiver.start();
}
}
@Override
public boolean scheduleRecords(int numberOfRecords, Scheduler<MPL_ClientWrapper> scheduler) {
int periods = (int) (numberOfRecords / AVG_SENDS_PER_PERIOD.drawIntSample());
if (periods == 0)
periods = 1;
int ctr = 0;
for (int j=0; j<periods; j++) { // for each period
long packetsInThisPeriod = randomDataImpl.nextPoisson(AVG_SENDS_PER_PERIOD.drawIntSample());
//System.out.println("packetsInThisPeriod: " +packetsInThisPeriod); // TODO: remove
long[] delays = new long[(int) packetsInThisPeriod];
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));
MPL_ClientWrapper client = clientsArray[clientId];
long timeToSend = startOfPeriod + delays[l];
scheduler.executeAt(
timeToSend,
scheduleTarget,
client
);
}
startOfPeriod += PULSE_LENGTH;
}
System.out.println("MPL_Poisson: scheduled " +ctr +" requests");
return true;
}
@Override
public MPL_ClientWrapper getClientWrapper(int identifier) {
return clientsArray[identifier];
}
}