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