]> git.sur5r.net Git - openldap/blob - servers/slapd/back-bdb/tools.c
More 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 {
138         struct bdb_info *bdb = (struct bdb_info *) be->be_private;
139         struct berval dn = e->e_nname;
140         struct berval pdn;
141         int rc;
142
143         rc = bdb_dn2id( be, tid, &dn, &e->e_id, 0 );
144         if ( rc == DB_NOTFOUND ) {
145                 if ( be_issuffix( be, &dn ) ) {
146                         pdn = slap_empty_bv;
147                 } else {
148                         dnParent( &dn, &pdn );
149                         e->e_nname = pdn;
150                         rc = bdb_tool_next_id( be, tid, e, text, 1 );
151                         if ( rc ) {
152                                 return rc;
153                         }
154                 }
155                 rc = bdb_next_id( be, tid, &e->e_id );
156                 if ( rc ) {
157                         snprintf( text->bv_val, text->bv_len,
158                                 "next_id failed: %s (%d)",
159                                 db_strerror(rc), rc );
160 #ifdef NEW_LOGGING
161                 LDAP_LOG ( TOOLS, ERR, 
162                         "=> bdb_tool_entry_put: %s\n", text->bv_val, 0, 0 );
163 #else
164                 Debug( LDAP_DEBUG_ANY,
165                         "=> bdb_tool_entry_put: %s\n", text->bv_val, 0, 0 );
166 #endif
167                         return rc;
168                 }
169                 e->e_nname = dn;
170                 rc = bdb_dn2id_add( be, tid, &pdn, e );
171                 if ( rc ) {
172                         snprintf( text->bv_val, text->bv_len, 
173                                 "dn2id_add failed: %s (%d)",
174                                 db_strerror(rc), rc );
175 #ifdef NEW_LOGGING
176                 LDAP_LOG ( TOOLS, ERR, 
177                         "=> bdb_tool_entry_put: %s\n", text->bv_val, 0, 0 );
178 #else
179                 Debug( LDAP_DEBUG_ANY,
180                         "=> bdb_tool_entry_put: %s\n", text->bv_val, 0, 0 );
181 #endif
182                 } else if ( hole ) {
183                         if ( nholes == nhmax - 1 ) {
184                                 if ( holes == hbuf ) {
185                                         holes = ch_malloc( nhmax * sizeof(ID) * 2 );
186                                         AC_MEMCPY( holes, hbuf, sizeof(hbuf) );
187                                 } else {
188                                         holes = ch_realloc( holes, nhmax * sizeof(ID) * 2 );
189                                 }
190                                 nhmax *= 2;
191                         }
192                         ber_dupbv( &holes[nholes].dn, &dn );
193                         holes[nholes++].id = e->e_id;
194                 }
195         } else if ( !hole ) {
196                 unsigned i;
197
198                 for ( i=0; i<nholes; i++) {
199                         if ( holes[i].id == e->e_id ) {
200                                 int j;
201                                 free(holes[i].dn.bv_val);
202                                 for (j=i;j<nholes;j++) holes[j] = holes[j+1];
203                                 holes[j].id = 0;
204                                 nholes--;
205                                 break;
206                         } else if ( holes[i].id > e->e_id ) {
207                                 break;
208                         }
209                 }
210         }
211         return rc;
212 }
213
214 ID bdb_tool_entry_put(
215         BackendDB *be,
216         Entry *e,
217         struct berval *text )
218 {
219         int rc;
220         struct bdb_info *bdb = (struct bdb_info *) be->be_private;
221         DB_TXN *tid = NULL;
222         struct berval pdn;
223         Operation op = {0};
224
225         assert( be != NULL );
226         assert( slapMode & SLAP_TOOL_MODE );
227
228         assert( text );
229         assert( text->bv_val );
230         assert( text->bv_val[0] == '\0' );      /* overconservative? */
231
232 #ifdef NEW_LOGGING
233         LDAP_LOG ( TOOLS, ARGS, "=> bdb_tool_entry_put( %ld, \"%s\" )\n",
234                 (long) e->e_id, e->e_dn, 0 );
235 #else
236         Debug( LDAP_DEBUG_TRACE, "=> bdb_tool_entry_put( %ld, \"%s\" )\n",
237                 (long) e->e_id, e->e_dn, 0 );
238 #endif
239
240         rc = TXN_BEGIN( bdb->bi_dbenv, NULL, &tid, 
241                 bdb->bi_db_opflags );
242         if( rc != 0 ) {
243                 snprintf( text->bv_val, text->bv_len,
244                         "txn_begin failed: %s (%d)",
245                         db_strerror(rc), rc );
246 #ifdef NEW_LOGGING
247         LDAP_LOG ( TOOLS, ERR, "=> bdb_tool_entry_put: %s\n", text->bv_val, 0, 0 );
248 #else
249                 Debug( LDAP_DEBUG_ANY,
250                         "=> bdb_tool_entry_put: %s\n",
251                          text->bv_val, 0, 0 );
252 #endif
253                 return NOID;
254         }
255
256         /* add dn2id indices */
257         rc = bdb_tool_next_id( be, tid, e, text, 0 );
258         if( rc != 0 ) {
259                 goto done;
260         }
261
262         /* id2entry index */
263         rc = bdb_id2entry_add( be, tid, e );
264         if( rc != 0 ) {
265                 snprintf( text->bv_val, text->bv_len,
266                                 "id2entry_add failed: %s (%d)",
267                                 db_strerror(rc), rc );
268 #ifdef NEW_LOGGING
269                 LDAP_LOG ( TOOLS, ERR, 
270                         "=> bdb_tool_entry_put: %s\n", text->bv_val, 0, 0 );
271 #else
272                 Debug( LDAP_DEBUG_ANY,
273                         "=> bdb_tool_entry_put: %s\n", text->bv_val, 0, 0 );
274 #endif
275                 goto done;
276         }
277
278         op.o_bd = be;
279         op.o_tmpmemctx = NULL;
280         op.o_tmpmfuncs = &ch_mfuncs;
281         rc = bdb_index_entry_add( &op, tid, e );
282         if( rc != 0 ) {
283                 snprintf( text->bv_val, text->bv_len,
284                                 "index_entry_add failed: %s (%d)",
285                                 db_strerror(rc), rc );
286 #ifdef NEW_LOGGING
287                 LDAP_LOG ( TOOLS, ERR, 
288                         "=> bdb_tool_entry_put: %s\n", text->bv_val, 0, 0 );
289 #else
290                 Debug( LDAP_DEBUG_ANY,
291                         "=> bdb_tool_entry_put: %s\n", text->bv_val, 0, 0 );
292 #endif
293                 goto done;
294         }
295
296 done:
297         if( rc == 0 ) {
298                 rc = TXN_COMMIT( tid, 0 );
299                 if( rc != 0 ) {
300                         snprintf( text->bv_val, text->bv_len,
301                                         "txn_commit failed: %s (%d)",
302                                         db_strerror(rc), rc );
303 #ifdef NEW_LOGGING
304                         LDAP_LOG ( TOOLS, ERR, 
305                                 "=> bdb_tool_entry_put: %s\n", text->bv_val, 0, 0 );
306 #else
307                         Debug( LDAP_DEBUG_ANY,
308                                 "=> bdb_tool_entry_put: %s\n",
309                                 text->bv_val, 0, 0 );
310 #endif
311                         e->e_id = NOID;
312                 }
313
314         } else {
315                 TXN_ABORT( tid );
316                 snprintf( text->bv_val, text->bv_len,
317                         "txn_aborted! %s (%d)",
318                         db_strerror(rc), rc );
319 #ifdef NEW_LOGGING
320                 LDAP_LOG ( TOOLS, ERR, 
321                         "=> bdb_tool_entry_put: %s\n", text->bv_val, 0, 0 );
322 #else
323                 Debug( LDAP_DEBUG_ANY,
324                         "=> bdb_tool_entry_put: %s\n",
325                         text->bv_val, 0, 0 );
326 #endif
327                 e->e_id = NOID;
328         }
329
330         return e->e_id;
331 }
332
333 int bdb_tool_entry_reindex(
334         BackendDB *be,
335         ID id )
336 {
337         struct bdb_info *bi = (struct bdb_info *) be->be_private;
338         int rc;
339         Entry *e;
340         DB_TXN *tid = NULL;
341         struct berval pdn;
342         Operation op = {0};
343
344 #ifdef NEW_LOGGING
345         LDAP_LOG ( TOOLS, ARGS, 
346                 "=> bdb_tool_entry_reindex( %ld )\n", (long) id, 0, 0 );
347 #else
348         Debug( LDAP_DEBUG_ARGS, "=> bdb_tool_entry_reindex( %ld )\n",
349                 (long) id, 0, 0 );
350 #endif
351
352         e = bdb_tool_entry_get( be, id );
353
354         if( e == NULL ) {
355 #ifdef NEW_LOGGING
356                 LDAP_LOG ( TOOLS, DETAIL1, 
357                         "bdb_tool_entry_reindex:: could not locate id=%ld\n", 
358                         (long) id, 0, 0 );
359 #else
360                 Debug( LDAP_DEBUG_ANY,
361                         "bdb_tool_entry_reindex:: could not locate id=%ld\n",
362                         (long) id, 0, 0 );
363 #endif
364                 return -1;
365         }
366
367         rc = TXN_BEGIN( bi->bi_dbenv, NULL, &tid, bi->bi_db_opflags );
368         if( rc != 0 ) {
369 #ifdef NEW_LOGGING
370                 LDAP_LOG ( TOOLS, ERR, 
371                         "=> bdb_tool_entry_reindex: txn_begin failed: %s (%d)\n", 
372                         db_strerror(rc), rc, 0 );
373 #else
374                 Debug( LDAP_DEBUG_ANY,
375                         "=> bdb_tool_entry_reindex: txn_begin failed: %s (%d)\n",
376                         db_strerror(rc), rc, 0 );
377 #endif
378                 goto done;
379         }
380         
381         /*
382          * just (re)add them for now
383          * assume that some other routine (not yet implemented)
384          * will zap index databases
385          *
386          */
387
388 #ifdef NEW_LOGGING
389         LDAP_LOG ( TOOLS, ERR, 
390                 "=> bdb_tool_entry_reindex( %ld, \"%s\" )\n", (long) id, e->e_dn, 0 );
391 #else
392         Debug( LDAP_DEBUG_TRACE, "=> bdb_tool_entry_reindex( %ld, \"%s\" )\n",
393                 (long) id, e->e_dn, 0 );
394 #endif
395
396         /* add dn2id indices */
397         if ( be_issuffix( be, &e->e_nname ) ) {
398                 pdn = slap_empty_bv;
399         } else {
400                 dnParent( &e->e_nname, &pdn );
401         }
402         rc = bdb_dn2id_add( be, tid, &pdn, e );
403         if( rc != 0 && rc != DB_KEYEXIST ) {
404 #ifdef NEW_LOGGING
405                 LDAP_LOG ( TOOLS, ERR, 
406                         "=> bdb_tool_entry_reindex: dn2id_add failed: %s (%d)\n", 
407                         db_strerror(rc), rc, 0 );
408 #else
409                 Debug( LDAP_DEBUG_ANY,
410                         "=> bdb_tool_entry_reindex: dn2id_add failed: %s (%d)\n",
411                         db_strerror(rc), rc, 0 );
412 #endif
413                 goto done;
414         }
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 }