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 /* initialize key and data thangs */
46 key.flags = DB_DBT_REALLOC;
47 data.flags = DB_DBT_REALLOC;
52 int bdb_tool_entry_close(
67 cursor->c_close( cursor );
73 fprintf( stderr, "Error, entries missing!\n");
74 for (i=0; i<nholes; i++) {
75 fprintf(stderr, " entry %ld: %s\n",
76 holes[i].id, holes[i].dn.bv_val);
84 static int bdb_reindex_cmp(const void *a, const void *b) { return 0; }
86 ID bdb_tool_entry_next(
91 struct bdb_info *bdb = (struct bdb_info *) be->be_private;
94 assert( slapMode & SLAP_TOOL_MODE );
95 assert( bdb != NULL );
99 rc = bdb->bi_id2entry->bdi_db->cursor(
100 bdb->bi_id2entry->bdi_db, NULL, &cursor,
101 bdb->bi_db_opflags );
107 rc = cursor->c_get( cursor, &key, &data, DB_NEXT );
110 /* If we're doing linear indexing and there are more attrs to
111 * index, and we're at the end of the database, start over.
113 if ( bdb->bi_attrs == &index_dummy ) {
114 if ( index_attrs && rc == DB_NOTFOUND ) {
115 /* optional - do a checkpoint here? */
116 index_dummy.avl_data = avl_delete(&index_attrs, NULL, bdb_reindex_cmp);
117 rc = cursor->c_get( cursor, &key, &data, DB_FIRST );
120 bdb->bi_attrs = NULL;
128 if( data.data == NULL ) {
132 BDB_DISK2ID( key.data, &id );
136 ID bdb_tool_dn2id_get(
143 EntryInfo *ei = NULL;
146 if ( BER_BVISEMPTY(dn) )
151 op.o_tmpmemctx = NULL;
152 op.o_tmpmfuncs = &ch_mfuncs;
154 rc = bdb_cache_find_ndn( &op, NULL, dn, &ei );
155 if ( ei ) bdb_cache_entryinfo_unlock( ei );
156 if ( rc == DB_NOTFOUND )
162 int bdb_tool_id2entry_get(
168 int rc = bdb_id2entry( be, NULL, id, e );
170 if ( rc == DB_NOTFOUND && id == 0 ) {
171 Entry *dummy = ch_calloc( 1, sizeof(Entry) );
172 struct berval gluebv = BER_BVC("glue");
173 dummy->e_name.bv_val = ch_strdup( "" );
174 dummy->e_nname.bv_val = ch_strdup( "" );
175 attr_merge_one( dummy, slap_schema.si_ad_objectClass, &gluebv, NULL );
176 attr_merge_one( dummy, slap_schema.si_ad_structuralObjectClass,
184 Entry* bdb_tool_entry_get( BackendDB *be, ID id )
190 assert( be != NULL );
191 assert( slapMode & SLAP_TOOL_MODE );
192 assert( data.data != NULL );
194 DBT2bv( &data, &bv );
196 #ifdef SLAP_ZONE_ALLOC
197 /* FIXME: will add ctx later */
198 rc = entry_decode( &bv, &e, NULL );
200 rc = entry_decode( &bv, &e );
203 if( rc == LDAP_SUCCESS ) {
208 EntryInfo *ei = NULL;
214 op.o_tmpmemctx = NULL;
215 op.o_tmpmfuncs = &ch_mfuncs;
217 rc = bdb_cache_find_parent( &op, NULL, cursor->locker, id, &ei );
218 if ( rc == LDAP_SUCCESS ) {
219 bdb_cache_entryinfo_unlock( ei );
231 static int bdb_tool_next_id(
238 struct berval dn = e->e_name;
239 struct berval ndn = e->e_nname;
240 struct berval pdn, npdn;
241 EntryInfo *ei = NULL, eidummy;
244 if (ndn.bv_len == 0) {
249 rc = bdb_cache_find_ndn( op, tid, &ndn, &ei );
250 if ( ei ) bdb_cache_entryinfo_unlock( ei );
251 if ( rc == DB_NOTFOUND ) {
252 if ( !be_issuffix( op->o_bd, &ndn ) ) {
254 dnParent( &dn, &pdn );
255 dnParent( &ndn, &npdn );
258 rc = bdb_tool_next_id( op, tid, e, text, 1 );
264 /* If parent didn't exist, it was created just now
265 * and its ID is now in e->e_id. Make sure the current
266 * entry gets added under the new parent ID.
268 if ( eid != e->e_id ) {
269 eidummy.bei_id = e->e_id;
273 rc = bdb_next_id( op->o_bd, tid, &e->e_id );
275 snprintf( text->bv_val, text->bv_len,
276 "next_id failed: %s (%d)",
277 db_strerror(rc), rc );
278 Debug( LDAP_DEBUG_ANY,
279 "=> bdb_tool_next_id: %s\n", text->bv_val, 0, 0 );
282 rc = bdb_dn2id_add( op, tid, ei, e );
284 snprintf( text->bv_val, text->bv_len,
285 "dn2id_add failed: %s (%d)",
286 db_strerror(rc), rc );
287 Debug( LDAP_DEBUG_ANY,
288 "=> bdb_tool_next_id: %s\n", text->bv_val, 0, 0 );
290 if ( nholes == nhmax - 1 ) {
291 if ( holes == hbuf ) {
292 holes = ch_malloc( nhmax * sizeof(dn_id) * 2 );
293 AC_MEMCPY( holes, hbuf, sizeof(hbuf) );
295 holes = ch_realloc( holes, nhmax * sizeof(dn_id) * 2 );
299 ber_dupbv( &holes[nholes].dn, &ndn );
300 holes[nholes++].id = e->e_id;
302 } else if ( !hole ) {
305 e->e_id = ei->bei_id;
307 for ( i=0; i<nholes; i++) {
308 if ( holes[i].id == e->e_id ) {
310 free(holes[i].dn.bv_val);
311 for (j=i;j<nholes;j++) holes[j] = holes[j+1];
315 } else if ( holes[i].id > e->e_id ) {
323 ID bdb_tool_entry_put(
326 struct berval *text )
329 struct bdb_info *bdb = (struct bdb_info *) be->be_private;
334 assert( be != NULL );
335 assert( slapMode & SLAP_TOOL_MODE );
337 assert( text != NULL );
338 assert( text->bv_val != NULL );
339 assert( text->bv_val[0] == '\0' ); /* overconservative? */
341 Debug( LDAP_DEBUG_TRACE, "=> " LDAP_XSTRING(bdb_tool_entry_put)
342 "( %ld, \"%s\" )\n", (long) e->e_id, e->e_dn, 0 );
344 if (! (slapMode & SLAP_TOOL_QUICK)) {
345 rc = TXN_BEGIN( bdb->bi_dbenv, NULL, &tid,
346 bdb->bi_db_opflags );
348 snprintf( text->bv_val, text->bv_len,
349 "txn_begin failed: %s (%d)",
350 db_strerror(rc), rc );
351 Debug( LDAP_DEBUG_ANY,
352 "=> " LDAP_XSTRING(bdb_tool_entry_put) ": %s\n",
353 text->bv_val, 0, 0 );
360 op.o_tmpmemctx = NULL;
361 op.o_tmpmfuncs = &ch_mfuncs;
363 /* add dn2id indices */
364 rc = bdb_tool_next_id( &op, tid, e, text, 0 );
370 rc = bdb_id2entry_add( be, tid, e );
372 snprintf( text->bv_val, text->bv_len,
373 "id2entry_add failed: %s (%d)",
374 db_strerror(rc), rc );
375 Debug( LDAP_DEBUG_ANY,
376 "=> " LDAP_XSTRING(bdb_tool_entry_put) ": %s\n",
377 text->bv_val, 0, 0 );
381 if ( !bdb->bi_linear_index )
382 rc = bdb_index_entry_add( &op, tid, e );
384 snprintf( text->bv_val, text->bv_len,
385 "index_entry_add failed: %s (%d)",
386 db_strerror(rc), rc );
387 Debug( LDAP_DEBUG_ANY,
388 "=> " LDAP_XSTRING(bdb_tool_entry_put) ": %s\n",
389 text->bv_val, 0, 0 );
395 if ( !( slapMode & SLAP_TOOL_QUICK )) {
396 rc = TXN_COMMIT( tid, 0 );
398 snprintf( text->bv_val, text->bv_len,
399 "txn_commit failed: %s (%d)",
400 db_strerror(rc), rc );
401 Debug( LDAP_DEBUG_ANY,
402 "=> " LDAP_XSTRING(bdb_tool_entry_put) ": %s\n",
403 text->bv_val, 0, 0 );
409 if ( !( slapMode & SLAP_TOOL_QUICK )) {
411 snprintf( text->bv_val, text->bv_len,
412 "txn_aborted! %s (%d)",
413 db_strerror(rc), rc );
414 Debug( LDAP_DEBUG_ANY,
415 "=> " LDAP_XSTRING(bdb_tool_entry_put) ": %s\n",
416 text->bv_val, 0, 0 );
424 int bdb_tool_entry_reindex(
428 struct bdb_info *bi = (struct bdb_info *) be->be_private;
435 Debug( LDAP_DEBUG_ARGS,
436 "=> " LDAP_XSTRING(bdb_tool_entry_reindex) "( %ld )\n",
439 /* No indexes configured, nothing to do. Could return an
440 * error here to shortcut things.
446 /* Get the first attribute to index */
447 if (bi->bi_linear_index && !index_attrs && bi->bi_attrs != &index_dummy) {
448 index_attrs = bi->bi_attrs;
449 bi->bi_attrs = &index_dummy;
450 index_dummy.avl_data = avl_delete(&index_attrs, NULL, bdb_reindex_cmp);
453 e = bdb_tool_entry_get( be, id );
456 Debug( LDAP_DEBUG_ANY,
457 LDAP_XSTRING(bdb_tool_entry_reindex)
458 ": could not locate id=%ld\n",
463 if (! (slapMode & SLAP_TOOL_QUICK)) {
464 rc = TXN_BEGIN( bi->bi_dbenv, NULL, &tid, bi->bi_db_opflags );
466 Debug( LDAP_DEBUG_ANY,
467 "=> " LDAP_XSTRING(bdb_tool_entry_reindex) ": "
468 "txn_begin failed: %s (%d)\n",
469 db_strerror(rc), rc, 0 );
475 * just (re)add them for now
476 * assume that some other routine (not yet implemented)
477 * will zap index databases
481 Debug( LDAP_DEBUG_TRACE,
482 "=> " LDAP_XSTRING(bdb_tool_entry_reindex) "( %ld, \"%s\" )\n",
483 (long) id, e->e_dn, 0 );
487 op.o_tmpmemctx = NULL;
488 op.o_tmpmfuncs = &ch_mfuncs;
490 rc = bdb_index_entry_add( &op, tid, e );
494 if (! (slapMode & SLAP_TOOL_QUICK)) {
495 rc = TXN_COMMIT( tid, 0 );
497 Debug( LDAP_DEBUG_ANY,
498 "=> " LDAP_XSTRING(bdb_tool_entry_reindex)
499 ": txn_commit failed: %s (%d)\n",
500 db_strerror(rc), rc, 0 );
506 if (! (slapMode & SLAP_TOOL_QUICK)) {
508 Debug( LDAP_DEBUG_ANY,
509 "=> " LDAP_XSTRING(bdb_tool_entry_reindex)
510 ": txn_aborted! %s (%d)\n",
511 db_strerror(rc), rc, 0 );
515 bdb_entry_release( &op, e, 0 );
520 ID bdb_tool_entry_modify(
523 struct berval *text )
526 struct bdb_info *bdb = (struct bdb_info *) be->be_private;
531 assert( be != NULL );
532 assert( slapMode & SLAP_TOOL_MODE );
534 assert( text != NULL );
535 assert( text->bv_val != NULL );
536 assert( text->bv_val[0] == '\0' ); /* overconservative? */
538 assert ( e->e_id != NOID );
540 Debug( LDAP_DEBUG_TRACE,
541 "=> " LDAP_XSTRING(bdb_tool_entry_modify) "( %ld, \"%s\" )\n",
542 (long) e->e_id, e->e_dn, 0 );
544 if (! (slapMode & SLAP_TOOL_QUICK)) {
545 rc = TXN_BEGIN( bdb->bi_dbenv, NULL, &tid,
546 bdb->bi_db_opflags );
548 snprintf( text->bv_val, text->bv_len,
549 "txn_begin failed: %s (%d)",
550 db_strerror(rc), rc );
551 Debug( LDAP_DEBUG_ANY,
552 "=> " LDAP_XSTRING(bdb_tool_entry_modify) ": %s\n",
553 text->bv_val, 0, 0 );
560 op.o_tmpmemctx = NULL;
561 op.o_tmpmfuncs = &ch_mfuncs;
564 rc = bdb_id2entry_update( be, tid, e );
566 snprintf( text->bv_val, text->bv_len,
567 "id2entry_add failed: %s (%d)",
568 db_strerror(rc), rc );
569 Debug( LDAP_DEBUG_ANY,
570 "=> " LDAP_XSTRING(bdb_tool_entry_modify) ": %s\n",
571 text->bv_val, 0, 0 );
576 /* FIXME: this is bogus, we don't have the old values to delete
577 * from the index because the given entry has already been modified.
579 rc = bdb_index_entry_del( &op, tid, e );
581 snprintf( text->bv_val, text->bv_len,
582 "index_entry_del failed: %s (%d)",
583 db_strerror(rc), rc );
584 Debug( LDAP_DEBUG_ANY,
585 "=> " LDAP_XSTRING(bdb_tool_entry_modify) ": %s\n",
586 text->bv_val, 0, 0 );
591 rc = bdb_index_entry_add( &op, tid, e );
593 snprintf( text->bv_val, text->bv_len,
594 "index_entry_add failed: %s (%d)",
595 db_strerror(rc), rc );
596 Debug( LDAP_DEBUG_ANY,
597 "=> " LDAP_XSTRING(bdb_tool_entry_modify) ": %s\n",
598 text->bv_val, 0, 0 );
604 if (! (slapMode & SLAP_TOOL_QUICK)) {
605 rc = TXN_COMMIT( tid, 0 );
607 snprintf( text->bv_val, text->bv_len,
608 "txn_commit failed: %s (%d)",
609 db_strerror(rc), rc );
610 Debug( LDAP_DEBUG_ANY,
611 "=> " LDAP_XSTRING(bdb_tool_entry_modify) ": "
612 "%s\n", text->bv_val, 0, 0 );
618 if (! (slapMode & SLAP_TOOL_QUICK)) {
620 snprintf( text->bv_val, text->bv_len,
621 "txn_aborted! %s (%d)",
622 db_strerror(rc), rc );
623 Debug( LDAP_DEBUG_ANY,
624 "=> " LDAP_XSTRING(bdb_tool_entry_modify) ": %s\n",
625 text->bv_val, 0, 0 );