/* * Netsim.java * * Network simulation program to test the performance of * various load balancing algorithms. * * Created by: Arthur L. Blais * Visteon/Ford Microelectronics Inc. * Colorado Springs, CO * * Date: Wed Sep 29 09:16:38 MDT 1999 */ import java.io.*; import java.util.*; import java.text.NumberFormat; import Client; import Clock; import Event; import LoadBalanceManager; import Queue; import Server; class Netsim { public static final int NEW_REQUEST = 0; public static final int DOCUMENT_REQUEST = 1; public static final int DOCUMENT_SEND = 2; public static final int DOCUMENT_DONE = 3; public static final int SERVER_REQUEST = 4; public static Clock clock; public static Queue eventQueue; public static Client[] client; public static Server[] server; public static LoadBalanceManager[] lbm; public static int requestNumber = 0; public static NumberFormat nf = NumberFormat.getInstance( Locale.US ); private static FileWriter eventOutput; private static FileWriter requestOutput; private static FileWriter clientOutput; private static FileWriter serverOutput; public static void main ( String args [] ) throws IOException { long terminateTime = Long.parseLong( args[0] ) * 1000; long statInterval = Long.parseLong( args[1] ) * 1000; // 3600000 // milliseconds (1 hour) long statTime = statInterval; nf.setMaximumFractionDigits( 4 ); eventOutput = new FileWriter( "event.out" ); requestOutput = new FileWriter( "requests.out" ); clientOutput = new FileWriter( "clients.out" ); serverOutput = new FileWriter( "servers.out" ); // initialize the system initSystem(); // run the simulator while ( true ) { if ( eventQueue.notEmpty() ) { Event event = ( Event ) eventQueue.getFrontElement(); if ( event.getTime() == clock.getTime() ) { // execute the event event = ( Event ) eventQueue.dequeue(); executeEvent( event ); } else { // warp the clock clock.setTime( event.getTime() ); // print stats while ( clock.getTime() >= statTime ) { printClientStats( statTime, clientOutput ); printServerStats( statTime, serverOutput ); statTime += statInterval; } } } else { System.out.println( "Event queue is empty!!!!" ); break; } if ( clock.getTime() >= terminateTime ) { break; } } System.out.println( "Program Done at Time: " + clock.getTime() ); while( eventQueue.notEmpty() ) { eventOutput.write( "Events not executed\n" ); Event e = ( Event ) eventQueue.dequeue(); printEvent( e ); Request r = e.getRequest(); r.printStats( requestOutput ); } printStats( clientOutput, serverOutput ); eventOutput.close(); requestOutput.close(); } // main /***********************************************************************/ /** * executeEvent * * executes the inputed event based on its event type */ public static void executeEvent( Event event ) throws IOException { Request request; int c; // client id int l; // lbm id int s; // server id long accessTime; // file access time long eventTime; // time of this event // printEvent( event ); request = event.getRequest(); eventTime = event.getTime(); switch( event.getType() ) { case NEW_REQUEST: // client c schedules a new request c = request.getClient(); long requestTime = eventTime + client[c].getNextRequestTime( eventTime ); request.setRequestTime( requestTime ); client[c].newRequest( request ); event.setTime( requestTime ); event.setType( SERVER_REQUEST ); schedule( event ); break; case SERVER_REQUEST: // client c's lbm selects a server to process the request and // schedules a document request for the server c = request.getClient(); l = client[c].getLbm(); request.setServer( lbm[l].nextServer() ); event.setTime( eventTime ); event.setType( DOCUMENT_REQUEST ); schedule( event ); break; case DOCUMENT_REQUEST: // server s receives a document request and places the request // in its request queue request.setReceiveTime( eventTime ); s = request.getServer(); server[s].newRequest( request ); // if the server is idle go ahead and schedule a document send //if ( server[s].isIdle() ) { if ( server[s].hasConnection() ) { request = server[s].dequeueRequest(); accessTime = server[s].getFileAccessTime(); request.setStartTime( eventTime + accessTime ); event.setRequest( request ); event.setTime( eventTime ); event.setType( DOCUMENT_SEND ); schedule( event ); } break; case DOCUMENT_SEND: // server s starts sending the request and schedules a document // done event s = request.getServer(); long requestSize = request.getSize(); long executionTime = server[s].getRequestExecutionTime( requestSize ); long doneTime = eventTime + executionTime; request.setCompleteTime( doneTime ); event.setTime( doneTime ); event.setType( DOCUMENT_DONE ); schedule( event ); break; case DOCUMENT_DONE: // save the request stats //request.printStats( requestOutput ); // do the client stats c = request.getClient(); client[c].updateStats( request ); // do the server stats s = request.getServer(); server[s].deleteCurrentRequest( request ); // send a request complete message to the client's lbm l = client[c].getLbm(); lbm[l].requestComplete( s ); // execute next request in server queue if ( server[s].requestQueueNotEmpty() ) { request = server[s].dequeueRequest(); accessTime = server[s].getFileAccessTime(); request.setStartTime( eventTime + accessTime ); event.setRequest( request ); event.setTime( eventTime ); event.setType( DOCUMENT_SEND ); schedule( event ); } //create a new document request for the client int requestNumber = getNextRequestNumber(); request = new Request( c, requestNumber ); event = new Event(); event.setTime( eventTime ); event.setType( NEW_REQUEST ); event.setRequest( request ); schedule( event ); break; default: System.out.println( "unknown request" ); } } // executeEvents /** * schedule * * place the event in the event queue */ static void schedule( Event event ) { if ( event != null ) { priorityEnqueue( event ); } } // schedule /** * initSystem * */ static void initSystem() { // create the clients client = initClients(); // create the servers server = initServers(); // create the load balancing agents lbm = initLBMs( server.length ); // create the event queue eventQueue = new Queue(); // create the system clock clock = new Clock(); // schedule the first client request for ( int i = 0; i < client.length; i++ ) { int requestNumber = getNextRequestNumber(); Request r = new Request( i, requestNumber ); Event event = new Event(); event.setTime( 0 ); event.setType( NEW_REQUEST ); event.setRequest( r ); schedule( event ); } } // initSystem /* * initClients */ static Client[] initClients() { FileReader clientData; BufferedReader inputBuffer = null; String inputStr; StringTokenizer str; Client[] list = null; int n; int id; int lbm; long wakeUpTime; long asleepTime; long seed = 1000; try { clientData = new FileReader( "client.dat" ); inputBuffer = new BufferedReader( clientData ); inputStr = inputBuffer.readLine(); str = new StringTokenizer( inputStr ); n = Integer.parseInt( str.nextToken() ); list = new Client[n]; while( ( inputStr = inputBuffer.readLine() ) != null ) { str = new StringTokenizer( inputStr ); id = Integer.parseInt( str.nextToken() ); lbm = Integer.parseInt( str.nextToken() ); wakeUpTime = Long.parseLong( str.nextToken() ); asleepTime = Long.parseLong( str.nextToken() ); list[ id ] = new Client( id, lbm, wakeUpTime, asleepTime, seed ); seed++; } } catch ( Exception e ) { System.err.println( e ); System.err.println( "Error: unable to initialize clients" ); System.exit( 1 ); } try { // close the input stream if ( inputBuffer != null ) { inputBuffer.close(); } } catch( IOException ie ) { } return list; } // initClients /* * initServers */ static Server[] initServers() { FileReader serverData; BufferedReader inputBuffer = null; String inputStr; StringTokenizer str; Server[] list = null; int n; int id; int connections; double power; long seed = 2000; try { serverData = new FileReader( "server.dat" ); inputBuffer = new BufferedReader( serverData ); inputStr = inputBuffer.readLine(); str = new StringTokenizer( inputStr ); n = Integer.parseInt( str.nextToken() ); list = new Server[n]; while( ( inputStr = inputBuffer.readLine() ) != null ) { str = new StringTokenizer( inputStr ); id = Integer.parseInt( str.nextToken() ); //power = Double.parseDouble( str.nextToken() ); power = Double.valueOf( str.nextToken() ).doubleValue(); connections = Integer.parseInt( str.nextToken() ); list[ id ] = new Server( id, power, connections, seed ); seed++; } } catch ( Exception e ) { System.err.println( e ); System.err.println( "Error: unable to initialize servers" ); System.exit( 1 ); } try { // close the input stream if ( inputBuffer != null ) { inputBuffer.close(); } } catch( IOException ie ) { } return list; } // initServers /* * initLBMs * * input: s = number of servers * foreach LBM * read its id * read the server count * if count == 1 then the lbm is a singe server lbm * else the lbm is a multi server lbm for all servers in s * * returns a list of lbms */ static LoadBalanceManager[] initLBMs( int s ) { FileReader lbmData; BufferedReader inputBuffer = null; String inputStr; StringTokenizer str; LoadBalanceManager[] list = null; int n; int id; int type; try { lbmData = new FileReader( "lbm.dat" ); inputBuffer = new BufferedReader( lbmData ); inputStr = inputBuffer.readLine(); str = new StringTokenizer( inputStr ); n = Integer.parseInt( str.nextToken() ); list = new LoadBalanceManager[n]; while( ( inputStr = inputBuffer.readLine() ) != null ) { str = new StringTokenizer( inputStr ); id = Integer.parseInt( str.nextToken() ); type = Integer.parseInt( str.nextToken() ); list[ id ] = new LoadBalanceManager( id, s, type ); } } catch ( Exception e ) { System.err.println( e ); System.err.println( "Error: unable to initialize LBM's" ); System.exit( 1 ); } try { // close the input stream if ( inputBuffer != null ) { inputBuffer.close(); } } catch( IOException ie ) { } return list; } // initLBMs /* * priorityEnqueue * * insert the new node in ascending order */ public static void priorityEnqueue( Event e ) { if ( eventQueue.isEmpty() ) { eventQueue.enqueue( e ); return; } Event newEvent = e; Event frontEvent = ( Event ) eventQueue.getFront().getElement(); Event tailEvent = ( Event ) eventQueue.getTail().getElement(); long newEventTime = newEvent.getTime(); long frontEventTime = frontEvent.getTime(); long tailEventTime = tailEvent.getTime(); if ( newEventTime < frontEventTime ) { // place node at front eventQueue.enqueueFront( e ); } else if ( newEventTime >= tailEventTime ) { // place at tail eventQueue.enqueue( e ); } else { // place in appropriate position in middle of the list ListNode currentNode = eventQueue.getFront(); ListNode lastNode = currentNode; Event thisEvent; long thisEventTime; // find the position while( currentNode.getNext() != null ) { thisEvent = ( Event ) currentNode.getElement(); thisEventTime = thisEvent.getTime(); if ( newEventTime < thisEventTime ) { break; } lastNode = currentNode; currentNode = currentNode.getNext(); } // insert the new node ListNode n = new ListNode(); n.setElement( e ); n.setNext( lastNode.getNext() ); lastNode.setNext( n ); } } // end priorityEnqueue /** * getNextRequestNumber * * return the current reqeustNumber and increment it */ static int getNextRequestNumber() { return requestNumber++; } // getNextRequestNumber /** * printEvent */ static void printEvent( Event e ) { String eventType[] = { "NEW_REQUEST", "DOCUMENT_REQUEST", "DOCUMENT_SEND", "DOCUMENT_DONE", "SERVER_REQUEST" }; Request request = e.getRequest(); try { eventOutput.write( "Event Time: " + e.getTime() + " " ); eventOutput.write( "Type: " + eventType[ e.getType() ] + " " ); eventOutput.write( "Request: " + request.getRequestNumber() + " " ); eventOutput.write( "Client: " + request.getClient() + " " ); eventOutput.write( "Server: " + request.getServer() + "\n" ); eventOutput.flush(); } catch ( IOException ioe ) { System.err.println( ioe ); System.exit( 1 ); } } /** * printStats */ static void printStats( FileWriter cf, FileWriter sf ) throws IOException { long currentTime = clock.getTime(); System.out.println( "\nClient Stats\n" ); printFinalClientStats( currentTime ); System.out.println( "\nServer Stats\n" ); printFinalServerStats( currentTime ); } // printStats /** * printClientSTats */ static void printClientStats( long statTime, FileWriter f ) throws IOException { int i; for ( i = 0; i < client.length; i++ ) { client[i].printStats( statTime, f ); } } // printClientStats /** * printFinalClientStats */ static void printFinalClientStats( long statTime ) throws IOException { long totalCount = 0; long totalBytes = 0; long totalResponseTime = 0; long totalExecutionTime = 0; long totalIdleTime = 0; long currentTime = clock.getTime(); System.out.println( "Client\tRequests\tAvg. Response Time\t" + "Avg. Execution Time\tIdle Time\tWait Time\tExec Time" ); for ( int i = 0; i < client.length; i++ ) { client[i].printStats( statTime, null ); totalCount += client[i].getRequestCount(); totalBytes += client[i].getBytesReceived(); totalResponseTime += client[i].getResponseTime(); totalExecutionTime += client[i].getExecutionTime(); totalIdleTime += client[i].getIdleTime( currentTime ); } double avgCount = ( double ) totalCount / ( double ) client.length; double avgSize = totalBytes / totalCount; double avgIdleTime = ( double ) totalIdleTime / ( double ) client.length; double avgResponseTime = ( double ) totalResponseTime / ( double ) client.length; double avgExecutionTime = ( double ) totalExecutionTime / ( double ) client.length; System.out.println( "\n" + totalCount + "\t" + nf.format( avgCount ) + "\t" + totalBytes + "\t" + avgSize + "\t" + nf.format( avgIdleTime ) + "\t" + nf.format( avgResponseTime ) + "\t" + nf.format( avgExecutionTime ) ); } // printFinalClientStats /** * printServerStats */ static void printServerStats( long statTime, FileWriter f ) throws IOException { long currentTime = clock.getTime(); for ( int i = 0; i < server.length; i++ ) { server[i].printStats( statTime, f ); } } // printServerStats /** * printFinalServerStats */ static void printFinalServerStats( long statTime ) throws IOException { System.out.println( "Server\tRequests\tTotal KB\tAvg Queue Length\t" + "Avg Wait Time\t%Utilization" ); for ( int i = 0; i < server.length; i++ ) { // server[i].printStats( statTime ); server[i].printStats( statTime, null ); } } // printFinalServerStats } // NetSim