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