]> git.sur5r.net Git - openldap/blob - tests/progs/slapd-tester.c
Update build tools based upon OPENLDAP_AC work
[openldap] / tests / progs / slapd-tester.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1999-2005 The OpenLDAP Foundation.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted only as authorized by the OpenLDAP
9  * Public License.
10  *
11  * A copy of this license is available in file LICENSE in the
12  * top-level directory of the distribution or, alternatively, at
13  * <http://www.OpenLDAP.org/license.html>.
14  */
15 /* ACKNOWLEDGEMENTS:
16  * This work was initially developed by Kurt Spanier for inclusion
17  * in OpenLDAP Software.
18  */
19
20 #include "portable.h"
21
22 #include <stdio.h>
23
24 #include <ac/stdlib.h>
25
26 #include <ac/ctype.h>
27 #include <ac/dirent.h>
28 #include <ac/param.h>
29 #include <ac/socket.h>
30 #include <ac/string.h>
31 #include <ac/unistd.h>
32 #include <ac/wait.h>
33
34
35 #include "ldap_defaults.h"
36
37
38 #define SEARCHCMD               "slapd-search"
39 #define READCMD                 "slapd-read"
40 #define ADDCMD                  "slapd-addel"
41 #define MODRDNCMD               "slapd-modrdn"
42 #define MODIFYCMD               "slapd-modify"
43 #define MAXARGS                 100
44 #define MAXREQS                 5000
45 #define LOOPS                   "100"
46 #define RETRIES                 "0"
47
48 #define TSEARCHFILE             "do_search.0"
49 #define TREADFILE               "do_read.0"
50 #define TADDFILE                "do_add."
51 #define TMODRDNFILE             "do_modrdn.0"
52 #define TMODIFYFILE             "do_modify.0"
53
54 static char *get_file_name( char *dirname, char *filename );
55 static int  get_search_filters( char *filename, char *filters[], char *bases[] );
56 static int  get_read_entries( char *filename, char *entries[] );
57 static void fork_child( char *prog, char **args );
58 static void     wait4kids( int nkidval );
59
60 static int      maxkids = 20;
61 static int      nkids;
62
63 #ifdef HAVE_WINSOCK
64 static HANDLE   *children;
65 static char argbuf[BUFSIZ];
66 #define ArgDup(x) strdup(strcat(strcat(strcpy(argbuf,"\""),x),"\""))
67 #else
68 #define ArgDup(x) strdup(x)
69 #endif
70
71 static void
72 usage( char *name )
73 {
74         fprintf( stderr,
75                 "usage: %s "
76                 "-H <uri> | ([-h <host>] -p <port>) "
77                 "-D <manager> "
78                 "-w <passwd> "
79                 "-d <datadir> "
80                 "[-j <maxchild>] "
81                 "[-l <loops>] "
82                 "-P <progdir> "
83                 "[-r <maxretries>]"
84                 "[-t <delay>]\n",
85                 name );
86         exit( EXIT_FAILURE );
87 }
88
89 int
90 main( int argc, char **argv )
91 {
92         int             i, j;
93         char            *uri = NULL;
94         char            *host = "localhost";
95         char            *port = NULL;
96         char            *manager = NULL;
97         char            *passwd = NULL;
98         char            *dirname = NULL;
99         char            *progdir = NULL;
100         char            *loops = LOOPS;
101         char            *retries = RETRIES;
102         char            *delay = "0";
103         DIR                     *datadir;
104         struct dirent   *file;
105         char            *sfile = NULL;
106         char            *sreqs[MAXREQS];
107         char            *sbase[MAXREQS];
108         int         snum = 0;
109         char            *rfile = NULL;
110         char            *rreqs[MAXREQS];
111         int         rnum = 0;
112         char            *afiles[MAXREQS];
113         int         anum = 0;
114         char            *mfile = NULL;
115         char            *mreqs[MAXREQS];
116         int             mnum = 0;
117         char            *sargs[MAXARGS];
118         int                     sanum;
119         char            scmd[MAXPATHLEN];
120         char            *rargs[MAXARGS];
121         int                     ranum;
122         char            rcmd[MAXPATHLEN];
123         char            *aargs[MAXARGS];
124         int                     aanum;
125         char            acmd[MAXPATHLEN];
126         char            *margs[MAXARGS];
127         int             manum;
128         char            mcmd[MAXPATHLEN];
129         char            *modargs[MAXARGS];
130         int             modanum;
131         char            modcmd[MAXPATHLEN];
132         char            *modfile = NULL;
133         char            *modreqs[MAXREQS];
134         char            *moddn[MAXREQS];
135         int             modnum = 0;
136
137         while ( (i = getopt( argc, argv, "D:d:H:h:j:l:P:p:r:t:w:" )) != EOF ) {
138                 switch( i ) {
139                 case 'D':               /* slapd manager */
140                         manager = ArgDup( optarg );
141                         break;
142
143                 case 'd':               /* data directory */
144                         dirname = strdup( optarg );
145                         break;
146
147                 case 'H':               /* slapd uri */
148                         uri = strdup( optarg );
149                         break;
150
151                 case 'h':               /* slapd host */
152                         host = strdup( optarg );
153                         break;
154
155                 case 'j':               /* the number of parallel clients */
156                         maxkids = atoi( optarg );
157                         break;
158
159                 case 'l':               /* the number of loops per client */
160                         loops = strdup( optarg );
161                         break;
162
163                 case 'P':               /* prog directory */
164                         progdir = strdup( optarg );
165                         break;
166
167                 case 'p':               /* the servers port number */
168                         port = strdup( optarg );
169                         break;
170
171                 case 'r':               /* the number of retries in case of error */
172                         retries = strdup( optarg );
173                         break;
174
175                 case 't':               /* the delay in seconds between each retry */
176                         delay = strdup( optarg );
177                         break;
178
179                 case 'w':               /* the managers passwd */
180                         passwd = ArgDup( optarg );
181                         break;
182
183                 default:
184                         usage( argv[0] );
185                         break;
186                 }
187         }
188
189         if (( dirname == NULL ) || ( port == NULL && uri == NULL ) ||
190                         ( manager == NULL ) || ( passwd == NULL ) || ( progdir == NULL ))
191                 usage( argv[0] );
192
193 #ifdef HAVE_WINSOCK
194         children = malloc( maxkids * sizeof(HANDLE) );
195 #endif
196         /* get the file list */
197         if ( ( datadir = opendir( dirname )) == NULL ) {
198
199                 fprintf( stderr, "%s: couldn't open data directory \"%s\".\n",
200                                         argv[0], dirname );
201                 exit( EXIT_FAILURE );
202
203         }
204
205         /*  look for search, read, modrdn, and add/delete files */
206         for ( file = readdir( datadir ); file; file = readdir( datadir )) {
207
208                 if ( !strcasecmp( file->d_name, TSEARCHFILE )) {
209                         sfile = get_file_name( dirname, file->d_name );
210                         continue;
211                 } else if ( !strcasecmp( file->d_name, TREADFILE )) {
212                         rfile = get_file_name( dirname, file->d_name );
213                         continue;
214                 } else if ( !strcasecmp( file->d_name, TMODRDNFILE )) {
215                         mfile = get_file_name( dirname, file->d_name );
216                         continue;
217                 } else if ( !strcasecmp( file->d_name, TMODIFYFILE )) {
218                         modfile = get_file_name( dirname, file->d_name );
219                         continue;
220                 } else if ( !strncasecmp( file->d_name, TADDFILE, strlen( TADDFILE ))
221                         && ( anum < MAXREQS )) {
222                         afiles[anum++] = get_file_name( dirname, file->d_name );
223                         continue;
224                 }
225         }
226
227         closedir( datadir );
228
229         /* look for search requests */
230         if ( sfile ) {
231                 snum = get_search_filters( sfile, sreqs, sbase );
232         }
233
234         /* look for read requests */
235         if ( rfile ) {
236                 rnum = get_read_entries( rfile, rreqs );
237         }
238
239         /* look for modrdn requests */
240         if ( mfile ) {
241                 mnum = get_read_entries( mfile, mreqs );
242         }
243         /* look for modify requests */
244         if ( modfile ) {
245                 modnum = get_search_filters( modfile, modreqs, moddn );
246         }
247
248         /*
249          * generate the search clients
250          */
251
252         sanum = 0;
253         snprintf( scmd, sizeof scmd, "%s" LDAP_DIRSEP SEARCHCMD,
254                 progdir );
255         sargs[sanum++] = scmd;
256         if ( uri ) {
257                 sargs[sanum++] = "-H";
258                 sargs[sanum++] = uri;
259         } else {
260                 sargs[sanum++] = "-h";
261                 sargs[sanum++] = host;
262                 sargs[sanum++] = "-p";
263                 sargs[sanum++] = port;
264         }
265         sargs[sanum++] = "-D";
266         sargs[sanum++] = manager;
267         sargs[sanum++] = "-w";
268         sargs[sanum++] = passwd;
269         sargs[sanum++] = "-l";
270         sargs[sanum++] = loops;
271         sargs[sanum++] = "-r";
272         sargs[sanum++] = retries;
273         sargs[sanum++] = "-t";
274         sargs[sanum++] = delay;
275         sargs[sanum++] = "-b";
276         sargs[sanum++] = NULL;          /* will hold the search base */
277         sargs[sanum++] = "-f";
278         sargs[sanum++] = NULL;          /* will hold the search request */
279         sargs[sanum++] = NULL;
280
281         /*
282          * generate the read clients
283          */
284
285         ranum = 0;
286         snprintf( rcmd, sizeof rcmd, "%s" LDAP_DIRSEP READCMD,
287                 progdir );
288         rargs[ranum++] = rcmd;
289         if ( uri ) {
290                 rargs[ranum++] = "-H";
291                 rargs[ranum++] = uri;
292         } else {
293                 rargs[ranum++] = "-h";
294                 rargs[ranum++] = host;
295                 rargs[ranum++] = "-p";
296                 rargs[ranum++] = port;
297         }
298         rargs[ranum++] = "-l";
299         rargs[ranum++] = loops;
300         rargs[ranum++] = "-r";
301         rargs[ranum++] = retries;
302         rargs[ranum++] = "-t";
303         rargs[ranum++] = delay;
304         rargs[ranum++] = "-e";
305         rargs[ranum++] = NULL;          /* will hold the read entry */
306         rargs[ranum++] = NULL;
307
308         /*
309          * generate the modrdn clients
310          */
311
312         manum = 0;
313         snprintf( mcmd, sizeof mcmd, "%s" LDAP_DIRSEP MODRDNCMD,
314                 progdir );
315         margs[manum++] = mcmd;
316         if ( uri ) {
317                 margs[manum++] = "-H";
318                 margs[manum++] = uri;
319         } else {
320                 margs[manum++] = "-h";
321                 margs[manum++] = host;
322                 margs[manum++] = "-p";
323                 margs[manum++] = port;
324         }
325         margs[manum++] = "-D";
326         margs[manum++] = manager;
327         margs[manum++] = "-w";
328         margs[manum++] = passwd;
329         margs[manum++] = "-l";
330         margs[manum++] = loops;
331         margs[manum++] = "-r";
332         margs[manum++] = retries;
333         margs[manum++] = "-t";
334         margs[manum++] = delay;
335         margs[manum++] = "-e";
336         margs[manum++] = NULL;          /* will hold the modrdn entry */
337         margs[manum++] = NULL;
338         
339         /*
340          * generate the modify clients
341          */
342
343         modanum = 0;
344         snprintf( modcmd, sizeof modcmd, "%s" LDAP_DIRSEP MODIFYCMD,
345                 progdir );
346         modargs[modanum++] = modcmd;
347         if ( uri ) {
348                 modargs[modanum++] = "-H";
349                 modargs[modanum++] = uri;
350         } else {
351                 modargs[modanum++] = "-h";
352                 modargs[modanum++] = host;
353                 modargs[modanum++] = "-p";
354                 modargs[modanum++] = port;
355         }
356         modargs[modanum++] = "-D";
357         modargs[modanum++] = manager;
358         modargs[modanum++] = "-w";
359         modargs[modanum++] = passwd;
360         modargs[modanum++] = "-l";
361         modargs[modanum++] = loops;
362         modargs[modanum++] = "-r";
363         modargs[modanum++] = retries;
364         modargs[modanum++] = "-t";
365         modargs[modanum++] = delay;
366         modargs[modanum++] = "-e";
367         modargs[modanum++] = NULL;              /* will hold the modify entry */
368         modargs[modanum++] = "-a";;
369         modargs[modanum++] = NULL;              /* will hold the ava */
370         modargs[modanum++] = NULL;
371
372         /*
373          * generate the add/delete clients
374          */
375
376         aanum = 0;
377         snprintf( acmd, sizeof acmd, "%s" LDAP_DIRSEP ADDCMD,
378                 progdir );
379         aargs[aanum++] = acmd;
380         if ( uri ) {
381                 aargs[aanum++] = "-H";
382                 aargs[aanum++] = uri;
383         } else {
384                 aargs[aanum++] = "-h";
385                 aargs[aanum++] = host;
386                 aargs[aanum++] = "-p";
387                 aargs[aanum++] = port;
388         }
389         aargs[aanum++] = "-D";
390         aargs[aanum++] = manager;
391         aargs[aanum++] = "-w";
392         aargs[aanum++] = passwd;
393         aargs[aanum++] = "-l";
394         aargs[aanum++] = loops;
395         aargs[aanum++] = "-r";
396         aargs[aanum++] = retries;
397         aargs[aanum++] = "-t";
398         aargs[aanum++] = delay;
399         aargs[aanum++] = "-f";
400         aargs[aanum++] = NULL;          /* will hold the add data file */
401         aargs[aanum++] = NULL;
402
403         for ( j = 0; j < MAXREQS; j++ ) {
404
405                 if ( j < snum ) {
406
407                         sargs[sanum - 2] = sreqs[j];
408                         sargs[sanum - 4] = sbase[j];
409                         fork_child( scmd, sargs );
410
411                 }
412
413                 if ( j < rnum ) {
414
415                         rargs[ranum - 2] = rreqs[j];
416                         fork_child( rcmd, rargs );
417
418                 }
419
420                 if ( j < mnum ) {
421
422                         margs[manum - 2] = mreqs[j];
423                         fork_child( mcmd, margs );
424
425                 }
426                 if ( j < modnum ) {
427
428                         modargs[modanum - 4] = moddn[j];
429                         modargs[modanum - 2] = modreqs[j];
430                         fork_child( modcmd, modargs );
431
432                 }
433
434                 if ( j < anum ) {
435
436                         aargs[aanum - 2] = afiles[j];
437                         fork_child( acmd, aargs );
438
439                 }
440
441         }
442
443         wait4kids( -1 );
444
445         exit( EXIT_SUCCESS );
446 }
447
448 static char *
449 get_file_name( char *dirname, char *filename )
450 {
451         char buf[MAXPATHLEN];
452
453         snprintf( buf, sizeof buf, "%s" LDAP_DIRSEP "%s",
454                 dirname, filename );
455         return( strdup( buf ));
456 }
457
458
459 static int
460 get_search_filters( char *filename, char *filters[], char *bases[] )
461 {
462         FILE    *fp;
463         int     filter = 0;
464
465         if ( (fp = fopen( filename, "r" )) != NULL ) {
466                 char  line[BUFSIZ];
467
468                 while (( filter < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
469                         char *nl;
470
471                         if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
472                                 *nl = '\0';
473                         bases[filter] = ArgDup( line );
474                         fgets( line, BUFSIZ, fp );
475                         if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
476                                 *nl = '\0';
477
478                         filters[filter++] = ArgDup( line );
479
480                 }
481                 fclose( fp );
482         }
483
484         return( filter );
485 }
486
487
488 static int
489 get_read_entries( char *filename, char *entries[] )
490 {
491         FILE    *fp;
492         int     entry = 0;
493
494         if ( (fp = fopen( filename, "r" )) != NULL ) {
495                 char  line[BUFSIZ];
496
497                 while (( entry < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
498                         char *nl;
499
500                         if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
501                                 *nl = '\0';
502                         entries[entry++] = ArgDup( line );
503
504                 }
505                 fclose( fp );
506         }
507
508         return( entry );
509 }
510
511 #ifndef HAVE_WINSOCK
512 static void
513 fork_child( char *prog, char **args )
514 {
515         pid_t   pid;
516
517         wait4kids( maxkids );
518
519         switch ( pid = fork() ) {
520         case 0:         /* child */
521 #ifdef HAVE_EBCDIC
522                 /* The __LIBASCII execvp only handles ASCII "prog",
523                  * we still need to translate the arg vec ourselves.
524                  */
525                 { char *arg2[MAXREQS];
526                 int i;
527
528                 for (i=0; args[i]; i++) {
529                         arg2[i] = ArgDup(args[i]);
530                         __atoe(arg2[i]);
531                 }
532                 arg2[i] = NULL;
533                 args = arg2; }
534 #endif
535                 execvp( prog, args );
536                 fprintf( stderr, "%s: ", prog );
537                 perror( "execv" );
538                 exit( EXIT_FAILURE );
539                 break;
540
541         case -1:        /* trouble */
542                 fprintf( stderr, "Could not fork to run %s\n", prog );
543                 perror( "fork" );
544                 break;
545
546         default:        /* parent */
547                 nkids++;
548                 break;
549         }
550 }
551
552 static void
553 wait4kids( int nkidval )
554 {
555         int             status;
556
557         while ( nkids >= nkidval ) {
558                 wait( &status );
559
560                 if ( WIFSTOPPED(status) ) {
561                         fprintf( stderr,
562                             "stopping: child stopped with signal %d\n",
563                             (int) WSTOPSIG(status) );
564
565                 } else if ( WIFSIGNALED(status) ) {
566                         fprintf( stderr, 
567                             "stopping: child terminated with signal %d%s\n",
568                             (int) WTERMSIG(status),
569 #ifdef WCOREDUMP
570                                 WCOREDUMP(status) ? ", core dumped" : ""
571 #else
572                                 ""
573 #endif
574                                 );
575                         exit( WEXITSTATUS(status)  );
576
577                 } else if ( WEXITSTATUS(status) != 0 ) {
578                         fprintf( stderr, 
579                             "stopping: child exited with status %d\n",
580                             (int) WEXITSTATUS(status) );
581                         exit( WEXITSTATUS(status) );
582
583                 } else {
584                         nkids--;
585                 }
586         }
587 }
588 #else
589
590 static void
591 wait4kids( int nkidval )
592 {
593         int rc, i;
594
595         while ( nkids >= nkidval ) {
596                 rc = WaitForMultipleObjects( nkids, children, FALSE, INFINITE );
597                 for ( i=rc - WAIT_OBJECT_0; i<nkids-1; i++)
598                         children[i] = children[i+1];
599                 nkids--;
600         }
601 }
602
603 static void
604 fork_child( char *prog, char **args )
605 {
606         int rc;
607
608         wait4kids( maxkids );
609
610         rc = _spawnvp( _P_NOWAIT, prog, args );
611
612         if ( rc == -1 ) {
613                 fprintf( stderr, "%s: ", prog );
614                 perror("spawnvp");
615         } else {
616                 children[nkids++] = (HANDLE)rc;
617         }
618 }
619 #endif