summaryrefslogtreecommitdiff
path: root/ACE/apps/JAWS/stress_testing
diff options
context:
space:
mode:
authorWilliam R. Otte <wotte@dre.vanderbilt.edu>2006-07-24 15:50:30 +0000
committerWilliam R. Otte <wotte@dre.vanderbilt.edu>2006-07-24 15:50:30 +0000
commitc44379cc7d9c7aa113989237ab0f56db12aa5219 (patch)
tree66a84b20d47f2269d8bdc6e0323f338763424d3a /ACE/apps/JAWS/stress_testing
parent3aff90f4a822fcf5d902bbfbcc9fa931d6191a8c (diff)
downloadATCD-c44379cc7d9c7aa113989237ab0f56db12aa5219.tar.gz
Repo restructuring
Diffstat (limited to 'ACE/apps/JAWS/stress_testing')
-rw-r--r--ACE/apps/JAWS/stress_testing/README54
-rw-r--r--ACE/apps/JAWS/stress_testing/benchd.cpp240
-rw-r--r--ACE/apps/JAWS/stress_testing/client.h8
-rw-r--r--ACE/apps/JAWS/stress_testing/config3
-rw-r--r--ACE/apps/JAWS/stress_testing/connection.cpp98
-rw-r--r--ACE/apps/JAWS/stress_testing/connection.h22
-rw-r--r--ACE/apps/JAWS/stress_testing/cp.cpp11
-rw-r--r--ACE/apps/JAWS/stress_testing/cp.h14
-rw-r--r--ACE/apps/JAWS/stress_testing/global.h31
-rw-r--r--ACE/apps/JAWS/stress_testing/http.h16
-rw-r--r--ACE/apps/JAWS/stress_testing/http_tester.cpp172
-rw-r--r--ACE/apps/JAWS/stress_testing/out2
-rw-r--r--ACE/apps/JAWS/stress_testing/stats.cpp88
-rw-r--r--ACE/apps/JAWS/stress_testing/stats.h31
-rw-r--r--ACE/apps/JAWS/stress_testing/util.cpp60
-rw-r--r--ACE/apps/JAWS/stress_testing/util.h34
16 files changed, 884 insertions, 0 deletions
diff --git a/ACE/apps/JAWS/stress_testing/README b/ACE/apps/JAWS/stress_testing/README
new file mode 100644
index 00000000000..0969522d638
--- /dev/null
+++ b/ACE/apps/JAWS/stress_testing/README
@@ -0,0 +1,54 @@
+http_tester
+-----------
+
+This is the http_tester suite, an ACE based HTTP benchmarking tool,
+used to evaluate the performance of JAWS and other HTTP servers.
+
+Usage
+-----
+
+To use the http_tester, you need to use a config file "infile", which
+consists of a list of experiments, one on each line. http_tester logs
+output data in the "outfile".
+
+Usage: http_tester infile outfile
+
+Experiments
+-----------
+
+Each experiment consists of several space-delimited compulsory
+fields, as follows:
+
+experiment_id (string)
+total_number_of_requests (integer)
+request_rate (float)
+url1 (first URL)
+p1 (probability of requesting the first URL)
+url2 (second URL)
+p2 (probability of requesting the second URL)
+url3 (third URL)
+p3 (probability of requesting the third URL)
+TCP_NODELAY (boolean, 1 == TCP_NODELAY is set)
+SOCKET_RECV_BUFSIZ (usually 65536)
+
+URLS must be of the form:
+
+http://www.cs.wustl.edu:8888/~sumedh/index.html
+
+(the port number is required, im making it optional in the next version).
+
+Please see the sample file "config", for an example.
+
+Output file
+-----------
+
+The output file consists of the following space delimited fields:
+
+Experiment Id (string)
+Average throughput of connection (float)
+Average latency of connection (float)
+Maximum number of active connections at any given time (int)
+
+
+Sumedh Mungee
+<sumedh@cs.wustl.edu>
diff --git a/ACE/apps/JAWS/stress_testing/benchd.cpp b/ACE/apps/JAWS/stress_testing/benchd.cpp
new file mode 100644
index 00000000000..ff17f669430
--- /dev/null
+++ b/ACE/apps/JAWS/stress_testing/benchd.cpp
@@ -0,0 +1,240 @@
+// $Id$
+
+// benchd: Adapted from the "ntalker" example.
+// Sumedh Mungee
+
+#include "ace/Process.h"
+#include "ace/INET_Addr.h"
+#include "ace/SOCK_Dgram_Mcast.h"
+#include "ace/Reactor.h"
+#include "ace/Get_Opt.h"
+#include "ace/ARGV.h"
+
+ACE_RCSID(stress_testing, benchd, "$Id$")
+
+#if defined (ACE_HAS_IP_MULTICAST)
+// network interface to subscribe to
+// this is hardware specific.
+// use netstat (1M) to find whether your interface
+// is le0 or ie0
+
+// Maximum number of arguments supported for a request
+static const int MAX_ARGS = 16;
+// Name of the client benchmarking tool
+static const char *TESTER = "http_tester";
+static int QUIET = 0;
+static const char *INTERFACE = "le0";
+static const char *MCAST_ADDR = ACE_DEFAULT_MULTICAST_ADDR;
+static const u_short UDP_PORT = ACE_DEFAULT_MULTICAST_PORT;
+static const char *OUTPUT_FILE_NAME = "benchd.log";
+static ACE_HANDLE OUTPUT_FILE;
+
+// Handle both multicast and stdin events.
+
+class Handle_Events : public ACE_Event_Handler
+{
+public:
+ Handle_Events (u_short udp_port,
+ const char *ip_addr,
+ const char *interface,
+ ACE_Reactor &reactor);
+ ~Handle_Events (void);
+
+ virtual int handle_input (ACE_HANDLE);
+ virtual int handle_close (ACE_HANDLE, ACE_Reactor_Mask);
+
+private:
+ int serve (char *buf);
+ ACE_SOCK_Dgram_Mcast mcast_;
+ ACE_Handle_Set handle_set_;
+};
+
+int
+Handle_Events::handle_input (ACE_HANDLE h)
+{
+ char buf[BUFSIZ];
+
+ if (h == 0)
+ {
+ int readresult = ACE_OS::read (h, buf, BUFSIZ);
+ if (readresult > 0)
+ {
+ if (this->mcast_.send (buf, readresult) != readresult)
+ {
+ ACE_OS::perror ("send error");
+ return -1;
+ }
+ return 0;
+ }
+ else if (readresult == -1)
+ ::perror ("can't read from STDIN");
+
+ return -1;
+ }
+ else
+ {
+ ACE_INET_Addr remote_addr;
+
+ // receive message from multicast group
+ int retcode = this->mcast_.recv (buf, sizeof buf, remote_addr);
+
+ if (retcode != -1)
+ {
+ /*
+ cout << "received datagram from host " << remote_addr.get_host_name ()
+ << " on port " << remote_addr.get_port_number ()
+ << " bytes = " << retcode << endl;
+ */
+ serve (buf);
+ return 0;
+ }
+
+ ACE_OS::perror ("Something amiss.");
+ return -1;
+ }
+}
+
+int
+Handle_Events::handle_close (ACE_HANDLE h, ACE_Reactor_Mask)
+{
+ if (h == 0)
+ cout << "STDIN_Events handle removed from reactor." << endl << flush;
+ else
+ cout << "Mcast_Events handle removed from reactor." << endl << flush;
+ return 0;
+}
+
+Handle_Events::~Handle_Events (void)
+{
+ // ACE_OS::exit on error (bogus)...
+
+ if (this->mcast_.unsubscribe () == -1)
+ ACE_OS::perror ("unsubscribe fails"), ACE_OS::exit (1);
+}
+
+Handle_Events::Handle_Events (u_short udp_port,
+ const char *ip_addr,
+ const char *interface,
+ ACE_Reactor &reactor)
+{
+ // Create multicast address to listen on.
+
+ ACE_INET_Addr sockmc_addr (udp_port, ip_addr);
+
+ // subscribe to multicast group.
+
+ if (this->mcast_.subscribe (sockmc_addr, 1, interface) == -1)
+ ACE_OS::perror ("can't subscribe to multicast group"), ACE_OS::exit (1);
+
+ // Disable loopbacks.
+ // if (this->mcast_.set_option (IP_MULTICAST_LOOP, 0) == -1 )
+ // ACE_OS::perror (" can't disable loopbacks " ), ACE_OS::exit (1);
+
+ if (!QUIET) {
+ this->handle_set_.set_bit (0);
+ }
+ this->handle_set_.set_bit (this->mcast_.get_handle ());
+
+ // Register callbacks with the ACE_Reactor.
+ if (reactor.register_handler (this->handle_set_,
+ this,
+ ACE_Event_Handler::READ_MASK) == -1)
+ ACE_OS::perror ("can't register events"), ACE_OS::exit (1);
+}
+
+
+// This method handles multicast requests..
+// These requests are of the following form:
+// command (arguments)
+
+
+// currently only one is supported (and indeed needed :-)) http_tester
+// arguments
+
+int
+Handle_Events::serve (char *buf)
+{
+ ACE_ARGV arguments (buf);
+
+ if (ACE_OS::strcmp (arguments[0], TESTER) == 0)
+ {
+ ACE_Process_Options po;
+ ACE_Process p;
+
+ po.set_handles (ACE_INVALID_HANDLE, OUTPUT_FILE, OUTPUT_FILE);
+ po.command_line (arguments.argv ());
+
+ p.spawn (po);
+ return 0;
+ }
+ else
+ return -1;
+}
+
+static void
+parse_args (int argc, char *argv[])
+{
+ ACE_Get_Opt get_opt (argc, argv, "i:u:q");
+
+ int c;
+
+ while ((c = get_opt ()) != -1)
+ switch (c)
+ {
+ case 'q':
+ QUIET = 1;
+ case 'i':
+ INTERFACE = get_opt.opt_arg ();
+ break;
+ case 'u':
+ // Usage fallthrough.
+ default:
+ ACE_DEBUG ((LM_DEBUG, "%s -i interface\n", argv[0]));
+ ACE_OS::exit (1);
+ }
+}
+
+static sig_atomic_t done = 0;
+
+// Signal handler.
+
+extern "C" void
+handler (int)
+{
+ done = 1;
+}
+
+int
+main (int argc, char *argv[])
+{
+ ACE_Sig_Action sa ((ACE_SignalHandler) handler, SIGINT);
+ ACE_OS::signal (SIGCLD, SIG_IGN);
+ ACE_UNUSED_ARG (sa);
+
+ parse_args (argc, argv);
+
+ OUTPUT_FILE = ACE_OS::open (OUTPUT_FILE_NAME, O_CREAT | O_WRONLY, 0644);
+ if (OUTPUT_FILE == 0)
+ return 1;
+
+ ACE_Reactor reactor;
+ Handle_Events handle_events (UDP_PORT, MCAST_ADDR, INTERFACE, reactor);
+
+ // main loop
+
+ while (!done)
+ reactor.handle_events ();
+
+ ACE_OS::close (OUTPUT_FILE);
+ cout << "\nbenchd done.\n";
+ return 0;
+}
+#else
+int
+main (int argc, char *argv[])
+{
+ ACE_ERROR ((LM_ERROR, "error: %s must be run on a platform that support IP multicast\n",
+ argv[0]));
+ return 0;
+}
+#endif /* ACE_HAS_IP_MULTICAST */
diff --git a/ACE/apps/JAWS/stress_testing/client.h b/ACE/apps/JAWS/stress_testing/client.h
new file mode 100644
index 00000000000..58ef98c7bdf
--- /dev/null
+++ b/ACE/apps/JAWS/stress_testing/client.h
@@ -0,0 +1,8 @@
+// $Id$
+
+#include "global.h"
+#include "util.h"
+#include "http.h"
+#include "cp.h"
+#include "stats.h"
+
diff --git a/ACE/apps/JAWS/stress_testing/config b/ACE/apps/JAWS/stress_testing/config
new file mode 100644
index 00000000000..7e730eaef10
--- /dev/null
+++ b/ACE/apps/JAWS/stress_testing/config
@@ -0,0 +1,3 @@
+1.0 1 1 http://localhost:5432/IO.h 1 a 0 b 0 1 65536
+2.0 1 1 http://localhost:5432/IO.h 1 a 0 b 0 1 65536
+
diff --git a/ACE/apps/JAWS/stress_testing/connection.cpp b/ACE/apps/JAWS/stress_testing/connection.cpp
new file mode 100644
index 00000000000..a243fdd01d5
--- /dev/null
+++ b/ACE/apps/JAWS/stress_testing/connection.cpp
@@ -0,0 +1,98 @@
+// $Id$
+
+#include "connection.h"
+
+ACE_RCSID(stress_testing, connection, "$Id$")
+
+// Make the connection to the WEB server
+
+int connection::connect(char *hostname_opt_port, int tcp_nodelay, int sockbufsiz) {
+ if(!hostname_opt_port) return 1;
+
+ char *hostname_with_port;
+ // Check to see if portnumber is specified in the hostnameport
+ // If not, append :80
+ if(!ACE_OS::strchr(hostname_opt_port,':')) {
+ hostname_with_port = new char[ACE_OS::strlen(hostname_opt_port) + 3];
+ ACE_OS::sprintf(hostname_with_port, "%s:%d", hostname_opt_port, 80);
+ }
+ else {
+ hostname_with_port = hostname_opt_port;
+ }
+
+ // Beyond this point, hostname_with_port is of the form hostname:port
+
+ ACE_INET_Addr server_addr(hostname_with_port);
+
+ // Connect to server
+
+ ACE_SOCK_Connector con;
+
+ if(con.connect(stream_, server_addr) == -1) {
+ perror("ACE_SOCK_Connector::connect");
+ return 1;
+ }
+
+
+ // tcp_nodelay processing.
+
+ // turn off weird ack things
+ if(tcp_nodelay) {
+ struct protoent *p = ACE_OS::getprotobyname ("tcp");
+ int one = 1;
+
+ if (p && stream_.set_option (p->p_proto,
+ TCP_NODELAY,
+ (char *)& one,
+ sizeof (one))) {
+ perror("tcp_nodelay");
+ return 1;
+ }
+ }
+
+ if(sockbufsiz)
+ if (stream_.set_option (SOL_SOCKET,
+ SO_RCVBUF,
+ (char *) &sockbufsiz,
+ sizeof sockbufsiz) == -1) {
+ perror("socket_queue_size");
+ return 1;
+ }
+
+ return 0;
+}
+
+int connection::read(void *buffer, size_t maxlen, unsigned int timeout_seconds) {
+ ACE_UNUSED_ARG (timeout_seconds);
+ return stream_.recv(buffer, maxlen);
+}
+
+int connection::write(const void *buffer, size_t maxlen, unsigned int timeout_seconds) {
+ ACE_UNUSED_ARG (timeout_seconds);
+ return stream_.send(buffer, maxlen);
+}
+
+int connection::write_n(const void *buffer, size_t len, unsigned int timeout_seconds) {
+ ACE_UNUSED_ARG (timeout_seconds);
+ if(stream_.send_n(buffer, len) == -1)
+ ACE_ERROR_RETURN((LM_ERROR, "Write failed for %s", buffer),1);
+ return 0;
+}
+
+int connection::read_n(void *buffer, size_t maxlen, unsigned int timeout_seconds) {
+ ACE_UNUSED_ARG (timeout_seconds);
+ if(stream_.recv_n(buffer, maxlen) == -1)
+ ACE_ERROR_RETURN((LM_ERROR, "Read failed.."),1);
+ return 1;
+}
+
+int connection::close(void) {
+ stream_.close_reader();
+ stream_.close_writer();
+ stream_.close();
+ return 0;
+}
+
+connection::~connection(void) {
+ this->close();
+}
diff --git a/ACE/apps/JAWS/stress_testing/connection.h b/ACE/apps/JAWS/stress_testing/connection.h
new file mode 100644
index 00000000000..db37ff07f35
--- /dev/null
+++ b/ACE/apps/JAWS/stress_testing/connection.h
@@ -0,0 +1,22 @@
+// $Id$
+
+#include "global.h"
+
+#ifndef _D_connection
+#define _D_connection
+class connection {
+
+public:
+ int connect(char *hostname_opt_port, int tcp_nodelay, int sockbufsiz);
+ int read(void *buffer, size_t maxlen, unsigned int timeout_seconds = 60);
+ int write(const void *buffer, size_t maxlen, unsigned int timeout_seconds = 60);
+ int write_n(const void *buffer, size_t len, unsigned int timeout_seconds = 60);
+ int read_n(void *buffer, size_t maxlen, unsigned int timeout_seconds = 60);
+ int close(void);
+ ~connection(void);
+
+private:
+ ACE_SOCK_Stream stream_;
+ char sockbuf[66000];
+};
+#endif
diff --git a/ACE/apps/JAWS/stress_testing/cp.cpp b/ACE/apps/JAWS/stress_testing/cp.cpp
new file mode 100644
index 00000000000..4829735aaa8
--- /dev/null
+++ b/ACE/apps/JAWS/stress_testing/cp.cpp
@@ -0,0 +1,11 @@
+// $Id$
+
+#include "cp.h"
+
+ACE_RCSID(stress_testing, cp, "$Id$")
+
+Client_Parameters::Client_Parameters(int i) {
+
+ id = i;
+
+}
diff --git a/ACE/apps/JAWS/stress_testing/cp.h b/ACE/apps/JAWS/stress_testing/cp.h
new file mode 100644
index 00000000000..ad2e5ddf31b
--- /dev/null
+++ b/ACE/apps/JAWS/stress_testing/cp.h
@@ -0,0 +1,14 @@
+// $Id$
+
+#include "util.h"
+#include "stats.h"
+
+class Client_Parameters {
+public:
+ Client_Parameters(int);
+ URL *url;
+ static Stats *stats;
+ static int tcp_nodelay;
+ static int sockbufsiz;
+ int id;
+};
diff --git a/ACE/apps/JAWS/stress_testing/global.h b/ACE/apps/JAWS/stress_testing/global.h
new file mode 100644
index 00000000000..0d916f2cc41
--- /dev/null
+++ b/ACE/apps/JAWS/stress_testing/global.h
@@ -0,0 +1,31 @@
+// $Id$
+
+#include "ace/ACE.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/SOCK_Acceptor.h"
+#include "ace/SOCK_Connector.h"
+#include "ace/Pipe.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/INET_Addr.h"
+#include "ace/Profile_Timer.h"
+#include "ace/Thread.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Service_Config.h"
+
+// FUZZ: disable check_for_math_include
+#include <math.h>
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ACE/apps/JAWS/stress_testing/http.h b/ACE/apps/JAWS/stress_testing/http.h
new file mode 100644
index 00000000000..efce9235e56
--- /dev/null
+++ b/ACE/apps/JAWS/stress_testing/http.h
@@ -0,0 +1,16 @@
+// $Id$
+
+#include "global.h"
+
+#define CONTENT_ENCODING_HEADER "Content-encoding: "
+#define CONTENT_TYPE_HEADER "Content-type: "
+#define INCOMING_FILE_NAME "/tmp/sumedh.web.inc"
+#define TEMPORARY_FILE_NAME "/tmp/sumedh.web.tmp"
+
+#define ENCODING_TAB "./encoding.tab"
+#define CONTENT_TAB "./content.tab"
+
+int demime(void);
+int decode(char *encoding);
+int view(char *content);
+
diff --git a/ACE/apps/JAWS/stress_testing/http_tester.cpp b/ACE/apps/JAWS/stress_testing/http_tester.cpp
new file mode 100644
index 00000000000..eb086262317
--- /dev/null
+++ b/ACE/apps/JAWS/stress_testing/http_tester.cpp
@@ -0,0 +1,172 @@
+// $Id$
+
+#include "client.h"
+
+ACE_RCSID(stress_testing, http_tester, "$Id$")
+
+int Client_Parameters::tcp_nodelay;
+int Client_Parameters::sockbufsiz;
+Stats *Client_Parameters::stats;
+
+static void *
+client_thread(void *data)
+{
+ Client_Parameters *cp = (Client_Parameters *) data;
+ float latency = 0, throughput;
+ URL *u = cp->url;
+
+ // Check for presence of protocol, hostname and filename.
+
+ if(!(u->get_protocol() && u->get_hostname() && u->get_filename())) {
+ cerr << "Invalid URL" << endl;
+ return NULL;
+ }
+
+ cp->stats->i_have_started(cp->id);
+
+ // Attempt connection
+ connection webserver;
+
+ if(webserver.connect(u->get_hostname(), cp->tcp_nodelay, cp->sockbufsiz)) return NULL;
+ // Send the request now.
+
+
+ char request[BUFSIZ];
+
+ ACE_Profile_Timer throughput_timer, latency_timer;
+ throughput_timer.start();
+ latency_timer.start();
+ ACE_OS::sprintf(request,"GET /%s HTTP/1.0\r\n\r\n",u->get_filename());
+ webserver.write_n(request, strlen(request)) ;
+
+ char buffer[BUFSIZ];
+ ssize_t num_read = 0, total_read = 0;
+ unsigned int first_time = 1;
+ for(;;) {
+ num_read = webserver.read(buffer, sizeof buffer);
+ if(first_time) {
+ ACE_Profile_Timer::ACE_Elapsed_Time et;
+ latency_timer.stop();
+ latency_timer.elapsed_time(et);
+ latency = et.real_time;
+ first_time = 0;
+ }
+ if(num_read <= 0)
+ break;
+ total_read += num_read;
+ }
+ cp->stats->i_am_done(cp->id);
+ ACE_Profile_Timer::ACE_Elapsed_Time et;
+ throughput_timer.stop();
+ throughput_timer.elapsed_time(et);
+ throughput = (8 * total_read/et.real_time) / (1000 * 1000); //pow(10,6) ;
+ cp->stats->log(cp->id, throughput, latency);
+ webserver.close();
+ return NULL;
+}
+
+int driver(char *id, int total_num, float requests_sec, char *url1, float p1, char *url2, float p2, char *url3, float p3, int tcp_nodelay, int sockbufsiz) {
+
+ // construct the client parameters packet
+
+ Client_Parameters::tcp_nodelay = tcp_nodelay;
+ Client_Parameters::sockbufsiz = sockbufsiz;
+
+ Client_Parameters::stats = new Stats(total_num);
+
+ int missed_deadlines = 0;
+ // sleep_time is in microseconds, and requests_sec is per second, hence the pow(10,6)
+ float sleep_time = (1/requests_sec) * (1000.0 * 1000.0); // pow(10,6);
+ float delta = 0;
+ srand(time(NULL));
+ for(int i = 0; i < total_num; i++) { // i is used as a id for threads
+ ACE_Profile_Timer timer;
+ if(sleep_time < delta)
+ {
+ // cerr << "Requested rate is too high, sleep_time == " << sleep_time << ", and delta = " << delta << ", after " << i << " iterations! " << endl;
+ missed_deadlines++;
+ }
+ else
+ {
+ ACE_Time_Value tv(0, (long int) (sleep_time - delta));
+ ACE_OS::sleep(tv);
+ timer.start();
+ }
+ Client_Parameters *cp = new Client_Parameters(i);
+
+ double r = ((double)rand()/(double)RAND_MAX);
+ // cerr << " choosing between " << url1 << url2 << url3 << " with r == " << r;
+ if(r <= p1) cp->url = new URL(url1);
+ if( (r > p1) && (r <= (p1 + p2))) cp->url = new URL(url2);
+ if( (r > (p1 + p2)) && (r <= p1 + p2 + p3)) cp->url = new URL(url3);
+ // cerr << "The URL being requested is " << cp->url->get_filename() << endl;
+
+
+ (ACE_Thread_Manager::instance ())->spawn(client_thread, (void *) cp);
+ timer.stop();
+ ACE_Profile_Timer::ACE_Elapsed_Time et;
+ timer.elapsed_time(et);
+ delta = ( (0.4 * fabs(et.real_time * (1000 * 1000))) + (0.6 * delta) ); // pow(10,6)
+ }
+
+ // Join the other threads..
+ (ACE_Thread_Manager::instance ())->wait();
+ // Now output the data for this test
+ cout << id;
+ Client_Parameters::stats->output();
+ cout << endl;
+ if (missed_deadlines != 0)
+ {
+ cout << "missed deadlines " << missed_deadlines << endl;
+ cout << "missed deadlines as a % of total requests: " << (float) missed_deadlines / total_num * 100 << endl;
+ }
+ return 0;
+}
+
+
+main(int argc, char **argv)
+{
+ // This will set the global scale factor if the ACE_SCALE_FACTOR
+ // environment variable is set.
+ ACE_High_Res_Timer::get_env_global_scale_factor ();
+
+ if(argc < 3) {
+ cerr << "Usage: " << argv[0] << " infile outfile " << endl;
+ cerr << "The input file contains lines, with the following fields: " << endl;
+ cerr << "experiment_id total_number_of_requests request_rate url1 p1 url2 p2 url3 p3 TCP_NODELAY SOCKET_RECV_BUFSIZ " << endl;
+
+ return 1;
+ }
+
+ FILE *fp = fopen(argv[1],"r");
+ if(fp == NULL) {
+ perror("fopen");
+ return 2;
+ }
+ close(1);
+ int fd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0644);
+ if(fd == -1) {
+ perror("open");
+ return 3;
+ }
+
+
+ int total_num, tcp, sock;
+ char *id = new char[BUFSIZ];
+ float rate, p1, p2, p3;
+ char *url1 = new char[BUFSIZ];
+ char *url2 = new char[BUFSIZ];
+ char *url3 = new char[BUFSIZ];
+
+
+ while(!feof(fp)) {
+ fscanf(fp,"%s %d %f %s %f %s %f %s %f %d %d\n", id, &total_num, &rate, url1, &p1, url2, &p2, url3, &p3, &tcp, &sock);
+ if (id[0] == '#') continue;
+ fprintf(stderr,"----\n");
+ fprintf(stderr,"\tNow performing experiment:%s\n\tSending %d requests at %f requests/second\n", id, total_num, rate);
+ driver(id, total_num, rate, url1, p1, url2, p2, url3, p3, tcp, sock);
+ }
+ fclose(fp);
+ close(fd);
+ return 0;
+}
diff --git a/ACE/apps/JAWS/stress_testing/out b/ACE/apps/JAWS/stress_testing/out
new file mode 100644
index 00000000000..c237b7f38bc
--- /dev/null
+++ b/ACE/apps/JAWS/stress_testing/out
@@ -0,0 +1,2 @@
+1.0 0.47895 0.00859167 1
+2.0 0.562603 0.00185976 1
diff --git a/ACE/apps/JAWS/stress_testing/stats.cpp b/ACE/apps/JAWS/stress_testing/stats.cpp
new file mode 100644
index 00000000000..6e71b91c014
--- /dev/null
+++ b/ACE/apps/JAWS/stress_testing/stats.cpp
@@ -0,0 +1,88 @@
+// $Id$
+
+#include "stats.h"
+
+ACE_RCSID(stress_testing, stats, "$Id$")
+
+Stats::Stats(int size) {
+ throughput_ = new float[size];
+ latency_ = new float[size];
+ thread_count_ = size;
+ init_fini_ = new Init_Fini_t[2*size];
+ for(int i = 0; i < size; i++)
+ throughput_[i] = latency_[i] = 0;
+}
+
+void Stats::log(int id, float throughput, float latency) {
+ throughput_[id] = throughput;
+ latency_[id] = latency;
+}
+
+// Unused for now.
+void Stats::print(char *message) {
+
+ ACE_UNUSED_ARG (message);
+
+ // char time_buf[64];
+ // long ltime;
+ // time(&ltime);
+
+ // ACE_OS::ctime_r(&ltime, time_buf, sizeof time_buf);
+
+ // if(ACE_OS::gettimeofday() == -1) {
+ // perror("gettimeofday");
+ // }
+ // time_buf[strlen(time_buf)-1] = 0;
+ // printf("%010ld%09ld \t %s %s\n", tp.tv_sec, tp.tv_usec, time_buf, message);
+}
+
+
+int comp(const void *a, const void *b) {
+
+ Init_Fini_t *A = (Init_Fini_t *)a;
+ Init_Fini_t *B = (Init_Fini_t *)b;
+
+ return (A->timestamp < B->timestamp) ? -1 : (A->timestamp > B->timestamp);
+}
+
+
+void Stats::output() {
+ int i;
+ float tavg = 0, lavg = 0;
+
+ qsort(init_fini_, 2*thread_count_, sizeof(Init_Fini_t), comp);
+
+ int max = 0,thread_peak = 0;
+
+ for(i = 0; i < 2*thread_count_; i++) {
+ // cerr << " " << ((init_fini_[i].type == THREAD_START) ? "START": "END") << " " << init_fini_[i].timestamp.sec() << "." << init_fini_[i].timestamp.usec() << endl;
+ if(init_fini_[i].type == THREAD_START) {
+ if(++thread_peak > max)
+ max = thread_peak;
+ }
+ else thread_peak--;
+ }
+ for(i = 0; i < thread_count_; i++) {
+ tavg += throughput_[i];
+ lavg += latency_[i];
+ }
+ cout << " " << tavg/thread_count_ << " " << lavg/thread_count_ << " " << max;
+}
+
+
+void Stats::i_have_started(int id) {
+
+ init_fini_[2*id].type = THREAD_START;
+ init_fini_[2*id].timestamp = ACE_OS::gettimeofday();
+
+}
+
+void Stats::i_am_done(int id) {
+
+ init_fini_[(2*id)+1].type = THREAD_END;
+
+ init_fini_[(2*id)+1].timestamp = ACE_OS::gettimeofday();
+
+}
+
+
diff --git a/ACE/apps/JAWS/stress_testing/stats.h b/ACE/apps/JAWS/stress_testing/stats.h
new file mode 100644
index 00000000000..b5ef4a4f4a0
--- /dev/null
+++ b/ACE/apps/JAWS/stress_testing/stats.h
@@ -0,0 +1,31 @@
+// $Id$
+
+#include "global.h"
+
+#ifndef _D_Stats
+#define _D_Stats
+
+#define THREAD_START 42
+#define THREAD_END 43
+
+class Init_Fini_t {
+public:
+ int type; // 0 is start, 1 is end
+ ACE_Time_Value timestamp;
+};
+
+class Stats {
+public:
+ Stats(int);
+ void log(int, float, float);
+ void i_have_started(int);
+ void i_am_done(int);
+ void print (char *);
+ void output();
+private:
+ float *throughput_;
+ float *latency_;
+ Init_Fini_t *init_fini_; // Array (2n deep) to count peak no. of active threads
+ int thread_count_;
+};
+#endif
diff --git a/ACE/apps/JAWS/stress_testing/util.cpp b/ACE/apps/JAWS/stress_testing/util.cpp
new file mode 100644
index 00000000000..29cd92ef143
--- /dev/null
+++ b/ACE/apps/JAWS/stress_testing/util.cpp
@@ -0,0 +1,60 @@
+// $Id$
+
+#include "util.h"
+
+ACE_RCSID(stress_testing, util, "$Id$")
+
+URL::URL(char *input_buf) {
+
+ char *buffer = new char[BUFSIZ];
+
+ ACE_OS::strcpy(buffer,input_buf);
+ if(buffer == NULL)
+ return;
+
+ char *temp;
+ char *lasts;
+
+ if((temp = ACE_OS::strtok_r(buffer,": ",&lasts))) {
+ protocol_ = (char *) ACE_OS::malloc(strlen(temp) + 1);
+ ACE_OS::strcpy(protocol_, temp);
+ }
+
+ if((temp = ACE_OS::strtok_r(NULL,"/",&lasts))) {
+ hostname_ = (char *) ACE_OS::malloc(strlen(temp) + 1);
+ ACE_OS::strcpy(hostname_, temp);
+ }
+ if((temp = ACE_OS::strtok_r(NULL,"\0",&lasts))) {
+ filename_ = (char *) malloc(strlen(temp) + 1);
+ ACE_OS::strcpy(filename_, temp);
+ }
+ else {
+ filename_ = (char *) malloc(strlen(INDEX_NAME) + 1);
+ ACE_OS::strcpy(filename_,INDEX_NAME);
+ }
+}
+
+char *URL::get_protocol(void) {
+ return protocol_;
+}
+
+char *URL::get_hostname(void) {
+ return hostname_;
+}
+
+char *URL::get_filename(void) {
+ return filename_;
+}
+
+
+
+
+
+void cleanup(void) {
+ unlink(TEMPORARY_FILE_NAME);
+ unlink(INCOMING_FILE_NAME);
+}
+
+void sigint(int) {
+ cleanup();
+}
diff --git a/ACE/apps/JAWS/stress_testing/util.h b/ACE/apps/JAWS/stress_testing/util.h
new file mode 100644
index 00000000000..875a8cd80e0
--- /dev/null
+++ b/ACE/apps/JAWS/stress_testing/util.h
@@ -0,0 +1,34 @@
+// $Id$
+
+#include "connection.h"
+
+#ifndef _D_URL
+#define _D_URL
+class URL {
+
+public:
+
+ URL(char *buffer);
+
+ char *get_protocol();
+ char *get_hostname();
+ char *get_filename();
+
+private:
+ char *protocol_;
+ char *hostname_;
+ char *filename_;
+};
+
+void cleanup(void);
+void sigint(int);
+int copier(connection in);
+
+#define INDEX_NAME "/index.html"
+#define INCOMING_FILE_NAME "/tmp/sumedh.web.inc"
+#define TEMPORARY_FILE_NAME "/tmp/sumedh.web.tmp"
+#endif
+
+
+
+