/*******************************************************************************
* 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.traceParser.statistics;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.Channels;
import java.security.SecureRandom;
import java.util.Vector;
import staticContent.evaluation.traceParser.engine.TraceInfo;
import staticContent.evaluation.traceParser.engine.dataStructure.Flow;
import staticContent.evaluation.traceParser.engine.dataStructure.Host;
import staticContent.evaluation.traceParser.engine.dataStructure.ModifiableHost;
import staticContent.evaluation.traceParser.engine.fileReader.FlowReader;
import staticContent.evaluation.traceParser.interfaces.FlowFilter;
public class HostSampleSource {
public enum UrnModel {DRAW_WITH_REPLACEMENT, DRAW_WITHOUT_REPLACEMENT};
private final static String URN_EMPTY_ERROR_MESSAGE = "no more samples available (urn is empty).\nconsider using a larger trace file or UrnModel.DRAW_WITH_REPLACEMENT.";
private SecureRandom secureRandom;
public RandomAccessFile sourceTrace;
public TraceInfo traceInfo;
public Host[] hosts;
public FlowFilter filter;
public int[] blacklist;
public final UrnModel urnModel;
public Vector<Host> urn_host;
public Vector<Integer> urn_numberOfFlows;
public Vector<Integer> urn_numberOfFlowGroups;
public Vector<Integer> urn_onlineTime;
public Vector<Long> urn_requestBytesTransferred;
public Vector<Long> urn_replyBytesTransferred;
public Vector<Integer> urn_userThinkTime;
public int numberOfFlows = 0;
/*public HostSampleSource(UrnModel urnModel, String pathToTraceFolder, FlowFilter filter) {
this(urnModel, pathToTraceFolder, filter, new SecureRandom());
}
public HostSampleSource(UrnModel urnModel, TraceInfo traceInfo, FlowFilter filter) {
this(urnModel, traceInfo, filter, new SecureRandom());
}
public HostSampleSource(UrnModel urnModel, Host[] hosts, RandomAccessFile sourceTrace, FlowFilter filter) {
this(urnModel, hosts, sourceTrace, filter, new SecureRandom());
}*/
public HostSampleSource(UrnModel urnModel, String pathToTraceFolder, FlowFilter filter, SecureRandom secureRandom, int[] blacklist) {
this(urnModel, new TraceInfo(pathToTraceFolder), filter, secureRandom, blacklist);
//System.err.println("WARNING: HostSampleSource was initialized without a blacklist. all connections of all hosts will be used for creating samples.");
}
public HostSampleSource(UrnModel urnModel, TraceInfo traceInfo, FlowFilter filter, SecureRandom secureRandom, int[] blacklist) {
this(urnModel, Host.getHostIndex(traceInfo, filter), traceInfo, initRandomAccessFile(traceInfo), filter, secureRandom, blacklist);
//System.err.println("WARNING: HostSampleSource was initialized without a blacklist. all connections of all hosts will be used for creating samples.");
}
public HostSampleSource(UrnModel urnModel, Host[] hosts, TraceInfo traceInfo, RandomAccessFile sourceTrace, FlowFilter filter, SecureRandom secureRandom, int[] blacklist) {
this.filter = filter;
this.urnModel = urnModel;
this.urn_host = new Vector<Host>((int) (hosts.length * 1.3));
this.hosts = hosts;
for (Host h: hosts)
this.urn_host.add(h);
this.secureRandom = secureRandom;
this.sourceTrace = sourceTrace;
this.blacklist = blacklist;
this.traceInfo = traceInfo;
//this.pathToTraceFile = Util.removeFileExtension(traceInfo.getPathToTraceFile()) +".gmf";
if (urnModel == UrnModel.DRAW_WITHOUT_REPLACEMENT) {
this.urn_numberOfFlows = new Vector<Integer>((int) (hosts.length * 1.3));
this.urn_numberOfFlowGroups = new Vector<Integer>((int) (hosts.length * 1.3));
this.urn_onlineTime = new Vector<Integer>((int) (hosts.length * 1.3));
this.urn_requestBytesTransferred = new Vector<Long>((int) (hosts.length * 1.3));
this.urn_replyBytesTransferred = new Vector<Long>((int) (hosts.length * 1.3));
this.urn_userThinkTime = new Vector<Integer>((int) (hosts.length * 3));
for (Host h: hosts) {
numberOfFlows += h.stat_numberOfFlows;
this.urn_numberOfFlows.add(h.stat_numberOfFlows);
this.urn_numberOfFlowGroups.add(h.stat_numberOfFlowGroups);
this.urn_onlineTime.add(h.stat_onlineTime);
this.urn_requestBytesTransferred.add(h.stat_requestBytesTransferred);
this.urn_replyBytesTransferred.add(h.stat_replyBytesTransferred);
for (int i=0; i<h.stat_userThinkTimes.length; i++)
this.urn_userThinkTime.add(h.stat_userThinkTimes[i]);
}
} else {
for (Host h: hosts)
numberOfFlows += h.stat_numberOfFlows;
}
}
private static RandomAccessFile initRandomAccessFile(TraceInfo traceInfo) {
String filePath = traceInfo.getPathToGmf();
RandomAccessFile file;
try {
file = new RandomAccessFile(filePath, "r");
} catch (IOException e) {
throw new RuntimeException("ERROR: could not open file " +filePath);
}
return file;
}
public int remainingHosts() {
return urn_host.size();
}
public ModifiableHost drawRandomHost() {
Host h = drawRandomHostSample();
h.loadFlowGroups(sourceTrace);
return new ModifiableHost(h);
}
private Host drawRandomHostSample() {
if (urnModel == UrnModel.DRAW_WITH_REPLACEMENT) {
return urn_host.get(secureRandom.nextInt(urn_host.size()));
} else if (urnModel == UrnModel.DRAW_WITHOUT_REPLACEMENT) {
if (urn_host.size() == 0)
throw new RuntimeException("no more hosts available (urn is empty).\nconsider using a larger trace file or UrnModel.DRAW_WITH_REPLACEMENT.\nto check the number of remaining hosts with \"remainingHosts()\"");
return urn_host.remove(secureRandom.nextInt(urn_host.size()));
} else {
throw new InternalError("no implementation for the urn model " +urnModel +" yet");
}
}
private long[] flowIndex;
public Flow drawRandomFlow() { // TODO: without replacement (store already drawn ids)
if (flowIndex == null) { // create flow index
System.out.println("creating flow index");
long start = System.currentTimeMillis();
flowIndex = new long[numberOfFlows];
try {
FlowReader fr = new FlowReader(traceInfo, filter, false);
Flow flow;
int indexCounter = 0;
int blackListCounter = 0;
int currentBlacklistedHost = -1;
while (true) {
flow = fr.readFlow();
if (flow == null)
break;
while (currentBlacklistedHost < flow.senderId && blackListCounter < blacklist.length) // both blacklist and trace are ordered by senderid
currentBlacklistedHost = blacklist[blackListCounter++];
if (flow.senderId == currentBlacklistedHost)
continue;
try {flowIndex[indexCounter++] = fr.getOffsetOfLastFlow();} catch (ArrayIndexOutOfBoundsException e) {System.err.println("indexCounter: " +indexCounter); System.err.println("currentBlacklistedHost: " +currentBlacklistedHost); System.err.println("flow.senderId: " +flow.senderId); throw new RuntimeException(""); }
}
assert indexCounter == numberOfFlows: "indexCounter: " +indexCounter +", numberOfFlows: " +numberOfFlows;
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("flow index created (duration: " +(System.currentTimeMillis() - start) +" ms)");
}
try {
int flowNumber = secureRandom.nextInt(numberOfFlows);
sourceTrace.seek(flowIndex[flowNumber]);
BufferedReader reader = new BufferedReader(Channels.newReader(sourceTrace.getChannel(), "ISO-8859-1"));
FlowReader fr = new FlowReader(reader, filter);
return fr.readFlow();
} catch (IOException e) {
throw new RuntimeException("ERROR: " +e.getLocalizedMessage());
}
/*try {
int flowNumber = secureRandom.nextInt(numberOfFlows);
int ctr = 0;
for (Host host: urn_host) {
if (flowNumber < (ctr + host.stat_numberOfFlows)) {
FlowReader fr = host.getFlowReader(sourceTrace);
for (int i=0; i<(flowNumber - ctr); i++)
fr.readLine(); // skip flow
return fr.readFlow();
} else {
ctr += host.stat_numberOfFlows;
}
}
throw new RuntimeException("implementation error");
} catch (IOException e) {
throw new RuntimeException("ERROR: " +e.getLocalizedMessage());
}*/
}
public int drawRandomSample_numberOfFlows() {
if (urnModel == UrnModel.DRAW_WITH_REPLACEMENT) {
return drawRandomHostSample().stat_numberOfFlows;
} else if (urnModel == UrnModel.DRAW_WITHOUT_REPLACEMENT) {
if (urn_numberOfFlows.size() == 0)
throw new RuntimeException(URN_EMPTY_ERROR_MESSAGE);
return urn_numberOfFlows.remove(secureRandom.nextInt(urn_numberOfFlows.size()));
} else {
throw new InternalError("no implementation for the urn model " +urnModel +" yet");
}
}
public int drawRandomSample_numberOfFlowGroups() {
if (urnModel == UrnModel.DRAW_WITH_REPLACEMENT) {
return drawRandomHostSample().stat_numberOfFlowGroups;
} else if (urnModel == UrnModel.DRAW_WITHOUT_REPLACEMENT) {
if (urn_numberOfFlowGroups.size() == 0)
throw new RuntimeException(URN_EMPTY_ERROR_MESSAGE);
return urn_numberOfFlowGroups.remove(secureRandom.nextInt(urn_numberOfFlowGroups.size()));
} else {
throw new InternalError("no implementation for the urn model " +urnModel +" yet");
}
}
public int drawRandomSample_onlineTime() {
if (urnModel == UrnModel.DRAW_WITH_REPLACEMENT) {
return drawRandomHostSample().stat_onlineTime;
} else if (urnModel == UrnModel.DRAW_WITHOUT_REPLACEMENT) {
if (urn_onlineTime.size() == 0)
throw new RuntimeException(URN_EMPTY_ERROR_MESSAGE);
return urn_onlineTime.remove(secureRandom.nextInt(urn_onlineTime.size()));
} else {
throw new InternalError("no implementation for the urn model " +urnModel +" yet");
}
}
public long drawRandomSample_requestBytesTransferred() {
if (urnModel == UrnModel.DRAW_WITH_REPLACEMENT) {
return drawRandomHostSample().stat_requestBytesTransferred;
} else if (urnModel == UrnModel.DRAW_WITHOUT_REPLACEMENT) {
if (urn_requestBytesTransferred.size() == 0)
throw new RuntimeException(URN_EMPTY_ERROR_MESSAGE);
return urn_requestBytesTransferred.remove(secureRandom.nextInt(urn_requestBytesTransferred.size()));
} else {
throw new InternalError("no implementation for the urn model " +urnModel +" yet");
}
}
public long drawRandomSample_replyBytesTransferred() {
if (urnModel == UrnModel.DRAW_WITH_REPLACEMENT) {
return drawRandomHostSample().stat_replyBytesTransferred;
} else if (urnModel == UrnModel.DRAW_WITHOUT_REPLACEMENT) {
if (urn_replyBytesTransferred.size() == 0)
throw new RuntimeException(URN_EMPTY_ERROR_MESSAGE);
return urn_replyBytesTransferred.remove(secureRandom.nextInt(urn_replyBytesTransferred.size()));
} else {
throw new InternalError("no implementation for the urn model " +urnModel +" yet");
}
}
public int drawRandomSample_userThinkTime() {
if (urnModel == UrnModel.DRAW_WITH_REPLACEMENT) {
Host h;
do {
h = drawRandomHostSample();
} while (h.stat_userThinkTimes == null);
return h.stat_userThinkTimes[secureRandom.nextInt(h.stat_userThinkTimes.length)];
} else if (urnModel == UrnModel.DRAW_WITHOUT_REPLACEMENT) {
if (urn_userThinkTime.size() == 0)
throw new RuntimeException(URN_EMPTY_ERROR_MESSAGE);
return urn_userThinkTime.remove(secureRandom.nextInt(urn_userThinkTime.size()));
} else {
throw new InternalError("no implementation for the urn model " +urnModel +" yet");
}
}
public int drawRandomSample_userThinkTime(int exclusiveUpperBound) {
int result;
do {
result = drawRandomSample_userThinkTime();
} while (result >= exclusiveUpperBound);
return result;
}
}