/*******************************************************************************
* 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 userGeneratedContent.simulatorPlugIns.plugins.trafficSource;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.Channels;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Vector;
import staticContent.evaluation.simulator.Simulator;
import staticContent.evaluation.simulator.annotations.plugin.Plugin;
import staticContent.evaluation.simulator.annotations.property.BoolSimulationProperty;
import staticContent.evaluation.simulator.annotations.property.IntSimulationProperty;
import staticContent.evaluation.simulator.annotations.property.StringSimulationProperty;
import staticContent.evaluation.simulator.annotations.property.requirements.TrafficSourceTraceFileClientLimitRequirement;
import staticContent.evaluation.simulator.core.networkComponent.AbstractClient;
import staticContent.evaluation.traceParser.engine.dataStructure.Flow;
import staticContent.evaluation.traceParser.engine.fileReader.FlowReader;
@Plugin(pluginKey = "TRACE_FILE", pluginName = "Tracefile")
public class TraceFileModel extends TrafficSourceImplementation {
private TraceReplayClient[] clients;
@StringSimulationProperty(
name = "Path to trace file",
key = "PATH_TO_TRACE",
info = "Please provide a relative path")
private String pathToTrace;
@BoolSimulationProperty(
name = "Limit client number",
key = "LIMIT_CLIENT_NUMBER")
private boolean limitClients;
@IntSimulationProperty(
name = "Client limit",
key = "CLIENT_LIMIT",
min = 1,enable_requirements=TrafficSourceTraceFileClientLimitRequirement.class)
private int limit;
@BoolSimulationProperty(
name = "Choose Clients at random",
key = "CHOOSE_RANDOM_CLIENTS")
private boolean chooseClientsAtRandom;
@Override
public AbstractClient[] createClientsArray() {
this.pathToTrace = Simulator.settings.getProperty("PATH_TO_TRACE");
this.limitClients = Simulator.settings.getPropertyAsBoolean("LIMIT_CLIENT_NUMBER");
this.limit = limitClients ? Simulator.settings.getPropertyAsInt("CLIENT_LIMIT") : 0;
this.chooseClientsAtRandom = Simulator.settings.getPropertyAsBoolean("CHOOSE_RANDOM_CLIENTS");
Vector<TraceReplayClient> clients = new Vector<TraceReplayClient>(1000);
HashSet<Integer> chosenClients = null;
int cid = -1;
try {
if (chooseClientsAtRandom)
chosenClients = getChosenClientIds(pathToTrace, limit);
FlowReader flowReader = new FlowReader(pathToTrace, null, false);
int currentClientId = -1;
while (flowReader.hasNextFlow()) {
Flow flow = flowReader.readFlow();
if (currentClientId != flow.senderId) {
currentClientId ++;
if (limitClients && !chooseClientsAtRandom && currentClientId == limit)
break;
if (flow.senderId != currentClientId)
throw new RuntimeException("the trace file " +pathToTrace +" seems to be not " +
"ordered correctly.\nmake sure to use an Extractor (package evaluation." +
"traceParser.scenarioExtractor) to generate the trace file and specify " +
"the path of the created trace file in the experiment config file correctly.)" );
long offset = flowReader.getOffsetOfLastFlow();
FlowReader readerOfClient;
try {
RandomAccessFile raf = new RandomAccessFile(pathToTrace, "r");
raf.seek(offset);
// use BufferedReader to read line instead of raf.readLine() for performance reasons:
BufferedReader reader = new BufferedReader(Channels.newReader(raf.getChannel(), "ISO-8859-1"));
readerOfClient = new FlowReader(reader, null, true, raf);
} catch (Exception e) {
System.err.println("could not read " +pathToTrace);
e.printStackTrace();
throw new RuntimeException();
}
if (chooseClientsAtRandom && !chosenClients.contains(currentClientId)) {
readerOfClient.close();
continue;
} else {
cid++;
TraceReplayClient client = new TraceReplayClient("Client" +cid, Simulator.getSimulator(), readerOfClient, cid, currentClientId);
clients.add(client);
}
}
}
} catch (Exception e) {
System.err.println("could not read trace file " +pathToTrace);
e.printStackTrace();
throw new RuntimeException();
}
this.clients = clients.toArray(new TraceReplayClient[0]);
return this.clients;
}
private HashSet<Integer> getChosenClientIds(String pathToTrace, int limit) throws FileNotFoundException, IOException {
// determine number of clients:
FlowReader flowReader = new FlowReader(pathToTrace, null, false);
int currentClientId = -1;
while (flowReader.hasNextFlow()) {
Flow flow = flowReader.readFlow();
if (currentClientId != flow.senderId)
currentClientId ++;
}
flowReader.close();
int numberofClients = currentClientId +1;
//chose clients (no duplicates):
ArrayList<Integer> all = new ArrayList<Integer>(numberofClients);
for (int i=0; i<numberofClients; i++)
all.add(i);
Collections.shuffle(all);
List<Integer> chosenOnes = all.subList(0, limit);
HashSet<Integer> result = new HashSet<Integer>(numberofClients);
result.addAll(chosenOnes);
return result;
}
@Override
public void startSending() {
for (TraceReplayClient client: clients)
client.startSending();
}
}