/* $Id: maxro_cps.C,v 1.3 2000/08/25 22:25:29 fubob Exp $ */ /* Use this program to simulate a herd of SFSRO clients. You can then test the maximum number of sustainable connections per second to an SFSRO server. Warning. this is almost as fast as a plain TCP connections. Running longer than 1/2 second will likely use up resources. cat /sfstest/soco.lcs.mit.edu:5eeagvu4nq92g5rk9zd258738yudgcgk/manual/mod/mod_ssl/ssl_template.head-chapter.gif > /dev/null */ /* * * Copyright (C) 2000 Kevin Fu (fubob@mit.edu) * * 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 2, 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, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA * */ #include "maxro_cps.h" u_int conncnt = 0; char *hostname; u_int64_t start_tm, end_tm; sfs_hash fh[10]; struct in_addr *ia; char *hostid; int sfsro_port; sfs_connectarg carg; u_int32_t bigdeal =0; char trace[][20] = { #include "maxro_trace.h" }; size_t trace_size = sizeof (trace) / sizeof (trace[0]); void srvcon::fail (int err) { warn << "connection failed" << strerror (errno) << "\n"; delete this; } void srvcon::init () { bigdeal++; tcpconnect (*ia, sfsro_port, wrap (this, &srvcon::getsockres)); } void srvcon::getsockres (int fd) { if (fd < 0) { timecb (timenow + 1, wrap (this, &srvcon::init)); } else { s = axprt_stream::alloc (fd); sfsc = aclnt::alloc (s, sfs_program_1); sfsc->call (SFSPROC_CONNECT, &carg, &conres, wrap (this, &srvcon::sfsconres)); } } void srvcon::sfsconres (clnt_stat err) { if (err) fail (EIO); else if (conres.status) fail (conres.status); else { sfsc->call (SFSPROC_GETFSINFO, NULL, &fsires, wrap (this, &srvcon::getfsinfores)); } } void srvcon::getfsinfores (clnt_stat err) { if (err) fail (EIO); else if (fsires.prog != SFSRO_PROGRAM || fsires.sfsro->vers != SFSRO_VERSION) fail (EPROTONOSUPPORT); else { sfsroc = aclnt::alloc (s, sfsro_program_1); sfsroc->call (SFSROPROC_GETDATA, &fsires.sfsro->v1->info.rootfh, &sfsrores, wrap (this, &srvcon::getdata, 0)); } } void srvcon::getdata (int num, clnt_stat err) { num++; if (err) fail (EIO); else if (num == 10) { conncnt++; vNew srvcon (); delete this; } else { sfsroc->call (SFSROPROC_GETDATA, &fh[num], &sfsrores, wrap (this, &srvcon::getdata, num)); } } void handler () { end_tm = wall_time (); warn << "Time spent: " << end_tm - start_tm << " usec\n"; warn << "Number of conns: " << conncnt << "\n"; warn << "Number of attempted connections: " << bigdeal << "\n"; warn << "Connections/sec: " << conncnt*1000000/(end_tm - start_tm) << "\n"; // XXXX print in one row. Wall time, req/sec (req #), err/sec (err#), latency? CPU time exit (0); } int main (int argc, char **argv) { setprogname (argv[0]); // warn ("pid %d\n", getpid ()); if (argc < 6 || argc > 7) fatal ("usage: %s []\n", progname.cstr ()); int numconn = atoi (argv[1]); sfsro_port = atoi (argv[2]); hostname = argv[3]; hostid = argv[4]; u_int64_t duration_tm = 1000 * atoi (argv[5]); if (duration_tm>= 1000000) { warn << "Duration too long. Go away.\n"; exit (-1); } warn << "Making " << duration_tm << " microseconds worth of calls in windows of " << numconn << " connections to " << hostname << ":" << hostid << "\n"; struct hostent *h; if ((h = gethostbyname (hostname)) == NULL) { warn << "gethostbyname failed\n"; exit(-1); } /* LOOKUP (rootfh's inode) 67, 87, 99, 42, 47, 38, 6d, 86, 75, 44, ff, 71, 2c, c5, 33, d1, 81, 76, aa, 08 */ memcpy (fh[0].base (), "\x67\x87\x99\x42\x47\x38\x6d\x86\x75\x44\xff\x71\x2c\xc5\x33\xd1\x81\x76\xaa\x08", 20); /* Get directory entries for / * 7e, 21, 6a, 57, 67, 4e, 97, 1d, 00, e5, 3a, 3f, 3a, ae, c0, a3, c4, 00, 2f, 60 */ memcpy (fh[1].base (), "\x7e\x21\x6a\x57\x67\x4e\x97\x1d\x00\xe5\x3a\x3f\x3a\xae\xc0\xa3\xc4\x00\x2f\x60", 20); /* Get inode for /manual 67, 4b, 44, 2d, 6c, ef, 71, 08, 6a, 21, fb, 79, 0b, c1, 57, 63, 70, d3, 3e, 3a */ memcpy (fh[2].base (), "\x67\x4b\x44\x2d\x6c\xef\x71\x08\x6a\x21\xfb\x79\x0b\xc1\x57\x63\x70\xd3\x3e\x3a", 20); /* Get directory entries in /manual 0e, fe, 04, 54, 9c, 30, 7e, 7a, e6, f6, 01, 94, 2b, 75, 7c, d4, 1a, 3c, a0, 52 */ memcpy (fh[3].base (), "\x0e\xfe\x04\x54\x9c\x30\x7e\x7a\xe6\xf6\x01\x94\x2b\x75\x7c\xd4\x1a\x3c\xa0\x52", 20); /* Get inode for /manual/mod/ e3, 30, 80, 79, 0f, c8, 04, 61, 0b, 73, 15, ee, 1e, bd, 79, e7, df, 6b, b3, 96 */ memcpy (fh[4].base (), "\xe3\x30\x80\x79\x0f\xc8\x04\x61\x0b\x73\x15\xee\x1e\xbd\x79\xe7\xdf\x6b\xb3\x96", 20); /* Get directory entries for /manual/mod 48, 26, 1e, 8a, da, 84, 5b, 75, fe, fb, d4, f2, 25, ad, 8e, 37, aa, de, 84, e1 */ memcpy (fh[5].base (), "\x48\x26\x1e\x8a\xda\x84\x5b\x75\xfe\xfb\xd4\xf2\x25\xad\x8e\x37\xaa\xde\x84\xe1", 20); /* Get inode for /manual/mod/mod_ssl/ 43, 5f, 7c, 36, 05, bc, 9c, a7, c0, c0, ff, f4, 99, 42, 1c, 69, 92, 93, a2, 9e */ memcpy (fh[6].base (), "\x43\x5f\x7c\x36\x05\xbc\x9c\xa7\xc0\xc0\xff\xf4\x99\x42\x1c\x69\x92\x93\xa2\x9e", 20); /* Get directory entries for /manual/mod/mod_ssl/ cd, 96, d9, 41, fe, d4, 46, 00, ea, 37, ef, 18, 93, 5c, e6, 94, 71, f1, d4, f1 */ memcpy (fh[7].base (), "\xcd\x96\xd9\x41\xfe\xd4\x46\x00\xea\x37\xef\x18\x93\x5c\xe6\x94\x71\xf1\xd4\xf1", 20); /* Get inode for /manual/mod/mod_ssl/ssl_template.head-chapter.gif 32, 33, b6, 26, 36, 55, cb, 50, 6d, 06, 8e, dd, 48, 3d, ce, 1a, b0, 5b, b8, 99 */ memcpy (fh[8].base (), "\x32\x33\xb6\x26\x36\x55\xcb\x50\x6d\x06\x8e\xdd\x48\x3d\xce\x1a\xb0\x5b\xb8\x99", 20); /* Get contents of /manual/mod/mod_ssl/ssl_template.head-chapter.gif 3c, 8e, cd, bb, 6b, 4c, 2c, f2, 02, 63, d7, 98, 4f, 89, 18, d2, 6f, e2, 4c, 2b */ memcpy (fh[9].base (), "\x3c\x8e\xcd\xbb\x6b\x4c\x2c\xf2\x02\x63\xd7\x98\x4f\x89\x18\xd2\x6f\xe2\x4c\x2b", 20); ia = (struct in_addr *) h->h_addr; carg.release = SFS_RELEASE; carg.service = SFS_SFS; carg.name = hostname; if (!sfs_ascii2hostid (&carg.hostid, hostid)) { warn << "Can't decode hostid\n"; exit (-1); } sigcb (SIGALRM, wrap (handler)); sigcb (SIGINT, wrap (handler)); sigcb (SIGTERM, wrap (handler)); struct itimerval itv; itv.it_value.tv_sec = 0; itv.it_value.tv_usec = duration_tm; // Trigger for remote synchronization if (argc == 7) { int udpsock = inetsocket (SOCK_DGRAM, atoi (argv[6])); if (udpsock < 0) { fatal ("socket"); } int broadcast = 1; if (setsockopt (udpsock, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof (broadcast)) < 0) fatal ("setsockopt: %m\n"); char buf[1]; // Block until triggered if (recvfrom (udpsock, buf, 1, 0, NULL, NULL) < 0) { fatal ("sendto: %m\n"); } } int err; if ((err = setitimer (ITIMER_REAL, &itv, NULL)) != 0) { warn << "setitimer failed " << strerror (errno) << "\n"; exit (-1); } start_tm = wall_time(); for (int i=0; i< numconn; i++) vNew srvcon (); amain (); }