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