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 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(
147 op.o_tmpmemctx = NULL;
148 op.o_tmpmfuncs = &ch_mfuncs;
152 bdb_dn2id( &op, NULL, dn, &ei );
157 int bdb_tool_id2entry_get(
163 return bdb_id2entry( be, NULL, id, e );
166 Entry* bdb_tool_entry_get( BackendDB *be, ID id )
172 assert( be != NULL );
173 assert( slapMode & SLAP_TOOL_MODE );
174 assert( data.data != NULL );
177 DBT2bv( &data, &bv );
179 #ifdef SLAP_ZONE_ALLOC
180 /* FIXME: will add ctx later */
181 rc = entry_decode( &bv, &e, NULL );
183 rc = entry_decode( &bv, &e );
186 if( rc == LDAP_SUCCESS ) {
191 EntryInfo *ei = NULL;
197 op.o_tmpmemctx = NULL;
198 op.o_tmpmfuncs = &ch_mfuncs;
200 rc = bdb_cache_find_id( &op, NULL, id, &ei, 0, 0, NULL );
201 if ( rc == LDAP_SUCCESS )
208 static int bdb_tool_next_id(
215 struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
216 struct berval dn = e->e_name;
217 struct berval ndn = e->e_nname;
218 struct berval pdn, npdn;
219 EntryInfo *ei = NULL;
222 if (ndn.bv_len == 0) return 0;
224 rc = bdb_cache_find_ndn( op, tid, &ndn, &ei );
225 if ( ei ) bdb_cache_entryinfo_unlock( ei );
226 if ( rc == DB_NOTFOUND ) {
227 if ( !be_issuffix( op->o_bd, &ndn ) ) {
228 dnParent( &dn, &pdn );
229 dnParent( &ndn, &npdn );
232 rc = bdb_tool_next_id( op, tid, e, text, 1 );
239 rc = bdb_next_id( op->o_bd, tid, &e->e_id );
241 snprintf( text->bv_val, text->bv_len,
242 "next_id failed: %s (%d)",
243 db_strerror(rc), rc );
244 Debug( LDAP_DEBUG_ANY,
245 "=> bdb_tool_next_id: %s\n", text->bv_val, 0, 0 );
248 rc = bdb_dn2id_add( op, tid, ei, e );
250 snprintf( text->bv_val, text->bv_len,
251 "dn2id_add failed: %s (%d)",
252 db_strerror(rc), rc );
253 Debug( LDAP_DEBUG_ANY,
254 "=> bdb_tool_next_id: %s\n", text->bv_val, 0, 0 );
256 if ( nholes == nhmax - 1 ) {
257 if ( holes == hbuf ) {
258 holes = ch_malloc( nhmax * sizeof(dn_id) * 2 );
259 AC_MEMCPY( holes, hbuf, sizeof(hbuf) );
261 holes = ch_realloc( holes, nhmax * sizeof(dn_id) * 2 );
265 ber_dupbv( &holes[nholes].dn, &ndn );
266 holes[nholes++].id = e->e_id;
268 } else if ( !hole ) {
271 e->e_id = ei->bei_id;
273 for ( i=0; i<nholes; i++) {
274 if ( holes[i].id == e->e_id ) {
276 free(holes[i].dn.bv_val);
277 for (j=i;j<nholes;j++) holes[j] = holes[j+1];
281 } else if ( holes[i].id > e->e_id ) {
289 ID bdb_tool_entry_put(
292 struct berval *text )
295 struct bdb_info *bdb = (struct bdb_info *) be->be_private;
300 assert( be != NULL );
301 assert( slapMode & SLAP_TOOL_MODE );
304 assert( text->bv_val );
305 assert( text->bv_val[0] == '\0' ); /* overconservative? */
307 Debug( LDAP_DEBUG_TRACE, "=> " LDAP_XSTRING(bdb_tool_entry_put)
308 "( %ld, \"%s\" )\n", (long) e->e_id, e->e_dn, 0 );
310 if (! (slapMode & SLAP_TOOL_QUICK)) {
311 rc = TXN_BEGIN( bdb->bi_dbenv, NULL, &tid,
312 bdb->bi_db_opflags );
314 snprintf( text->bv_val, text->bv_len,
315 "txn_begin failed: %s (%d)",
316 db_strerror(rc), rc );
317 Debug( LDAP_DEBUG_ANY,
318 "=> " LDAP_XSTRING(bdb_tool_entry_put) ": %s\n",
319 text->bv_val, 0, 0 );
326 op.o_tmpmemctx = NULL;
327 op.o_tmpmfuncs = &ch_mfuncs;
329 /* add dn2id indices */
330 rc = bdb_tool_next_id( &op, tid, e, text, 0 );
336 rc = bdb_id2entry_add( be, tid, e );
338 snprintf( text->bv_val, text->bv_len,
339 "id2entry_add failed: %s (%d)",
340 db_strerror(rc), rc );
341 Debug( LDAP_DEBUG_ANY,
342 "=> " LDAP_XSTRING(bdb_tool_entry_put) ": %s\n",
343 text->bv_val, 0, 0 );
347 if ( !bdb->bi_linear_index )
348 rc = bdb_index_entry_add( &op, tid, e );
350 snprintf( text->bv_val, text->bv_len,
351 "index_entry_add failed: %s (%d)",
352 db_strerror(rc), rc );
353 Debug( LDAP_DEBUG_ANY,
354 "=> " LDAP_XSTRING(bdb_tool_entry_put) ": %s\n",
355 text->bv_val, 0, 0 );
361 if ( !( slapMode & SLAP_TOOL_QUICK )) {
362 rc = TXN_COMMIT( tid, 0 );
364 snprintf( text->bv_val, text->bv_len,
365 "txn_commit failed: %s (%d)",
366 db_strerror(rc), rc );
367 Debug( LDAP_DEBUG_ANY,
368 "=> " LDAP_XSTRING(bdb_tool_entry_put) ": %s\n",
369 text->bv_val, 0, 0 );
375 if ( !( slapMode & SLAP_TOOL_QUICK )) {
377 snprintf( text->bv_val, text->bv_len,
378 "txn_aborted! %s (%d)",
379 db_strerror(rc), rc );
380 Debug( LDAP_DEBUG_ANY,
381 "=> " LDAP_XSTRING(bdb_tool_entry_put) ": %s\n",
382 text->bv_val, 0, 0 );
390 int bdb_tool_entry_reindex(
394 struct bdb_info *bi = (struct bdb_info *) be->be_private;
401 Debug( LDAP_DEBUG_ARGS,
402 "=> " LDAP_XSTRING(bdb_tool_entry_reindex) "( %ld )\n",
405 /* No indexes configured, nothing to do. Could return an
406 * error here to shortcut things.
412 /* Get the first attribute to index */
413 if (bi->bi_linear_index && !index_attrs && bi->bi_attrs != &index_dummy) {
414 index_attrs = bi->bi_attrs;
415 bi->bi_attrs = &index_dummy;
416 index_dummy.avl_data = avl_delete(&index_attrs, NULL, bdb_reindex_cmp);
419 e = bdb_tool_entry_get( be, id );
422 Debug( LDAP_DEBUG_ANY,
423 LDAP_XSTRING(bdb_tool_entry_reindex)
424 ": could not locate id=%ld\n",
429 rc = TXN_BEGIN( bi->bi_dbenv, NULL, &tid, bi->bi_db_opflags );
431 Debug( LDAP_DEBUG_ANY,
432 "=> " LDAP_XSTRING(bdb_tool_entry_reindex) ": "
433 "txn_begin failed: %s (%d)\n",
434 db_strerror(rc), rc, 0 );
439 * just (re)add them for now
440 * assume that some other routine (not yet implemented)
441 * will zap index databases
445 Debug( LDAP_DEBUG_TRACE,
446 "=> " LDAP_XSTRING(bdb_tool_entry_reindex) "( %ld, \"%s\" )\n",
447 (long) id, e->e_dn, 0 );
451 op.o_tmpmemctx = NULL;
452 op.o_tmpmfuncs = &ch_mfuncs;
454 #if 0 /* ndef BDB_HIER */
455 /* add dn2id indices */
456 rc = bdb_dn2id_add( &op, tid, NULL, e );
457 if( rc != 0 && rc != DB_KEYEXIST ) {
458 Debug( LDAP_DEBUG_ANY,
459 "=> " LDAP_XSTRING(bdb_tool_entry_reindex)
460 ": dn2id_add failed: %s (%d)\n",
461 db_strerror(rc), rc, 0 );
466 rc = bdb_index_entry_add( &op, tid, e );
470 rc = TXN_COMMIT( tid, 0 );
472 Debug( LDAP_DEBUG_ANY,
473 "=> " LDAP_XSTRING(bdb_tool_entry_reindex)
474 ": txn_commit failed: %s (%d)\n",
475 db_strerror(rc), rc, 0 );
481 Debug( LDAP_DEBUG_ANY,
482 "=> " LDAP_XSTRING(bdb_tool_entry_reindex)
483 ": txn_aborted! %s (%d)\n",
484 db_strerror(rc), rc, 0 );
487 bdb_entry_release( &op, e, 0 );
492 ID bdb_tool_entry_modify(
495 struct berval *text )
498 struct bdb_info *bdb = (struct bdb_info *) be->be_private;
503 assert( be != NULL );
504 assert( slapMode & SLAP_TOOL_MODE );
507 assert( text->bv_val );
508 assert( text->bv_val[0] == '\0' ); /* overconservative? */
510 assert ( e->e_id != NOID );
511 assert ( e->e_id != 0 );
513 Debug( LDAP_DEBUG_TRACE,
514 "=> " LDAP_XSTRING(bdb_tool_entry_modify) "( %ld, \"%s\" )\n",
515 (long) e->e_id, e->e_dn, 0 );
517 rc = TXN_BEGIN( bdb->bi_dbenv, NULL, &tid,
518 bdb->bi_db_opflags );
520 snprintf( text->bv_val, text->bv_len,
521 "txn_begin failed: %s (%d)",
522 db_strerror(rc), rc );
523 Debug( LDAP_DEBUG_ANY,
524 "=> " LDAP_XSTRING(bdb_tool_entry_modify) ": %s\n",
525 text->bv_val, 0, 0 );
531 op.o_tmpmemctx = NULL;
532 op.o_tmpmfuncs = &ch_mfuncs;
535 rc = bdb_id2entry_update( be, tid, e );
537 snprintf( text->bv_val, text->bv_len,
538 "id2entry_add failed: %s (%d)",
539 db_strerror(rc), rc );
540 Debug( LDAP_DEBUG_ANY,
541 "=> " LDAP_XSTRING(bdb_tool_entry_modify) ": %s\n",
542 text->bv_val, 0, 0 );
546 rc = bdb_index_entry_del( &op, tid, e );
548 snprintf( text->bv_val, text->bv_len,
549 "index_entry_del 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 );
557 rc = bdb_index_entry_add( &op, tid, e );
559 snprintf( text->bv_val, text->bv_len,
560 "index_entry_add failed: %s (%d)",
561 db_strerror(rc), rc );
562 Debug( LDAP_DEBUG_ANY,
563 "=> " LDAP_XSTRING(bdb_tool_entry_modify) ": %s\n",
564 text->bv_val, 0, 0 );
570 rc = TXN_COMMIT( tid, 0 );
572 snprintf( text->bv_val, text->bv_len,
573 "txn_commit failed: %s (%d)",
574 db_strerror(rc), rc );
575 Debug( LDAP_DEBUG_ANY,
576 "=> " LDAP_XSTRING(bdb_tool_entry_modify) ": "
577 "%s\n", text->bv_val, 0, 0 );
583 snprintf( text->bv_val, text->bv_len,
584 "txn_aborted! %s (%d)",
585 db_strerror(rc), rc );
586 Debug( LDAP_DEBUG_ANY,
587 "=> " LDAP_XSTRING(bdb_tool_entry_modify) ": %s\n",
588 text->bv_val, 0, 0 );