]> git.sur5r.net Git - openldap/blob - tests/progs/slapd-addel.c
allow a friendly behavior of write stress testers...
[openldap] / tests / progs / slapd-addel.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/param.h>
28 #include <ac/socket.h>
29 #include <ac/string.h>
30 #include <ac/unistd.h>
31 #include <ac/wait.h>
32
33 #define LDAP_DEPRECATED 1
34 #include <ldap.h>
35
36 #define LOOPS   100
37 #define RETRIES 0
38
39 static char *
40 get_add_entry( char *filename, LDAPMod ***mods );
41
42 static void
43 do_addel( char *uri, char *host, int port, char *manager, char *passwd,
44         char *dn, LDAPMod **attrs, int maxloop, int maxretries, int delay,
45         int friendly );
46
47 static void
48 usage( char *name )
49 {
50         fprintf( stderr,
51                 "usage: %s "
52                 "-H <uri> | ([-h <host>] -p <port>) "
53                 "-D <manager> "
54                 "-w <passwd> "
55                 "-f <addfile> "
56                 "[-l <loops>] "
57                 "[-r <maxretries>] "
58                 "[-t <delay>]\n",
59                         name );
60         exit( EXIT_FAILURE );
61 }
62
63 int
64 main( int argc, char **argv )
65 {
66         int             i;
67         char            *host = "localhost";
68         char            *uri = NULL;
69         int             port = -1;
70         char            *manager = NULL;
71         char            *passwd = NULL;
72         char            *filename = NULL;
73         char            *entry = NULL;
74         int             loops = LOOPS;
75         int             retries = RETRIES;
76         int             delay = 0;
77         int             friendly = 0;
78         LDAPMod         **attrs = NULL;
79
80         while ( (i = getopt( argc, argv, "FH:h:p:D:w:f:l:r:t:" )) != EOF ) {
81                 switch( i ) {
82                 case 'F':
83                         friendly++;
84                         break;
85                         
86                 case 'H':               /* the server's URI */
87                         uri = strdup( optarg );
88                         break;
89
90                 case 'h':               /* the servers host */
91                         host = strdup( optarg );
92                         break;
93
94                 case 'p':               /* the servers port */
95                         port = atoi( optarg );
96                         break;
97
98                 case 'D':               /* the servers manager */
99                         manager = strdup( optarg );
100                         break;
101
102                 case 'w':               /* the server managers password */
103                         passwd = strdup( optarg );
104                         break;
105
106                 case 'f':               /* file with entry search request */
107                         filename = strdup( optarg );
108                         break;
109
110                 case 'l':               /* the number of loops */
111                         loops = atoi( optarg );
112                         break;
113
114                 case 'r':               /* number of retries */
115                         retries = atoi( optarg );
116                         break;
117
118                 case 't':               /* delay in seconds */
119                         delay = atoi( optarg );
120                         break;
121
122                 default:
123                         usage( argv[0] );
124                         break;
125                 }
126         }
127
128         if (( filename == NULL ) || ( port == -1 && uri == NULL ) ||
129                                 ( manager == NULL ) || ( passwd == NULL ))
130                 usage( argv[0] );
131
132         entry = get_add_entry( filename, &attrs );
133         if (( entry == NULL ) || ( *entry == '\0' )) {
134
135                 fprintf( stderr, "%s: invalid entry DN in file \"%s\".\n",
136                                 argv[0], filename );
137                 exit( EXIT_FAILURE );
138
139         }
140
141         if (( attrs == NULL ) || ( *attrs == '\0' )) {
142
143                 fprintf( stderr, "%s: invalid attrs in file \"%s\".\n",
144                                 argv[0], filename );
145                 exit( EXIT_FAILURE );
146
147         }
148
149         do_addel( uri, host, port, manager, passwd, entry, attrs,
150                         loops, retries, delay, friendly );
151
152         exit( EXIT_SUCCESS );
153 }
154
155
156 static void
157 addmodifyop( LDAPMod ***pmodsp, int modop, char *attr, char *value, int vlen )
158 {
159     LDAPMod             **pmods;
160     int                 i, j;
161     struct berval       *bvp;
162
163     pmods = *pmodsp;
164     modop |= LDAP_MOD_BVALUES;
165
166     i = 0;
167     if ( pmods != NULL ) {
168                 for ( ; pmods[ i ] != NULL; ++i ) {
169                 if ( strcasecmp( pmods[ i ]->mod_type, attr ) == 0 &&
170                         pmods[ i ]->mod_op == modop ) {
171                                 break;
172                 }
173                 }
174     }
175
176     if ( pmods == NULL || pmods[ i ] == NULL ) {
177                 if (( pmods = (LDAPMod **)realloc( pmods, (i + 2) *
178                         sizeof( LDAPMod * ))) == NULL ) {
179                         perror( "realloc" );
180                         exit( EXIT_FAILURE );
181                 }
182                 *pmodsp = pmods;
183                 pmods[ i + 1 ] = NULL;
184                 if (( pmods[ i ] = (LDAPMod *)calloc( 1, sizeof( LDAPMod )))
185                         == NULL ) {
186                         perror( "calloc" );
187                         exit( EXIT_FAILURE );
188                 }
189                 pmods[ i ]->mod_op = modop;
190                 if (( pmods[ i ]->mod_type = strdup( attr )) == NULL ) {
191                 perror( "strdup" );
192                 exit( EXIT_FAILURE );
193                 }
194     }
195
196     if ( value != NULL ) {
197                 j = 0;
198                 if ( pmods[ i ]->mod_bvalues != NULL ) {
199                 for ( ; pmods[ i ]->mod_bvalues[ j ] != NULL; ++j ) {
200                                 ;
201                 }
202                 }
203                 if (( pmods[ i ]->mod_bvalues =
204                         (struct berval **)ber_memrealloc( pmods[ i ]->mod_bvalues,
205                         (j + 2) * sizeof( struct berval * ))) == NULL ) {
206                         perror( "ber_realloc" );
207                         exit( EXIT_FAILURE );
208                 }
209                 pmods[ i ]->mod_bvalues[ j + 1 ] = NULL;
210                 if (( bvp = (struct berval *)ber_memalloc( sizeof( struct berval )))
211                         == NULL ) {
212                         perror( "malloc" );
213                         exit( EXIT_FAILURE );
214                 }
215                 pmods[ i ]->mod_bvalues[ j ] = bvp;
216
217             bvp->bv_len = vlen;
218             if (( bvp->bv_val = (char *)malloc( vlen + 1 )) == NULL ) {
219                         perror( "malloc" );
220                         exit( EXIT_FAILURE );
221             }
222             AC_MEMCPY( bvp->bv_val, value, vlen );
223             bvp->bv_val[ vlen ] = '\0';
224     }
225 }
226
227
228 static char *
229 get_add_entry( char *filename, LDAPMod ***mods )
230 {
231         FILE    *fp;
232         char    *entry = NULL;
233
234         if ( (fp = fopen( filename, "r" )) != NULL ) {
235                 char  line[BUFSIZ];
236
237                 if ( fgets( line, BUFSIZ, fp )) {
238                         char *nl;
239
240                         if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
241                                 *nl = '\0';
242                         entry = strdup( line );
243
244                 }
245
246                 while ( fgets( line, BUFSIZ, fp )) {
247                         char    *nl;
248                         char    *value;
249
250                         if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
251                                 *nl = '\0';
252
253                         if ( *line == '\0' ) break;
254                         if ( !( value = strchr( line, ':' ))) break;
255
256                         *value++ = '\0'; 
257                         while ( *value && isspace( (unsigned char) *value ))
258                                 value++;
259
260                         addmodifyop( mods, LDAP_MOD_ADD, line, value, strlen( value ));
261
262                 }
263                 fclose( fp );
264         }
265
266         return( entry );
267 }
268
269
270 static void
271 do_addel(
272         char *uri,
273         char *host,
274         int port,
275         char *manager,
276         char *passwd,
277         char *entry,
278         LDAPMod **attrs,
279         int maxloop,
280         int maxretries,
281         int delay,
282         int friendly
283 )
284 {
285         LDAP    *ld = NULL;
286         int     i = 0, do_retry = maxretries;
287         pid_t   pid = getpid();
288         int     rc = LDAP_SUCCESS;
289
290 retry:;
291         if ( uri ) {
292                 ldap_initialize( &ld, uri );
293         } else {
294                 ld = ldap_init( host, port );
295         }
296         if ( ld == NULL ) {
297                 perror( "ldap_init" );
298                 exit( EXIT_FAILURE );
299         }
300
301         {
302                 int version = LDAP_VERSION3;
303                 (void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION,
304                         &version ); 
305         }
306
307         if ( do_retry == maxretries ) {
308                 fprintf( stderr, "PID=%ld - Add/Delete(%d): entry=\"%s\".\n",
309                         (long) pid, maxloop, entry );
310         }
311
312         rc = ldap_bind_s( ld, manager, passwd, LDAP_AUTH_SIMPLE );
313         if ( rc != LDAP_SUCCESS ) {
314                 ldap_perror( ld, "ldap_bind" );
315                 switch ( rc ) {
316                 case LDAP_BUSY:
317                 case LDAP_UNAVAILABLE:
318                         if ( do_retry > 0 ) {
319                                 do_retry--;
320                                 if ( delay != 0 ) {
321                                     sleep( delay );
322                                 }
323                                 goto retry;
324                         }
325                 /* fallthru */
326                 default:
327                         break;
328                 }
329                 exit( EXIT_FAILURE );
330         }
331
332         for ( ; i < maxloop; i++ ) {
333
334                 /* add the entry */
335                 rc = ldap_add_s( ld, entry, attrs );
336                 if ( rc != LDAP_SUCCESS ) {
337                         ldap_perror( ld, "ldap_add" );
338                         switch ( rc ) {
339                         case LDAP_ALREADY_EXISTS:
340                                 /* NOTE: this likely means
341                                  * the delete failed
342                                  * during the previous round... */
343                                 if ( !friendly ) {
344                                         goto done;
345                                 }
346                                 break;
347
348                         case LDAP_BUSY:
349                         case LDAP_UNAVAILABLE:
350                                 if ( do_retry > 0 ) {
351                                         do_retry--;
352                                         goto retry;
353                                 }
354                                 /* fall thru */
355
356                         default:
357                                 goto done;
358                         }
359                 }
360
361 #if 0
362                 /* wait a second for the add to really complete */
363                 /* This masks some race conditions though. */
364                 sleep( 1 );
365 #endif
366
367                 /* now delete the entry again */
368                 rc = ldap_delete_s( ld, entry );
369                 if ( rc != LDAP_SUCCESS ) {
370                         ldap_perror( ld, "ldap_delete" );
371                         switch ( rc ) {
372                         case LDAP_NO_SUCH_OBJECT:
373                                 /* NOTE: this likely means
374                                  * the add failed
375                                  * during the previous round... */
376                                 if ( !friendly ) {
377                                         goto done;
378                                 }
379                                 break;
380
381                         case LDAP_BUSY:
382                         case LDAP_UNAVAILABLE:
383                                 if ( do_retry > 0 ) {
384                                         do_retry--;
385                                         goto retry;
386                                 }
387                                 /* fall thru */
388
389                         default:
390                                 goto done;
391                         }
392                 }
393         }
394
395 done:;
396         fprintf( stderr, " PID=%ld - Add/Delete done (%d).\n", (long) pid, rc );
397
398         ldap_unbind( ld );
399 }
400
401