]> git.sur5r.net Git - openldap/blob - tests/progs/slapd-tester.c
Set BDB's global allocators to ber_*, don't bother with the per-env setting.
[openldap] / tests / progs / slapd-tester.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6 #include "portable.h"
7
8 #include <stdio.h>
9
10 #include <ac/stdlib.h>
11
12 #include <ac/ctype.h>
13 #include <ac/dirent.h>
14 #include <ac/param.h>
15 #include <ac/socket.h>
16 #include <ac/string.h>
17 #include <ac/unistd.h>
18 #include <ac/wait.h>
19
20
21 #include "ldap_defaults.h"
22
23
24 #define SEARCHCMD               "slapd-search"
25 #define READCMD                 "slapd-read"
26 #define ADDCMD                  "slapd-addel"
27 #define MAXARGS         100
28 #define MAXREQS                 20
29 #define LOOPS                   "100"
30
31 #define TSEARCHFILE             "do_search.0"
32 #define TREADFILE               "do_read.0"
33 #define TADDFILE                "do_add."
34
35 static char *get_file_name( char *dirname, char *filename );
36 static int  get_search_filters( char *filename, char *filters[] );
37 static int  get_read_entries( char *filename, char *entries[] );
38 static void fork_child( char *prog, char **args );
39 static void     wait4kids( int nkidval );
40
41 static int      maxkids = 20;
42 static int      nkids;
43
44 #ifdef HAVE_WINSOCK
45 static HANDLE   *children;
46 static char argbuf[BUFSIZ];
47 #define ArgDup(x) strdup(strcat(strcat(strcpy(argbuf,"\""),x),"\""))
48 #else
49 #define ArgDup(x) strdup(x)
50 #endif
51
52 static void
53 usage( char *name )
54 {
55         fprintf( stderr, "usage: %s [-h <host>] -p <port> -D <manager> -w <passwd> -d <datadir> -b <baseDN> [-j <maxchild>] [-l <loops>] -P <progdir>\n", name );
56         exit( EXIT_FAILURE );
57 }
58
59 int
60 main( int argc, char **argv )
61 {
62         int             i, j;
63         char            *host = "localhost";
64         char            *port = NULL;
65         char            *manager = NULL;
66         char            *passwd = NULL;
67         char            *dirname = NULL;
68         char        *sbase = NULL;
69         char            *progdir = NULL;
70         char            *loops = LOOPS;
71         DIR                     *datadir;
72         struct dirent   *file;
73         char            *sfile = NULL;
74         char            *sreqs[MAXREQS];
75         int         snum = 0;
76         char            *rfile = NULL;
77         char            *rreqs[MAXREQS];
78         int         rnum = 0;
79         char            *afiles[MAXREQS];
80         int         anum = 0;
81         char            *sargs[MAXARGS];
82         int                     sanum;
83         char            scmd[MAXPATHLEN];
84         char            *rargs[MAXARGS];
85         int                     ranum;
86         char            rcmd[MAXPATHLEN];
87         char            *aargs[MAXARGS];
88         int                     aanum;
89         char            acmd[MAXPATHLEN];
90
91         while ( (i = getopt( argc, argv, "h:p:D:w:b:d:j:l:P:" )) != EOF ) {
92                 switch( i ) {
93                         case 'h':               /* slapd host */
94                                 host = strdup( optarg );
95                         break;
96
97                         case 'p':               /* the servers port number */
98                                 port = strdup( optarg );
99                                 break;
100
101                         case 'D':               /* slapd manager */
102                                 manager = ArgDup( optarg );
103                         break;
104
105                         case 'w':               /* the managers passwd */
106                                 passwd = ArgDup( optarg );
107                                 break;
108
109                         case 'b':               /* the base DN */
110                                 sbase = ArgDup( optarg );
111                                 break;
112
113                         case 'd':               /* data directory */
114                                 dirname = strdup( optarg );
115                         break;
116
117                         case 'P':               /* prog directory */
118                                 progdir = strdup( optarg );
119                         break;
120
121                         case 'j':               /* the number of parallel clients */
122                                 maxkids = atoi( optarg );
123                                 break;
124
125                         case 'l':               /* the number of loops per client */
126                                 loops = strdup( optarg );
127                                 break;
128
129                         default:
130                                 usage( argv[0] );
131                                 break;
132                 }
133         }
134
135         if (( dirname == NULL ) || ( sbase == NULL ) || ( port == NULL ) ||
136                         ( manager == NULL ) || ( passwd == NULL ) || ( progdir == NULL ))
137                 usage( argv[0] );
138
139 #ifdef HAVE_WINSOCK
140         children = malloc( maxkids * sizeof(HANDLE) );
141 #endif
142         /* get the file list */
143         if ( ( datadir = opendir( dirname )) == NULL ) {
144
145                 fprintf( stderr, "%s: couldn't open data directory \"%s\".\n",
146                                         argv[0], dirname );
147                 exit( EXIT_FAILURE );
148
149         }
150
151         /*  look for search, read, and add/delete files */
152         for ( file = readdir( datadir ); file; file = readdir( datadir )) {
153
154                 if ( !strcasecmp( file->d_name, TSEARCHFILE )) {
155                         sfile = get_file_name( dirname, file->d_name );
156                         continue;
157                 } else if ( !strcasecmp( file->d_name, TREADFILE )) {
158                         rfile = get_file_name( dirname, file->d_name );
159                         continue;
160                 } else if ( !strncasecmp( file->d_name, TADDFILE, strlen( TADDFILE ))
161                         && ( anum < MAXREQS )) {
162                         afiles[anum++] = get_file_name( dirname, file->d_name );
163                         continue;
164                 }
165         }
166
167         closedir( datadir );
168
169         /* look for search requests */
170         if ( sfile ) {
171                 snum = get_search_filters( sfile, sreqs );
172         }
173
174         /* look for read requests */
175         if ( rfile ) {
176                 rnum = get_read_entries( rfile, rreqs );
177         }
178
179         /*
180          * generate the search clients
181          */
182
183         sanum = 0;
184         snprintf( scmd, sizeof scmd, "%s" LDAP_DIRSEP SEARCHCMD,
185                 progdir );
186         sargs[sanum++] = scmd;
187         sargs[sanum++] = "-h";
188         sargs[sanum++] = host;
189         sargs[sanum++] = "-p";
190         sargs[sanum++] = port;
191         sargs[sanum++] = "-b";
192         sargs[sanum++] = sbase;
193         sargs[sanum++] = "-l";
194         sargs[sanum++] = loops;
195         sargs[sanum++] = "-f";
196         sargs[sanum++] = NULL;          /* will hold the search request */
197         sargs[sanum++] = NULL;
198
199         /*
200          * generate the read clients
201          */
202
203         ranum = 0;
204         snprintf( rcmd, sizeof rcmd, "%s" LDAP_DIRSEP READCMD,
205                 progdir );
206         rargs[ranum++] = rcmd;
207         rargs[ranum++] = "-h";
208         rargs[ranum++] = host;
209         rargs[ranum++] = "-p";
210         rargs[ranum++] = port;
211         rargs[ranum++] = "-l";
212         rargs[ranum++] = loops;
213         rargs[ranum++] = "-e";
214         rargs[ranum++] = NULL;          /* will hold the read entry */
215         rargs[ranum++] = NULL;
216
217         /*
218          * generate the add/delete clients
219          */
220
221         aanum = 0;
222         snprintf( acmd, sizeof acmd, "%s" LDAP_DIRSEP ADDCMD,
223                 progdir );
224         aargs[aanum++] = acmd;
225         aargs[aanum++] = "-h";
226         aargs[aanum++] = host;
227         aargs[aanum++] = "-p";
228         aargs[aanum++] = port;
229         aargs[aanum++] = "-D";
230         aargs[aanum++] = manager;
231         aargs[aanum++] = "-w";
232         aargs[aanum++] = passwd;
233         aargs[aanum++] = "-l";
234         aargs[aanum++] = loops;
235         aargs[aanum++] = "-f";
236         aargs[aanum++] = NULL;          /* will hold the add data file */
237         aargs[aanum++] = NULL;
238
239         for ( j = 0; j < MAXREQS; j++ ) {
240
241                 if ( j < snum ) {
242
243                         sargs[sanum - 2] = sreqs[j];
244                         fork_child( scmd, sargs );
245
246                 }
247
248                 if ( j < rnum ) {
249
250                         rargs[ranum - 2] = rreqs[j];
251                         fork_child( rcmd, rargs );
252
253                 }
254
255                 if ( j < anum ) {
256
257                         aargs[aanum - 2] = afiles[j];
258                         fork_child( acmd, aargs );
259
260                 }
261
262         }
263
264         wait4kids( -1 );
265
266         exit( EXIT_SUCCESS );
267 }
268
269 static char *
270 get_file_name( char *dirname, char *filename )
271 {
272         char buf[MAXPATHLEN];
273
274         snprintf( buf, sizeof buf, "%s" LDAP_DIRSEP "%s",
275                 dirname, filename );
276         return( strdup( buf ));
277 }
278
279
280 static int
281 get_search_filters( char *filename, char *filters[] )
282 {
283         FILE    *fp;
284         int     filter = 0;
285
286         if ( (fp = fopen( filename, "r" )) != NULL ) {
287                 char  line[BUFSIZ];
288
289                 while (( filter < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
290                         char *nl;
291
292                         if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
293                                 *nl = '\0';
294                         filters[filter++] = ArgDup( line );
295
296                 }
297                 fclose( fp );
298         }
299
300         return( filter );
301 }
302
303
304 static int
305 get_read_entries( char *filename, char *entries[] )
306 {
307         FILE    *fp;
308         int     entry = 0;
309
310         if ( (fp = fopen( filename, "r" )) != NULL ) {
311                 char  line[BUFSIZ];
312
313                 while (( entry < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
314                         char *nl;
315
316                         if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
317                                 *nl = '\0';
318                         entries[entry++] = ArgDup( line );
319
320                 }
321                 fclose( fp );
322         }
323
324         return( entry );
325 }
326
327 #ifndef HAVE_WINSOCK
328 static void
329 fork_child( char *prog, char **args )
330 {
331         pid_t   pid;
332
333         wait4kids( maxkids );
334
335         switch ( pid = fork() ) {
336         case 0:         /* child */
337 #ifdef HAVE_EBCDIC
338                 /* The __LIBASCII execvp only handles ASCII "prog",
339                  * we still need to translate the arg vec ourselves.
340                  */
341                 { char *arg2[MAXREQS];
342                 int i;
343
344                 for (i=0; args[i]; i++) {
345                         arg2[i] = ArgDup(args[i]);
346                         __atoe(arg2[i]);
347                 }
348                 arg2[i] = NULL;
349                 args = arg2; }
350 #endif
351                 execvp( prog, args );
352                 fprintf( stderr, "%s: ", prog );
353                 perror( "execv" );
354                 exit( EXIT_FAILURE );
355                 break;
356
357         case -1:        /* trouble */
358                 fprintf( stderr, "Could not fork to run %s\n", prog );
359                 perror( "fork" );
360                 break;
361
362         default:        /* parent */
363                 nkids++;
364                 break;
365         }
366 }
367
368 static void
369 wait4kids( int nkidval )
370 {
371         int             status;
372
373         while ( nkids >= nkidval ) {
374                 wait( &status );
375
376                 if ( WIFSTOPPED(status) ) {
377                         fprintf( stderr,
378                             "stopping: child stopped with signal %d\n",
379                             (int) WSTOPSIG(status) );
380
381                 } else if ( WIFSIGNALED(status) ) {
382                         fprintf( stderr, 
383                             "stopping: child terminated with signal %d%s\n",
384                             (int) WTERMSIG(status),
385 #ifdef WCOREDUMP
386                                 WCOREDUMP(status) ? ", core dumped" : ""
387 #else
388                                 ""
389 #endif
390                                 );
391                         exit( WEXITSTATUS(status)  );
392
393                 } else if ( WEXITSTATUS(status) != 0 ) {
394                         fprintf( stderr, 
395                             "stopping: child exited with status %d\n",
396                             (int) WEXITSTATUS(status) );
397                         exit( WEXITSTATUS(status) );
398
399                 } else {
400                         nkids--;
401                 }
402         }
403 }
404 #else
405
406 static void
407 wait4kids( int nkidval )
408 {
409         int rc, i;
410
411         while ( nkids >= nkidval ) {
412                 rc = WaitForMultipleObjects( nkids, children, FALSE, INFINITE );
413                 for ( i=rc - WAIT_OBJECT_0; i<nkids-1; i++)
414                         children[i] = children[i+1];
415                 nkids--;
416         }
417 }
418
419 static void
420 fork_child( char *prog, char **args )
421 {
422         int rc;
423
424         wait4kids( maxkids );
425
426         rc = _spawnvp( _P_NOWAIT, prog, args );
427
428         if ( rc == -1 ) {
429                 fprintf( stderr, "%s: ", prog );
430                 perror("spawnvp");
431         } else {
432                 children[nkids++] = (HANDLE)rc;
433         }
434 }
435 #endif