]> git.sur5r.net Git - openldap/blob - servers/slapd/back-bdb/tools.c
memory context tweaks
[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, &pdn, 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         struct berval pdn;
226         Operation op = {0};
227         u_int32_t locker;
228
229         assert( be != NULL );
230         assert( slapMode & SLAP_TOOL_MODE );
231
232         assert( text );
233         assert( text->bv_val );
234         assert( text->bv_val[0] == '\0' );      /* overconservative? */
235
236 #ifdef NEW_LOGGING
237         LDAP_LOG ( TOOLS, ARGS, "=> bdb_tool_entry_put( %ld, \"%s\" )\n",
238                 (long) e->e_id, e->e_dn, 0 );
239 #else
240         Debug( LDAP_DEBUG_TRACE, "=> bdb_tool_entry_put( %ld, \"%s\" )\n",
241                 (long) e->e_id, e->e_dn, 0 );
242 #endif
243
244         rc = TXN_BEGIN( bdb->bi_dbenv, NULL, &tid, 
245                 bdb->bi_db_opflags );
246         if( rc != 0 ) {
247                 snprintf( text->bv_val, text->bv_len,
248                         "txn_begin failed: %s (%d)",
249                         db_strerror(rc), rc );
250 #ifdef NEW_LOGGING
251         LDAP_LOG ( TOOLS, ERR, "=> bdb_tool_entry_put: %s\n", text->bv_val, 0, 0 );
252 #else
253                 Debug( LDAP_DEBUG_ANY,
254                         "=> bdb_tool_entry_put: %s\n",
255                          text->bv_val, 0, 0 );
256 #endif
257                 return NOID;
258         }
259
260         locker = TXN_ID( tid );
261         /* add dn2id indices */
262         rc = bdb_tool_next_id( be, tid, e, text, 0, locker );
263         if( rc != 0 ) {
264                 goto done;
265         }
266
267         /* id2entry index */
268         rc = bdb_id2entry_add( be, tid, e );
269         if( rc != 0 ) {
270                 snprintf( text->bv_val, text->bv_len,
271                                 "id2entry_add failed: %s (%d)",
272                                 db_strerror(rc), rc );
273 #ifdef NEW_LOGGING
274                 LDAP_LOG ( TOOLS, ERR, 
275                         "=> bdb_tool_entry_put: %s\n", text->bv_val, 0, 0 );
276 #else
277                 Debug( LDAP_DEBUG_ANY,
278                         "=> bdb_tool_entry_put: %s\n", text->bv_val, 0, 0 );
279 #endif
280                 goto done;
281         }
282
283         op.o_bd = be;
284         op.o_tmpmemctx = NULL;
285         op.o_tmpmfuncs = &ch_mfuncs;
286         rc = bdb_index_entry_add( &op, tid, e );
287         if( rc != 0 ) {
288                 snprintf( text->bv_val, text->bv_len,
289                                 "index_entry_add failed: %s (%d)",
290                                 db_strerror(rc), rc );
291 #ifdef NEW_LOGGING
292                 LDAP_LOG ( TOOLS, ERR, 
293                         "=> bdb_tool_entry_put: %s\n", text->bv_val, 0, 0 );
294 #else
295                 Debug( LDAP_DEBUG_ANY,
296                         "=> bdb_tool_entry_put: %s\n", text->bv_val, 0, 0 );
297 #endif
298                 goto done;
299         }
300
301 done:
302         if( rc == 0 ) {
303                 rc = TXN_COMMIT( tid, 0 );
304                 if( rc != 0 ) {
305                         snprintf( text->bv_val, text->bv_len,
306                                         "txn_commit failed: %s (%d)",
307                                         db_strerror(rc), rc );
308 #ifdef NEW_LOGGING
309                         LDAP_LOG ( TOOLS, ERR, 
310                                 "=> bdb_tool_entry_put: %s\n", text->bv_val, 0, 0 );
311 #else
312                         Debug( LDAP_DEBUG_ANY,
313                                 "=> bdb_tool_entry_put: %s\n",
314                                 text->bv_val, 0, 0 );
315 #endif
316                         e->e_id = NOID;
317                 }
318
319         } else {
320                 TXN_ABORT( tid );
321                 snprintf( text->bv_val, text->bv_len,
322                         "txn_aborted! %s (%d)",
323                         db_strerror(rc), rc );
324 #ifdef NEW_LOGGING
325                 LDAP_LOG ( TOOLS, ERR, 
326                         "=> bdb_tool_entry_put: %s\n", text->bv_val, 0, 0 );
327 #else
328                 Debug( LDAP_DEBUG_ANY,
329                         "=> bdb_tool_entry_put: %s\n",
330                         text->bv_val, 0, 0 );
331 #endif
332                 e->e_id = NOID;
333         }
334
335         return e->e_id;
336 }
337
338 int bdb_tool_entry_reindex(
339         BackendDB *be,
340         ID id )
341 {
342         struct bdb_info *bi = (struct bdb_info *) be->be_private;
343         int rc;
344         Entry *e;
345         DB_TXN *tid = NULL;
346         struct berval pdn;
347         Operation op = {0};
348
349 #ifdef NEW_LOGGING
350         LDAP_LOG ( TOOLS, ARGS, 
351                 "=> bdb_tool_entry_reindex( %ld )\n", (long) id, 0, 0 );
352 #else
353         Debug( LDAP_DEBUG_ARGS, "=> bdb_tool_entry_reindex( %ld )\n",
354                 (long) id, 0, 0 );
355 #endif
356
357         e = bdb_tool_entry_get( be, id );
358
359         if( e == NULL ) {
360 #ifdef NEW_LOGGING
361                 LDAP_LOG ( TOOLS, DETAIL1, 
362                         "bdb_tool_entry_reindex:: could not locate id=%ld\n", 
363                         (long) id, 0, 0 );
364 #else
365                 Debug( LDAP_DEBUG_ANY,
366                         "bdb_tool_entry_reindex:: could not locate id=%ld\n",
367                         (long) id, 0, 0 );
368 #endif
369                 return -1;
370         }
371
372         rc = TXN_BEGIN( bi->bi_dbenv, NULL, &tid, bi->bi_db_opflags );
373         if( rc != 0 ) {
374 #ifdef NEW_LOGGING
375                 LDAP_LOG ( TOOLS, ERR, 
376                         "=> bdb_tool_entry_reindex: txn_begin failed: %s (%d)\n", 
377                         db_strerror(rc), rc, 0 );
378 #else
379                 Debug( LDAP_DEBUG_ANY,
380                         "=> bdb_tool_entry_reindex: txn_begin failed: %s (%d)\n",
381                         db_strerror(rc), rc, 0 );
382 #endif
383                 goto done;
384         }
385         
386         /*
387          * just (re)add them for now
388          * assume that some other routine (not yet implemented)
389          * will zap index databases
390          *
391          */
392
393 #ifdef NEW_LOGGING
394         LDAP_LOG ( TOOLS, ERR, 
395                 "=> bdb_tool_entry_reindex( %ld, \"%s\" )\n", (long) id, e->e_dn, 0 );
396 #else
397         Debug( LDAP_DEBUG_TRACE, "=> bdb_tool_entry_reindex( %ld, \"%s\" )\n",
398                 (long) id, e->e_dn, 0 );
399 #endif
400
401         /* add dn2id indices */
402         if ( be_issuffix( be, &e->e_nname ) ) {
403                 pdn = slap_empty_bv;
404         } else {
405                 dnParent( &e->e_nname, &pdn );
406         }
407         rc = bdb_dn2id_add( be, tid, &pdn, 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
421         op.o_bd = be;
422         op.o_tmpmemctx = NULL;
423         op.o_tmpmfuncs = &ch_mfuncs;
424         rc = bdb_index_entry_add( &op, tid, e );
425
426 done:
427         if( rc == 0 ) {
428                 rc = TXN_COMMIT( tid, 0 );
429                 if( rc != 0 ) {
430 #ifdef NEW_LOGGING
431                         LDAP_LOG ( TOOLS, ERR, 
432                                 "=> bdb_tool_entry_reindex: txn_commit failed: %s (%d)\n", 
433                                 db_strerror(rc), rc, 0 );
434 #else
435                         Debug( LDAP_DEBUG_ANY,
436                                 "=> bdb_tool_entry_reindex: txn_commit failed: %s (%d)\n",
437                                 db_strerror(rc), rc, 0 );
438 #endif
439                         e->e_id = NOID;
440                 }
441
442         } else {
443                 TXN_ABORT( tid );
444 #ifdef NEW_LOGGING
445                 LDAP_LOG ( TOOLS, DETAIL1, 
446                         "=> bdb_tool_entry_reindex: txn_aborted! %s (%d)\n", 
447                         db_strerror(rc), rc, 0 );
448 #else
449                 Debug( LDAP_DEBUG_ANY,
450                         "=> bdb_tool_entry_reindex: txn_aborted! %s (%d)\n",
451                         db_strerror(rc), rc, 0 );
452 #endif
453                 e->e_id = NOID;
454         }
455
456         return rc;
457 }