2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1999-2006 The OpenLDAP Foundation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted only as authorized by the OpenLDAP
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>.
16 * This work was initially developed by Kurt Spanier for inclusion
17 * in OpenLDAP Software.
24 #include <ac/stdlib.h>
27 #include <ac/dirent.h>
29 #include <ac/socket.h>
30 #include <ac/string.h>
31 #include <ac/unistd.h>
35 #include "ldap_defaults.h"
39 #include "slapd-common.h"
41 #define SEARCHCMD "slapd-search"
42 #define READCMD "slapd-read"
43 #define ADDCMD "slapd-addel"
44 #define MODRDNCMD "slapd-modrdn"
45 #define MODIFYCMD "slapd-modify"
46 #define BINDCMD "slapd-bind"
50 #define OUTERLOOPS "1"
53 #define TSEARCHFILE "do_search.0"
54 #define TREADFILE "do_read.0"
55 #define TADDFILE "do_add."
56 #define TMODRDNFILE "do_modrdn.0"
57 #define TMODIFYFILE "do_modify.0"
58 #define TBINDFILE "do_bind.0"
60 static char *get_file_name( char *dirname, char *filename );
61 static int get_search_filters( char *filename, char *filters[], char *bases[] );
62 static int get_read_entries( char *filename, char *entries[] );
63 static void fork_child( char *prog, char **args );
64 static void wait4kids( int nkidval );
66 static int maxkids = 20;
70 static HANDLE *children;
71 static char argbuf[BUFSIZ];
72 #define ArgDup(x) strdup(strcat(strcat(strcpy(argbuf,"\""),x),"\""))
74 #define ArgDup(x) strdup(x)
82 "-H <uri> | ([-h <host>] -p <port>) "
98 main( int argc, char **argv )
102 char *host = "localhost";
104 char *manager = NULL;
106 char *dirname = NULL;
107 char *progdir = NULL;
109 char *outerloops = OUTERLOOPS;
110 char *retries = RETRIES;
117 char *sreqs[MAXREQS];
118 char *sbase[MAXREQS];
120 char *sargs[MAXARGS];
122 char scmd[MAXPATHLEN];
123 char sloops[] = "18446744073709551615UL";
126 char *rreqs[MAXREQS];
128 char *rargs[MAXARGS];
130 char rcmd[MAXPATHLEN];
131 char rloops[] = "18446744073709551615UL";
133 char *afiles[MAXREQS];
135 char *aargs[MAXARGS];
137 char acmd[MAXPATHLEN];
138 char aloops[] = "18446744073709551615UL";
141 char *mreqs[MAXREQS];
143 char *margs[MAXARGS];
145 char mcmd[MAXPATHLEN];
146 char mloops[] = "18446744073709551615UL";
148 char *modfile = NULL;
149 char *modreqs[MAXREQS];
150 char *moddn[MAXREQS];
152 char *modargs[MAXARGS];
154 char modcmd[MAXPATHLEN];
155 char modloops[] = "18446744073709551615UL";
158 char *breqs[MAXREQS];
159 char *bcreds[MAXREQS];
161 char *bargs[MAXARGS];
163 char bcmd[MAXPATHLEN];
164 char bloops[] = "18446744073709551615UL";
166 char *friendlyOpt = NULL;
168 tester_init( "slapd-tester" );
170 while ( (i = getopt( argc, argv, "D:d:FH:h:j:l:L:P:p:r:t:w:" )) != EOF ) {
172 case 'D': /* slapd manager */
173 manager = ArgDup( optarg );
176 case 'd': /* data directory */
177 dirname = strdup( optarg );
184 case 'H': /* slapd uri */
185 uri = strdup( optarg );
188 case 'h': /* slapd host */
189 host = strdup( optarg );
192 case 'j': /* the number of parallel clients */
193 if ( lutil_atoi( &maxkids, optarg ) != 0 ) {
198 case 'l': /* the number of loops per client */
199 if ( lutil_atoi( &loops, optarg ) != 0 ) {
204 case 'L': /* the number of outerloops per client */
205 outerloops = strdup( optarg );
208 case 'P': /* prog directory */
209 progdir = strdup( optarg );
212 case 'p': /* the servers port number */
213 port = strdup( optarg );
216 case 'r': /* the number of retries in case of error */
217 retries = strdup( optarg );
220 case 't': /* the delay in seconds between each retry */
221 delay = strdup( optarg );
224 case 'w': /* the managers passwd */
225 passwd = ArgDup( optarg );
234 if (( dirname == NULL ) || ( port == NULL && uri == NULL ) ||
235 ( manager == NULL ) || ( passwd == NULL ) || ( progdir == NULL ))
239 children = malloc( maxkids * sizeof(HANDLE) );
241 /* get the file list */
242 if ( ( datadir = opendir( dirname )) == NULL ) {
244 fprintf( stderr, "%s: couldn't open data directory \"%s\".\n",
246 exit( EXIT_FAILURE );
250 /* look for search, read, modrdn, and add/delete files */
251 for ( file = readdir( datadir ); file; file = readdir( datadir )) {
253 if ( !strcasecmp( file->d_name, TSEARCHFILE )) {
254 sfile = get_file_name( dirname, file->d_name );
256 } else if ( !strcasecmp( file->d_name, TREADFILE )) {
257 rfile = get_file_name( dirname, file->d_name );
259 } else if ( !strcasecmp( file->d_name, TMODRDNFILE )) {
260 mfile = get_file_name( dirname, file->d_name );
262 } else if ( !strcasecmp( file->d_name, TMODIFYFILE )) {
263 modfile = get_file_name( dirname, file->d_name );
265 } else if ( !strncasecmp( file->d_name, TADDFILE, strlen( TADDFILE ))
266 && ( anum < MAXREQS )) {
267 afiles[anum++] = get_file_name( dirname, file->d_name );
269 } else if ( !strcasecmp( file->d_name, TBINDFILE )) {
270 bfile = get_file_name( dirname, file->d_name );
277 /* look for search requests */
279 snum = get_search_filters( sfile, sreqs, sbase );
282 /* look for read requests */
284 rnum = get_read_entries( rfile, rreqs );
287 /* look for modrdn requests */
289 mnum = get_read_entries( mfile, mreqs );
292 /* look for modify requests */
294 modnum = get_search_filters( modfile, modreqs, moddn );
297 /* look for bind requests */
299 bnum = get_search_filters( bfile, bcreds, breqs );
302 /* setup friendly option */
304 switch ( friendly ) {
313 /* NOTE: right now we don't need it more than twice */
319 snprintf( sloops, sizeof( sloops ), "%d", 10 * loops );
320 snprintf( rloops, sizeof( rloops ), "%d", 20 * loops );
321 snprintf( aloops, sizeof( aloops ), "%d", loops );
322 snprintf( mloops, sizeof( mloops ), "%d", loops );
323 snprintf( modloops, sizeof( modloops ), "%d", loops );
324 snprintf( bloops, sizeof( bloops ), "%d", 20 * loops );
327 * generate the search clients
331 snprintf( scmd, sizeof scmd, "%s" LDAP_DIRSEP SEARCHCMD,
333 sargs[sanum++] = scmd;
335 sargs[sanum++] = "-H";
336 sargs[sanum++] = uri;
338 sargs[sanum++] = "-h";
339 sargs[sanum++] = host;
340 sargs[sanum++] = "-p";
341 sargs[sanum++] = port;
343 sargs[sanum++] = "-D";
344 sargs[sanum++] = manager;
345 sargs[sanum++] = "-w";
346 sargs[sanum++] = passwd;
347 sargs[sanum++] = "-l";
348 sargs[sanum++] = sloops;
349 sargs[sanum++] = "-L";
350 sargs[sanum++] = outerloops;
351 sargs[sanum++] = "-r";
352 sargs[sanum++] = retries;
353 sargs[sanum++] = "-t";
354 sargs[sanum++] = delay;
356 sargs[sanum++] = friendlyOpt;
358 sargs[sanum++] = "-b";
359 sargs[sanum++] = NULL; /* will hold the search base */
360 sargs[sanum++] = "-f";
361 sargs[sanum++] = NULL; /* will hold the search request */
362 sargs[sanum++] = NULL;
365 * generate the read clients
369 snprintf( rcmd, sizeof rcmd, "%s" LDAP_DIRSEP READCMD,
371 rargs[ranum++] = rcmd;
373 rargs[ranum++] = "-H";
374 rargs[ranum++] = uri;
376 rargs[ranum++] = "-h";
377 rargs[ranum++] = host;
378 rargs[ranum++] = "-p";
379 rargs[ranum++] = port;
381 rargs[ranum++] = "-l";
382 rargs[ranum++] = rloops;
383 rargs[ranum++] = "-L";
384 rargs[ranum++] = outerloops;
385 rargs[ranum++] = "-r";
386 rargs[ranum++] = retries;
387 rargs[ranum++] = "-t";
388 rargs[ranum++] = delay;
390 rargs[ranum++] = friendlyOpt;
392 rargs[ranum++] = "-e";
393 rargs[ranum++] = NULL; /* will hold the read entry */
394 rargs[ranum++] = NULL;
397 * generate the modrdn clients
401 snprintf( mcmd, sizeof mcmd, "%s" LDAP_DIRSEP MODRDNCMD,
403 margs[manum++] = mcmd;
405 margs[manum++] = "-H";
406 margs[manum++] = uri;
408 margs[manum++] = "-h";
409 margs[manum++] = host;
410 margs[manum++] = "-p";
411 margs[manum++] = port;
413 margs[manum++] = "-D";
414 margs[manum++] = manager;
415 margs[manum++] = "-w";
416 margs[manum++] = passwd;
417 margs[manum++] = "-l";
418 margs[manum++] = mloops;
419 margs[manum++] = "-L";
420 margs[manum++] = outerloops;
421 margs[manum++] = "-r";
422 margs[manum++] = retries;
423 margs[manum++] = "-t";
424 margs[manum++] = delay;
426 margs[manum++] = friendlyOpt;
428 margs[manum++] = "-e";
429 margs[manum++] = NULL; /* will hold the modrdn entry */
430 margs[manum++] = NULL;
433 * generate the modify clients
437 snprintf( modcmd, sizeof modcmd, "%s" LDAP_DIRSEP MODIFYCMD,
439 modargs[modanum++] = modcmd;
441 modargs[modanum++] = "-H";
442 modargs[modanum++] = uri;
444 modargs[modanum++] = "-h";
445 modargs[modanum++] = host;
446 modargs[modanum++] = "-p";
447 modargs[modanum++] = port;
449 modargs[modanum++] = "-D";
450 modargs[modanum++] = manager;
451 modargs[modanum++] = "-w";
452 modargs[modanum++] = passwd;
453 modargs[modanum++] = "-l";
454 modargs[modanum++] = modloops;
455 modargs[modanum++] = "-L";
456 modargs[modanum++] = outerloops;
457 modargs[modanum++] = "-r";
458 modargs[modanum++] = retries;
459 modargs[modanum++] = "-t";
460 modargs[modanum++] = delay;
462 modargs[modanum++] = friendlyOpt;
464 modargs[modanum++] = "-e";
465 modargs[modanum++] = NULL; /* will hold the modify entry */
466 modargs[modanum++] = "-a";;
467 modargs[modanum++] = NULL; /* will hold the ava */
468 modargs[modanum++] = NULL;
471 * generate the add/delete clients
475 snprintf( acmd, sizeof acmd, "%s" LDAP_DIRSEP ADDCMD,
477 aargs[aanum++] = acmd;
479 aargs[aanum++] = "-H";
480 aargs[aanum++] = uri;
482 aargs[aanum++] = "-h";
483 aargs[aanum++] = host;
484 aargs[aanum++] = "-p";
485 aargs[aanum++] = port;
487 aargs[aanum++] = "-D";
488 aargs[aanum++] = manager;
489 aargs[aanum++] = "-w";
490 aargs[aanum++] = passwd;
491 aargs[aanum++] = "-l";
492 aargs[aanum++] = aloops;
493 aargs[aanum++] = "-L";
494 aargs[aanum++] = outerloops;
495 aargs[aanum++] = "-r";
496 aargs[aanum++] = retries;
497 aargs[aanum++] = "-t";
498 aargs[aanum++] = delay;
500 aargs[aanum++] = friendlyOpt;
502 aargs[aanum++] = "-f";
503 aargs[aanum++] = NULL; /* will hold the add data file */
504 aargs[aanum++] = NULL;
507 * generate the bind clients
511 snprintf( bcmd, sizeof bcmd, "%s" LDAP_DIRSEP BINDCMD,
513 bargs[banum++] = bcmd;
515 bargs[banum++] = "-H";
516 bargs[banum++] = uri;
518 bargs[banum++] = "-h";
519 bargs[banum++] = host;
520 bargs[banum++] = "-p";
521 bargs[banum++] = port;
523 bargs[banum++] = "-l";
524 bargs[banum++] = bloops;
525 bargs[banum++] = "-L";
526 bargs[banum++] = outerloops;
528 bargs[banum++] = "-r";
529 bargs[banum++] = retries;
530 bargs[banum++] = "-t";
531 bargs[banum++] = delay;
534 bargs[banum++] = friendlyOpt;
536 bargs[banum++] = "-D";
537 bargs[banum++] = NULL;
538 bargs[banum++] = "-w";
539 bargs[banum++] = NULL;
540 bargs[banum++] = NULL;
542 for ( j = 0; j < MAXREQS; j++ ) {
545 sargs[sanum - 2] = sreqs[j];
546 sargs[sanum - 4] = sbase[j];
547 fork_child( scmd, sargs );
553 rargs[ranum - 2] = rreqs[j];
554 fork_child( rcmd, rargs );
560 margs[manum - 2] = mreqs[j];
561 fork_child( mcmd, margs );
566 modargs[modanum - 4] = moddn[j];
567 modargs[modanum - 2] = modreqs[j];
568 fork_child( modcmd, modargs );
574 aargs[aanum - 2] = afiles[j];
575 fork_child( acmd, aargs );
581 bargs[banum - 4] = breqs[j];
582 bargs[banum - 2] = bcreds[j];
583 fork_child( bcmd, bargs );
591 exit( EXIT_SUCCESS );
595 get_file_name( char *dirname, char *filename )
597 char buf[MAXPATHLEN];
599 snprintf( buf, sizeof buf, "%s" LDAP_DIRSEP "%s",
601 return( strdup( buf ));
606 get_search_filters( char *filename, char *filters[], char *bases[] )
611 if ( (fp = fopen( filename, "r" )) != NULL ) {
614 while (( filter < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
617 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
619 bases[filter] = ArgDup( line );
620 fgets( line, BUFSIZ, fp );
621 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
624 filters[filter++] = ArgDup( line );
635 get_read_entries( char *filename, char *entries[] )
640 if ( (fp = fopen( filename, "r" )) != NULL ) {
643 while (( entry < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
646 if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
648 entries[entry++] = ArgDup( line );
659 fork_child( char *prog, char **args )
663 wait4kids( maxkids );
665 switch ( pid = fork() ) {
668 /* The __LIBASCII execvp only handles ASCII "prog",
669 * we still need to translate the arg vec ourselves.
671 { char *arg2[MAXREQS];
674 for (i=0; args[i]; i++) {
675 arg2[i] = ArgDup(args[i]);
681 execvp( prog, args );
682 tester_perror( "execvp" );
683 exit( EXIT_FAILURE );
686 case -1: /* trouble */
687 tester_perror( "fork" );
690 default: /* parent */
697 wait4kids( int nkidval )
701 while ( nkids >= nkidval ) {
704 if ( WIFSTOPPED(status) ) {
706 "stopping: child stopped with signal %d\n",
707 (int) WSTOPSIG(status) );
709 } else if ( WIFSIGNALED(status) ) {
711 "stopping: child terminated with signal %d%s\n",
712 (int) WTERMSIG(status),
714 WCOREDUMP(status) ? ", core dumped" : ""
719 exit( WEXITSTATUS(status) );
721 } else if ( WEXITSTATUS(status) != 0 ) {
723 "stopping: child exited with status %d\n",
724 (int) WEXITSTATUS(status) );
725 exit( WEXITSTATUS(status) );
735 wait4kids( int nkidval )
739 while ( nkids >= nkidval ) {
740 rc = WaitForMultipleObjects( nkids, children, FALSE, INFINITE );
741 for ( i=rc - WAIT_OBJECT_0; i<nkids-1; i++)
742 children[i] = children[i+1];
748 fork_child( char *prog, char **args )
752 wait4kids( maxkids );
754 rc = _spawnvp( _P_NOWAIT, prog, args );
757 tester_perror( "_spawnvp" );
759 children[nkids++] = (HANDLE)rc;