/*******************************************************************************
* 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.util.concurrent.TimeUnit;
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_ConstantRate implements ClientTrafficScheduleWriter<ApplicationLevelMessage> {
private Settings settings;
private ScheduleTarget<ApplicationLevelMessage> scheduleTarget;
private ALRR_ClientWrapper[] clientsArray;
private long experimentStart; // in nanosec
private long sumOfPlanedDelays = 0; // in nanosec
private AnonNode client;
private ALRR_ReplyReceiver replyReceiver;
//private int PERIOD_LENGTH; // in ms
//private int MESSAGES_PER_PERIOD;
private RandomVariable REQUEST_PAYLOAD_SIZE;
private RandomVariable REPLY_PAYLOAD_SIZE;
private long TIME_BETWEEN_SENDS; // in nanosec
private RandomVariable REPLY_DELAY; // in sec
public ALM_FS_ConstantRate(AL_FixedScheduleLoadGenerator owner) {
this.settings = owner.getSettings();
this.experimentStart = owner.getScheduler().now() + TimeUnit.SECONDS.toNanos(2);
int numberOfClients = settings.getPropertyAsInt("AL-CONSTANT_RATE-NUMBER_OF_CLIENTS");
float float_periodLength = settings.getPropertyAsFloat("AL-CONSTANT_RATE-PERIOD");
float float_messagesPerPeriod = settings.getPropertyAsFloat("AL-CONSTANT_RATE-MESSAGES_PER_PERIOD");
float float_timeBetweenSends = (float_periodLength*1000000000f) / (float_messagesPerPeriod * (float)numberOfClients);
if (float_timeBetweenSends < 1f)
this.TIME_BETWEEN_SENDS = 1;
else
this.TIME_BETWEEN_SENDS = Math.round(float_timeBetweenSends);
String str_constantRateReplyDelay = settings.getProperty("AL-CONSTANT_RATE-REPLY_DELAY");
if (RandomVariable.isRandomVariable(str_constantRateReplyDelay))
this.REPLY_DELAY = RandomVariable.createRandomVariable(str_constantRateReplyDelay);
else
this.REPLY_DELAY = new FakeRandom(Double.parseDouble(str_constantRateReplyDelay));
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-CONSTANT_RATE-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-CONSTANT_RATE-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) {
ApplicationLevelMessage currentEntry;
int nextClientId = -1;
for (int i=0; i<numberOfRecords; i++) {
if (++nextClientId == clientsArray.length) // round robin choose clients
nextClientId = 0;
currentEntry = new ApplicationLevelMessage(
TIME_BETWEEN_SENDS,
nextClientId,
nextClientId,
REQUEST_PAYLOAD_SIZE.drawIntSample(),
REPLY_PAYLOAD_SIZE.drawIntSample(),
(float) REPLY_DELAY.drawDoubleSample()
);
sumOfPlanedDelays += TIME_BETWEEN_SENDS;
long timeToSend = experimentStart + sumOfPlanedDelays;
currentEntry.setPlanedSendTime(timeToSend);
scheduler.executeAt(
currentEntry.getPlanedSendTime(),
scheduleTarget,
currentEntry
);
}
return true;
}
@Override
public ALRR_ClientWrapper getClientWrapper(int identifier) {
return clientsArray[identifier];
}
}