VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/nsprpub/pr/tests/thrpool_client.c@ 1

Last change on this file since 1 was 1, checked in by vboxsync, 55 years ago

import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.1 KB
Line 
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is the Netscape Portable Runtime (NSPR).
16 *
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1999-2000
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 *
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
35 *
36 * ***** END LICENSE BLOCK ***** */
37
38/***********************************************************************
39**
40** Name: thrpool_client.c
41**
42** Description: Test threadpool functionality.
43**
44** Modification History:
45*/
46#include "primpl.h"
47
48#include "plgetopt.h"
49
50#include <stdio.h>
51#include <string.h>
52#include <errno.h>
53#ifdef XP_UNIX
54#include <sys/mman.h>
55#endif
56#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
57#include <pthread.h>
58#endif
59
60#ifdef WIN32
61#include <process.h>
62#endif
63
64static int _debug_on = 0;
65static int server_port = -1;
66static char *program_name = NULL;
67
68#ifdef XP_MAC
69#include "prlog.h"
70#include "prsem.h"
71int fprintf(FILE *stream, const char *fmt, ...)
72{
73 PR_LogPrint(fmt);
74 return 0;
75}
76#define printf PR_LogPrint
77extern void SetupMacPrintfLog(char *logFile);
78#else
79#include "obsolete/prsem.h"
80#endif
81
82#ifdef XP_PC
83#define mode_t int
84#endif
85
86#define DPRINTF(arg) if (_debug_on) printf arg
87
88#define BUF_DATA_SIZE (2 * 1024)
89#define TCP_MESG_SIZE 1024
90#define NUM_TCP_CLIENTS 10 /* for a listen queue depth of 5 */
91
92#define NUM_TCP_CONNECTIONS_PER_CLIENT 10
93#define NUM_TCP_MESGS_PER_CONNECTION 10
94#define TCP_SERVER_PORT 10000
95
96static PRInt32 num_tcp_clients = NUM_TCP_CLIENTS;
97static PRInt32 num_tcp_connections_per_client = NUM_TCP_CONNECTIONS_PER_CLIENT;
98static PRInt32 tcp_mesg_size = TCP_MESG_SIZE;
99static PRInt32 num_tcp_mesgs_per_connection = NUM_TCP_MESGS_PER_CONNECTION;
100
101int failed_already=0;
102
103typedef struct buffer {
104 char data[BUF_DATA_SIZE];
105} buffer;
106
107PRNetAddr tcp_server_addr, udp_server_addr;
108
109typedef struct Client_Param {
110 PRNetAddr server_addr;
111 PRMonitor *exit_mon; /* monitor to signal on exit */
112 PRInt32 *exit_counter; /* counter to decrement, before exit */
113 PRInt32 datalen;
114} Client_Param;
115
116/*
117 * readn
118 * read data from sockfd into buf
119 */
120static PRInt32
121readn(PRFileDesc *sockfd, char *buf, int len)
122{
123 int rem;
124 int bytes;
125 int offset = 0;
126 PRIntervalTime timeout = PR_INTERVAL_NO_TIMEOUT;
127
128 for (rem=len; rem; offset += bytes, rem -= bytes) {
129 DPRINTF(("thread = 0x%lx: calling PR_Recv, bytes = %d\n",
130 PR_GetCurrentThread(), rem));
131 bytes = PR_Recv(sockfd, buf + offset, rem, 0,
132 timeout);
133 DPRINTF(("thread = 0x%lx: returning from PR_Recv, bytes = %d\n",
134 PR_GetCurrentThread(), bytes));
135 if (bytes < 0) {
136 return -1;
137 }
138 }
139 return len;
140}
141
142/*
143 * writen
144 * write data from buf to sockfd
145 */
146static PRInt32
147writen(PRFileDesc *sockfd, char *buf, int len)
148{
149 int rem;
150 int bytes;
151 int offset = 0;
152
153 for (rem=len; rem; offset += bytes, rem -= bytes) {
154 DPRINTF(("thread = 0x%lx: calling PR_Send, bytes = %d\n",
155 PR_GetCurrentThread(), rem));
156 bytes = PR_Send(sockfd, buf + offset, rem, 0,
157 PR_INTERVAL_NO_TIMEOUT);
158 DPRINTF(("thread = 0x%lx: returning from PR_Send, bytes = %d\n",
159 PR_GetCurrentThread(), bytes));
160 if (bytes <= 0)
161 return -1;
162 }
163 return len;
164}
165
166/*
167 * TCP_Client
168 * Client job
169 * Connect to the server at the address specified in the argument.
170 * Fill in a buffer, write data to server, read it back and check
171 * for data corruption.
172 * Close the socket for server connection
173 */
174static void PR_CALLBACK
175TCP_Client(void *arg)
176{
177 Client_Param *cp = (Client_Param *) arg;
178 PRFileDesc *sockfd;
179 buffer *in_buf, *out_buf;
180 union PRNetAddr netaddr;
181 PRInt32 bytes, i, j;
182
183
184 DPRINTF(("TCP client started\n"));
185 bytes = cp->datalen;
186 out_buf = PR_NEW(buffer);
187 if (out_buf == NULL) {
188 fprintf(stderr,"%s: failed to alloc buffer struct\n", program_name);
189 failed_already=1;
190 return;
191 }
192 in_buf = PR_NEW(buffer);
193 if (in_buf == NULL) {
194 fprintf(stderr,"%s: failed to alloc buffer struct\n", program_name);
195 failed_already=1;
196 return;
197 }
198 netaddr.inet.family = cp->server_addr.inet.family;
199 netaddr.inet.port = cp->server_addr.inet.port;
200 netaddr.inet.ip = cp->server_addr.inet.ip;
201
202 for (i = 0; i < num_tcp_connections_per_client; i++) {
203 if ((sockfd = PR_OpenTCPSocket(PR_AF_INET)) == NULL) {
204 fprintf(stderr,"%s: PR_OpenTCPSocket failed\n", program_name);
205 failed_already=1;
206 return;
207 }
208
209 DPRINTF(("TCP client connecting to server:%d\n", server_port));
210 if (PR_Connect(sockfd, &netaddr,PR_INTERVAL_NO_TIMEOUT) < 0){
211 fprintf(stderr, "PR_Connect failed: (%ld, %ld)\n",
212 PR_GetError(), PR_GetOSError());
213 failed_already=1;
214 return;
215 }
216 for (j = 0; j < num_tcp_mesgs_per_connection; j++) {
217 /*
218 * fill in random data
219 */
220 memset(out_buf->data, ((PRInt32) (&netaddr)) + i + j, bytes);
221 /*
222 * write to server
223 */
224 if (writen(sockfd, out_buf->data, bytes) < bytes) {
225 fprintf(stderr,"%s: ERROR - TCP_Client:writen\n", program_name);
226 failed_already=1;
227 return;
228 }
229 /*
230 DPRINTF(("TCP Client [0x%lx]: out_buf = 0x%lx out_buf[0] = 0x%lx\n",
231 PR_GetCurrentThread(), out_buf, (*((int *) out_buf->data))));
232 */
233 if (readn(sockfd, in_buf->data, bytes) < bytes) {
234 fprintf(stderr,"%s: ERROR - TCP_Client:readn\n", program_name);
235 failed_already=1;
236 return;
237 }
238 /*
239 * verify the data read
240 */
241 if (memcmp(in_buf->data, out_buf->data, bytes) != 0) {
242 fprintf(stderr,"%s: ERROR - data corruption\n", program_name);
243 failed_already=1;
244 return;
245 }
246 }
247 /*
248 * shutdown reads and writes
249 */
250 if (PR_Shutdown(sockfd, PR_SHUTDOWN_BOTH) < 0) {
251 fprintf(stderr,"%s: ERROR - PR_Shutdown\n", program_name);
252 failed_already=1;
253 }
254 PR_Close(sockfd);
255 }
256
257 PR_DELETE(out_buf);
258 PR_DELETE(in_buf);
259
260 /*
261 * Decrement exit_counter and notify parent thread
262 */
263
264 PR_EnterMonitor(cp->exit_mon);
265 --(*cp->exit_counter);
266 PR_Notify(cp->exit_mon);
267 PR_ExitMonitor(cp->exit_mon);
268 DPRINTF(("TCP_Client exiting\n"));
269}
270
271/*
272 * TCP_Socket_Client_Server_Test - concurrent server test
273 *
274 * Each client connects to the server and sends a chunk of data
275 * For each connection, server reads the data
276 * from the client and sends it back to the client, unmodified.
277 * Each client checks that data received from server is same as the
278 * data it sent to the server.
279 *
280 */
281
282static PRInt32
283TCP_Socket_Client_Server_Test(void)
284{
285 int i;
286 Client_Param *cparamp;
287 PRMonitor *mon2;
288 PRInt32 datalen;
289 PRInt32 connections = 0;
290 PRThread *thr;
291
292 datalen = tcp_mesg_size;
293 connections = 0;
294
295 mon2 = PR_NewMonitor();
296 if (mon2 == NULL) {
297 fprintf(stderr,"%s: PR_NewMonitor failed\n", program_name);
298 failed_already=1;
299 return -1;
300 }
301
302 /*
303 * Start client jobs
304 */
305 cparamp = PR_NEW(Client_Param);
306 if (cparamp == NULL) {
307 fprintf(stderr,"%s: PR_NEW failed\n", program_name);
308 failed_already=1;
309 return -1;
310 }
311 cparamp->server_addr.inet.family = PR_AF_INET;
312 cparamp->server_addr.inet.port = PR_htons(server_port);
313 cparamp->server_addr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);
314 cparamp->exit_mon = mon2;
315 cparamp->exit_counter = &connections;
316 cparamp->datalen = datalen;
317 for (i = 0; i < num_tcp_clients; i++) {
318 thr = PR_CreateThread(PR_USER_THREAD, TCP_Client, (void *)cparamp,
319 PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0);
320 if (NULL == thr) {
321 fprintf(stderr,"%s: PR_CreateThread failed\n", program_name);
322 failed_already=1;
323 return -1;
324 }
325 PR_EnterMonitor(mon2);
326 connections++;
327 PR_ExitMonitor(mon2);
328 DPRINTF(("Created TCP client = 0x%lx\n", thr));
329 }
330 /* Wait for client jobs to exit */
331 PR_EnterMonitor(mon2);
332 while (0 != connections) {
333 PR_Wait(mon2, PR_INTERVAL_NO_TIMEOUT);
334 DPRINTF(("Client job count = %d\n", connections));
335 }
336 PR_ExitMonitor(mon2);
337 printf("%30s","TCP_Socket_Client_Server_Test:");
338 printf("%2ld Server %2ld Clients %2ld connections_per_client\n",1l,
339 num_tcp_clients, num_tcp_connections_per_client);
340 printf("%30s %2ld messages_per_connection %4ld bytes_per_message\n",":",
341 num_tcp_mesgs_per_connection, tcp_mesg_size);
342
343 PR_DELETE(cparamp);
344 return 0;
345}
346
347/************************************************************************/
348
349int
350main(int argc, char **argv)
351{
352 /*
353 * -d debug mode
354 */
355 PLOptStatus os;
356 PLOptState *opt;
357 program_name = argv[0];
358
359 opt = PL_CreateOptState(argc, argv, "dp:");
360 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
361 {
362 if (PL_OPT_BAD == os) continue;
363 switch (opt->option)
364 {
365 case 'd': /* debug mode */
366 _debug_on = 1;
367 break;
368 case 'p':
369 server_port = atoi(opt->value);
370 break;
371 default:
372 break;
373 }
374 }
375 PL_DestroyOptState(opt);
376
377 PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
378 PR_STDIO_INIT();
379
380#ifdef XP_MAC
381 SetupMacPrintfLog("socket.log");
382#endif
383 PR_SetConcurrency(4);
384
385 TCP_Socket_Client_Server_Test();
386
387 PR_Cleanup();
388 if (failed_already)
389 return 1;
390 else
391 return 0;
392}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette