/* * Server.java * * server data and operations * * Created by: Arthur L. Blais * Visteon/Ford Microelectronics Inc. * Colorado Springs, CO * * Date: Fri Sep 24 08:43:13 MDT 1999 * **************************************************************************** * * Notes and Acknowledgments: * * Request sizes are generated from one of two distributions modeled by * Barford and Crovella at Boston University. The first distribution is a * table of values generated with a curve fitted to a lognormal distribution. * The lognormal distribution represents the distribution body. The * second distribution represents the tail. The The values for alpha and * k (lowerBound) were fitted the pareto distribution to measured data. * Paul A. Barford and Mark Crovella, Generating Representitive Web * Workloads for Network and Server Performance Evaluation, Technical * Paper BU-CS-07-006, Boston University, December 31, 1997 * **************************************************************************** * * Class Methods * * **************************************************************************** */ import java.io.*; import java.util.*; import java.text.*; public class Server { int id; // server id long requestCount = 0; // number of requests received long requestsComplete = 0; // number of requests completed long totalQueueWaitTime = 0; // queue wait time long totalQueueLength = 0; // for calc average queue length long currentQueueLength = 0; // current number of queued requests int connectionCount = 0; // current number of connections int maxConnections; // maximum number of connections long totalBytes = 0; // total bytes transfered Queue requestQueue; // request queue Request connection[]; // requests being processed double processorPower; // relative processing power double clientThroughput = 4. * 1024.; // default 4 kilobytes per second static Random randomNumber; // psuedo random number generator long table [] = { 92,114,131,144,155,166,175,184,192,200,207,214,221,227,234,240,246,251,257,263, 268,273,278,283,288,293,298,303,308,312,317,321,326,330,335,339,343,348,352, 356,360,364,368,372,376,380,384,388,392,396,400,403,407,411,415,419,422,426, 430,433,437,441,444,448,451,455,458,462,465,469,472,476,479,483,486,490,493, 497,500,503,507,510,514,517,520,524,527,530,534,537,540,544,547,550,554,557, 560,563,567,570,573,576,580,583,586,589,593,596,599,602,605,609,612,615,618, 621,625,628,631,634,637,640,644,647,650,653,656,659,663,666,669,672,675,678, 682,685,688,691,694,697,700,704,707,710,713,716,719,722,725,729,732,735,738, 741,744,747,751,754,757,760,763,766,769,772,776,779,782,785,788,791,794,798, 801,804,807,810,813,816,819,823,826,829,832,835,838,842,845,848,851,854,857, 860,864,867,870,873,876,879,883,886,889,892,895,898,902,905,908,911,914,918, 921,924,927,930,934,937,940,943,946,950,953,956,959,962,966,969,972,975,979, 982,985,988,992,995,998,1001,1005,1008,1011,1014,1018,1021,1024,1027,1031,1034, 1037,1041,1044,1047,1051,1054,1057,1060,1064,1067,1070,1074,1077,1080,1084,1087, 1090,1094,1097,1100,1104,1107,1111,1114,1117,1121,1124,1127,1131,1134,1138,1141, 1145,1148,1151,1155,1158,1162,1165,1168,1172,1175,1179,1182,1186,1189,1193,1196, 1200,1203,1207,1210,1214,1217,1221,1224,1228,1231,1235,1238,1242,1245,1249,1252, 1256,1260,1263,1267,1270,1274,1277,1281,1285,1288,1292,1296,1299,1303,1306,1310, 1314,1317,1321,1325,1328,1332,1336,1339,1343,1347,1350,1354,1358,1362,1365,1369, 1373,1377,1380,1384,1388,1392,1395,1399,1403,1407,1410,1414,1418,1422,1426,1430, 1433,1437,1441,1445,1449,1453,1457,1460,1464,1468,1472,1476,1480,1484,1488,1492, 1496,1500,1504,1508,1512,1516,1520,1524,1528,1532,1536,1540,1544,1548,1552,1556, 1560,1564,1568,1572,1576,1580,1584,1589,1593,1597,1601,1605,1609,1613,1618,1622, 1626,1630,1634,1639,1643,1647,1651,1656,1660,1664,1668,1673,1677,1681,1686,1690, 1694,1699,1703,1707,1712,1716,1720,1725,1729,1734,1738,1742,1747,1751,1756,1760, 1765,1769,1774,1778,1783,1787,1792,1796,1801,1806,1810,1815,1819,1824,1828,1833, 1838,1842,1847,1852,1856,1861,1866,1871,1875,1880,1885,1889,1894,1899,1904,1909, 1913,1918,1923,1928,1933,1938,1943,1947,1952,1957,1962,1967,1972,1977,1982,1987, 1992,1997,2002,2007,2012,2017,2022,2027,2032,2037,2043,2048,2053,2058,2063,2068, 2074,2079,2084,2089,2095,2100,2105,2110,2116,2121,2126,2132,2137,2142,2148,2153, 2159,2164,2170,2175,2180,2186,2191,2197,2202,2208,2214,2219,2225,2230,2236,2242, 2247,2253,2259,2264,2270,2276,2282,2287,2293,2299,2305,2311,2316,2322,2328,2334, 2340,2346,2352,2358,2364,2370,2376,2382,2388,2394,2400,2406,2412,2418,2425,2431, 2437,2443,2449,2456,2462,2468,2475,2481,2487,2494,2500,2506,2513,2519,2526,2532, 2539,2545,2552,2558,2565,2571,2578,2585,2591,2598,2605,2612,2618,2625,2632,2639, 2646,2652,2659,2666,2673,2680,2687,2694,2701,2708,2715,2722,2729,2737,2744,2751, 2758,2765,2773,2780,2787,2795,2802,2809,2817,2824,2832,2839,2847,2854,2862,2869, 2877,2885,2892,2900,2908,2915,2923,2931,2939,2947,2955,2963,2971,2979,2987,2995, 3003,3011,3019,3027,3035,3044,3052,3060,3068,3077,3085,3094,3102,3111,3119,3128, 3136,3145,3153,3162,3171,3180,3188,3197,3206,3215,3224,3233,3242,3251,3260,3269, 3278,3287,3297,3306,3315,3325,3334,3343,3353,3362,3372,3381,3391,3401,3410,3420, 3430,3440,3450,3460,3469,3479,3490,3500,3510,3520,3530,3540,3551,3561,3571,3582, 3592,3603,3614,3624,3635,3646,3656,3667,3678,3689,3700,3711,3722,3733,3745,3756, 3767,3779,3790,3802,3813,3825,3836,3848,3860,3872,3884,3895,3907,3920,3932,3944, 3956,3968,3981,3993,4006,4018,4031,4044,4056,4069,4082,4095,4108,4121,4135,4148, 4161,4175,4188,4202,4215,4229,4243,4257,4271,4285,4299,4313,4327,4341,4356,4370, 4385,4400,4414,4429,4444,4459,4474,4490,4505,4520,4536,4551,4567,4583,4599,4615, 4631,4647,4663,4680,4696,4713,4729,4746,4763,4780,4797,4815,4832,4850,4867,4885, 4903,4921,4939,4957,4975,4994,5013,5031,5050,5069,5088,5108,5127,5147,5166,5186, 5206,5226,5247,5267,5288,5308,5329,5350,5372,5393,5415,5436,5458,5480,5503,5525, 5548,5571,5594,5617,5640,5664,5688,5712,5736,5760,5785,5810,5835,5860,5886,5911, 5937,5964,5990,6017,6044,6071,6098,6126,6154,6182,6211,6239,6268,6298,6327,6357, 6388,6418,6449,6480,6512,6543,6576,6608,6641,6674,6708,6742,6776,6811,6846,6881, 6917,6954,6990,7028,7065,7103,7142,7181,7221,7261,7301,7342,7384,7426,7468,7512, 7555,7600,7645,7690,7736,7783,7831,7879,7928,7978,8028,8079,8131,8184,8237,8292, 8347,8403,8460,8518,8577,8637,8698,8760,8823,8888,8953,9020 }; // Statistical Variables long lastStatTime = 0; // time last stats done long lastRequestCount = 0; // last requestCount long lastRequestsComplete = 0; // for last stat interval long lastTotalBytes = 0; // last totalKB long lastTotalQueueLength = 0; long lastTotalQueueWaitTime = 0; long lastTotalQueueUpdate = 0; // last queue totals update /* * Server */ public Server ( int n, double p, int c, long seed ) { id = n; processorPower = p; randomNumber = new Random( seed ); requestQueue = new Queue(); maxConnections = c; connection = new Request[ maxConnections ]; for ( int i = 0; i < maxConnections; i++ ) { connection[i] = null; } } /** * newRequest * */ void newRequest( Request r ) { long requestSize = getRequestSize(); r.setSize( requestSize ); requestQueue.enqueue( r ); updateTotalQueueLength( r.getRequestTime() ); currentQueueLength++; requestCount++; } /** * dequeueRequest * * get the complete time from current request, it's done * dequeue the next request and put it into the current request * update the request wait time * decrement the queue length * update the total queue length (for avg queue len calc) */ Request dequeueRequest() { Request currentRequest = ( Request ) requestQueue.dequeue(); currentQueueLength--; int i = 0; while ( i < maxConnections ) { if ( connection[i] == null ) { connection[i] = currentRequest; connectionCount++; return currentRequest; } i++; } return null; } /** * deleteCurrentRequest */ void deleteCurrentRequest( Request r ) { int i = 0; this.updateStats( r ); while ( i < maxConnections ) { if ( connection[i] == r ) { connection[i] = null; connectionCount--; requestsComplete++; totalQueueWaitTime += r.getWaitTime(); break; } i++; } return; } /** * getId */ int getId() { return id; } /** * getRequestSize * */ private long getRequestSize() { double tailStart = 0.930; double alpha; double lowerBound; double Fx; long x; Fx = randomNumber.nextDouble(); //System.out.println( "F(x): " + Fx ); if ( Fx < tailStart ) { // value in the distribution body use table lookup int i = ( int ) ( Fx * 1000.0 ); x = table[i]; //System.out.println( "F(x): " + Fx +" Table[" + i + "] " + table[i] ); } else { // value in the distribution tail use Pareto distribution alpha = 1.0; lowerBound = 9020.0; Fx = randomNumber.nextDouble(); if ( Fx > 0.9991397858 ) { // limit file size to 10 MB Fx = 0.9991397858; } x = ( ( long ) Pareto.getX( Fx, lowerBound , alpha ) ); //System.out.println( "size: " + x + " " + F1x + " " + lowerBound + " " + alpha); } return x; } /** * getRequestExecutionTime * * input: size (bytes) * output: time ( milliseconds ) * * Assumed Default Throughput: 10 Kilobytes per second per connection * times the processor power. */ long getRequestExecutionTime( long size ) { double throughput = clientThroughput * processorPower; // bytes per second double time = ( size / throughput ) * 1000; // milliseconds long execTime = ( long ) ( time + .5 ); // round up & truncate return ( execTime ); } /** * getFileAccessTime * * Returns the time it takes for the server to access the requested * file based upon the server load, and disk caching. * * Version 1 assumes no caching */ long getFileAccessTime() { long defaultTime = 100; double accessTime = connectionCount * defaultTime / processorPower; return ( ( long ) accessTime ); } /** * requestQueueNotEmpty * */ boolean requestQueueNotEmpty() { return( requestQueue.notEmpty() ); } /** * serverBusy */ boolean serverBusy() { if ( this.hasConnection() ) { return false; } return true; } /** * hasConnection */ boolean hasConnection() { int i = 0; if ( connectionCount < maxConnections ) { return true; } return false; } /** * isIdle */ boolean isIdle() { return this.hasConnection(); } /** * getRequestCount */ long getRequestCount() { return requestCount; } /** * getRequestsComplete */ long getRequestsComplete() { return requestsComplete; } /** * getTotalQueueWaitTime */ long getTotalQueueWaitTime() { return totalQueueWaitTime; } /** * getQueueLength */ long getCurrentQueueLength() { return currentQueueLength; } /** * updateTotalQueueLength */ void updateTotalQueueLength( long t ) { //System.out.print( id + "\t" + t + "\t" + lastTotalQueueUpdate + "\t" + currentQueueLength + "\t" + totalQueueLength ); long length; long dt = t - lastTotalQueueUpdate; length = dt * currentQueueLength; totalQueueLength += length; lastTotalQueueUpdate = t; //System.out.println( "\t" + totalQueueLength ); } /** * getTotalQueueLength */ long getTotalQueueLength() { return totalQueueLength; } /** * getTotalBytes * */ long getTotalBytes() { return totalBytes; } /** * updateStats * */ void updateStats( Request r ) { if ( r.getStartTime() < lastStatTime ) { // job started before last stat time long ctime = r.getCompleteTime(); double xferRate = clientThroughput * processorPower / 1000.0; // bytes per ms double bytes = ( ctime - lastStatTime ) * xferRate; bytes += 0.5; // rounding totalBytes += ( long ) bytes; } else { // job started and completed during stat interval totalBytes += r.getSize(); } //totalQueueWaitTime += r.queueWaitTime(); long completeTime = r.getCompleteTime(); updateTotalQueueLength( completeTime ); } /** * printStats */ void printStats( long statTime, FileWriter f ) throws IOException { DecimalFormat df1 = new DecimalFormat( "#,###,###,###,###" ); DecimalFormat df2 = new DecimalFormat( "###,##0.0000" ); // get the request totals long currentRequestCount = requestCount - lastRequestCount; long currentRequestsComplete = requestsComplete - lastRequestsComplete; // calculate the max transfer rate ( bytes/ms ) double xferRate = clientThroughput * processorPower * maxConnections / 1000.0; // calculate the utilization this.updateTotalBytes( statTime ); long currentTotalBytes = totalBytes - lastTotalBytes; double utilization = ( double ) totalBytes / ( ( double )( statTime ) * xferRate ); double currentUtilization = ( double ) ( currentTotalBytes ) / ( ( double ) ( statTime - lastStatTime ) * xferRate ); double avgWaitTime = ( double ) totalQueueWaitTime / ( double ) requestsComplete; avgWaitTime = avgWaitTime / 1000; // convert to seconds long currentWaitTime = totalQueueWaitTime - lastTotalQueueWaitTime; double lastAvgWaitTime = 0; if ( currentRequestCount > 0 ) { lastAvgWaitTime = ( double ) currentWaitTime / ( double ) currentRequestCount; } lastAvgWaitTime = lastAvgWaitTime / 1000; // convert to seconds lastTotalQueueLength += currentQueueLength; // format data for output long hour = ( statTime / 3600000 ) % 24; long reportTime = statTime / 1000; long totalKB = totalBytes / 1024; long currentTotalKB = currentTotalBytes / 1024; double avgQueueLength = ( double ) lastTotalQueueLength / ( double ) ( reportTime / 1000 ); // divide by number of reports String outputStr = id + "\t" + hour + "\t" + reportTime + "\t" + requestCount + "\t" + currentRequestCount + "\t" + printAlignColumn( df1.format( totalKB ), 12 ) + "\t" + printAlignColumn( df1.format( currentTotalKB ), 12 ) + "\t" + currentQueueLength + "\t" + printAlignColumn( df2.format( avgQueueLength ), 8 ) + "\t" + // printAlignColumn( df2.format( avgWaitTime ), 8 ) + "\t" + // printAlignColumn( df2.format( lastAvgWaitTime ), 8 ) + "\t" + df2.format( utilization ) + "\t" + df2.format( currentUtilization ); if ( f != null ) { f.write( outputStr ); f.write( "\n" ); f.flush(); } else { System.out.println( outputStr ); } lastStatTime = statTime; lastRequestCount = requestCount; lastTotalBytes = totalBytes; lastTotalQueueWaitTime = totalQueueWaitTime; } //printStats /* * updateTotalBytes * * Calculate the total bytes transfered by adding the bytes * transfered of the currently connected requests to the * totalBytes at the current stat time */ void updateTotalBytes( long stattime ) { int i; long starttime; double bytes; double xferRate = clientThroughput * processorPower / 1000.0; // bytes per ms for ( i = 0; i < maxConnections; i++ ) { if ( connection[i] != null ) { starttime = connection[i].getStartTime(); if ( starttime < lastStatTime ) { starttime = lastStatTime; } bytes = ( stattime - starttime ) * xferRate; bytes += 0.5; // rounding totalBytes += ( long ) bytes; } } } /** * printAlignColumn */ static String printAlignColumn( String s, int c ) { String blanks = " "; for ( int p = s.length(); p < c; p++ ) { blanks += " "; } return ( blanks + s ); } } // class Server