nsprpub/pr/tests/servr_kk.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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;
    65 static void do_work(void);
    67 /* --- Server state functions --------------------------------------------- */
    68 void
    69 SetServerState(char *waiter, PRInt32 state)
    70 {
    71     PR_Lock(ServerStateCVLock);
    72     ServerState = state;
    73     PR_NotifyCondVar(ServerStateCV);
    75 	if (debug_mode) DPRINTF("\t%s changed state to %d\n", waiter, state);
    77     PR_Unlock(ServerStateCVLock);
    78 }
    80 int
    81 WaitServerState(char *waiter, PRInt32 state)
    82 {
    83     PRInt32 rv;
    85     PR_Lock(ServerStateCVLock);
    87     if (debug_mode) DPRINTF("\t%s waiting for state %d\n", waiter, state);
    89     while(!(ServerState & state))
    90         PR_WaitCondVar(ServerStateCV, PR_INTERVAL_NO_TIMEOUT);
    91     rv = ServerState;
    93     if (debug_mode) DPRINTF("\t%s resuming from wait for state %d; state now %d\n", 
    94         waiter, state, ServerState);
    95     PR_Unlock(ServerStateCVLock);
    97     return rv;
    98 }
   100 /* --- Server Functions ------------------------------------------- */
   102 PRLock *workerThreadsLock;
   103 PRInt32 workerThreads;
   104 PRInt32 workerThreadsBusy;
   106 void
   107 WorkerThreadFunc(void *_listenSock)
   108 {
   109     PRFileDesc *listenSock = (PRFileDesc *)_listenSock;
   110     PRInt32 bytesRead;
   111     PRInt32 bytesWritten;
   112     char *dataBuf;
   113     char *sendBuf;
   115     if (debug_mode) DPRINTF("\tServer buffer is %d bytes; %d data, %d netaddrs\n",
   116             _client_data+(2*sizeof(PRNetAddr))+32, _client_data, (2*sizeof(PRNetAddr))+32);
   117     dataBuf = (char *)PR_MALLOC(_client_data + 2*sizeof(PRNetAddr) + 32);
   118     if (!dataBuf)
   119         if (debug_mode) printf("\tServer could not malloc space!?\n");
   120     sendBuf = (char *)PR_MALLOC(_server_data *sizeof(char));
   121     if (!sendBuf)
   122         if (debug_mode) printf("\tServer could not malloc space!?\n");
   124     if (debug_mode) DPRINTF("\tServer worker thread running\n");
   126     while(1) {
   127         PRInt32 bytesToRead = _client_data;
   128         PRInt32 bytesToWrite = _server_data;
   129         PRFileDesc *newSock;
   130         PRNetAddr *rAddr;
   131         PRInt32 loops = 0;
   133         loops++;
   135         if (debug_mode) DPRINTF("\tServer thread going into accept\n");
   137         bytesRead = PR_AcceptRead(listenSock, 
   138                                   &newSock,
   139                                   &rAddr,
   140                                   dataBuf,
   141                                   bytesToRead,
   142                                   PR_INTERVAL_NO_TIMEOUT);
   144         if (bytesRead < 0) {
   145             if (debug_mode) printf("\tServer error in accept (%d)\n", bytesRead);
   146             continue;
   147         }
   149         if (debug_mode) DPRINTF("\tServer accepted connection (%d bytes)\n", bytesRead);
   151         PR_AtomicIncrement(&workerThreadsBusy);
   152 #ifdef SYMBIAN
   153         if (workerThreadsBusy == workerThreads && workerThreads<1) {
   154 #else
   155         if (workerThreadsBusy == workerThreads) {
   156 #endif
   157             PR_Lock(workerThreadsLock);
   158             if (workerThreadsBusy == workerThreads) {
   159                 PRThread *WorkerThread;
   161                 WorkerThread = PR_CreateThread(
   162                                   PR_SYSTEM_THREAD,
   163                                   WorkerThreadFunc,
   164                                   listenSock,
   165                                   PR_PRIORITY_NORMAL,
   166                                   ServerScope,
   167                                   PR_UNJOINABLE_THREAD,
   168                                   THREAD_STACKSIZE);
   170                 if (!WorkerThread) {
   171                     if (debug_mode) printf("Error creating client thread %d\n", workerThreads);
   172                 } else {
   173                     PR_AtomicIncrement(&workerThreads);
   174                     if (debug_mode) DPRINTF("\tServer creates worker (%d)\n", workerThreads);
   175                 }
   176             }
   177             PR_Unlock(workerThreadsLock);
   178         }
   180         bytesToRead -= bytesRead;
   181         while (bytesToRead) {
   182             bytesRead = PR_Recv(newSock, 
   183                                 dataBuf, 
   184                                 bytesToRead, 
   185                                 0, 
   186                                 PR_INTERVAL_NO_TIMEOUT);
   187             if (bytesRead < 0) {
   188                 if (debug_mode) printf("\tServer error receiving data (%d)\n", bytesRead);
   189                 continue;
   190             }
   191             if (debug_mode) DPRINTF("\tServer received %d bytes\n", bytesRead);
   192         }
   194         bytesWritten = PR_Send(newSock,
   195                                sendBuf, 
   196                                bytesToWrite, 
   197                                0, 
   198                                PR_INTERVAL_NO_TIMEOUT);
   199         if (bytesWritten != _server_data) {
   200             if (debug_mode) printf("\tError sending data to client (%d, %d)\n", 
   201                 bytesWritten, PR_GetOSError());
   202         } else {
   203             if (debug_mode) DPRINTF("\tServer sent %d bytes\n", bytesWritten);
   204         }
   206         PR_Close(newSock);
   207         PR_AtomicDecrement(&workerThreadsBusy);
   208     }
   209 }
   211 PRFileDesc *
   212 ServerSetup(void)
   213 {
   214     PRFileDesc *listenSocket;
   215     PRSocketOptionData sockOpt;
   216     PRNetAddr serverAddr;
   217     PRThread *WorkerThread;
   219     if ( (listenSocket = PR_NewTCPSocket()) == NULL) {
   220         if (debug_mode) printf("\tServer error creating listen socket\n");
   221 		else failed_already=1;
   222         return NULL;
   223     }
   225     sockOpt.option = PR_SockOpt_Reuseaddr;
   226     sockOpt.value.reuse_addr = PR_TRUE;
   227     if ( PR_SetSocketOption(listenSocket, &sockOpt) == PR_FAILURE) {
   228         if (debug_mode) printf("\tServer error setting socket option: OS error %d\n",
   229                 PR_GetOSError());
   230 		else failed_already=1;
   231         PR_Close(listenSocket);
   232         return NULL;
   233     }
   235     memset(&serverAddr, 0, sizeof(PRNetAddr));
   236     serverAddr.inet.family = PR_AF_INET;
   237     serverAddr.inet.port = PR_htons(PORT);
   238     serverAddr.inet.ip = PR_htonl(PR_INADDR_ANY);
   240     if ( PR_Bind(listenSocket, &serverAddr) == PR_FAILURE) {
   241         if (debug_mode) printf("\tServer error binding to server address: OS error %d\n",
   242                 PR_GetOSError());
   243 		else failed_already=1;
   244         PR_Close(listenSocket);
   245         return NULL;
   246     }
   248     if ( PR_Listen(listenSocket, 128) == PR_FAILURE) {
   249         if (debug_mode) printf("\tServer error listening to server socket\n");
   250 		else failed_already=1;
   251         PR_Close(listenSocket);
   253         return NULL;
   254     }
   256     /* Create Clients */
   257     workerThreads = 0;
   258     workerThreadsBusy = 0;
   260     workerThreadsLock = PR_NewLock();
   262     WorkerThread = PR_CreateThread(
   263                       PR_SYSTEM_THREAD,
   264                       WorkerThreadFunc,
   265                       listenSocket,
   266                       PR_PRIORITY_NORMAL,
   267                       ServerScope,
   268                       PR_UNJOINABLE_THREAD,
   269                       THREAD_STACKSIZE);
   271     if (!WorkerThread) {
   272         if (debug_mode) printf("error creating working thread\n");
   273         PR_Close(listenSocket);
   274         return NULL;
   275     }
   276     PR_AtomicIncrement(&workerThreads);
   277     if (debug_mode) DPRINTF("\tServer created primordial worker thread\n");
   279     return listenSocket;
   280 }
   282 /* The main server loop */
   283 void
   284 ServerThreadFunc(void *unused)
   285 {
   286     PRFileDesc *listenSocket;
   288     /* Do setup */
   289     listenSocket = ServerSetup();
   291     if (!listenSocket) {
   292         SetServerState(SERVER, SERVER_STATE_DEAD);
   293     } else {
   295         if (debug_mode) DPRINTF("\tServer up\n");
   297         /* Tell clients they can start now. */
   298         SetServerState(SERVER, SERVER_STATE_READY);
   300         /* Now wait for server death signal */
   301         WaitServerState(SERVER, SERVER_STATE_DYING);
   303         /* Cleanup */
   304         SetServerState(SERVER, SERVER_STATE_DEAD);
   305     }
   306 }
   308 /* --- Client Functions ------------------------------------------- */
   310 PRInt32 numRequests;
   311 PRInt32 numClients;
   312 PRMonitor *clientMonitor;
   314 void
   315 ClientThreadFunc(void *unused)
   316 {
   317     PRNetAddr serverAddr;
   318     PRFileDesc *clientSocket;
   319     char *sendBuf;
   320     char *recvBuf;
   321     PRInt32 rv;
   322     PRInt32 bytesNeeded;
   324     sendBuf = (char *)PR_MALLOC(_client_data * sizeof(char));
   325     if (!sendBuf)
   326         if (debug_mode) printf("\tClient could not malloc space!?\n");
   327     recvBuf = (char *)PR_MALLOC(_server_data * sizeof(char));
   328     if (!recvBuf)
   329         if (debug_mode) printf("\tClient could not malloc space!?\n");
   331     memset(&serverAddr, 0, sizeof(PRNetAddr));
   332     serverAddr.inet.family = PR_AF_INET;
   333     serverAddr.inet.port = PR_htons(PORT);
   334     serverAddr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);
   336     while(numRequests > 0) {
   338         if ( (numRequests % 10) == 0 )
   339             if (debug_mode) printf(".");
   340         if (debug_mode) DPRINTF("\tClient starting request %d\n", numRequests);
   342         clientSocket = PR_NewTCPSocket();
   343         if (!clientSocket) {
   344             if (debug_mode) printf("Client error creating socket: OS error %d\n",
   345 		    PR_GetOSError());
   346             continue;
   347         }
   349         if (debug_mode) DPRINTF("\tClient connecting\n");
   351         rv = PR_Connect(clientSocket, 
   352                         &serverAddr,
   353                         PR_INTERVAL_NO_TIMEOUT);
   354         if (!clientSocket) {
   355             if (debug_mode) printf("\tClient error connecting\n");
   356             continue;
   357         }
   359         if (debug_mode) DPRINTF("\tClient connected\n");
   361         rv = PR_Send(clientSocket, 
   362                      sendBuf, 
   363                      _client_data, 
   364                      0, 
   365                      PR_INTERVAL_NO_TIMEOUT);
   366         if (rv != _client_data) {
   367             if (debug_mode) printf("Client error sending data (%d)\n", rv);
   368             PR_Close(clientSocket);
   369             continue;
   370         }
   372         if (debug_mode) DPRINTF("\tClient sent %d bytes\n", rv);
   374         bytesNeeded = _server_data;
   375         while(bytesNeeded) {
   376             rv = PR_Recv(clientSocket, 
   377                          recvBuf, 
   378                          bytesNeeded, 
   379                          0, 
   380                          PR_INTERVAL_NO_TIMEOUT);
   381             if (rv <= 0) {
   382                 if (debug_mode) printf("Client error receiving data (%d) (%d/%d)\n", 
   383                     rv, (_server_data - bytesNeeded), _server_data);
   384                 break;
   385             }
   386             if (debug_mode) DPRINTF("\tClient received %d bytes; need %d more\n", rv, bytesNeeded - rv);
   387             bytesNeeded -= rv;
   388         }
   390         PR_Close(clientSocket);
   392         PR_AtomicDecrement(&numRequests);
   393     }
   395     PR_EnterMonitor(clientMonitor);
   396     --numClients;
   397     PR_Notify(clientMonitor);
   398     PR_ExitMonitor(clientMonitor);
   400     PR_DELETE(sendBuf);
   401     PR_DELETE(recvBuf);
   402 }
   404 void
   405 RunClients(void)
   406 {
   407     PRInt32 index;
   409     numRequests = _iterations;
   410     numClients = _clients;
   411     clientMonitor = PR_NewMonitor();
   413     for (index=0; index<_clients; index++) {
   414         PRThread *clientThread;
   417         clientThread = PR_CreateThread(
   418                           PR_USER_THREAD,
   419                           ClientThreadFunc,
   420                           NULL,
   421                           PR_PRIORITY_NORMAL,
   422                           ClientScope,
   423                           PR_UNJOINABLE_THREAD,
   424                           THREAD_STACKSIZE);
   426         if (!clientThread) {
   427             if (debug_mode) printf("\terror creating client thread %d\n", index);
   428         } else
   429             if (debug_mode) DPRINTF("\tMain created client %d/%d\n", index+1, _clients);
   431     }
   433     PR_EnterMonitor(clientMonitor);
   434     while(numClients)
   435         PR_Wait(clientMonitor, PR_INTERVAL_NO_TIMEOUT);
   436     PR_ExitMonitor(clientMonitor);
   437 }
   439 /* --- Main Function ---------------------------------------------- */
   441 static
   442 void do_work()
   443 {
   444     PRThread *ServerThread;
   445     PRInt32 state;
   447     SetServerState(MAIN, SERVER_STATE_STARTUP);
   448     ServerThread = PR_CreateThread(
   449                       PR_USER_THREAD,
   450                       ServerThreadFunc,
   451                       NULL,
   452                       PR_PRIORITY_NORMAL,
   453                       ServerScope,
   454                       PR_JOINABLE_THREAD,
   455                       THREAD_STACKSIZE);
   456     if (!ServerThread) {
   457         if (debug_mode) printf("error creating main server thread\n");
   458         return;
   459     }
   461     /* Wait for server to be ready */
   462     state = WaitServerState(MAIN, SERVER_STATE_READY|SERVER_STATE_DEAD);
   464     if (!(state & SERVER_STATE_DEAD)) {
   465         /* Run Test Clients */
   466         RunClients();
   468         /* Send death signal to server */
   469         SetServerState(MAIN, SERVER_STATE_DYING);
   470     }
   472     PR_JoinThread(ServerThread);
   473 }
   475 static void do_workUU(void)
   476 {
   477     ServerScope = PR_LOCAL_THREAD;
   478     ClientScope = PR_LOCAL_THREAD;
   479     do_work();
   480 }
   482 static void do_workUK(void)
   483 {
   484     ServerScope = PR_LOCAL_THREAD;
   485     ClientScope = PR_GLOBAL_THREAD;
   486     do_work();
   487 }
   489 static void do_workKU(void)
   490 {
   491     ServerScope = PR_GLOBAL_THREAD;
   492     ClientScope = PR_LOCAL_THREAD;
   493     do_work();
   494 }
   496 static void do_workKK(void)
   497 {
   498     ServerScope = PR_GLOBAL_THREAD;
   499     ClientScope = PR_GLOBAL_THREAD;
   500     do_work();
   501 }
   504 static void Measure(void (*func)(void), const char *msg)
   505 {
   506     PRIntervalTime start, stop;
   507     double d;
   509     start = PR_IntervalNow();
   510     (*func)();
   511     stop = PR_IntervalNow();
   513     d = (double)PR_IntervalToMicroseconds(stop - start);
   515     if (debug_mode) printf("\n%40s: %6.2f usec\n", msg, d / _iterations);
   516 }
   519 int main(int argc, char **argv)
   520 {
   521 	/* The command line argument: -d is used to determine if the test is being run
   522 	in debug mode. The regress tool requires only one line output:PASS or FAIL.
   523 	All of the printfs associated with this test has been handled with a if (debug_mode)
   524 	test.
   525 	Usage: test_name -d
   526 	*/
   527 	PLOptStatus os;
   528 	PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
   529 	while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
   530     {
   531 		if (PL_OPT_BAD == os) continue;
   532         switch (opt->option)
   533         {
   534         case 'd':  /* debug mode */
   535 			debug_mode = 1;
   536             break;
   537          default:
   538             break;
   539         }
   540     }
   541 	PL_DestroyOptState(opt);
   543  /* main test */
   544 #ifndef SYMBIAN
   545     if (debug_mode) {
   546 		printf("Enter number of iterations: \n");
   547 		scanf("%d", &_iterations);
   548 		printf("Enter number of clients   : \n");
   549 		scanf("%d", &_clients);
   550 		printf("Enter size of client data : \n");
   551 		scanf("%d", &_client_data);
   552 		printf("Enter size of server data : \n");
   553 		scanf("%d", &_server_data);
   554 	}
   555 	else 
   556 #endif
   557 	{
   558 		_iterations = 7;
   559 		_clients = 7;
   560 		_client_data = 100;
   561 		_server_data = 100;
   562 	}
   564     if (debug_mode) {
   565 		printf("\n\n%d iterations with %d client threads.\n", 
   566         _iterations, _clients);
   567 		printf("Sending %d bytes of client data and %d bytes of server data\n", 
   568         _client_data, _server_data);
   569 	}
   570     PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
   571     PR_STDIO_INIT();
   573     PR_SetThreadRecycleMode(64);
   575     ServerStateCVLock = PR_NewLock();
   576     ServerStateCV = PR_NewCondVar(ServerStateCVLock);
   579     Measure(do_workKK, "server loop kernel/kernel");
   581 	PR_Cleanup();
   583 	if(failed_already)	
   584 		return 1;
   585 	else
   586 		return 0;
   588 }

mercurial