]> git.sur5r.net Git - openldap/blob - servers/slapd/back-bdb/tools.c
Pass parent EntryInfo instead of parent DN to dn2id_add/delete.
[openldap] / servers / slapd / back-bdb / tools.c
1 /* tools.c - tools for slap tools */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 #include "portable.h"
9
10 #include <stdio.h>
11 #include <ac/string.h>
12
13 #include "back-bdb.h"
14
15 static DBC *cursor = NULL;
16 static DBT key, data;
17
18 typedef struct dn_id {
19         ID id;
20         struct berval dn;
21 } dn_id;
22
23 #define HOLE_SIZE       4096
24 dn_id hbuf[HOLE_SIZE], *holes = hbuf;
25 unsigned nhmax = HOLE_SIZE;
26 unsigned nholes;
27
28 int bdb_tool_entry_open(
29         BackendDB *be, int mode )
30 {
31         /* initialize key and data thangs */
32         DBTzero( &key );
33         DBTzero( &data );
34         key.flags = DB_DBT_REALLOC;
35         data.flags = DB_DBT_REALLOC;
36
37         return 0;
38 }
39
40 int bdb_tool_entry_close(
41         BackendDB *be )
42 {
43         assert( be != NULL );
44
45         if( key.data ) {
46                 ch_free( key.data );
47                 key.data = NULL;
48         }
49         if( data.data ) {
50                 ch_free( data.data );
51                 data.data = NULL;
52         }
53
54         if( cursor ) {
55                 cursor->c_close( cursor );
56                 cursor = NULL;
57         }
58
59         if( nholes ) {
60                 unsigned i;
61                 fprintf( stderr, "Error, entries missing!\n");
62                 for (i=0; i<nholes; i++) {
63                         fprintf(stderr, "  entry %d: %s\n",
64                                 holes[i].id, holes[i].dn.bv_val, 0);
65                 }
66                 return -1;
67         }
68                         
69         return 0;
70 }
71
72 ID bdb_tool_entry_next(
73         BackendDB *be )
74 {
75         int rc;
76         ID id;
77         struct bdb_info *bdb = (struct bdb_info *) be->be_private;
78
79         assert( be != NULL );
80         assert( slapMode & SLAP_TOOL_MODE );
81         assert( bdb != NULL );
82         
83         if (cursor == NULL) {
84                 rc = bdb->bi_id2entry->bdi_db->cursor(
85                         bdb->bi_id2entry->bdi_db, NULL, &cursor,
86                         bdb->bi_db_opflags );
87                 if( rc != 0 ) {
88                         return NOID;
89                 }
90         }
91
92         rc = cursor->c_get( cursor, &key, &data, DB_NEXT );
93
94         if( rc != 0 ) {
95                 return NOID;
96         }
97
98         if( data.data == NULL ) {
99                 return NOID;
100         }
101
102         AC_MEMCPY( &id, key.data, key.size );
103         return id;
104 }
105
106 Entry* bdb_tool_entry_get( BackendDB *be, ID id )
107 {
108         int rc;
109         Entry *e;
110         struct berval bv;
111
112         assert( be != NULL );
113         assert( slapMode & SLAP_TOOL_MODE );
114         assert( data.data != NULL );
115
116         DBT2bv( &data, &bv );
117
118         rc = entry_decode( &bv, &e );
119
120         if( rc == LDAP_SUCCESS ) {
121                 e->e_id = id;
122         }
123
124 #ifdef BDB_HIER
125         bdb_fix_dn(be, id, e);
126 #endif
127
128         return e;
129 }
130
131 int bdb_tool_next_id(
132         BackendDB *be,
133         DB_TXN *tid,
134         Entry *e,
135         struct berval *text,
136         int hole,
137         u_int32_t locker )
138 {
139         struct bdb_info *bdb = (struct bdb_info *) be->be_private;
140         struct berval dn = e->e_nname;
141         struct berval pdn;
142         EntryInfo *ei = NULL;
143         int rc;
144
145         rc = bdb_cache_find_entry_ndn2id( be, tid, &dn, &ei, locker, NULL );
146         if ( ei ) bdb_cache_entryinfo_unlock( ei );
147         if ( rc == DB_NOTFOUND ) {
148                 if ( be_issuffix( be, &dn ) ) {
149                         pdn = slap_empty_bv;
150                 } else {
151                         dnParent( &dn, &pdn );
152                         e->e_nname = pdn;
153                         rc = bdb_tool_next_id( be, tid, e, text, 1, locker );
154                         if ( rc ) {
155                                 return rc;
156                         }
157                 }
158                 rc = bdb_next_id( be, tid, &e->e_id );
159                 if ( rc ) {
160                         snprintf( text->bv_val, text->bv_len,
161                                 "next_id failed: %s (%d)",
162                                 db_strerror(rc), rc );
163 #ifdef NEW_LOGGING
164                 LDAP_LOG ( TOOLS, ERR, 
165                         "=> bdb_tool_entry_put: %s\n", text->bv_val, 0, 0 );
166 #else
167                 Debug( LDAP_DEBUG_ANY,
168                         "=> bdb_tool_entry_put: %s\n", text->bv_val, 0, 0 );
169 #endif
170                         return rc;
171                 }
172                 e->e_nname = dn;
173                 rc = bdb_dn2id_add( be, tid, ei, e, NULL );
174                 if ( rc ) {
175                         snprintf( text->bv_val, text->bv_len, 
176                                 "dn2id_add failed: %s (%d)",
177                                 db_strerror(rc), rc );
178 #ifdef NEW_LOGGING
179                 LDAP_LOG ( TOOLS, ERR, 
180                         "=> bdb_tool_entry_put: %s\n", text->bv_val, 0, 0 );
181 #else
182                 Debug( LDAP_DEBUG_ANY,
183                         "=> bdb_tool_entry_put: %s\n", text->bv_val, 0, 0 );
184 #endif
185                 } else if ( hole ) {
186                         if ( nholes == nhmax - 1 ) {
187                                 if ( holes == hbuf ) {
188                                         holes = ch_malloc( nhmax * sizeof(ID) * 2 );
189                                         AC_MEMCPY( holes, hbuf, sizeof(hbuf) );
190                                 } else {
191                                         holes = ch_realloc( holes, nhmax * sizeof(ID) * 2 );
192                                 }
193                                 nhmax *= 2;
194                         }
195                         ber_dupbv( &holes[nholes].dn, &dn );
196                         holes[nholes++].id = e->e_id;
197                 }
198         } else if ( !hole ) {
199                 unsigned i;
200
201                 for ( i=0; i<nholes; i++) {
202                         if ( holes[i].id == e->e_id ) {
203                                 int j;
204                                 free(holes[i].dn.bv_val);
205                                 for (j=i;j<nholes;j++) holes[j] = holes[j+1];
206                                 holes[j].id = 0;
207                                 nholes--;
208                                 break;
209                         } else if ( holes[i].id > e->e_id ) {
210                                 break;
211                         }
212                 }
213         }
214         return rc;
215 }
216
217 ID bdb_tool_entry_put(
218         BackendDB *be,
219         Entry *e,
220         struct berval *text )
221 {
222         int rc;
223         struct bdb_info *bdb = (struct bdb_info *) be->be_private;
224         DB_TXN *tid = NULL;
225         Operation op = {0};
226         u_int32_t locker;
227
228         assert( be != NULL );
229         assert( slapMode & SLAP_TOOL_MODE );
230
231         assert( text );
232         assert( text->bv_val );
233         assert( text->bv_val[0] == '\0' );      /* overconservative? */
234
235 #ifdef NEW_LOGGING
236         LDAP_LOG ( TOOLS, ARGS, "=> bdb_tool_entry_put( %ld, \"%s\" )\n",
237                 (long) e->e_id, e->e_dn, 0 );
238 #else
239         Debug( LDAP_DEBUG_TRACE, "=> bdb_tool_entry_put( %ld, \"%s\" )\n",
240                 (long) e->e_id, e->e_dn, 0 );
241 #endif
242
243         rc = TXN_BEGIN( bdb->bi_dbenv, NULL, &tid, 
244                 bdb->bi_db_opflags );
245         if( rc != 0 ) {
246                 snprintf( text->bv_val, text->bv_len,
247                         "txn_begin failed: %s (%d)",
248                         db_strerror(rc), rc );
249 #ifdef NEW_LOGGING
250         LDAP_LOG ( TOOLS, ERR, "=> bdb_tool_entry_put: %s\n", text->bv_val, 0, 0 );
251 #else
252                 Debug( LDAP_DEBUG_ANY,
253                         "=> bdb_tool_entry_put: %s\n",
254                          text->bv_val, 0, 0 );
255 #endif
256                 return NOID;
257         }
258
259         locker = TXN_ID( tid );
260         /* add dn2id indices */
261         rc = bdb_tool_next_id( be, tid, e, text, 0, locker );
262         if( rc != 0 ) {
263                 goto done;
264         }
265
266         /* id2entry index */
267         rc = bdb_id2entry_add( be, tid, e );
268         if( rc != 0 ) {
269                 snprintf( text->bv_val, text->bv_len,
270                                 "id2entry_add failed: %s (%d)",
271                                 db_strerror(rc), rc );
272 #ifdef NEW_LOGGING
273                 LDAP_LOG ( TOOLS, ERR, 
274                         "=> bdb_tool_entry_put: %s\n", text->bv_val, 0, 0 );
275 #else
276                 Debug( LDAP_DEBUG_ANY,
277                         "=> bdb_tool_entry_put: %s\n", text->bv_val, 0, 0 );
278 #endif
279                 goto done;
280         }
281
282         op.o_bd = be;
283         op.o_tmpmemctx = NULL;
284         op.o_tmpmfuncs = &ch_mfuncs;
285         rc = bdb_index_entry_add( &op, tid, e );
286         if( rc != 0 ) {
287                 snprintf( text->bv_val, text->bv_len,
288                                 "index_entry_add failed: %s (%d)",
289                                 db_strerror(rc), rc );
290 #ifdef NEW_LOGGING
291                 LDAP_LOG ( TOOLS, ERR, 
292                         "=> bdb_tool_entry_put: %s\n", text->bv_val, 0, 0 );
293 #else
294                 Debug( LDAP_DEBUG_ANY,
295                         "=> bdb_tool_entry_put: %s\n", text->bv_val, 0, 0 );
296 #endif
297                 goto done;
298         }
299
300 done:
301         if( rc == 0 ) {
302                 rc = TXN_COMMIT( tid, 0 );
303                 if( rc != 0 ) {
304                         snprintf( text->bv_val, text->bv_len,
305                                         "txn_commit failed: %s (%d)",
306                                         db_strerror(rc), rc );
307 #ifdef NEW_LOGGING
308                         LDAP_LOG ( TOOLS, ERR, 
309                                 "=> bdb_tool_entry_put: %s\n", text->bv_val, 0, 0 );
310 #else
311                         Debug( LDAP_DEBUG_ANY,
312                                 "=> bdb_tool_entry_put: %s\n",
313                                 text->bv_val, 0, 0 );
314 #endif
315                         e->e_id = NOID;
316                 }
317
318         } else {
319                 TXN_ABORT( tid );
320                 snprintf( text->bv_val, text->bv_len,
321                         "txn_aborted! %s (%d)",
322                         db_strerror(rc), rc );
323 #ifdef NEW_LOGGING
324                 LDAP_LOG ( TOOLS, ERR, 
325                         "=> bdb_tool_entry_put: %s\n", text->bv_val, 0, 0 );
326 #else
327                 Debug( LDAP_DEBUG_ANY,
328                         "=> bdb_tool_entry_put: %s\n",
329                         text->bv_val, 0, 0 );
330 #endif
331                 e->e_id = NOID;
332         }
333
334         return e->e_id;
335 }
336
337 int bdb_tool_entry_reindex(
338         BackendDB *be,
339         ID id )
340 {
341         struct bdb_info *bi = (struct bdb_info *) be->be_private;
342         int rc;
343         Entry *e;
344         DB_TXN *tid = NULL;
345         Operation op = {0};
346
347 #ifdef NEW_LOGGING
348         LDAP_LOG ( TOOLS, ARGS, 
349                 "=> bdb_tool_entry_reindex( %ld )\n", (long) id, 0, 0 );
350 #else
351         Debug( LDAP_DEBUG_ARGS, "=> bdb_tool_entry_reindex( %ld )\n",
352                 (long) id, 0, 0 );
353 #endif
354
355         e = bdb_tool_entry_get( be, id );
356
357         if( e == NULL ) {
358 #ifdef NEW_LOGGING
359                 LDAP_LOG ( TOOLS, DETAIL1, 
360                         "bdb_tool_entry_reindex:: could not locate id=%ld\n", 
361                         (long) id, 0, 0 );
362 #else
363                 Debug( LDAP_DEBUG_ANY,
364                         "bdb_tool_entry_reindex:: could not locate id=%ld\n",
365                         (long) id, 0, 0 );
366 #endif
367                 return -1;
368         }
369
370         rc = TXN_BEGIN( bi->bi_dbenv, NULL, &tid, bi->bi_db_opflags );
371         if( rc != 0 ) {
372 #ifdef NEW_LOGGING
373                 LDAP_LOG ( TOOLS, ERR, 
374                         "=> bdb_tool_entry_reindex: txn_begin failed: %s (%d)\n", 
375                         db_strerror(rc), rc, 0 );
376 #else
377                 Debug( LDAP_DEBUG_ANY,
378                         "=> bdb_tool_entry_reindex: txn_begin failed: %s (%d)\n",
379                         db_strerror(rc), rc, 0 );
380 #endif
381                 goto done;
382         }
383         
384         /*
385          * just (re)add them for now
386          * assume that some other routine (not yet implemented)
387          * will zap index databases
388          *
389          */
390
391 #ifdef NEW_LOGGING
392         LDAP_LOG ( TOOLS, ERR, 
393                 "=> bdb_tool_entry_reindex( %ld, \"%s\" )\n", (long) id, e->e_dn, 0 );
394 #else
395         Debug( LDAP_DEBUG_TRACE, "=> bdb_tool_entry_reindex( %ld, \"%s\" )\n",
396                 (long) id, e->e_dn, 0 );
397 #endif
398
399 #ifndef BDB_HIER
400         /* add dn2id indices */
401         rc = bdb_dn2id_add( be, tid, NULL, e, NULL );
402         if( rc != 0 && rc != DB_KEYEXIST ) {
403 #ifdef NEW_LOGGING
404                 LDAP_LOG ( TOOLS, ERR, 
405                         "=> bdb_tool_entry_reindex: dn2id_add failed: %s (%d)\n", 
406                         db_strerror(rc), rc, 0 );
407 #else
408                 Debug( LDAP_DEBUG_ANY,
409                         "=> bdb_tool_entry_reindex: dn2id_add failed: %s (%d)\n",
410                         db_strerror(rc), rc, 0 );
411 #endif
412                 goto done;
413         }
414 #endif
415
416         op.o_bd = be;
417         op.o_tmpmemctx = NULL;
418         op.o_tmpmfuncs = &ch_mfuncs;
419         rc = bdb_index_entry_add( &op, tid, e );
420
421 done:
422         if( rc == 0 ) {
423                 rc = TXN_COMMIT( tid, 0 );
424                 if( rc != 0 ) {
425 #ifdef NEW_LOGGING
426                         LDAP_LOG ( TOOLS, ERR, 
427                                 "=> bdb_tool_entry_reindex: txn_commit failed: %s (%d)\n", 
428                                 db_strerror(rc), rc, 0 );
429 #else
430                         Debug( LDAP_DEBUG_ANY,
431                                 "=> bdb_tool_entry_reindex: txn_commit failed: %s (%d)\n",
432                                 db_strerror(rc), rc, 0 );
433 #endif
434                         e->e_id = NOID;
435                 }
436
437         } else {
438                 TXN_ABORT( tid );
439 #ifdef NEW_LOGGING
440                 LDAP_LOG ( TOOLS, DETAIL1, 
441                         "=> bdb_tool_entry_reindex: txn_aborted! %s (%d)\n", 
442                         db_strerror(rc), rc, 0 );
443 #else
444                 Debug( LDAP_DEBUG_ANY,
445                         "=> bdb_tool_entry_reindex: txn_aborted! %s (%d)\n",
446                         db_strerror(rc), rc, 0 );
447 #endif
448                 e->e_id = NOID;
449         }
450
451         return rc;
452 }