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