nsprpub/pr/tests/servr_uk.c

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

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

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

     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;
    68 static void do_work(void);
    70 /* --- Server state functions --------------------------------------------- */
    71 void
    72 SetServerState(char *waiter, PRInt32 state)
    73 {
    74     PR_Lock(ServerStateCVLock);
    75     ServerState = state;
    76     PR_NotifyCondVar(ServerStateCV);
    78 	if (debug_mode) DPRINTF("\t%s changed state to %d\n", waiter, state);
    80     PR_Unlock(ServerStateCVLock);
    81 }
    83 int
    84 WaitServerState(char *waiter, PRInt32 state)
    85 {
    86     PRInt32 rv;
    88     PR_Lock(ServerStateCVLock);
    90     if (debug_mode) DPRINTF("\t%s waiting for state %d\n", waiter, state);
    92     while(!(ServerState & state))
    93         PR_WaitCondVar(ServerStateCV, PR_INTERVAL_NO_TIMEOUT);
    94     rv = ServerState;
    96     if (debug_mode) DPRINTF("\t%s resuming from wait for state %d; state now %d\n", 
    97         waiter, state, ServerState);
    98     PR_Unlock(ServerStateCVLock);
   100     return rv;
   101 }
   103 /* --- Server Functions ------------------------------------------- */
   105 PRLock *workerThreadsLock;
   106 PRInt32 workerThreads;
   107 PRInt32 workerThreadsBusy;
   109 void
   110 WorkerThreadFunc(void *_listenSock)
   111 {
   112     PRFileDesc *listenSock = (PRFileDesc *)_listenSock;
   113     PRInt32 bytesRead;
   114     PRInt32 bytesWritten;
   115     char *dataBuf;
   116     char *sendBuf;
   118     if (debug_mode) DPRINTF("\tServer buffer is %d bytes; %d data, %d netaddrs\n",
   119             _client_data+(2*sizeof(PRNetAddr))+32, _client_data, (2*sizeof(PRNetAddr))+32);
   120     dataBuf = (char *)PR_MALLOC(_client_data + 2*sizeof(PRNetAddr) + 32);
   121     if (!dataBuf)
   122         if (debug_mode) printf("\tServer could not malloc space!?\n");
   123     sendBuf = (char *)PR_MALLOC(_server_data *sizeof(char));
   124     if (!sendBuf)
   125         if (debug_mode) printf("\tServer could not malloc space!?\n");
   127     if (debug_mode) DPRINTF("\tServer worker thread running\n");
   129     while(1) {
   130         PRInt32 bytesToRead = _client_data;
   131         PRInt32 bytesToWrite = _server_data;
   132         PRFileDesc *newSock;
   133         PRNetAddr *rAddr;
   134         PRInt32 loops = 0;
   136         loops++;
   138         if (debug_mode) DPRINTF("\tServer thread going into accept\n");
   140         bytesRead = PR_AcceptRead(listenSock, 
   141                                   &newSock,
   142                                   &rAddr,
   143                                   dataBuf,
   144                                   bytesToRead,
   145                                   PR_INTERVAL_NO_TIMEOUT);
   147         if (bytesRead < 0) {
   148             if (debug_mode) printf("\tServer error in accept (%d)\n", bytesRead);
   149             continue;
   150         }
   152         if (debug_mode) DPRINTF("\tServer accepted connection (%d bytes)\n", bytesRead);
   154         PR_AtomicIncrement(&workerThreadsBusy);
   155 #ifdef SYMBIAN
   156         if (workerThreadsBusy == workerThreads && workerThreads<1) {
   157 #else
   158         if (workerThreadsBusy == workerThreads) {
   159 #endif
   160             PR_Lock(workerThreadsLock);
   161             if (workerThreadsBusy == workerThreads) {
   162                 PRThread *WorkerThread;
   164                 WorkerThread = PR_CreateThread(
   165                                   PR_SYSTEM_THREAD,
   166                                   WorkerThreadFunc,
   167                                   listenSock,
   168                                   PR_PRIORITY_NORMAL,
   169                                   ServerScope,
   170                                   PR_UNJOINABLE_THREAD,
   171                                   THREAD_STACKSIZE);
   173                 if (!WorkerThread) {
   174                     if (debug_mode) printf("Error creating client thread %d\n", workerThreads);
   175                 } else {
   176                     PR_AtomicIncrement(&workerThreads);
   177                     if (debug_mode) DPRINTF("\tServer creates worker (%d)\n", workerThreads);
   178                 }
   179             }
   180             PR_Unlock(workerThreadsLock);
   181         }
   183         bytesToRead -= bytesRead;
   184         while (bytesToRead) {
   185             bytesRead = PR_Recv(newSock, 
   186                                 dataBuf, 
   187                                 bytesToRead, 
   188                                 0, 
   189                                 PR_INTERVAL_NO_TIMEOUT);
   190             if (bytesRead < 0) {
   191                 if (debug_mode) printf("\tServer error receiving data (%d)\n", bytesRead);
   192                 continue;
   193             }
   194             if (debug_mode) DPRINTF("\tServer received %d bytes\n", bytesRead);
   195         }
   197         bytesWritten = PR_Send(newSock,
   198                                sendBuf, 
   199                                bytesToWrite, 
   200                                0, 
   201                                PR_INTERVAL_NO_TIMEOUT);
   202         if (bytesWritten != _server_data) {
   203             if (debug_mode) printf("\tError sending data to client (%d, %d)\n", 
   204                 bytesWritten, PR_GetOSError());
   205         } else {
   206             if (debug_mode) DPRINTF("\tServer sent %d bytes\n", bytesWritten);
   207         }
   209         PR_Close(newSock);
   210         PR_AtomicDecrement(&workerThreadsBusy);
   211     }
   212 }
   214 PRFileDesc *
   215 ServerSetup(void)
   216 {
   217     PRFileDesc *listenSocket;
   218     PRSocketOptionData sockOpt;
   219     PRNetAddr serverAddr;
   220     PRThread *WorkerThread;
   222     if ( (listenSocket = PR_NewTCPSocket()) == NULL) {
   223         if (debug_mode) printf("\tServer error creating listen socket\n");
   224 		else 
   225         return NULL;
   226     }
   228     sockOpt.option = PR_SockOpt_Reuseaddr;
   229     sockOpt.value.reuse_addr = PR_TRUE;
   230     if ( PR_SetSocketOption(listenSocket, &sockOpt) == PR_FAILURE) {
   231         if (debug_mode) printf("\tServer error setting socket option: OS error %d\n",
   232                 PR_GetOSError());
   233 		else failed_already=1;
   234         PR_Close(listenSocket);
   235         return NULL;
   236     }
   238     memset(&serverAddr, 0, sizeof(PRNetAddr));
   239     serverAddr.inet.family = PR_AF_INET;
   240     serverAddr.inet.port = PR_htons(PORT);
   241     serverAddr.inet.ip = PR_htonl(PR_INADDR_ANY);
   243     if ( PR_Bind(listenSocket, &serverAddr) == PR_FAILURE) {
   244         if (debug_mode) printf("\tServer error binding to server address: OS error %d\n",
   245                 PR_GetOSError());
   246 		else failed_already=1;
   247         PR_Close(listenSocket);
   248         return NULL;
   249     }
   251     if ( PR_Listen(listenSocket, 128) == PR_FAILURE) {
   252         if (debug_mode) printf("\tServer error listening to server socket\n");
   253 		else failed_already=1;
   254         PR_Close(listenSocket);
   256         return NULL;
   257     }
   259     /* Create Clients */
   260     workerThreads = 0;
   261     workerThreadsBusy = 0;
   263     workerThreadsLock = PR_NewLock();
   265     WorkerThread = PR_CreateThread(
   266                       PR_SYSTEM_THREAD,
   267                       WorkerThreadFunc,
   268                       listenSocket,
   269                       PR_PRIORITY_NORMAL,
   270                       ServerScope,
   271                       PR_UNJOINABLE_THREAD,
   272                       THREAD_STACKSIZE);
   274     if (!WorkerThread) {
   275         if (debug_mode) printf("error creating working thread\n");
   276         PR_Close(listenSocket);
   277         return NULL;
   278     }
   279     PR_AtomicIncrement(&workerThreads);
   280     if (debug_mode) DPRINTF("\tServer created primordial worker thread\n");
   282     return listenSocket;
   283 }
   285 /* The main server loop */
   286 void
   287 ServerThreadFunc(void *unused)
   288 {
   289     PRFileDesc *listenSocket;
   291     /* Do setup */
   292     listenSocket = ServerSetup();
   294     if (!listenSocket) {
   295         SetServerState(SERVER, SERVER_STATE_DEAD);
   296     } else {
   298         if (debug_mode) DPRINTF("\tServer up\n");
   300         /* Tell clients they can start now. */
   301         SetServerState(SERVER, SERVER_STATE_READY);
   303         /* Now wait for server death signal */
   304         WaitServerState(SERVER, SERVER_STATE_DYING);
   306         /* Cleanup */
   307         SetServerState(SERVER, SERVER_STATE_DEAD);
   308     }
   309 }
   311 /* --- Client Functions ------------------------------------------- */
   313 PRInt32 numRequests;
   314 PRInt32 numClients;
   315 PRMonitor *clientMonitor;
   317 void
   318 ClientThreadFunc(void *unused)
   319 {
   320     PRNetAddr serverAddr;
   321     PRFileDesc *clientSocket;
   322     char *sendBuf;
   323     char *recvBuf;
   324     PRInt32 rv;
   325     PRInt32 bytesNeeded;
   327     sendBuf = (char *)PR_MALLOC(_client_data * sizeof(char));
   328     if (!sendBuf)
   329         if (debug_mode) printf("\tClient could not malloc space!?\n");
   330     recvBuf = (char *)PR_MALLOC(_server_data * sizeof(char));
   331     if (!recvBuf)
   332         if (debug_mode) printf("\tClient could not malloc space!?\n");
   334     memset(&serverAddr, 0, sizeof(PRNetAddr));
   335     serverAddr.inet.family = PR_AF_INET;
   336     serverAddr.inet.port = PR_htons(PORT);
   337     serverAddr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);
   339     while(numRequests > 0) {
   341         if ( (numRequests % 10) == 0 )
   342             if (debug_mode) printf(".");
   343         if (debug_mode) DPRINTF("\tClient starting request %d\n", numRequests);
   345         clientSocket = PR_NewTCPSocket();
   346         if (!clientSocket) {
   347             if (debug_mode) printf("Client error creating socket: OS error %d\n",
   348 		    PR_GetOSError());
   349             continue;
   350         }
   352         if (debug_mode) DPRINTF("\tClient connecting\n");
   354         rv = PR_Connect(clientSocket, 
   355                         &serverAddr,
   356                         PR_INTERVAL_NO_TIMEOUT);
   357         if (!clientSocket) {
   358             if (debug_mode) printf("\tClient error connecting\n");
   359             continue;
   360         }
   362         if (debug_mode) DPRINTF("\tClient connected\n");
   364         rv = PR_Send(clientSocket, 
   365                      sendBuf, 
   366                      _client_data, 
   367                      0, 
   368                      PR_INTERVAL_NO_TIMEOUT);
   369         if (rv != _client_data) {
   370             if (debug_mode) printf("Client error sending data (%d)\n", rv);
   371             PR_Close(clientSocket);
   372             continue;
   373         }
   375         if (debug_mode) DPRINTF("\tClient sent %d bytes\n", rv);
   377         bytesNeeded = _server_data;
   378         while(bytesNeeded) {
   379             rv = PR_Recv(clientSocket, 
   380                          recvBuf, 
   381                          bytesNeeded, 
   382                          0, 
   383                          PR_INTERVAL_NO_TIMEOUT);
   384             if (rv <= 0) {
   385                 if (debug_mode) printf("Client error receiving data (%d) (%d/%d)\n", 
   386                     rv, (_server_data - bytesNeeded), _server_data);
   387                 break;
   388             }
   389             if (debug_mode) DPRINTF("\tClient received %d bytes; need %d more\n", rv, bytesNeeded - rv);
   390             bytesNeeded -= rv;
   391         }
   393         PR_Close(clientSocket);
   395         PR_AtomicDecrement(&numRequests);
   396     }
   398     PR_EnterMonitor(clientMonitor);
   399     --numClients;
   400     PR_Notify(clientMonitor);
   401     PR_ExitMonitor(clientMonitor);
   403     PR_DELETE(sendBuf);
   404     PR_DELETE(recvBuf);
   405 }
   407 void
   408 RunClients(void)
   409 {
   410     PRInt32 index;
   412     numRequests = _iterations;
   413     numClients = _clients;
   414     clientMonitor = PR_NewMonitor();
   416     for (index=0; index<_clients; index++) {
   417         PRThread *clientThread;
   420         clientThread = PR_CreateThread(
   421                           PR_USER_THREAD,
   422                           ClientThreadFunc,
   423                           NULL,
   424                           PR_PRIORITY_NORMAL,
   425                           ClientScope,
   426                           PR_UNJOINABLE_THREAD,
   427                           THREAD_STACKSIZE);
   429         if (!clientThread) {
   430             if (debug_mode) printf("\terror creating client thread %d\n", index);
   431         } else
   432             if (debug_mode) DPRINTF("\tMain created client %d/%d\n", index+1, _clients);
   434     }
   436     PR_EnterMonitor(clientMonitor);
   437     while(numClients)
   438         PR_Wait(clientMonitor, PR_INTERVAL_NO_TIMEOUT);
   439     PR_ExitMonitor(clientMonitor);
   440 }
   442 /* --- Main Function ---------------------------------------------- */
   444 static
   445 void do_work()
   446 {
   447     PRThread *ServerThread;
   448     PRInt32 state;
   450     SetServerState(MAIN, SERVER_STATE_STARTUP);
   451     ServerThread = PR_CreateThread(
   452                       PR_USER_THREAD,
   453                       ServerThreadFunc,
   454                       NULL,
   455                       PR_PRIORITY_NORMAL,
   456                       ServerScope,
   457                       PR_JOINABLE_THREAD,
   458                       THREAD_STACKSIZE);
   459     if (!ServerThread) {
   460         if (debug_mode) printf("error creating main server thread\n");
   461         return;
   462     }
   464     /* Wait for server to be ready */
   465     state = WaitServerState(MAIN, SERVER_STATE_READY|SERVER_STATE_DEAD);
   467     if (!(state & SERVER_STATE_DEAD)) {
   468         /* Run Test Clients */
   469         RunClients();
   471         /* Send death signal to server */
   472         SetServerState(MAIN, SERVER_STATE_DYING);
   473     }
   475     PR_JoinThread(ServerThread);
   476 }
   479 static void do_workUK(void)
   480 {
   481     ServerScope = PR_LOCAL_THREAD;
   482     ClientScope = PR_GLOBAL_THREAD;
   483     do_work();
   484 }
   488 static void Measure(void (*func)(void), const char *msg)
   489 {
   490     PRIntervalTime start, stop;
   491     double d;
   493     start = PR_IntervalNow();
   494     (*func)();
   495     stop = PR_IntervalNow();
   497     d = (double)PR_IntervalToMicroseconds(stop - start);
   499     if (debug_mode) printf("\n%40s: %6.2f usec\n", msg, d / _iterations);
   500 }
   503 int main(int argc, char **argv)
   504 {
   505 	/* The command line argument: -d is used to determine if the test is being run
   506 	in debug mode. The regress tool requires only one line output:PASS or FAIL.
   507 	All of the printfs associated with this test has been handled with a if (debug_mode)
   508 	test.
   509 	Usage: test_name -d
   510 	*/
   511 	PLOptStatus os;
   512 	PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
   513 	while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
   514     {
   515 		if (PL_OPT_BAD == os) continue;
   516         switch (opt->option)
   517         {
   518         case 'd':  /* debug mode */
   519 			debug_mode = 1;
   520             break;
   521          default:
   522             break;
   523         }
   524     }
   525 	PL_DestroyOptState(opt);
   527  /* main test */
   528 #ifndef SYMBIAN
   529     if (debug_mode) {
   530 		printf("Enter number of iterations: \n");
   531 		scanf("%d", &_iterations);
   532 		printf("Enter number of clients   : \n");
   533 		scanf("%d", &_clients);
   534 		printf("Enter size of client data : \n");
   535 		scanf("%d", &_client_data);
   536 		printf("Enter size of server data : \n");
   537 		scanf("%d", &_server_data);
   538 	}
   539 	else 
   540 #endif
   541 	{
   542 		_iterations = 7;
   543 		_clients = 7;
   544 		_client_data = 100;
   545 		_server_data = 100;
   546 	}
   548     if (debug_mode) {
   549 		printf("\n\n%d iterations with %d client threads.\n", 
   550         _iterations, _clients);
   551 		printf("Sending %d bytes of client data and %d bytes of server data\n", 
   552         _client_data, _server_data);
   553 	}
   554     PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
   555     PR_STDIO_INIT();
   557     PR_SetThreadRecycleMode(64);
   559     ServerStateCVLock = PR_NewLock();
   560     ServerStateCV = PR_NewCondVar(ServerStateCVLock);
   562     Measure(do_workUK, "server loop user/kernel");
   564     PR_Cleanup();
   566 	if(failed_already)	
   567 		return 1;
   568 	else
   569 		return 0;
   570 }

mercurial