]> git.sur5r.net Git - openldap/blob - tests/progs/slapd-modify.c
allow a friendly behavior of write stress testers...
[openldap] / tests / progs / slapd-modify.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
16 #include "portable.h"
17
18 #include <stdio.h>
19
20 #include <ac/stdlib.h>
21
22 #include <ac/ctype.h>
23 #include <ac/param.h>
24 #include <ac/socket.h>
25 #include <ac/string.h>
26 #include <ac/unistd.h>
27 #include <ac/wait.h>
28
29 #define LDAP_DEPRECATED 1
30 #include <ldap.h>
31
32 #define LOOPS   100
33 #define RETRIES 0
34
35 static void
36 do_modify( char *uri, char *host, int port, char *manager, char *passwd,
37                 char *entry, char *attr, char *value, int maxloop,
38                 int maxretries, int delay, int friendly );
39
40
41 static void
42 usage( char *name )
43 {
44         fprintf( stderr,
45                 "usage: %s "
46                 "-H <uri> | ([-h <host>] -p <port>) "
47                 "-D <manager> "
48                 "-w <passwd> "
49                 "-e <entry> "
50                 "[-l <loops>] "
51                 "[-r <maxretries>] "
52                 "[-t <delay>]\n",
53                         name );
54         exit( EXIT_FAILURE );
55 }
56
57 int
58 main( int argc, char **argv )
59 {
60         int             i;
61         char            *uri = NULL;
62         char            *host = "localhost";
63         int             port = -1;
64         char            *manager = NULL;
65         char            *passwd = NULL;
66         char            *entry = NULL;
67         char            *ava = NULL;
68         char            *value = NULL;
69         int             loops = LOOPS;
70         int             retries = RETRIES;
71         int             delay = 0;
72         int             friendly = 0;
73
74         while ( (i = getopt( argc, argv, "FH:h:p:D:w:e:a:l:r:t:" )) != EOF ) {
75                 switch( i ) {
76                 case 'F':
77                         friendly++;
78                         break;
79
80                 case 'H':               /* the server uri */
81                         uri = strdup( optarg );
82                         break;
83
84                 case 'h':               /* the servers host */
85                         host = strdup( optarg );
86                         break;
87
88                 case 'p':               /* the servers port */
89                         port = atoi( optarg );
90                         break;
91
92                 case 'D':               /* the servers manager */
93                         manager = strdup( optarg );
94                         break;
95
96                 case 'w':               /* the server managers password */
97                         passwd = strdup( optarg );
98                         break;
99
100                 case 'e':               /* entry to modify */
101                         entry = strdup( optarg );
102                         break;
103
104                 case 'a':
105                         ava = strdup( optarg );
106                         break;
107
108                 case 'l':               /* the number of loops */
109                         loops = atoi( optarg );
110                         break;
111
112                 case 'r':               /* number of retries */
113                         retries = atoi( optarg );
114                         break;
115
116                 case 't':               /* delay in seconds */
117                         delay = atoi( optarg );
118                         break;
119
120                 default:
121                         usage( argv[0] );
122                         break;
123                 }
124         }
125
126         if (( entry == NULL ) || ( ava == NULL ) || ( port == -1 && uri == NULL ))
127                 usage( argv[0] );
128
129         if ( *entry == '\0' ) {
130
131                 fprintf( stderr, "%s: invalid EMPTY entry DN.\n",
132                                 argv[0] );
133                 exit( EXIT_FAILURE );
134
135         }
136         if ( *ava  == '\0' ) {
137                 fprintf( stderr, "%s: invalid EMPTY AVA.\n",
138                                 argv[0] );
139                 exit( EXIT_FAILURE );
140         }
141         
142         if ( !( value = strchr( ava, ':' ))) {
143                 fprintf( stderr, "%s: invalid AVA.\n",
144                                 argv[0] );
145                 exit( EXIT_FAILURE );
146         }
147         *value++ = '\0'; 
148         while ( *value && isspace( (unsigned char) *value ))
149                 value++;
150
151         do_modify( uri, host, port, manager, passwd, entry, ava, value,
152                         loops, retries, delay, friendly );
153         exit( EXIT_SUCCESS );
154 }
155
156
157 static void
158 do_modify( char *uri, char *host, int port, char *manager,
159         char *passwd, char *entry, char* attr, char* value,
160         int maxloop, int maxretries, int delay, int friendly )
161 {
162         LDAP    *ld = NULL;
163         int     i = 0, do_retry = maxretries;
164         pid_t   pid;
165         int     rc = LDAP_SUCCESS;
166
167         struct ldapmod mod;
168         struct ldapmod *mods[2];
169         char *values[2];
170
171         pid = getpid();
172         
173         values[0] = value;
174         values[1] = NULL;
175         mod.mod_op = LDAP_MOD_ADD;
176         mod.mod_type = attr;
177         mod.mod_values = values;
178         mods[0] = &mod;
179         mods[1] = NULL;
180
181 retry:;
182         if ( uri ) {
183                 ldap_initialize( &ld, uri );
184         } else {
185                 ld = ldap_init( host, port );
186         }
187         if ( ld == NULL ) {
188                 perror( "ldap_init" );
189                 exit( EXIT_FAILURE );
190         }
191
192         {
193                 int version = LDAP_VERSION3;
194                 (void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION,
195                         &version ); 
196         }
197
198         if ( do_retry == maxretries ) {
199                 fprintf( stderr, "PID=%ld - Modify(%d): entry=\"%s\".\n",
200                         (long) pid, maxloop, entry );
201         }
202
203         rc = ldap_bind_s( ld, manager, passwd, LDAP_AUTH_SIMPLE );
204         if ( rc != LDAP_SUCCESS ) {
205                 ldap_perror( ld, "ldap_bind" );
206                 switch ( rc ) {
207                 case LDAP_BUSY:
208                 case LDAP_UNAVAILABLE:
209                         if ( do_retry > 0 ) {
210                                 do_retry--;
211                                 if ( delay > 0 ) {
212                                     sleep( delay );
213                                 }
214                                 goto retry;
215                         }
216                 /* fallthru */
217                 default:
218                         break;
219                 }
220                 exit( EXIT_FAILURE );
221         }
222
223         for ( ; i < maxloop; i++ ) {
224                 mod.mod_op = LDAP_MOD_ADD;
225                 rc = ldap_modify_s( ld, entry, mods );
226                 if ( rc != LDAP_SUCCESS ) {
227                         ldap_perror( ld, "ldap_modify" );
228                         switch ( rc ) {
229                         case LDAP_TYPE_OR_VALUE_EXISTS:
230                                 /* NOTE: this likely means
231                                  * the second modify failed
232                                  * during the previous round... */
233                                 if ( !friendly ) {
234                                         goto done;
235                                 }
236                                 break;
237
238                         case LDAP_BUSY:
239                         case LDAP_UNAVAILABLE:
240                                 if ( do_retry > 0 ) {
241                                         do_retry--;
242                                         goto retry;
243                                 }
244                                 /* fall thru */
245
246                         default:
247                                 goto done;
248                         }
249                 }
250                 
251                 mod.mod_op = LDAP_MOD_DELETE;
252                 rc = ldap_modify_s( ld, entry, mods );
253                 if ( rc != LDAP_SUCCESS ) {
254                         ldap_perror( ld, "ldap_modify" );
255                         switch ( rc ) {
256                         case LDAP_NO_SUCH_ATTRIBUTE:
257                                 /* NOTE: this likely means
258                                  * the first modify failed
259                                  * during the previous round... */
260                                 if ( !friendly ) {
261                                         goto done;
262                                 }
263                                 break;
264
265                         case LDAP_BUSY:
266                         case LDAP_UNAVAILABLE:
267                                 if ( do_retry > 0 ) {
268                                         do_retry--;
269                                         goto retry;
270                                 }
271                                 /* fall thru */
272
273                         default:
274                                 goto done;
275                         }
276                 }
277
278         }
279
280 done:;
281         fprintf( stderr, " PID=%ld - Modify done (%d).\n", (long) pid, rc );
282
283         ldap_unbind( ld );
284 }
285
286