1 /* tools.c - tools for slap tools */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 2000-2005 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
20 #include <ac/string.h>
25 static DBC *cursor = NULL;
28 typedef struct dn_id {
33 #define HOLE_SIZE 4096
34 static dn_id hbuf[HOLE_SIZE], *holes = hbuf;
35 static unsigned nhmax = HOLE_SIZE;
36 static unsigned nholes;
38 static Avlnode *index_attrs, index_dummy;
40 int bdb_tool_entry_open(
41 BackendDB *be, int mode )
43 struct bdb_info *bdb = (struct bdb_info *) be->be_private;
45 /* initialize key and data thangs */
48 key.flags = DB_DBT_REALLOC;
49 data.flags = DB_DBT_REALLOC;
52 int rc = bdb->bi_id2entry->bdi_db->cursor(
53 bdb->bi_id2entry->bdi_db, NULL, &cursor,
63 int bdb_tool_entry_close(
78 cursor->c_close( cursor );
84 fprintf( stderr, "Error, entries missing!\n");
85 for (i=0; i<nholes; i++) {
86 fprintf(stderr, " entry %ld: %s\n",
87 holes[i].id, holes[i].dn.bv_val);
95 static int bdb_reindex_cmp(const void *a, const void *b) { return 0; }
97 ID bdb_tool_entry_next(
102 struct bdb_info *bdb = (struct bdb_info *) be->be_private;
104 assert( be != NULL );
105 assert( slapMode & SLAP_TOOL_MODE );
106 assert( bdb != NULL );
108 rc = cursor->c_get( cursor, &key, &data, DB_NEXT );
111 /* If we're doing linear indexing and there are more attrs to
112 * index, and we're at the end of the database, start over.
114 if ( bdb->bi_attrs == &index_dummy ) {
115 if ( index_attrs && rc == DB_NOTFOUND ) {
116 /* optional - do a checkpoint here? */
117 index_dummy.avl_data = avl_delete(&index_attrs, NULL, bdb_reindex_cmp);
118 rc = cursor->c_get( cursor, &key, &data, DB_FIRST );
121 bdb->bi_attrs = NULL;
129 if( data.data == NULL ) {
133 BDB_DISK2ID( key.data, &id );
137 ID bdb_tool_dn2id_get(
144 EntryInfo *ei = NULL;
147 if ( BER_BVISEMPTY(dn) )
152 op.o_tmpmemctx = NULL;
153 op.o_tmpmfuncs = &ch_mfuncs;
155 rc = bdb_cache_find_ndn( &op, NULL, dn, &ei );
156 if ( ei ) bdb_cache_entryinfo_unlock( ei );
157 if ( rc == DB_NOTFOUND )
163 int bdb_tool_id2entry_get(
169 int rc = bdb_id2entry( be, NULL, 0, id, e );
171 if ( rc == DB_NOTFOUND && id == 0 ) {
172 Entry *dummy = ch_calloc( 1, sizeof(Entry) );
173 struct berval gluebv = BER_BVC("glue");
174 dummy->e_name.bv_val = ch_strdup( "" );
175 dummy->e_nname.bv_val = ch_strdup( "" );
176 attr_merge_one( dummy, slap_schema.si_ad_objectClass, &gluebv, NULL );
177 attr_merge_one( dummy, slap_schema.si_ad_structuralObjectClass,
185 Entry* bdb_tool_entry_get( BackendDB *be, ID id )
191 assert( be != NULL );
192 assert( slapMode & SLAP_TOOL_MODE );
193 assert( data.data != NULL );
195 DBT2bv( &data, &bv );
197 #ifdef SLAP_ZONE_ALLOC
198 /* FIXME: will add ctx later */
199 rc = entry_decode( &bv, &e, NULL );
201 rc = entry_decode( &bv, &e );
204 if( rc == LDAP_SUCCESS ) {
209 EntryInfo *ei = NULL;
215 op.o_tmpmemctx = NULL;
216 op.o_tmpmfuncs = &ch_mfuncs;
218 rc = bdb_cache_find_parent( &op, NULL, cursor->locker, id, &ei );
219 if ( rc == LDAP_SUCCESS ) {
220 bdb_cache_entryinfo_unlock( ei );
232 static int bdb_tool_next_id(
239 struct berval dn = e->e_name;
240 struct berval ndn = e->e_nname;
241 struct berval pdn, npdn;
242 EntryInfo *ei = NULL, eidummy;
245 if (ndn.bv_len == 0) {
250 rc = bdb_cache_find_ndn( op, tid, &ndn, &ei );
251 if ( ei ) bdb_cache_entryinfo_unlock( ei );
252 if ( rc == DB_NOTFOUND ) {
253 if ( !be_issuffix( op->o_bd, &ndn ) ) {
255 dnParent( &dn, &pdn );
256 dnParent( &ndn, &npdn );
259 rc = bdb_tool_next_id( op, tid, e, text, 1 );
265 /* If parent didn't exist, it was created just now
266 * and its ID is now in e->e_id. Make sure the current
267 * entry gets added under the new parent ID.
269 if ( eid != e->e_id ) {
270 eidummy.bei_id = e->e_id;
274 rc = bdb_next_id( op->o_bd, tid, &e->e_id );
276 snprintf( text->bv_val, text->bv_len,
277 "next_id failed: %s (%d)",
278 db_strerror(rc), rc );
279 Debug( LDAP_DEBUG_ANY,
280 "=> bdb_tool_next_id: %s\n", text->bv_val, 0, 0 );
283 rc = bdb_dn2id_add( op, tid, ei, e );
285 snprintf( text->bv_val, text->bv_len,
286 "dn2id_add failed: %s (%d)",
287 db_strerror(rc), rc );
288 Debug( LDAP_DEBUG_ANY,
289 "=> bdb_tool_next_id: %s\n", text->bv_val, 0, 0 );
291 if ( nholes == nhmax - 1 ) {
292 if ( holes == hbuf ) {
293 holes = ch_malloc( nhmax * sizeof(dn_id) * 2 );
294 AC_MEMCPY( holes, hbuf, sizeof(hbuf) );
296 holes = ch_realloc( holes, nhmax * sizeof(dn_id) * 2 );
300 ber_dupbv( &holes[nholes].dn, &ndn );
301 holes[nholes++].id = e->e_id;
303 } else if ( !hole ) {
306 e->e_id = ei->bei_id;
308 for ( i=0; i<nholes; i++) {
309 if ( holes[i].id == e->e_id ) {
311 free(holes[i].dn.bv_val);
312 for (j=i;j<nholes;j++) holes[j] = holes[j+1];
316 } else if ( holes[i].id > e->e_id ) {
324 ID bdb_tool_entry_put(
327 struct berval *text )
330 struct bdb_info *bdb = (struct bdb_info *) be->be_private;
335 assert( be != NULL );
336 assert( slapMode & SLAP_TOOL_MODE );
338 assert( text != NULL );
339 assert( text->bv_val != NULL );
340 assert( text->bv_val[0] == '\0' ); /* overconservative? */
342 Debug( LDAP_DEBUG_TRACE, "=> " LDAP_XSTRING(bdb_tool_entry_put)
343 "( %ld, \"%s\" )\n", (long) e->e_id, e->e_dn, 0 );
345 if (! (slapMode & SLAP_TOOL_QUICK)) {
346 rc = TXN_BEGIN( bdb->bi_dbenv, NULL, &tid,
347 bdb->bi_db_opflags );
349 snprintf( text->bv_val, text->bv_len,
350 "txn_begin failed: %s (%d)",
351 db_strerror(rc), rc );
352 Debug( LDAP_DEBUG_ANY,
353 "=> " LDAP_XSTRING(bdb_tool_entry_put) ": %s\n",
354 text->bv_val, 0, 0 );
361 op.o_tmpmemctx = NULL;
362 op.o_tmpmfuncs = &ch_mfuncs;
364 /* add dn2id indices */
365 rc = bdb_tool_next_id( &op, tid, e, text, 0 );
371 rc = bdb_id2entry_add( be, tid, e );
373 snprintf( text->bv_val, text->bv_len,
374 "id2entry_add failed: %s (%d)",
375 db_strerror(rc), rc );
376 Debug( LDAP_DEBUG_ANY,
377 "=> " LDAP_XSTRING(bdb_tool_entry_put) ": %s\n",
378 text->bv_val, 0, 0 );
382 if ( !bdb->bi_linear_index )
383 rc = bdb_index_entry_add( &op, tid, e );
385 snprintf( text->bv_val, text->bv_len,
386 "index_entry_add failed: %s (%d)",
387 db_strerror(rc), rc );
388 Debug( LDAP_DEBUG_ANY,
389 "=> " LDAP_XSTRING(bdb_tool_entry_put) ": %s\n",
390 text->bv_val, 0, 0 );
396 if ( !( slapMode & SLAP_TOOL_QUICK )) {
397 rc = TXN_COMMIT( tid, 0 );
399 snprintf( text->bv_val, text->bv_len,
400 "txn_commit failed: %s (%d)",
401 db_strerror(rc), rc );
402 Debug( LDAP_DEBUG_ANY,
403 "=> " LDAP_XSTRING(bdb_tool_entry_put) ": %s\n",
404 text->bv_val, 0, 0 );
410 if ( !( slapMode & SLAP_TOOL_QUICK )) {
412 snprintf( text->bv_val, text->bv_len,
413 "txn_aborted! %s (%d)",
414 db_strerror(rc), rc );
415 Debug( LDAP_DEBUG_ANY,
416 "=> " LDAP_XSTRING(bdb_tool_entry_put) ": %s\n",
417 text->bv_val, 0, 0 );
425 int bdb_tool_entry_reindex(
429 struct bdb_info *bi = (struct bdb_info *) be->be_private;
436 Debug( LDAP_DEBUG_ARGS,
437 "=> " LDAP_XSTRING(bdb_tool_entry_reindex) "( %ld )\n",
440 /* No indexes configured, nothing to do. Could return an
441 * error here to shortcut things.
447 /* Get the first attribute to index */
448 if (bi->bi_linear_index && !index_attrs && bi->bi_attrs != &index_dummy) {
449 index_attrs = bi->bi_attrs;
450 bi->bi_attrs = &index_dummy;
451 index_dummy.avl_data = avl_delete(&index_attrs, NULL, bdb_reindex_cmp);
454 e = bdb_tool_entry_get( be, id );
457 Debug( LDAP_DEBUG_ANY,
458 LDAP_XSTRING(bdb_tool_entry_reindex)
459 ": could not locate id=%ld\n",
464 if (! (slapMode & SLAP_TOOL_QUICK)) {
465 rc = TXN_BEGIN( bi->bi_dbenv, NULL, &tid, bi->bi_db_opflags );
467 Debug( LDAP_DEBUG_ANY,
468 "=> " LDAP_XSTRING(bdb_tool_entry_reindex) ": "
469 "txn_begin failed: %s (%d)\n",
470 db_strerror(rc), rc, 0 );
476 * just (re)add them for now
477 * assume that some other routine (not yet implemented)
478 * will zap index databases
482 Debug( LDAP_DEBUG_TRACE,
483 "=> " LDAP_XSTRING(bdb_tool_entry_reindex) "( %ld, \"%s\" )\n",
484 (long) id, e->e_dn, 0 );
488 op.o_tmpmemctx = NULL;
489 op.o_tmpmfuncs = &ch_mfuncs;
491 rc = bdb_index_entry_add( &op, tid, e );
495 if (! (slapMode & SLAP_TOOL_QUICK)) {
496 rc = TXN_COMMIT( tid, 0 );
498 Debug( LDAP_DEBUG_ANY,
499 "=> " LDAP_XSTRING(bdb_tool_entry_reindex)
500 ": txn_commit failed: %s (%d)\n",
501 db_strerror(rc), rc, 0 );
507 if (! (slapMode & SLAP_TOOL_QUICK)) {
509 Debug( LDAP_DEBUG_ANY,
510 "=> " LDAP_XSTRING(bdb_tool_entry_reindex)
511 ": txn_aborted! %s (%d)\n",
512 db_strerror(rc), rc, 0 );
516 bdb_entry_release( &op, e, 0 );
521 ID bdb_tool_entry_modify(
524 struct berval *text )
527 struct bdb_info *bdb = (struct bdb_info *) be->be_private;
532 assert( be != NULL );
533 assert( slapMode & SLAP_TOOL_MODE );
535 assert( text != NULL );
536 assert( text->bv_val != NULL );
537 assert( text->bv_val[0] == '\0' ); /* overconservative? */
539 assert ( e->e_id != NOID );
541 Debug( LDAP_DEBUG_TRACE,
542 "=> " LDAP_XSTRING(bdb_tool_entry_modify) "( %ld, \"%s\" )\n",
543 (long) e->e_id, e->e_dn, 0 );
545 if (! (slapMode & SLAP_TOOL_QUICK)) {
546 rc = TXN_BEGIN( bdb->bi_dbenv, NULL, &tid,
547 bdb->bi_db_opflags );
549 snprintf( text->bv_val, text->bv_len,
550 "txn_begin failed: %s (%d)",
551 db_strerror(rc), rc );
552 Debug( LDAP_DEBUG_ANY,
553 "=> " LDAP_XSTRING(bdb_tool_entry_modify) ": %s\n",
554 text->bv_val, 0, 0 );
561 op.o_tmpmemctx = NULL;
562 op.o_tmpmfuncs = &ch_mfuncs;
565 rc = bdb_id2entry_update( be, tid, e );
567 snprintf( text->bv_val, text->bv_len,
568 "id2entry_add failed: %s (%d)",
569 db_strerror(rc), rc );
570 Debug( LDAP_DEBUG_ANY,
571 "=> " LDAP_XSTRING(bdb_tool_entry_modify) ": %s\n",
572 text->bv_val, 0, 0 );
577 /* FIXME: this is bogus, we don't have the old values to delete
578 * from the index because the given entry has already been modified.
580 rc = bdb_index_entry_del( &op, tid, e );
582 snprintf( text->bv_val, text->bv_len,
583 "index_entry_del failed: %s (%d)",
584 db_strerror(rc), rc );
585 Debug( LDAP_DEBUG_ANY,
586 "=> " LDAP_XSTRING(bdb_tool_entry_modify) ": %s\n",
587 text->bv_val, 0, 0 );
592 rc = bdb_index_entry_add( &op, tid, e );
594 snprintf( text->bv_val, text->bv_len,
595 "index_entry_add failed: %s (%d)",
596 db_strerror(rc), rc );
597 Debug( LDAP_DEBUG_ANY,
598 "=> " LDAP_XSTRING(bdb_tool_entry_modify) ": %s\n",
599 text->bv_val, 0, 0 );
605 if (! (slapMode & SLAP_TOOL_QUICK)) {
606 rc = TXN_COMMIT( tid, 0 );
608 snprintf( text->bv_val, text->bv_len,
609 "txn_commit failed: %s (%d)",
610 db_strerror(rc), rc );
611 Debug( LDAP_DEBUG_ANY,
612 "=> " LDAP_XSTRING(bdb_tool_entry_modify) ": "
613 "%s\n", text->bv_val, 0, 0 );
619 if (! (slapMode & SLAP_TOOL_QUICK)) {
621 snprintf( text->bv_val, text->bv_len,
622 "txn_aborted! %s (%d)",
623 db_strerror(rc), rc );
624 Debug( LDAP_DEBUG_ANY,
625 "=> " LDAP_XSTRING(bdb_tool_entry_modify) ": %s\n",
626 text->bv_val, 0, 0 );