/* $Id: playtrace_rw.C,v 1.1 2000/08/30 07:53:53 fubob Exp $ */ /* * * Copyright (C) 2000 David Mazieres (dm@uun.org) * 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 "arpc.h" #include "sfsmisc.h" #include "sfsro_prot.h" #include "parseopt.h" #include "crypt.h" ptr client_key; sfs_connectarg carg; nfs_fh3 getattrarg; diropargs3 lookuparg; access3args accessarg1; nfs_fh3 fsinfoarg; nfs_fh3 readlinkarg; struct player { static unsigned long playcount; static unsigned long playcount_attempted; const in_addr srvaddr; ptr cs; ptr cr; ptr sfsc; ptr sfsrwc; sfs_connectres cres; sfs_fsinfo fsires; ex_lookup3res lres; ex_readlink3res rres; player (in_addr a) : srvaddr (a) { start (); } void start (); void getfd (int fd); void conres (clnt_stat stat); void cryptres (const sfs_hash *sessid); void fsinfores (clnt_stat stat); void lookupres (clnt_stat stat); void readlinkres (clnt_stat stat); }; unsigned long player::playcount; unsigned long player::playcount_attempted; bool opt_verbose = false; int opt_trace = -1; void player::start () { cr = cs = NULL; playcount_attempted++; tcpconnect (srvaddr, sfs_port, wrap (this, &player::getfd)); } void player::getfd (int fd) { if (fd < 0) { warn ("tcpconnect: %m\n"); // XXX timecb (timenow + 1, wrap (this, &player::start)); return; } ref x (axprt_crypt::alloc (fd)); cs = aclnt::alloc (x, sfs_program_1); cr = aclnt::alloc (x, ex_nfs_program_3); sfs_connectarg carg; carg.release = sfs_release; carg.service = SFS_SFS; carg.name = ""; cs->call (SFSPROC_CONNECT, &carg, &cres, wrap (this, &player::conres)); } void player::conres (clnt_stat stat) { if (stat) { warn << stat; start (); return; } sfs_client_crypt (cs, client_key, carg, *cres.reply, wrap (this, &player::cryptres)); } void player::cryptres (const sfs_hash *sessid) { if (!sessid) { warn << sessid; start (); return; } cs->call (SFSPROC_GETFSINFO, NULL, &fsires, wrap (this, &player::fsinfores)); } void player::fsinfores (clnt_stat stat) { if (stat) { warn << stat; start (); return; } if (fsires.status) warn ("ENOENT\n"); cr->call (ex_NFSPROC3_GETATTR, &getattrarg, NULL, wrap (this, &player::getattrres)); } void player::fsinfores (clnt_stat stat) { if (stat) { warn << stat; start (); return; } if (fsires.status) warn ("ENOENT\n"); cr->call (ex_NFSPROC3_LOOKUP, &lookuparg, &lres, wrap (this, &player::lookupres)); } void player::lookupres (clnt_stat stat) { if (stat) { warn << stat << "\n"; start (); return; } if (lres.status) warn ("ENOENT\n"); cr->call (ex_NFSPROC3_READLINK, &readlinkarg, &rres, wrap (this, &player::readlinkres)); } void player::readlinkres (clnt_stat stat) { if (stat) { warn << stat << "\n"; start (); return; } playcount++; start (); } inline u_int64_t gettime () { timeval tv; gettimeofday (&tv, NULL); return tv.tv_sec * INT64(1000000) + tv.tv_usec; } u_int64_t starttime; void finish () { u_int64_t elapsed_usec = gettime () - starttime; if (opt_verbose) { printf (" usec: %qd\n", elapsed_usec); printf ("Successful plays: %lu\n", player::playcount); printf ("Attempted plays: %lu\n", player::playcount_attempted); printf ("Successful plays/s: %f\n", player::playcount / (elapsed_usec / 1e6F)); printf ("Attempted plays/s: %f\n\n", player::playcount_attempted / (elapsed_usec/ 1e6F)); } else { printf ("%21qd %17lu %6lu %14f %14f\n", elapsed_usec, player::playcount, player::playcount_attempted, player::playcount / (elapsed_usec / 1e6F), player::playcount_attempted / (elapsed_usec / 1e6F)); } exit (0); } void usage () { warnx << "Trace numbers are:\n\n" << "0: Readlink\n" << "1: cat of multi-component dir\n"; fatal << "\nusage: " << progname << " [-p trigger-port] [-n num-clients]\n" << " [-t seconds] [-v] -r trace-num server hostid\n\n" << "Remember to set SFS_PORT\n"; } int main (int argc, char **argv) { setprogname (argv[0]); sfsconst_init (); int opt_triggerport = 0; int opt_nclients = 20; double opt_nseconds = 5.0; int ch; while ((ch = getopt (argc, argv, "p:n:t:r:v")) != -1) switch (ch) { case 'p': if (!convertint (optarg, &opt_triggerport)) usage (); break; case 'n': if (!convertint (optarg, &opt_nclients)) usage (); break; case 't': opt_nseconds = atof (optarg); if (opt_nseconds <= 0) usage (); break; case 'r': if (!convertint (optarg, &opt_trace)) usage (); break; case 'v': opt_verbose = true; break; default: usage (); break; } if ((optind + 2 != argc) || (opt_trace < 0) || (opt_trace >= (int)tracevec_size)) usage (); hostent *hp = gethostbyname (argv[optind]); if (!hp) fatal << argv[1] << ": no such host\n"; in_addr addr = *(in_addr *) hp->h_addr; itimerval itv; bzero (&itv, sizeof (itv)); itv.it_value.tv_sec = long (opt_nseconds); itv.it_value.tv_usec = long (1000000 * (opt_nseconds - itv.it_value.tv_sec)); sigcb (SIGALRM, wrap (finish)); if (opt_verbose) { printf ("Clients Est. Duration (usec) Bytes Act. Duration (usec) MB/s Succ. Plays Attem. Plays Succ. Plays/s Attem. Plays/s\n"); printf ("[ %d clients / %f seconds ]\n", opt_nclients, opt_nseconds); } if (opt_triggerport) { int fd = inetsocket (SOCK_DGRAM, opt_triggerport); if (fd < 0) fatal ("socket: %m\n"); char c; socklen_t l = 0; recvfrom (fd, &c, 1, 0, NULL, &l); } if (setitimer (ITIMER_REAL, &itv, NULL) < 0) fatal ("setitimer: %m\n"); starttime = gettime (); carg.release = SFS_RELEASE; carg.service = SFS_SFS; carg.name = argv[optind]; if (!sfs_ascii2hostid (&carg.hostid, hostid)) { warn << "Can't decode hostid\n"; exit (-1); } lookuparg.dir.data.setsize (32); memcpy (lookuparg.dir.data.base (), "\xe1\x86\x8e\x80\xdc\x20\xfa\x38\x93\xc5\x09\xbc\x44\xa6\x01\xe0\x71\x48\xc6\x50\x75\xd2\xdd\xda\x7f\xd7\xc8\x5e\xc1\xe1\x14\x06", 32); lookuparg.name = "bar"; readlinkarg.data.setsize (32); memcpy (readlinkarg.data.base (), "\x7a\x8a\x25\xbb\x89\xaf\x6e\xda\xe9\x8d\x38\x05\x4b\x98\x80\x25\x80\xec\x50\xfc\xc4\x68\xd1\x81\xac\xf8\x25\x6d\x5b\xb2\x15\x77\xae\x29\xb5\xcf\xba\xa3\x4e\x2b", 32); for (int i = 0; i < opt_nclients; i++) vNew player (addr); amain (); }