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