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 int bdb_tool_entry_open(
39 BackendDB *be, int mode )
41 /* initialize key and data thangs */
44 key.flags = DB_DBT_REALLOC;
45 data.flags = DB_DBT_REALLOC;
50 int bdb_tool_entry_close(
65 cursor->c_close( cursor );
71 fprintf( stderr, "Error, entries missing!\n");
72 for (i=0; i<nholes; i++) {
73 fprintf(stderr, " entry %ld: %s\n",
74 holes[i].id, holes[i].dn.bv_val);
82 ID bdb_tool_entry_next(
87 struct bdb_info *bdb = (struct bdb_info *) be->be_private;
90 assert( slapMode & SLAP_TOOL_MODE );
91 assert( bdb != NULL );
94 rc = bdb->bi_id2entry->bdi_db->cursor(
95 bdb->bi_id2entry->bdi_db, NULL, &cursor,
102 rc = cursor->c_get( cursor, &key, &data, DB_NEXT );
108 if( data.data == NULL ) {
112 AC_MEMCPY( &id, key.data, key.size );
116 ID bdb_tool_dn2id_get(
121 struct bdb_info *bdb = (struct bdb_info *) be->be_private;
122 DB *db = bdb->bi_dn2id->bdi_db;
128 key.size = dn->bv_len + 2;
129 key.data = ch_malloc( key.size );
130 ((char*)key.data)[0] = DN_BASE_PREFIX;
131 AC_MEMCPY( &((char*)key.data)[1], dn->bv_val, key.size - 1 );
135 data.ulen = sizeof(ID);
136 data.flags = DB_DBT_USERMEM;
138 rc = db->get( db, NULL, &key, &data, bdb->bi_db_opflags );
141 Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_tool_dn2id_get)
142 ": get failed: %s (%d)\n",
143 db_strerror( rc ), rc, 0 );
151 int bdb_tool_id2entry_get(
157 return bdb_id2entry( be, NULL, id, e );
160 Entry* bdb_tool_entry_get( BackendDB *be, ID id )
166 assert( be != NULL );
167 assert( slapMode & SLAP_TOOL_MODE );
168 assert( data.data != NULL );
171 DBT2bv( &data, &bv );
173 rc = entry_decode( &bv, &e );
175 if( rc == LDAP_SUCCESS ) {
180 EntryInfo *ei = NULL;
184 op.o_tmpmemctx = NULL;
185 op.o_tmpmfuncs = &ch_mfuncs;
187 rc = bdb_cache_find_id( &op, NULL, id, &ei, 0, 0, NULL );
188 if ( rc == LDAP_SUCCESS )
195 static int bdb_tool_next_id(
202 struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
203 struct berval dn = e->e_name;
204 struct berval ndn = e->e_nname;
205 struct berval pdn, npdn;
206 EntryInfo *ei = NULL, eidummy;
209 if (ndn.bv_len == 0) return 0;
211 rc = bdb_cache_find_ndn( op, tid, &ndn, &ei );
212 if ( ei ) bdb_cache_entryinfo_unlock( ei );
213 if ( rc == DB_NOTFOUND ) {
214 if ( !be_issuffix( op->o_bd, &ndn ) ) {
216 dnParent( &dn, &pdn );
217 dnParent( &ndn, &npdn );
220 rc = bdb_tool_next_id( op, tid, e, text, 1 );
226 /* If parent didn't exist, it was created just now
227 * and its ID is now in e->e_id. Make sure the current
228 * entry gets added under the new parent ID.
230 if ( eid != e->e_id ) {
231 eidummy.bei_id = e->e_id;
235 rc = bdb_next_id( op->o_bd, tid, &e->e_id );
237 snprintf( text->bv_val, text->bv_len,
238 "next_id failed: %s (%d)",
239 db_strerror(rc), rc );
240 Debug( LDAP_DEBUG_ANY,
241 "=> bdb_tool_next_id: %s\n", text->bv_val, 0, 0 );
244 rc = bdb_dn2id_add( op, tid, ei, e );
246 snprintf( text->bv_val, text->bv_len,
247 "dn2id_add failed: %s (%d)",
248 db_strerror(rc), rc );
249 Debug( LDAP_DEBUG_ANY,
250 "=> bdb_tool_next_id: %s\n", text->bv_val, 0, 0 );
252 if ( nholes == nhmax - 1 ) {
253 if ( holes == hbuf ) {
254 holes = ch_malloc( nhmax * sizeof(dn_id) * 2 );
255 AC_MEMCPY( holes, hbuf, sizeof(hbuf) );
257 holes = ch_realloc( holes, nhmax * sizeof(dn_id) * 2 );
261 ber_dupbv( &holes[nholes].dn, &ndn );
262 holes[nholes++].id = e->e_id;
264 } else if ( !hole ) {
267 e->e_id = ei->bei_id;
269 for ( i=0; i<nholes; i++) {
270 if ( holes[i].id == e->e_id ) {
272 free(holes[i].dn.bv_val);
273 for (j=i;j<nholes;j++) holes[j] = holes[j+1];
277 } else if ( holes[i].id > e->e_id ) {
285 ID bdb_tool_entry_put(
288 struct berval *text )
291 struct bdb_info *bdb = (struct bdb_info *) be->be_private;
295 assert( be != NULL );
296 assert( slapMode & SLAP_TOOL_MODE );
299 assert( text->bv_val );
300 assert( text->bv_val[0] == '\0' ); /* overconservative? */
302 Debug( LDAP_DEBUG_TRACE, "=> " LDAP_XSTRING(bdb_tool_entry_put)
303 "( %ld, \"%s\" )\n", (long) e->e_id, e->e_dn, 0 );
305 rc = TXN_BEGIN( bdb->bi_dbenv, NULL, &tid,
306 bdb->bi_db_opflags );
308 snprintf( text->bv_val, text->bv_len,
309 "txn_begin failed: %s (%d)",
310 db_strerror(rc), rc );
311 Debug( LDAP_DEBUG_ANY,
312 "=> " LDAP_XSTRING(bdb_tool_entry_put) ": %s\n",
313 text->bv_val, 0, 0 );
318 op.o_tmpmemctx = NULL;
319 op.o_tmpmfuncs = &ch_mfuncs;
321 /* add dn2id indices */
322 rc = bdb_tool_next_id( &op, tid, e, text, 0 );
328 rc = bdb_id2entry_add( be, tid, e );
330 snprintf( text->bv_val, text->bv_len,
331 "id2entry_add failed: %s (%d)",
332 db_strerror(rc), rc );
333 Debug( LDAP_DEBUG_ANY,
334 "=> " LDAP_XSTRING(bdb_tool_entry_put) ": %s\n",
335 text->bv_val, 0, 0 );
339 rc = bdb_index_entry_add( &op, tid, e );
341 snprintf( text->bv_val, text->bv_len,
342 "index_entry_add failed: %s (%d)",
343 db_strerror(rc), rc );
344 Debug( LDAP_DEBUG_ANY,
345 "=> " LDAP_XSTRING(bdb_tool_entry_put) ": %s\n",
346 text->bv_val, 0, 0 );
352 rc = TXN_COMMIT( tid, 0 );
354 snprintf( text->bv_val, text->bv_len,
355 "txn_commit failed: %s (%d)",
356 db_strerror(rc), rc );
357 Debug( LDAP_DEBUG_ANY,
358 "=> " LDAP_XSTRING(bdb_tool_entry_put) ": %s\n",
359 text->bv_val, 0, 0 );
365 snprintf( text->bv_val, text->bv_len,
366 "txn_aborted! %s (%d)",
367 db_strerror(rc), rc );
368 Debug( LDAP_DEBUG_ANY,
369 "=> " LDAP_XSTRING(bdb_tool_entry_put) ": %s\n",
370 text->bv_val, 0, 0 );
377 int bdb_tool_entry_reindex(
381 struct bdb_info *bi = (struct bdb_info *) be->be_private;
387 Debug( LDAP_DEBUG_ARGS,
388 "=> " LDAP_XSTRING(bdb_tool_entry_reindex) "( %ld )\n",
391 e = bdb_tool_entry_get( be, id );
394 Debug( LDAP_DEBUG_ANY,
395 LDAP_XSTRING(bdb_tool_entry_reindex)
396 ": could not locate id=%ld\n",
401 rc = TXN_BEGIN( bi->bi_dbenv, NULL, &tid, bi->bi_db_opflags );
403 Debug( LDAP_DEBUG_ANY,
404 "=> " LDAP_XSTRING(bdb_tool_entry_reindex) ": "
405 "txn_begin failed: %s (%d)\n",
406 db_strerror(rc), rc, 0 );
411 * just (re)add them for now
412 * assume that some other routine (not yet implemented)
413 * will zap index databases
417 Debug( LDAP_DEBUG_TRACE,
418 "=> " LDAP_XSTRING(bdb_tool_entry_reindex) "( %ld, \"%s\" )\n",
419 (long) id, e->e_dn, 0 );
422 op.o_tmpmemctx = NULL;
423 op.o_tmpmfuncs = &ch_mfuncs;
426 /* add dn2id indices */
427 rc = bdb_dn2id_add( &op, tid, NULL, e );
428 if( rc != 0 && rc != DB_KEYEXIST ) {
429 Debug( LDAP_DEBUG_ANY,
430 "=> " LDAP_XSTRING(bdb_tool_entry_reindex)
431 ": dn2id_add failed: %s (%d)\n",
432 db_strerror(rc), rc, 0 );
437 rc = bdb_index_entry_add( &op, tid, e );
441 rc = TXN_COMMIT( tid, 0 );
443 Debug( LDAP_DEBUG_ANY,
444 "=> " LDAP_XSTRING(bdb_tool_entry_reindex)
445 ": txn_commit failed: %s (%d)\n",
446 db_strerror(rc), rc, 0 );
452 Debug( LDAP_DEBUG_ANY,
453 "=> " LDAP_XSTRING(bdb_tool_entry_reindex)
454 ": txn_aborted! %s (%d)\n",
455 db_strerror(rc), rc, 0 );
458 bdb_entry_release( &op, e, 0 );
463 ID bdb_tool_entry_modify(
466 struct berval *text )
469 struct bdb_info *bdb = (struct bdb_info *) be->be_private;
473 assert( be != NULL );
474 assert( slapMode & SLAP_TOOL_MODE );
477 assert( text->bv_val );
478 assert( text->bv_val[0] == '\0' ); /* overconservative? */
480 assert ( e->e_id != NOID );
481 assert ( e->e_id != 0 );
483 Debug( LDAP_DEBUG_TRACE,
484 "=> " LDAP_XSTRING(bdb_tool_entry_modify) "( %ld, \"%s\" )\n",
485 (long) e->e_id, e->e_dn, 0 );
487 rc = TXN_BEGIN( bdb->bi_dbenv, NULL, &tid,
488 bdb->bi_db_opflags );
490 snprintf( text->bv_val, text->bv_len,
491 "txn_begin failed: %s (%d)",
492 db_strerror(rc), rc );
493 Debug( LDAP_DEBUG_ANY,
494 "=> " LDAP_XSTRING(bdb_tool_entry_modify) ": %s\n",
495 text->bv_val, 0, 0 );
500 op.o_tmpmemctx = NULL;
501 op.o_tmpmfuncs = &ch_mfuncs;
504 rc = bdb_id2entry_update( be, tid, e );
506 snprintf( text->bv_val, text->bv_len,
507 "id2entry_add failed: %s (%d)",
508 db_strerror(rc), rc );
509 Debug( LDAP_DEBUG_ANY,
510 "=> " LDAP_XSTRING(bdb_tool_entry_modify) ": %s\n",
511 text->bv_val, 0, 0 );
515 rc = bdb_index_entry_del( &op, tid, e );
517 snprintf( text->bv_val, text->bv_len,
518 "index_entry_del failed: %s (%d)",
519 db_strerror(rc), rc );
520 Debug( LDAP_DEBUG_ANY,
521 "=> " LDAP_XSTRING(bdb_tool_entry_modify) ": %s\n",
522 text->bv_val, 0, 0 );
526 rc = bdb_index_entry_add( &op, tid, e );
528 snprintf( text->bv_val, text->bv_len,
529 "index_entry_add failed: %s (%d)",
530 db_strerror(rc), rc );
531 Debug( LDAP_DEBUG_ANY,
532 "=> " LDAP_XSTRING(bdb_tool_entry_modify) ": %s\n",
533 text->bv_val, 0, 0 );
539 rc = TXN_COMMIT( tid, 0 );
541 snprintf( text->bv_val, text->bv_len,
542 "txn_commit failed: %s (%d)",
543 db_strerror(rc), rc );
544 Debug( LDAP_DEBUG_ANY,
545 "=> " LDAP_XSTRING(bdb_tool_entry_modify) ": "
546 "%s\n", text->bv_val, 0, 0 );
552 snprintf( text->bv_val, text->bv_len,
553 "txn_aborted! %s (%d)",
554 db_strerror(rc), rc );
555 Debug( LDAP_DEBUG_ANY,
556 "=> " LDAP_XSTRING(bdb_tool_entry_modify) ": %s\n",
557 text->bv_val, 0, 0 );