/*
* Initializer :
* This class is responsible for starting the main execution loop. It also
* will initialize the logging classes in addition to the SimulatedTime
* main class.
*/
//import EthernetSimulator.*;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.RollingFileAppender;
import org.apache.log4j.NDC;
import java.net.URL;
import java.io.*;
import java.util.Arrays;
import java.util.ArrayList;
import java.lang.Math;
import java.util.Random;
import java.util.UUID;
import java.util.Date;
//import java.sql.*;
//import SQLiteLogger;
//import SimulatedEvent;
import Ethernet.*;
public class Initializer
{
static Logger logger = Logger.getLogger(Initializer.class);
static String propFile = "/l4j.properties";
private SQLiteLogger sqlEvtLogger;
private static int MAX_EXPERIMENT_TIME = 150000000; // 15 seconds * 10^7 Mbits/second, which is 10 seconds + 5 seconds of stabilization
private static int MIN_MEASUREMENT_TIME = 50000000; // 5 seconds * 10^7 MBits/second to stabilize
//private static int STDOUT_REPORT_INTERVAL = 5000000; // print something to standard out every half second of simulation elapse
// an ArrayList of packet sizes in bytes as ints
private static ArrayList<Integer> PACKET_SIZE_LIST = new ArrayList<Integer>(Arrays.asList(64, 128, 256, 512, 768, 1024, 1536, 2048, 3072, 4000));
// number of times to run a simulation for a set of transmitting host numbers and packet sizes
private static int NUM_TRIALS_PER_CONFIG = 1;
public Initializer(String dbFileLoc)
{
try
{
sqlEvtLogger = new SQLiteLogger(dbFileLoc);
}
catch(Exception e)
{
logger.error(e.getMessage());
}
}
public SQLiteLogger getEvtLogger()
{
return sqlEvtLogger;
}
public static void main(String[] args)
{
URL confResource = Initializer.class.getResource(propFile);
PropertyConfigurator.configure(confResource);
logger.info("Initializing");
System.out.println("EthernetSimulator by Nathaniel Lim and Lee Wang");
System.out.println("Type \"quit\" at any time to exit this program.");
String curInput = "";
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
Initializer initThis = new Initializer("ESData.s3db");
SQLiteLogger curLogger = initThis.getEvtLogger();
// record the current time in unix-time and store it
long curUnixTime = System.currentTimeMillis() / 1000L;
// keep track of the standard representation of current datetime
Date curDate = new Date();
// new experiment with 24 hosts
int newExperimentID = curLogger.CreateNewExperiment(curUnixTime, curDate.toString(), 24);
logger.info("New experiment ID: " + newExperimentID);
do
{
try
{
System.out.println("Run a new experiment? (y/n)");
curInput = in.readLine();
if(curInput.equals("y"))
{
//System.out.println("Enter a packet size in bytes");
//curInput = in.readLine();
//for(int activeHosts = 2; activeHosts < 25; activeHosts++)
// {
int activeHosts = 6;
for(int packSize = 0; packSize < PACKET_SIZE_LIST.size(); packSize++)
{
for(int numTrial = 0; numTrial < NUM_TRIALS_PER_CONFIG; numTrial++)
{
System.out.println("Initializing simulation with " + activeHosts + " transmitting hosts and " + PACKET_SIZE_LIST.get(packSize) + " byte sized packets. Trial " + numTrial);
RunSimulationWithHostNumAndPacketSize(activeHosts, PACKET_SIZE_LIST.get(packSize), curLogger, newExperimentID);
}
}
// }
}
}
catch(NullPointerException nulle)
{
logger.error(nulle.getMessage());
}
catch(Exception e)
{
logger.error(e.getMessage());
}
}
while(!curInput.equals("quit"));
curLogger.close();
logger.info("Done");
}
public static void RunSimulationWithHostNumAndPacketSize(int activeHosts, int packSizeForThisExperiment,
SQLiteLogger curLogger, int newExperimentID)
{
// number of hosts to run experiment on, 24 from paper where 0-5, 6-11, 12-17, 18-23
// where on the same repeater so where 20 feet * 2 from each other, but inbetween
// the groups of hosts, there were 1000 feet so you need to take the
// abs((floor(host id) / 6) - floor(other host id) / 6) * 1000 feet to find the
// distance between them in feet, then its 65.62 feet / bit so divide by that
// to find the number of bits between any two hosts
int numHosts = 24;
if(newExperimentID > 0)
{
// create SimulatedTime for this experiment
SimulatedTime stime = new SimulatedTime();
ArrayList<Host> hostList = new ArrayList<Host>();
ArrayList<Integer> hostIndices = new ArrayList<Integer>();
// create hosts
for(int i = 0; i < numHosts; i++)
{
Host hostToAdd = new Host(stime, packSizeForThisExperiment, i);
hostList.add(hostToAdd);
hostIndices.add(i);
stime.addHost(hostToAdd);
// debugging, log creation of each host
//curLogger.CreateNewHost(newExperimentID, i);
}
Random r = new Random();
boolean evenTopology = true;
if (evenTopology){
for(int k = 0; k < activeHosts; k++){
Host hostToActivate = hostList.get(hostIndices.get(k));
hostToActivate.scheduleMyEvent(SimulatedEvent.SimEvtType.PACKET_READY, hostToActivate.RandomProcessTime(), true);
}
} else {
// randomly remove all but activeHosts number of indices from the array containing the all of the host id's
for(int j = 0; j < (numHosts - activeHosts); j++) {
hostIndices.remove(r.nextInt(hostIndices.size()));
}
// schedule initialization events in the indices that are still active
for(int k = 0; k < hostIndices.size(); k++){
Host hostToActivate = hostList.get(hostIndices.get(k));
hostToActivate.scheduleMyEvent(SimulatedEvent.SimEvtType.PACKET_READY, hostToActivate.RandomProcessTime(), true);
}
}
//logger.info("Beginning elapse loop.");
//int curEvtCount = 0;
boolean beganMeasuring = false;
//int elapseInterval = STDOUT_REPORT_INTERVAL;
// run elapse();
while(stime.elapse() && stime.getCurrentTime() < MAX_EXPERIMENT_TIME)
{
//if(stime.getCurrentTime() > elapseInterval)
//{
// System.out.println(stime.getCurrentTime() + " bit times have elapsed; " + stime.GetTimelineSize() + " events in priority queue;");
// elapseInterval += STDOUT_REPORT_INTERVAL;
// }
//logger.info("Elapsing");
//SimulatedEvent evtToLog = stime.CurrentEvent;
//SimulatedEvent.SimEvtType curEvtType = evtToLog.getEventType();
// it's working, don't log anything in terms of individual events right now
/*
if(!evtToLog.justMyself || curEvtType == SimulatedEvent.SimEvtType.BACKOFF_DONE
|| curEvtType == SimulatedEvent.SimEvtType.PACKET_READY || curEvtType ==
SimulatedEvent.SimEvtType.PACKET_ABORTED)
{
curLogger.CreateNewEvent(
newExperimentID,
evtToLog.TimeStart,
evtToLog.TimeDuration,
curEvtType.name(),
evtToLog.hostCreated,
(evtToLog.justMyself ? 1 : 0)
);
}
*/
//curEvtCount++;
// if we have passed the minimum threshold for beginning to record statistics, and we have not called
// hosts.StartMeasuring yet, then do so
if(!beganMeasuring && stime.getCurrentTime() > MIN_MEASUREMENT_TIME)
{
// schedule initialization events in the indices that are still active
for(int m = 0; m < hostIndices.size(); m++)
{
Host hostToStartMeasure = hostList.get(hostIndices.get(m));
hostToStartMeasure.StartMeasuring();
}
beganMeasuring = true;
}
}
// afterwards, get all of the values for collision periods and slots
int totalBitsSent = 0;
int totalPacketsSent = 0;
double avgTransDelayNumerator = 0;
ArrayList<Double> throughputs = new ArrayList<Double>();
for(Host h : hostList)
{
System.out.println("Host " + h.hostId + ": AvgSlotVal = " + h.reportAverageWaitSlots() +
"; NumCollisionPeriods = " + h.reportTotalCollisionPeriods() + "; Sent " +
h.reportTotalPacketsSent() + " packets; Dropped " + h.reportTotalPacketsDropped()
+ " packets;");
totalBitsSent += h.reportTotalBitsSent();
totalPacketsSent += h.reportTotalPacketsSent();
// to keep the squared numbers manageable, lets divide by some amount, all that matters is their
// ratio in the end anyways. Let's say bits / millisecond.
throughputs.add(new Double(h.reportTotalBitsSent() / 1000));
// if this host was active, sum its transmission delay for division later
if(h.reportTotalPacketsSent() > 0)
{
avgTransDelayNumerator += h.reportAverageTransDelay();
}
}
double fairnessIndex = CalculateFairness(throughputs);
double avgTransDelay = avgTransDelayNumerator / activeHosts;
double experimentDuration = stime.getCurrentTime() - MIN_MEASUREMENT_TIME;
System.out.println("Bits of packet data sent:" + totalBitsSent + "; Total bit times: " + experimentDuration);
System.out.println("Average transmission delay: " + avgTransDelay + "; Fairness Index: " + fairnessIndex);
curLogger.CreateNewExperimentSummary(newExperimentID, activeHosts, packSizeForThisExperiment, totalPacketsSent, totalBitsSent, experimentDuration, avgTransDelay, fairnessIndex);
}
else
{
System.out.println("Database unavailable, quitting.");
logger.info("Unable to create new Experiment row in database, ID returned:" + newExperimentID);
}
}
public static double CalculateFairness(ArrayList<Double> throughputs)
{
double numerator = 0;
double denominator = 0;
int numActive = 0;
for(Double thru : throughputs)
{
if(thru > 0)
{
numActive++;
numerator += thru;
denominator += Math.pow(thru, 2.0);
}
}
numerator = Math.pow(numerator, 2.0);
return numerator / (numActive * denominator);
}
}