Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

TestNullSRPC.C

Go to the documentation of this file.
00001 // Copyright (C) 2001, Compaq Computer Corporation
00002 // 
00003 // This file is part of Vesta.
00004 // 
00005 // Vesta is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public
00007 // License as published by the Free Software Foundation; either
00008 // version 2.1 of the License, or (at your option) any later version.
00009 // 
00010 // Vesta is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // Lesser General Public License for more details.
00014 // 
00015 // You should have received a copy of the GNU Lesser General Public
00016 // License along with Vesta; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 
00019 // Created on Fri Jun 13 10:57:17 PDT 1997 by heydon
00020 // Last modified on Sun May 22 22:45:34 EDT 2005 by ken@xorian.net         
00021 //      modified on Fri Apr 22 14:40:01 EDT 2005 by irina.furman@intel.com 
00022 //      modified on Sat Feb 12 17:40:10 PST 2000 by mann  
00023 //      modified on Wed Jul  9 11:27:01 PDT 1997 by heydon
00024 
00025 /* This program is used to measure the performance of a null SRPC call. The
00026    same program is used for both the server and client; the first command-line
00027    switch must be either "-client" or "-server". When invoked as a client, the
00028    name of the host on which the server program is running may also be
00029    supplied.
00030 
00031    Here is the syntax of the client and server variants of the program:
00032 
00033    client: TestNullSRPC -client [ -blocks b ] [ -sz s ] [ -calls n ] [ host ]
00034    server: TestNullSRPC -server [ -blocks b ] [ -sz s ]
00035 
00036    By default, the client makes null SRPC calls on the server indefinitiely.
00037    If "-calls n" is specified, only "n" calls are made, and the client then
00038    exits. By default, the client tries to contact a server on the same host;
00039    this can be overridden by specifying an explicit "host" to contact.
00040 
00041    If "-blocks b" is specified on either the client or the server, then "b"
00042    data blocks are sent. For the client, these will be RPC arguments; for the
00043    server, they will be RPC results. By default, the blocks are 1K bytes. If
00044    "-sz s" is specfied, the blocks are "s" bytes long.
00045 
00046    The server continues to listen for connections indefinitely. If using etp
00047    to monitor the server, set the ETPFLAGS environment variable to the string
00048    "s2", and interrupt the server by typing "^C". This setting of ETPFLAGS
00049    causes the etp machinery to catch signal 2 (SIGINT) and flush the etp logs
00050    before exiting. */
00051 
00052 #include <Basics.H>
00053 #include <SRPC.H>
00054 #include <MultiSRPC.H>
00055 #include <LimService.H>
00056 
00057 using std::ostream;
00058 using std::endl;
00059 using std::cout;
00060 using std::cerr;
00061 
00062 // SRPC constants
00063 const Text IntfName("1235");
00064 const int  IntfVersion = 1;
00065 const int  ProcId1 = 1;
00066 
00067 // protects writing to "cout"
00068 static Basics::mutex mu;
00069 
00070 typedef char *String;
00071 
00072 ostream& operator << (ostream &os, const SRPC::failure &f) throw ()
00073 /* Print a "SRPC::failure" object to "os" .*/
00074 {
00075     mu.lock();
00076     int i;
00077     for (i = 0; i < 70; i++) os << '*'; os << endl;
00078     os << "SRPC failure (error " << f.r << ") :" << endl;
00079     os << "  " << f.msg << endl;
00080     for (i = 0; i < 70; i++) os << '*'; os << endl << endl;
00081     mu.unlock();
00082     return os;
00083 }
00084 
00085 // ------------------------------- Client -------------------------------------
00086 
00087 void ClientCall(SRPC *srpc, int blocks, int sz, String *buff)
00088   throw (SRPC::failure)
00089 {
00090     // null call
00091     srpc->start_call(ProcId1, IntfVersion);
00092     srpc->send_int(blocks);
00093     srpc->send_int(sz);
00094     if (blocks > 0) {
00095         for (int i = 0; i < blocks; i++) {
00096             srpc->send_bytes(buff[i], sz);
00097         }
00098     }
00099     srpc->send_end();
00100 
00101     // null result
00102     int recv_blocks = srpc->recv_int();
00103     int recv_sz = srpc->recv_int();
00104     if (recv_blocks > 0) {
00105         assert(recv_blocks <= blocks);
00106         assert(recv_sz <= sz);
00107         for (int i = 0; i < recv_blocks; i++) {
00108             int len = recv_sz;
00109             srpc->recv_bytes_here(buff[i], /*INOUT*/ len);
00110             assert(len == recv_sz);
00111         }
00112     }
00113     srpc->recv_end();
00114 }
00115 
00116 void Client(int blocks, int sz, int numCalls, char *hostname) throw ()
00117 {
00118     MultiSRPC multi(IntfName);
00119     try {
00120         // establish SRPC connection
00121         SRPC *srpc;
00122         MultiSRPC::ConnId connId;
00123         connId = multi.Start(hostname, /*OUT*/ srpc);
00124 
00125         // make client calls
00126         String *buff = (String *)NULL;
00127         if (blocks > 0) {
00128             buff = NEW_ARRAY(String, blocks);
00129             for (int i=0; i < blocks; i++) {
00130                 buff[i] = NEW_PTRFREE_ARRAY(char, sz);
00131                 memset(buff[i], 0, sz);
00132             }
00133         }
00134         for (int callCnt = 0; numCalls < 0 || callCnt < numCalls; callCnt++) {
00135             ClientCall(srpc, blocks, sz, buff);
00136         }
00137 
00138         // close connection
00139         multi.End(connId);
00140     } catch (const SRPC::failure &f) {
00141         cout << f;
00142     }
00143 }
00144 
00145 // ------------------------------- Server -------------------------------------
00146 
00147 class ServerArgs {
00148   public:
00149     int blocks;
00150     int sz;
00151     String *buff; // array of strings
00152     ServerArgs(int blocks, int sz) throw ();
00153 };
00154 
00155 ServerArgs::ServerArgs(int blocks, int sz) throw ()
00156 : blocks(blocks), sz(sz), buff((String *)NULL)
00157 {
00158     if (this->blocks > 0) {
00159         this->buff = NEW_ARRAY(String, this->blocks);
00160         for (int i = 0; i < this->blocks; i++) {
00161             this->buff[i] = NEW_PTRFREE_ARRAY(char, this->sz);
00162         }
00163     }
00164 }
00165 
00166 void ServerFailureCallback(/*UNUSED*/ SRPC *srpc, const SRPC::failure &f,
00167   /*UNUSED*/ void *arg) throw ()
00168 {
00169     cout << f;
00170 }
00171 
00172 void ServerWork(const ServerArgs *args) throw ()
00173 {
00174     if (args->buff != (String *)NULL) {
00175         for (int i = 0; i < args->blocks; i++) {
00176             memset(args->buff[i], 0, args->sz);
00177         }
00178     }
00179 }
00180 
00181 void ServerProc1(SRPC *srpc, const ServerArgs *args)
00182   throw (SRPC::failure)
00183 {
00184     // null call
00185     int recv_blocks = srpc->recv_int();
00186     int recv_sz = srpc->recv_int();
00187     if (recv_blocks > 0) {
00188         assert(recv_blocks <= args->blocks);
00189         assert(recv_sz <= args->sz);
00190         for (int i = 0; i < recv_blocks; i++) {
00191             int len = recv_sz;
00192             srpc->recv_bytes_here(args->buff[i], /*INOUT*/ len);
00193             assert(len == recv_sz);
00194         }
00195     }
00196     srpc->recv_end();
00197 
00198     // null work
00199     ServerWork(args);
00200 
00201     // null result
00202     srpc->send_int(args->blocks);
00203     srpc->send_int(args->sz);
00204     if (args->blocks > 0) {
00205         for (int i = 0; i < args->blocks; i++) {
00206             srpc->send_bytes(args->buff[i], args->sz);
00207         }
00208     }
00209     srpc->send_end();
00210 }
00211 
00212 void ServerCallback(SRPC *srpc, int procId, void *arg)
00213   throw (SRPC::failure)
00214 {
00215     const ServerArgs *args = (ServerArgs *)arg;
00216     switch (procId) {
00217       case ProcId1: ServerProc1(srpc, args); break;
00218       default: assert(false);
00219     }
00220 }
00221 
00222 void Server(int blocks, int sz) throw ()
00223 {
00224     // start server
00225     const int MaxRunning = 10, MaxBlocked = 10;
00226     ServerArgs *args = NEW_CONSTR(ServerArgs, (blocks, sz));
00227     LimService ls(IntfName, IntfVersion, MaxRunning, MaxBlocked,
00228       ServerCallback, ServerFailureCallback, (void *)args);
00229     Basics::thread th = ls.Forked_Run();
00230 
00231     // print ready msg
00232     mu.lock();
00233     cout << "Server ready..." << endl << endl;
00234     mu.unlock();
00235 
00236     // wait on forked thread
00237     (void) th.join();
00238 }
00239 
00240 // -------------------------------- Main --------------------------------------
00241 
00242 void SyntaxError(char *msg, char *arg = (char *)NULL) throw ()
00243 {
00244     cerr << "Error: " << msg;
00245     if (arg != (char *)NULL) cerr << ": '" << arg << "'";
00246     cerr << endl;
00247     cerr << "SYNTAX: TestNullSRPC -client "
00248       << " [ -blocks b ] [ -sz s ] [ -calls n ] [ host ]" << endl;
00249     cerr << "SYNTAX: TestNullSRPC -server "
00250       << " [ -blocks b ] [ -sz s ]" << endl;
00251     exit(1);
00252 }
00253 
00254 int main(int argc, char *argv[]) 
00255 {
00256     enum Role { ClientRole, ServerRole };
00257     Role role;
00258     if (argc < 2) SyntaxError("too few arguments");
00259     if (strcmp(argv[1], "-client") == 0) {
00260         role = ClientRole;
00261     } else if (strcmp(argv[1], "-server") == 0) {
00262         role = ServerRole;
00263     } else {
00264         SyntaxError("first argument must be '-client' or '-server'");
00265     }
00266 
00267     // determine other arguments
00268     int blocks = 0, sz = 1024;
00269     int numCalls = -1;
00270     char *hostname = "localhost";
00271     int arg;
00272     for (arg = 2; arg < argc && *argv[arg] == '-'; arg++) {
00273         if (strcmp(argv[arg], "-blocks") == 0) {
00274             if (++arg >= argc) SyntaxError("no argument for '-blocks'");
00275             if (sscanf(argv[arg], "%d", &blocks) != 1)
00276                 SyntaxError("illegal argument to '-blocks'", argv[arg]);
00277         } else if (strcmp(argv[arg], "-sz") == 0) {
00278             if (++arg >= argc) SyntaxError("no argument for '-sz'");
00279             if (sscanf(argv[arg], "%d", &sz) != 1)
00280                 SyntaxError("illegal argument to '-sz'", argv[arg]);
00281         } else if (strcmp(argv[arg], "-calls") == 0) {
00282             if (role == ServerRole)
00283                 SyntaxError("'-calls' not understood by server");
00284             if (++arg >= argc) SyntaxError("no argument for '-calls'");
00285             if (sscanf(argv[arg], "%d", &numCalls) != 1)
00286                 SyntaxError("illegal argument to '-calls'", argv[arg]);
00287         } else {
00288             SyntaxError("unrecognized switch", argv[arg]);
00289         }
00290     }
00291     switch (role) {
00292       case ClientRole:
00293         if (arg < argc) hostname = argv[arg++];
00294         if (arg < argc) SyntaxError("too many arguments");
00295         Client(blocks, sz, numCalls, hostname);
00296         break;
00297       case ServerRole:
00298         if (argc > arg) SyntaxError("too many arguments");
00299         Server(blocks, sz);
00300         break;
00301       default:
00302         assert(false);
00303     }
00304     return 0;
00305 }

Generated on Mon May 8 00:48:58 2006 for Vesta by  doxygen 1.4.2