nsprpub/pr/tests/servr_uu.c

Wed, 31 Dec 2014 06:55:46 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:46 +0100
changeset 1
ca08bd8f51b2
permissions
-rw-r--r--

Added tag TORBROWSER_REPLICA for changeset 6474c204b198

     1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 /***********************************************************************
     7 **
     8 ** This server simulates a server running in loopback mode.
     9 **
    10 ** The idea is that a single server is created.  The server initially creates
    11 ** a number of worker threads.  Then, with the server running, a number of 
    12 ** clients are created which start requesting service from the server.
    13 **
    14 **
    15 ** Modification History:
    16 ** 19-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
    17 **	         The debug mode will print all of the printfs associated with this test.
    18 **			 The regress mode will be the default mode. Since the regress tool limits
    19 **           the output to a one line status:PASS or FAIL,all of the printf statements
    20 **			 have been handled with an if (debug_mode) statement.
    21 ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
    22 **			recognize the return code from tha main program.
    23 ***********************************************************************/
    25 /***********************************************************************
    26 ** Includes
    27 ***********************************************************************/
    28 /* Used to get the command line option */
    29 #include "plgetopt.h"
    31 #include "nspr.h"
    32 #include "pprthred.h"
    34 #include <string.h>
    36 #define PORT 15004
    37 #define THREAD_STACKSIZE 0
    39 static int _iterations = 1000;
    40 static int _clients = 1;
    41 static int _client_data = 250;
    42 static int _server_data = (8*1024);
    44 static PRThreadScope ServerScope, ClientScope;
    46 #define SERVER "Server"
    47 #define MAIN   "Main"
    49 #define SERVER_STATE_STARTUP 0
    50 #define SERVER_STATE_READY   1
    51 #define SERVER_STATE_DYING   2
    52 #define SERVER_STATE_DEAD    4
    53 int       ServerState;
    54 PRLock    *ServerStateCVLock;
    55 PRCondVar *ServerStateCV;
    57 #ifdef DEBUGPRINTS
    58 #define DPRINTF printf
    59 #else
    60 #define DPRINTF
    61 #endif
    63 PRIntn failed_already=0;
    64 PRIntn debug_mode;
    66 static void do_work(void);
    68 /* --- Server state functions --------------------------------------------- */
    69 void
    70 SetServerState(char *waiter, PRInt32 state)
    71 {
    72     PR_Lock(ServerStateCVLock);
    73     ServerState = state;
    74     PR_NotifyCondVar(ServerStateCV);
    76 	if (debug_mode) DPRINTF("\t%s changed state to %d\n", waiter, state);
    78     PR_Unlock(ServerStateCVLock);
    79 }
    81 int
    82 WaitServerState(char *waiter, PRInt32 state)
    83 {
    84     PRInt32 rv;
    86     PR_Lock(ServerStateCVLock);
    88     if (debug_mode) DPRINTF("\t%s waiting for state %d\n", waiter, state);
    90     while(!(ServerState & state))
    91         PR_WaitCondVar(ServerStateCV, PR_INTERVAL_NO_TIMEOUT);
    92     rv = ServerState;
    94     if (debug_mode) DPRINTF("\t%s resuming from wait for state %d; state now %d\n", 
    95         waiter, state, ServerState);
    96     PR_Unlock(ServerStateCVLock);
    98     return rv;
    99 }
   101 /* --- Server Functions ------------------------------------------- */
   103 PRLock *workerThreadsLock;
   104 PRInt32 workerThreads;
   105 PRInt32 workerThreadsBusy;
   107 void
   108 WorkerThreadFunc(void *_listenSock)
   109 {
   110     PRFileDesc *listenSock = (PRFileDesc *)_listenSock;
   111     PRInt32 bytesRead;
   112     PRInt32 bytesWritten;
   113     char *dataBuf;
   114     char *sendBuf;
   116     if (debug_mode) DPRINTF("\tServer buffer is %d bytes; %d data, %d netaddrs\n",
   117             _client_data+(2*sizeof(PRNetAddr))+32, _client_data, (2*sizeof(PRNetAddr))+32);
   118     dataBuf = (char *)PR_MALLOC(_client_data + 2*sizeof(PRNetAddr) + 32);
   119     if (!dataBuf)
   120         if (debug_mode) printf("\tServer could not malloc space!?\n");
   121     sendBuf = (char *)PR_MALLOC(_server_data *sizeof(char));
   122     if (!sendBuf)
   123         if (debug_mode) printf("\tServer could not malloc space!?\n");
   125     if (debug_mode) DPRINTF("\tServer worker thread running\n");
   127     while(1) {
   128         PRInt32 bytesToRead = _client_data;
   129         PRInt32 bytesToWrite = _server_data;
   130         PRFileDesc *newSock;
   131         PRNetAddr *rAddr;
   132         PRInt32 loops = 0;
   134         loops++;
   136         if (debug_mode) DPRINTF("\tServer thread going into accept\n");
   138         bytesRead = PR_AcceptRead(listenSock, 
   139                                   &newSock,
   140                                   &rAddr,
   141                                   dataBuf,
   142                                   bytesToRead,
   143                                   PR_INTERVAL_NO_TIMEOUT);
   145         if (bytesRead < 0) {
   146             if (debug_mode) printf("\tServer error in accept (%d)\n", bytesRead);
   147             continue;
   148         }
   150         if (debug_mode) DPRINTF("\tServer accepted connection (%d bytes)\n", bytesRead);
   152         PR_AtomicIncrement(&workerThreadsBusy);
   153 #ifdef SYMBIAN
   154         if (workerThreadsBusy == workerThreads && workerThreads<1) {
   155 #else
   156         if (workerThreadsBusy == workerThreads) {
   157 #endif
   159             PR_Lock(workerThreadsLock);
   160             if (workerThreadsBusy == workerThreads) {
   161                 PRThread *WorkerThread;
   163                 WorkerThread = PR_CreateThread(
   164                                   PR_SYSTEM_THREAD,
   165                                   WorkerThreadFunc,
   166                                   listenSock,
   167                                   PR_PRIORITY_NORMAL,
   168                                   ServerScope,
   169                                   PR_UNJOINABLE_THREAD,
   170                                   THREAD_STACKSIZE);
   172                 if (!WorkerThread) {
   173                     if (debug_mode) printf("Error creating client thread %d\n", workerThreads);
   174                 } else {
   175                     PR_AtomicIncrement(&workerThreads);
   176                     if (debug_mode) DPRINTF("\tServer creates worker (%d)\n", workerThreads);
   177                 }
   178             }
   179             PR_Unlock(workerThreadsLock);
   180         }
   182         bytesToRead -= bytesRead;
   183         while (bytesToRead) {
   184             bytesRead = PR_Recv(newSock, 
   185                                 dataBuf, 
   186                                 bytesToRead, 
   187                                 0, 
   188                                 PR_INTERVAL_NO_TIMEOUT);
   189             if (bytesRead < 0) {
   190                 if (debug_mode) printf("\tServer error receiving data (%d)\n", bytesRead);
   191                 continue;
   192             }
   193             if (debug_mode) DPRINTF("\tServer received %d bytes\n", bytesRead);
   194         }
   196         bytesWritten = PR_Send(newSock,
   197                                sendBuf, 
   198                                bytesToWrite, 
   199                                0, 
   200                                PR_INTERVAL_NO_TIMEOUT);
   201         if (bytesWritten != _server_data) {
   202             if (debug_mode) printf("\tError sending data to client (%d, %d)\n", 
   203                 bytesWritten, PR_GetOSError());
   204         } else {
   205             if (debug_mode) DPRINTF("\tServer sent %d bytes\n", bytesWritten);
   206         } 
   208         PR_Close(newSock);
   209         PR_AtomicDecrement(&workerThreadsBusy);
   210     }
   211 }
   213 PRFileDesc *
   214 ServerSetup(void)
   215 {
   216     PRFileDesc *listenSocket;
   217     PRSocketOptionData sockOpt;
   218     PRNetAddr serverAddr;
   219     PRThread *WorkerThread;
   221     if ( (listenSocket = PR_NewTCPSocket()) == NULL) {
   222         if (debug_mode) printf("\tServer error creating listen socket\n");
   223 		else failed_already=1;
   224         return NULL;
   225     }
   227     sockOpt.option = PR_SockOpt_Reuseaddr;
   228     sockOpt.value.reuse_addr = PR_TRUE;
   229     if ( PR_SetSocketOption(listenSocket, &sockOpt) == PR_FAILURE) {
   230         if (debug_mode) printf("\tServer error setting socket option: OS error %d\n",
   231                 PR_GetOSError());
   232 		else failed_already=1;
   233         PR_Close(listenSocket);
   234         return NULL;
   235     }
   237     memset(&serverAddr, 0, sizeof(PRNetAddr));
   238     serverAddr.inet.family = PR_AF_INET;
   239     serverAddr.inet.port = PR_htons(PORT);
   240     serverAddr.inet.ip = PR_htonl(PR_INADDR_ANY);
   242     if ( PR_Bind(listenSocket, &serverAddr) == PR_FAILURE) {
   243         if (debug_mode) printf("\tServer error binding to server address: OS error %d\n",
   244                 PR_GetOSError());
   245 		else failed_already=1;
   246         PR_Close(listenSocket);
   247         return NULL;
   248     }
   250     if ( PR_Listen(listenSocket, 128) == PR_FAILURE) {
   251         if (debug_mode) printf("\tServer error listening to server socket\n");
   252 		else failed_already=1;
   253         PR_Close(listenSocket);
   255         return NULL;
   256     }
   258     /* Create Clients */
   259     workerThreads = 0;
   260     workerThreadsBusy = 0;
   262     workerThreadsLock = PR_NewLock();
   264     WorkerThread = PR_CreateThread(
   265                       PR_SYSTEM_THREAD,
   266                       WorkerThreadFunc,
   267                       listenSocket,
   268                       PR_PRIORITY_NORMAL,
   269                       ServerScope,
   270                       PR_UNJOINABLE_THREAD,
   271                       THREAD_STACKSIZE);
   273     if (!WorkerThread) {
   274         if (debug_mode) printf("error creating working thread\n");
   275         PR_Close(listenSocket);
   276         return NULL;
   277     }
   278     PR_AtomicIncrement(&workerThreads);
   279     if (debug_mode) DPRINTF("\tServer created primordial worker thread\n");
   281     return listenSocket;
   282 }
   284 /* The main server loop */
   285 void
   286 ServerThreadFunc(void *unused)
   287 {
   288     PRFileDesc *listenSocket;
   290     /* Do setup */
   291     listenSocket = ServerSetup();
   293     if (!listenSocket) {
   294         SetServerState(SERVER, SERVER_STATE_DEAD);
   295     } else {
   297         if (debug_mode) DPRINTF("\tServer up\n");
   299         /* Tell clients they can start now. */
   300         SetServerState(SERVER, SERVER_STATE_READY);
   302         /* Now wait for server death signal */
   303         WaitServerState(SERVER, SERVER_STATE_DYING);
   305         /* Cleanup */
   306         SetServerState(SERVER, SERVER_STATE_DEAD);
   307     }
   308 }
   310 /* --- Client Functions ------------------------------------------- */
   312 PRInt32 numRequests;
   313 PRInt32 numClients;
   314 PRMonitor *clientMonitor;
   316 void
   317 ClientThreadFunc(void *unused)
   318 {
   319     PRNetAddr serverAddr;
   320     PRFileDesc *clientSocket;
   321     char *sendBuf;
   322     char *recvBuf;
   323     PRInt32 rv;
   324     PRInt32 bytesNeeded;
   326     sendBuf = (char *)PR_MALLOC(_client_data * sizeof(char));
   327     if (!sendBuf)
   328         if (debug_mode) printf("\tClient could not malloc space!?\n");
   329     recvBuf = (char *)PR_MALLOC(_server_data * sizeof(char));
   330     if (!recvBuf)
   331         if (debug_mode) printf("\tClient could not malloc space!?\n");
   333     memset(&serverAddr, 0, sizeof(PRNetAddr));
   334     serverAddr.inet.family = PR_AF_INET;
   335     serverAddr.inet.port = PR_htons(PORT);
   336     serverAddr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);
   338     while(numRequests > 0) {
   340         if ( (numRequests % 10) == 0 )
   341             if (debug_mode) printf(".");
   342         if (debug_mode) DPRINTF("\tClient starting request %d\n", numRequests);
   344         clientSocket = PR_NewTCPSocket();
   345         if (!clientSocket) {
   346             if (debug_mode) printf("Client error creating socket: OS error %d\n",
   347 		    PR_GetOSError());
   348             continue;
   349         }
   351         if (debug_mode) DPRINTF("\tClient connecting\n");
   353         rv = PR_Connect(clientSocket, 
   354                         &serverAddr,
   355                         PR_INTERVAL_NO_TIMEOUT);
   356         if (!clientSocket) {
   357             if (debug_mode) printf("\tClient error connecting\n");
   358             continue;
   359         }
   361         if (debug_mode) DPRINTF("\tClient connected\n");
   363         rv = PR_Send(clientSocket, 
   364                      sendBuf, 
   365                      _client_data, 
   366                      0, 
   367                      PR_INTERVAL_NO_TIMEOUT);
   368         if (rv != _client_data) {
   369             if (debug_mode) printf("Client error sending data (%d)\n", rv);
   370             PR_Close(clientSocket);
   371             continue;
   372         }
   374         if (debug_mode) DPRINTF("\tClient sent %d bytes\n", rv);
   376         bytesNeeded = _server_data;
   377         while(bytesNeeded) {
   378             rv = PR_Recv(clientSocket, 
   379                          recvBuf, 
   380                          bytesNeeded, 
   381                          0, 
   382                          PR_INTERVAL_NO_TIMEOUT);
   383             if (rv <= 0) {
   384                 if (debug_mode) printf("Client error receiving data (%d) (%d/%d)\n", 
   385                     rv, (_server_data - bytesNeeded), _server_data);
   386                 break;
   387             }
   388             if (debug_mode) DPRINTF("\tClient received %d bytes; need %d more\n", rv, bytesNeeded - rv);
   389             bytesNeeded -= rv;
   390         }
   392         PR_Close(clientSocket);
   394         PR_AtomicDecrement(&numRequests);
   395     }
   397     PR_EnterMonitor(clientMonitor);
   398     --numClients;
   399     PR_Notify(clientMonitor);
   400     PR_ExitMonitor(clientMonitor);
   402     PR_DELETE(sendBuf);
   403     PR_DELETE(recvBuf);
   404 }
   406 void
   407 RunClients(void)
   408 {
   409     PRInt32 index;
   411     numRequests = _iterations;
   412     numClients = _clients;
   413     clientMonitor = PR_NewMonitor();
   415     for (index=0; index<_clients; index++) {
   416         PRThread *clientThread;
   419         clientThread = PR_CreateThread(
   420                           PR_USER_THREAD,
   421                           ClientThreadFunc,
   422                           NULL,
   423                           PR_PRIORITY_NORMAL,
   424                           ClientScope,
   425                           PR_UNJOINABLE_THREAD,
   426                           THREAD_STACKSIZE);
   428         if (!clientThread) {
   429             if (debug_mode) printf("\terror creating client thread %d\n", index);
   430         } else
   431             if (debug_mode) DPRINTF("\tMain created client %d/%d\n", index+1, _clients);
   433     }
   435     PR_EnterMonitor(clientMonitor);
   436     while(numClients)
   437         PR_Wait(clientMonitor, PR_INTERVAL_NO_TIMEOUT);
   438     PR_ExitMonitor(clientMonitor);
   439 }
   441 /* --- Main Function ---------------------------------------------- */
   443 static
   444 void do_work()
   445 {
   446     PRThread *ServerThread;
   447     PRInt32 state;
   449     SetServerState(MAIN, SERVER_STATE_STARTUP);
   450     ServerThread = PR_CreateThread(
   451                       PR_USER_THREAD,
   452                       ServerThreadFunc,
   453                       NULL,
   454                       PR_PRIORITY_NORMAL,
   455                       ServerScope,
   456                       PR_JOINABLE_THREAD,
   457                       THREAD_STACKSIZE);
   458     if (!ServerThread) {
   459         if (debug_mode) printf("error creating main server thread\n");
   460         return;
   461     }
   463     /* Wait for server to be ready */
   464     state = WaitServerState(MAIN, SERVER_STATE_READY|SERVER_STATE_DEAD);
   466     if (!(state & SERVER_STATE_DEAD)) {
   467         /* Run Test Clients */
   468         RunClients();
   470         /* Send death signal to server */
   471         SetServerState(MAIN, SERVER_STATE_DYING);
   472     }
   474     PR_JoinThread(ServerThread);
   475 }
   477 static void do_workUU(void)
   478 {
   479     ServerScope = PR_LOCAL_THREAD;
   480     ClientScope = PR_LOCAL_THREAD;
   481     do_work();
   482 }
   486 static void Measure(void (*func)(void), const char *msg)
   487 {
   488     PRIntervalTime start, stop;
   489     double d;
   491     start = PR_IntervalNow();
   492     (*func)();
   493     stop = PR_IntervalNow();
   495     d = (double)PR_IntervalToMicroseconds(stop - start);
   497     if (debug_mode) printf("\n%40s: %6.2f usec\n", msg, d / _iterations);
   498 }
   501 int main(int argc, char **argv)
   502 {
   503 	/* The command line argument: -d is used to determine if the test is being run
   504 	in debug mode. The regress tool requires only one line output:PASS or FAIL.
   505 	All of the printfs associated with this test has been handled with a if (debug_mode)
   506 	test.
   507 	Usage: test_name -d
   508 	*/
   509 	PLOptStatus os;
   510 	PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
   511 	while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
   512     {
   513 		if (PL_OPT_BAD == os) continue;
   514         switch (opt->option)
   515         {
   516         case 'd':  /* debug mode */
   517 			debug_mode = 1;
   518             break;
   519          default:
   520             break;
   521         }
   522     }
   523 	PL_DestroyOptState(opt);
   525  /* main test */
   526 #ifndef SYMBIAN
   527     if (debug_mode) {
   528 		printf("Enter number of iterations: \n");
   529 		scanf("%d", &_iterations);
   530 		printf("Enter number of clients   : \n");
   531 		scanf("%d", &_clients);
   532 		printf("Enter size of client data : \n");
   533 		scanf("%d", &_client_data);
   534 		printf("Enter size of server data : \n");
   535 		scanf("%d", &_server_data);
   536 	}
   537 	else 
   538 #endif
   539 	{
   540 		_iterations = 7;
   541 		_clients = 7;
   542 		_client_data = 100;
   543 		_server_data = 100;
   544 	}
   546     if (debug_mode) {
   547 		printf("\n\n%d iterations with %d client threads.\n", 
   548         _iterations, _clients);
   549 		printf("Sending %d bytes of client data and %d bytes of server data\n", 
   550         _client_data, _server_data);
   551 	}
   552     PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
   553     PR_STDIO_INIT();
   555     PR_SetThreadRecycleMode(64);
   557     ServerStateCVLock = PR_NewLock();
   558     ServerStateCV = PR_NewCondVar(ServerStateCVLock);
   560     Measure(do_workUU, "server loop user/user");
   562     PR_Cleanup();
   564 	if(failed_already)	
   565 		return 1;
   566 	else
   567 		return 0;
   569 }

mercurial