1 1.1 christos /* $NetBSD: tools.c,v 1.3 2025/09/05 21:16:32 christos Exp $ */ 2 1.1 christos 3 1.1 christos /* OpenLDAP WiredTiger backend */ 4 1.1 christos /* $OpenLDAP$ */ 5 1.1 christos /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 1.1 christos * 7 1.3 christos * Copyright 2002-2024 The OpenLDAP Foundation. 8 1.1 christos * All rights reserved. 9 1.1 christos * 10 1.1 christos * Redistribution and use in source and binary forms, with or without 11 1.1 christos * modification, are permitted only as authorized by the OpenLDAP 12 1.1 christos * Public License. 13 1.1 christos * 14 1.1 christos * A copy of this license is available in the file LICENSE in the 15 1.1 christos * top-level directory of the distribution or, alternatively, at 16 1.1 christos * <http://www.OpenLDAP.org/license.html>. 17 1.1 christos */ 18 1.1 christos /* ACKNOWLEDGEMENTS: 19 1.1 christos * This work was developed by HAMANO Tsukasa <hamano (at) osstech.co.jp> 20 1.1 christos * based on back-bdb for inclusion in OpenLDAP Software. 21 1.1 christos * WiredTiger is a product of MongoDB Inc. 22 1.1 christos */ 23 1.1 christos 24 1.1 christos #include <sys/cdefs.h> 25 1.1 christos __RCSID("$NetBSD: tools.c,v 1.3 2025/09/05 21:16:32 christos Exp $"); 26 1.1 christos 27 1.1 christos #include "portable.h" 28 1.1 christos 29 1.1 christos #include <stdio.h> 30 1.1 christos #include <ac/string.h> 31 1.1 christos #include "back-wt.h" 32 1.1 christos #include "slap-config.h" 33 1.1 christos 34 1.1 christos typedef struct dn_id { 35 1.1 christos ID id; 36 1.1 christos struct berval dn; 37 1.1 christos } dn_id; 38 1.1 christos 39 1.1 christos #define HOLE_SIZE 4096 40 1.1 christos static dn_id hbuf[HOLE_SIZE], *holes = hbuf; 41 1.1 christos static unsigned nholes; 42 1.1 christos 43 1.1 christos static struct berval *tool_base; 44 1.1 christos static int tool_scope; 45 1.1 christos static Filter *tool_filter; 46 1.1 christos 47 1.1 christos static wt_ctx *wc; 48 1.1 christos static WT_CURSOR *reader; 49 1.1 christos static WT_ITEM item; 50 1.1 christos 51 1.1 christos int 52 1.1 christos wt_tool_entry_open( BackendDB *be, int mode ) 53 1.1 christos { 54 1.1 christos struct wt_info *wi = (struct wt_info *) be->be_private; 55 1.1 christos int rc; 56 1.1 christos 57 1.3 christos if ( slapMode & SLAP_TOOL_DRYRUN ) 58 1.3 christos return 0; 59 1.3 christos 60 1.1 christos wc = wt_ctx_init(wi); 61 1.1 christos if( !wc ){ 62 1.1 christos Debug( LDAP_DEBUG_ANY, 63 1.3 christos "wt_tool_entry_open: wt_ctx_get failed\n" ); 64 1.1 christos return -1; 65 1.1 christos } 66 1.1 christos 67 1.1 christos rc = wc->session->open_cursor(wc->session, WT_TABLE_ID2ENTRY"(entry)" 68 1.1 christos ,NULL, NULL, &reader); 69 1.1 christos if ( rc ) { 70 1.1 christos Debug( LDAP_DEBUG_ANY, 71 1.3 christos "wt_tool_entry_open: cursor open failed: %s (%d)\n", 72 1.1 christos wiredtiger_strerror(rc), rc ); 73 1.1 christos return -1; 74 1.1 christos } 75 1.1 christos 76 1.1 christos return 0; 77 1.1 christos } 78 1.1 christos 79 1.1 christos int 80 1.1 christos wt_tool_entry_close( BackendDB *be ) 81 1.1 christos { 82 1.3 christos if ( slapMode & SLAP_TOOL_DRYRUN ) 83 1.3 christos return 0; 84 1.1 christos 85 1.1 christos if( reader ) { 86 1.1 christos reader->close(reader); 87 1.1 christos reader = NULL; 88 1.1 christos } 89 1.1 christos 90 1.1 christos wt_ctx_free(NULL, wc); 91 1.1 christos 92 1.1 christos if( nholes ) { 93 1.1 christos unsigned i; 94 1.1 christos fprintf( stderr, "Error, entries missing!\n"); 95 1.1 christos for (i=0; i<nholes; i++) { 96 1.1 christos fprintf(stderr, " entry %ld: %s\n", 97 1.1 christos holes[i].id, holes[i].dn.bv_val); 98 1.1 christos } 99 1.1 christos return -1; 100 1.1 christos } 101 1.1 christos 102 1.1 christos return 0; 103 1.1 christos } 104 1.1 christos 105 1.1 christos ID 106 1.1 christos wt_tool_entry_first_x( BackendDB *be, 107 1.1 christos struct berval *base, 108 1.1 christos int scope, 109 1.1 christos Filter *f ) 110 1.1 christos { 111 1.1 christos tool_base = base; 112 1.1 christos tool_scope = scope; 113 1.1 christos tool_filter = f; 114 1.1 christos 115 1.1 christos return wt_tool_entry_next( be ); 116 1.1 christos } 117 1.1 christos 118 1.1 christos ID 119 1.1 christos wt_tool_entry_next( BackendDB *be ) 120 1.1 christos { 121 1.1 christos int rc; 122 1.1 christos ID id; 123 1.1 christos 124 1.1 christos rc = reader->next(reader); 125 1.1 christos switch( rc ){ 126 1.1 christos case 0: 127 1.1 christos break; 128 1.1 christos case WT_NOTFOUND: 129 1.1 christos return NOID; 130 1.1 christos default: 131 1.1 christos Debug( LDAP_DEBUG_ANY, 132 1.3 christos "wt_tool_entry_next: next failed: %s (%d)\n", 133 1.1 christos wiredtiger_strerror(rc), rc ); 134 1.1 christos return NOID; 135 1.1 christos } 136 1.1 christos 137 1.1 christos rc = reader->get_key(reader, &id); 138 1.1 christos if( rc ){ 139 1.1 christos Debug( LDAP_DEBUG_ANY, 140 1.3 christos "wt_tool_entry_next: get_key failed: %s (%d)\n", 141 1.1 christos wiredtiger_strerror(rc), rc ); 142 1.1 christos } 143 1.1 christos return id; 144 1.1 christos } 145 1.1 christos 146 1.1 christos static ber_len_t 147 1.1 christos entry_getlen(unsigned char **buf) 148 1.1 christos { 149 1.1 christos ber_len_t len; 150 1.1 christos int i; 151 1.1 christos 152 1.1 christos len = *(*buf)++; 153 1.1 christos if (len <= 0x7f) 154 1.1 christos return len; 155 1.1 christos i = len & 0x7f; 156 1.1 christos len = 0; 157 1.1 christos for (;i > 0; i--) { 158 1.1 christos len <<= 8; 159 1.1 christos len |= *(*buf)++; 160 1.1 christos } 161 1.1 christos return len; 162 1.1 christos } 163 1.1 christos 164 1.3 christos int wt_entry_header(WT_ITEM *item, EntryHeader *eh) 165 1.3 christos { 166 1.1 christos unsigned char *ptr = (unsigned char *)item->data; 167 1.1 christos 168 1.1 christos /* Some overlays can create empty entries 169 1.1 christos * so don't check for zeros here. 170 1.1 christos */ 171 1.1 christos eh->nattrs = entry_getlen(&ptr); 172 1.1 christos eh->nvals = entry_getlen(&ptr); 173 1.1 christos eh->data = (char *)ptr; 174 1.1 christos return LDAP_SUCCESS; 175 1.1 christos } 176 1.1 christos 177 1.1 christos Entry * 178 1.1 christos wt_tool_entry_get( BackendDB *be, ID id ) 179 1.1 christos { 180 1.1 christos Entry *e = NULL; 181 1.1 christos static EntryHeader eh; 182 1.1 christos int rc, eoff; 183 1.1 christos 184 1.1 christos assert( be != NULL ); 185 1.1 christos assert( slapMode & SLAP_TOOL_MODE ); 186 1.1 christos 187 1.3 christos reader->set_key(reader, id); 188 1.3 christos rc = reader->search(reader); 189 1.3 christos if ( rc ) { 190 1.3 christos Debug( LDAP_DEBUG_ANY, 191 1.3 christos "wt_tool_entry_get: search failed: %s (%d)\n", 192 1.3 christos wiredtiger_strerror(rc), rc ); 193 1.3 christos goto done; 194 1.3 christos } 195 1.3 christos rc = reader->get_value(reader, &item); 196 1.3 christos if( rc ){ 197 1.3 christos Debug( LDAP_DEBUG_ANY, 198 1.3 christos "wt_tool_entry_get: get_value failed: %s (%d)\n", 199 1.3 christos wiredtiger_strerror(rc), rc ); 200 1.3 christos goto done; 201 1.3 christos } 202 1.3 christos 203 1.1 christos rc = wt_entry_header( &item, &eh ); 204 1.1 christos assert( rc == 0 ); 205 1.1 christos eoff = eh.data - (char *)item.data; 206 1.1 christos 207 1.1 christos eh.bv.bv_len = eh.nvals * sizeof( struct berval ) + item.size; 208 1.1 christos eh.bv.bv_val = ch_realloc( eh.bv.bv_val, eh.bv.bv_len ); 209 1.1 christos memset(eh.bv.bv_val, 0xff, eh.bv.bv_len); 210 1.1 christos eh.data = eh.bv.bv_val + eh.nvals * sizeof( struct berval ); 211 1.1 christos memcpy(eh.data, item.data, item.size); 212 1.1 christos eh.data += eoff; 213 1.1 christos 214 1.1 christos rc = entry_decode( &eh, &e ); 215 1.1 christos assert( rc == 0 ); 216 1.1 christos 217 1.1 christos if( rc == LDAP_SUCCESS ) { 218 1.1 christos e->e_id = id; 219 1.1 christos } 220 1.1 christos 221 1.3 christos done: 222 1.1 christos return e; 223 1.1 christos } 224 1.1 christos 225 1.1 christos static int wt_tool_next_id( 226 1.1 christos Operation *op, 227 1.1 christos Entry *e, 228 1.1 christos struct berval *text, 229 1.1 christos int hole ) 230 1.1 christos { 231 1.1 christos struct berval dn = e->e_name; 232 1.1 christos struct berval ndn = e->e_nname; 233 1.1 christos struct berval pdn, npdn; 234 1.1 christos int rc; 235 1.1 christos ID id = 0; 236 1.1 christos ID pid = 0; 237 1.1 christos 238 1.1 christos if(ndn.bv_len == 0){ 239 1.1 christos e->e_id = 0; 240 1.1 christos return 0; 241 1.1 christos } 242 1.1 christos 243 1.3 christos rc = wt_dn2id(op, wc, &ndn, &id); 244 1.1 christos if(rc == 0){ 245 1.1 christos e->e_id = id; 246 1.1 christos }else if( rc == WT_NOTFOUND ){ 247 1.1 christos if ( !be_issuffix( op->o_bd, &ndn ) ) { 248 1.1 christos ID eid = e->e_id; 249 1.1 christos dnParent( &dn, &pdn ); 250 1.1 christos dnParent( &ndn, &npdn ); 251 1.1 christos e->e_name = pdn; 252 1.1 christos e->e_nname = npdn; 253 1.1 christos rc = wt_tool_next_id( op, e, text, 1 ); 254 1.1 christos e->e_name = dn; 255 1.1 christos e->e_nname = ndn; 256 1.1 christos if ( rc ) { 257 1.1 christos return rc; 258 1.1 christos } 259 1.1 christos /* If parent didn't exist, it was created just now 260 1.1 christos * and its ID is now in e->e_id. Make sure the current 261 1.1 christos * entry gets added under the new parent ID. 262 1.1 christos */ 263 1.1 christos if ( eid != e->e_id ) { 264 1.1 christos pid = e->e_id; 265 1.1 christos } 266 1.1 christos }else{ 267 1.1 christos pid = id; 268 1.1 christos } 269 1.1 christos wt_next_id( op->o_bd, &e->e_id ); 270 1.3 christos rc = wt_dn2id_add(op, wc, pid, e); 271 1.1 christos if( rc ){ 272 1.1 christos snprintf( text->bv_val, text->bv_len, 273 1.1 christos "wt_dn2id_add failed: %s (%d)", 274 1.1 christos wiredtiger_strerror(rc), rc ); 275 1.1 christos Debug( LDAP_DEBUG_ANY, 276 1.1 christos "=> wt_tool_next_id: %s\n", text->bv_val ); 277 1.1 christos } 278 1.1 christos 279 1.1 christos }else if ( !hole ) { 280 1.1 christos unsigned i, j; 281 1.1 christos e->e_id = id; 282 1.1 christos 283 1.1 christos for ( i=0; i<nholes; i++) { 284 1.1 christos if ( holes[i].id == e->e_id ) { 285 1.1 christos free(holes[i].dn.bv_val); 286 1.1 christos for (j=i;j<nholes;j++) holes[j] = holes[j+1]; 287 1.1 christos holes[j].id = 0; 288 1.1 christos nholes--; 289 1.1 christos break; 290 1.1 christos } else if ( holes[i].id > e->e_id ) { 291 1.1 christos break; 292 1.1 christos } 293 1.1 christos } 294 1.1 christos } 295 1.1 christos return rc; 296 1.1 christos } 297 1.1 christos 298 1.1 christos static int 299 1.1 christos wt_tool_index_add( 300 1.1 christos Operation *op, 301 1.1 christos wt_ctx *wc, 302 1.1 christos Entry *e ) 303 1.1 christos { 304 1.1 christos return wt_index_entry_add( op, wc, e ); 305 1.1 christos } 306 1.1 christos 307 1.1 christos ID 308 1.1 christos wt_tool_entry_put( BackendDB *be, Entry *e, struct berval *text ) 309 1.1 christos { 310 1.1 christos int rc; 311 1.3 christos Operation op = {0}; 312 1.3 christos Opheader ohdr = {0}; 313 1.1 christos 314 1.3 christos if ( slapMode & SLAP_TOOL_DRYRUN ) 315 1.3 christos return 0; 316 1.1 christos 317 1.1 christos assert( slapMode & SLAP_TOOL_MODE ); 318 1.1 christos assert( text != NULL ); 319 1.1 christos assert( text->bv_val != NULL ); 320 1.1 christos assert( text->bv_val[0] == '\0' ); /* overconservative? */ 321 1.1 christos 322 1.1 christos Debug( LDAP_DEBUG_TRACE, 323 1.3 christos "=> wt_tool_entry_put: ( \"%s\" )\n", e->e_dn ); 324 1.1 christos 325 1.1 christos rc = wc->session->begin_transaction(wc->session, NULL); 326 1.1 christos if( rc ){ 327 1.1 christos Debug( LDAP_DEBUG_ANY, 328 1.3 christos "wt_dn2id_add: begin_transaction failed: %s (%d)\n", 329 1.1 christos wiredtiger_strerror(rc), rc ); 330 1.1 christos return NOID; 331 1.1 christos } 332 1.1 christos 333 1.1 christos op.o_hdr = &ohdr; 334 1.1 christos op.o_bd = be; 335 1.1 christos op.o_tmpmemctx = NULL; 336 1.1 christos op.o_tmpmfuncs = &ch_mfuncs; 337 1.1 christos 338 1.1 christos rc = wt_tool_next_id( &op, e, text, 0 ); 339 1.1 christos if( rc != 0 ) { 340 1.1 christos snprintf( text->bv_val, text->bv_len, 341 1.1 christos "wt_tool_next_id failed: %s (%d)", 342 1.1 christos wiredtiger_strerror(rc), rc ); 343 1.1 christos Debug( LDAP_DEBUG_ANY, 344 1.3 christos "=> wt_tool_entry_put: %s\n", text->bv_val ); 345 1.1 christos goto done; 346 1.1 christos } 347 1.1 christos 348 1.3 christos rc = wt_id2entry_add( &op, wc, e ); 349 1.1 christos if( rc != 0 ) { 350 1.1 christos snprintf( text->bv_val, text->bv_len, 351 1.1 christos "id2entry_add failed: %s (%d)", 352 1.1 christos wiredtiger_strerror(rc), rc ); 353 1.1 christos Debug( LDAP_DEBUG_ANY, 354 1.3 christos "=> wt_tool_entry_put: %s\n", 355 1.1 christos text->bv_val ); 356 1.1 christos goto done; 357 1.1 christos } 358 1.1 christos 359 1.1 christos rc = wt_tool_index_add( &op, wc, e ); 360 1.1 christos if( rc != 0 ) { 361 1.1 christos snprintf( text->bv_val, text->bv_len, 362 1.1 christos "index_entry_add failed: %s (%d)", 363 1.1 christos rc == LDAP_OTHER ? "Internal error" : 364 1.1 christos wiredtiger_strerror(rc), rc ); 365 1.1 christos Debug( LDAP_DEBUG_ANY, 366 1.3 christos "=> wt_tool_entry_put: %s\n", text->bv_val ); 367 1.1 christos goto done; 368 1.1 christos } 369 1.1 christos 370 1.1 christos done: 371 1.1 christos if ( rc == 0 ){ 372 1.1 christos rc = wc->session->commit_transaction(wc->session, NULL); 373 1.1 christos if( rc != 0 ) { 374 1.1 christos snprintf( text->bv_val, text->bv_len, 375 1.1 christos "txn_commit failed: %s (%d)", 376 1.1 christos wiredtiger_strerror(rc), rc ); 377 1.1 christos Debug( LDAP_DEBUG_ANY, 378 1.3 christos "=> wt_tool_entry_put: %s\n", text->bv_val ); 379 1.1 christos e->e_id = NOID; 380 1.1 christos } 381 1.1 christos }else{ 382 1.1 christos rc = wc->session->rollback_transaction(wc->session, NULL); 383 1.1 christos snprintf( text->bv_val, text->bv_len, 384 1.1 christos "txn_aborted! %s (%d)", 385 1.1 christos rc == LDAP_OTHER ? "Internal error" : 386 1.1 christos wiredtiger_strerror(rc), rc ); 387 1.1 christos Debug( LDAP_DEBUG_ANY, 388 1.3 christos "=> wt_tool_entry_put: %s\n", text->bv_val ); 389 1.1 christos e->e_id = NOID; 390 1.1 christos } 391 1.1 christos 392 1.1 christos return e->e_id; 393 1.1 christos } 394 1.1 christos 395 1.1 christos int wt_tool_entry_reindex( 396 1.1 christos BackendDB *be, 397 1.1 christos ID id, 398 1.1 christos AttributeDescription **adv ) 399 1.1 christos { 400 1.1 christos struct wt_info *wi = (struct wt_info *) be->be_private; 401 1.1 christos int rc; 402 1.1 christos Entry *e; 403 1.1 christos Operation op = {0}; 404 1.1 christos Opheader ohdr = {0}; 405 1.1 christos 406 1.1 christos Debug( LDAP_DEBUG_ARGS, 407 1.3 christos "=> wt_tool_entry_reindex( %ld )\n", (long) id ); 408 1.1 christos assert( tool_base == NULL ); 409 1.1 christos assert( tool_filter == NULL ); 410 1.1 christos 411 1.1 christos /* No indexes configured, nothing to do. Could return an 412 1.1 christos * error here to shortcut things. 413 1.1 christos */ 414 1.1 christos if (!wi->wi_attrs) { 415 1.1 christos return 0; 416 1.1 christos } 417 1.1 christos 418 1.1 christos /* Check for explicit list of attrs to index */ 419 1.1 christos if ( adv ) { 420 1.1 christos int i, j, n; 421 1.1 christos 422 1.1 christos if ( wi->wi_attrs[0]->ai_desc != adv[0] ) { 423 1.1 christos /* count */ 424 1.1 christos for ( n = 0; adv[n]; n++ ) ; 425 1.1 christos 426 1.1 christos /* insertion sort */ 427 1.1 christos for ( i = 0; i < n; i++ ) { 428 1.1 christos AttributeDescription *ad = adv[i]; 429 1.1 christos for ( j = i-1; j>=0; j--) { 430 1.1 christos if ( SLAP_PTRCMP( adv[j], ad ) <= 0 ) break; 431 1.1 christos adv[j+1] = adv[j]; 432 1.1 christos } 433 1.1 christos adv[j+1] = ad; 434 1.1 christos } 435 1.1 christos } 436 1.1 christos 437 1.1 christos for ( i = 0; adv[i]; i++ ) { 438 1.1 christos if ( wi->wi_attrs[i]->ai_desc != adv[i] ) { 439 1.1 christos for ( j = i+1; j < wi->wi_nattrs; j++ ) { 440 1.1 christos if ( wi->wi_attrs[j]->ai_desc == adv[i] ) { 441 1.1 christos AttrInfo *ai = wi->wi_attrs[i]; 442 1.1 christos wi->wi_attrs[i] = wi->wi_attrs[j]; 443 1.1 christos wi->wi_attrs[j] = ai; 444 1.1 christos break; 445 1.1 christos } 446 1.1 christos } 447 1.1 christos if ( j == wi->wi_nattrs ) { 448 1.1 christos Debug( LDAP_DEBUG_ANY, 449 1.3 christos "wt_tool_entry_reindex: no index configured for %s\n", 450 1.1 christos adv[i]->ad_cname.bv_val ); 451 1.1 christos return -1; 452 1.1 christos } 453 1.1 christos } 454 1.1 christos } 455 1.1 christos wi->wi_nattrs = i; 456 1.1 christos } 457 1.1 christos 458 1.1 christos e = wt_tool_entry_get( be, id ); 459 1.1 christos 460 1.1 christos if( e == NULL ) { 461 1.3 christos Debug( LDAP_DEBUG_ANY, "=> wt_tool_entry_reindex" 462 1.1 christos ": could not locate id=%ld\n", 463 1.1 christos (long) id ); 464 1.1 christos return -1; 465 1.1 christos } 466 1.1 christos 467 1.1 christos op.o_hdr = &ohdr; 468 1.1 christos op.o_bd = be; 469 1.1 christos op.o_tmpmemctx = NULL; 470 1.1 christos op.o_tmpmfuncs = &ch_mfuncs; 471 1.1 christos 472 1.1 christos rc = wc->session->begin_transaction(wc->session, NULL); 473 1.1 christos if( rc ){ 474 1.1 christos Debug( LDAP_DEBUG_ANY, 475 1.3 christos "wt_tool_entry_reindex: begin_transaction failed %s (%d)\n", 476 1.1 christos wiredtiger_strerror(rc), rc ); 477 1.1 christos goto done; 478 1.1 christos } 479 1.1 christos Debug( LDAP_DEBUG_TRACE, 480 1.3 christos "=> wt_tool_entry_reindex( %ld, \"%s\" )\n", 481 1.1 christos (long) id, e->e_dn ); 482 1.1 christos 483 1.1 christos rc = wt_tool_index_add( &op, wc, e ); 484 1.1 christos 485 1.1 christos done: 486 1.1 christos if ( rc == 0 ){ 487 1.1 christos rc = wc->session->commit_transaction(wc->session, NULL); 488 1.1 christos if( rc ) { 489 1.1 christos Debug( LDAP_DEBUG_ANY, 490 1.3 christos "=> wt_tool_entry_reindex: commit_transaction failed %s (%d)\n", 491 1.1 christos wiredtiger_strerror(rc), rc ); 492 1.1 christos } 493 1.1 christos }else{ 494 1.1 christos rc = wc->session->rollback_transaction(wc->session, NULL); 495 1.1 christos Debug( LDAP_DEBUG_ANY, 496 1.3 christos "=> wt_tool_entry_reindex: rollback transaction %s (%d)\n", 497 1.1 christos wiredtiger_strerror(rc), rc ); 498 1.1 christos } 499 1.1 christos 500 1.1 christos wt_entry_release( &op, e, 0 ); 501 1.1 christos 502 1.1 christos return rc; 503 1.1 christos } 504 1.1 christos 505 1.3 christos ID wt_tool_dn2id_get( 506 1.3 christos Backend *be, 507 1.3 christos struct berval *dn 508 1.3 christos ) 509 1.3 christos { 510 1.3 christos Operation op = {0}; 511 1.3 christos Opheader ohdr = {0}; 512 1.3 christos ID id; 513 1.3 christos int rc; 514 1.3 christos 515 1.3 christos if ( BER_BVISEMPTY(dn) ) 516 1.3 christos return 0; 517 1.3 christos 518 1.3 christos op.o_hdr = &ohdr; 519 1.3 christos op.o_bd = be; 520 1.3 christos op.o_tmpmemctx = NULL; 521 1.3 christos op.o_tmpmfuncs = &ch_mfuncs; 522 1.3 christos 523 1.3 christos rc = wt_dn2id(&op, wc, dn, &id); 524 1.3 christos switch( rc ){ 525 1.3 christos case 0: 526 1.3 christos break; 527 1.3 christos case WT_NOTFOUND: 528 1.3 christos return NOID; 529 1.3 christos default: 530 1.3 christos Debug( LDAP_DEBUG_ANY, 531 1.3 christos "wt_tool_entry_get: entry get failed: %s (%d)\n", 532 1.3 christos wiredtiger_strerror(rc), rc ); 533 1.3 christos return NOID; 534 1.3 christos } 535 1.3 christos return id; 536 1.3 christos } 537 1.3 christos 538 1.3 christos ID wt_tool_entry_modify( 539 1.3 christos BackendDB *be, 540 1.3 christos Entry *e, 541 1.3 christos struct berval *text ) 542 1.3 christos { 543 1.3 christos int rc; 544 1.3 christos Operation op = {0}; 545 1.3 christos Opheader ohdr = {0}; 546 1.3 christos 547 1.3 christos assert( be != NULL ); 548 1.3 christos assert( slapMode & SLAP_TOOL_MODE ); 549 1.3 christos 550 1.3 christos assert( text != NULL ); 551 1.3 christos assert( text->bv_val != NULL ); 552 1.3 christos assert( text->bv_val[0] == '\0' ); /* overconservative? */ 553 1.3 christos 554 1.3 christos assert ( e->e_id != NOID ); 555 1.3 christos 556 1.3 christos Debug( LDAP_DEBUG_TRACE, 557 1.3 christos "=> wt_tool_entry_modify( %ld, \"%s\" )\n", 558 1.3 christos (long) e->e_id, e->e_dn ); 559 1.3 christos 560 1.3 christos rc = wc->session->begin_transaction(wc->session, NULL); 561 1.3 christos if( rc ){ 562 1.3 christos Debug( LDAP_DEBUG_ANY, "=> wt_tool_entry_modify" 563 1.3 christos ": begin_transaction failed: %s (%d)\n", 564 1.3 christos wiredtiger_strerror(rc), rc ); 565 1.3 christos return NOID; 566 1.3 christos } 567 1.3 christos 568 1.3 christos op.o_hdr = &ohdr; 569 1.3 christos op.o_bd = be; 570 1.3 christos op.o_tmpmemctx = NULL; 571 1.3 christos op.o_tmpmfuncs = &ch_mfuncs; 572 1.3 christos 573 1.3 christos rc = wt_id2entry_update( &op, wc, e ); 574 1.3 christos if( rc != 0 ) { 575 1.3 christos snprintf( text->bv_val, text->bv_len, 576 1.3 christos "id2entry_update failed: %s (%d)", 577 1.3 christos wiredtiger_strerror(rc), rc ); 578 1.3 christos Debug( LDAP_DEBUG_ANY, "=> wt_tool_entry_modify: %s\n", 579 1.3 christos text->bv_val ); 580 1.3 christos goto done; 581 1.3 christos } 582 1.3 christos 583 1.3 christos done: 584 1.3 christos if ( rc == 0 ){ 585 1.3 christos rc = wc->session->commit_transaction(wc->session, NULL); 586 1.3 christos if( rc != 0 ) { 587 1.3 christos snprintf( text->bv_val, text->bv_len, 588 1.3 christos "txn_commit failed: %s (%d)", 589 1.3 christos wiredtiger_strerror(rc), rc ); 590 1.3 christos Debug( LDAP_DEBUG_ANY, "=> wt_tool_entry_modify: %s\n", 591 1.3 christos text->bv_val ); 592 1.3 christos e->e_id = NOID; 593 1.3 christos } 594 1.3 christos }else{ 595 1.3 christos rc = wc->session->rollback_transaction(wc->session, NULL); 596 1.3 christos snprintf( text->bv_val, text->bv_len, 597 1.3 christos "txn_aborted! %s (%d)", 598 1.3 christos rc == LDAP_OTHER ? "Internal error" : 599 1.3 christos wiredtiger_strerror(rc), rc ); 600 1.3 christos Debug( LDAP_DEBUG_ANY, "=> wt_tool_entry_modify: %s\n", 601 1.3 christos text->bv_val ); 602 1.3 christos e->e_id = NOID; 603 1.3 christos } 604 1.3 christos 605 1.3 christos return e->e_id; 606 1.3 christos } 607 1.3 christos 608 1.3 christos int wt_tool_entry_delete( 609 1.3 christos BackendDB *be, 610 1.3 christos struct berval *ndn, 611 1.3 christos struct berval *text ) 612 1.3 christos { 613 1.3 christos struct wt_info *wi = (struct wt_info *) be->be_private; 614 1.3 christos int rc; 615 1.3 christos Operation op = {0}; 616 1.3 christos Opheader ohdr = {0}; 617 1.3 christos Entry *e = NULL; 618 1.3 christos 619 1.3 christos assert( be != NULL ); 620 1.3 christos assert( slapMode & SLAP_TOOL_MODE ); 621 1.3 christos 622 1.3 christos assert( text != NULL ); 623 1.3 christos assert( text->bv_val != NULL ); 624 1.3 christos assert( text->bv_val[0] == '\0' ); /* overconservative? */ 625 1.3 christos 626 1.3 christos assert ( ndn != NULL ); 627 1.3 christos assert ( ndn->bv_val != NULL ); 628 1.3 christos 629 1.3 christos Debug( LDAP_DEBUG_TRACE, 630 1.3 christos "=> wt_tool_entry_delete( %s )\n", 631 1.3 christos ndn->bv_val ); 632 1.3 christos 633 1.3 christos op.o_hdr = &ohdr; 634 1.3 christos op.o_bd = be; 635 1.3 christos op.o_tmpmemctx = NULL; 636 1.3 christos op.o_tmpmfuncs = &ch_mfuncs; 637 1.3 christos 638 1.3 christos /* get entry */ 639 1.3 christos rc = wt_dn2entry(op.o_bd, wc, ndn, &e); 640 1.3 christos switch( rc ) { 641 1.3 christos case 0: 642 1.3 christos break; 643 1.3 christos case WT_NOTFOUND: 644 1.3 christos Debug( LDAP_DEBUG_ARGS, 645 1.3 christos "<== wt_tool_entry_delete: no such object %s\n", 646 1.3 christos ndn->bv_val); 647 1.3 christos goto done; 648 1.3 christos default: 649 1.3 christos Debug( LDAP_DEBUG_ANY, 650 1.3 christos "wt_tool_entry_delete: error at wt_dn2entry() rc=%d\n", 651 1.3 christos rc ); 652 1.3 christos goto done; 653 1.3 christos } 654 1.3 christos 655 1.3 christos rc = wt_dn2id_has_children( &op, wc, e->e_id ); 656 1.3 christos if( rc != WT_NOTFOUND ) { 657 1.3 christos /* subordinate objects must be deleted first */ 658 1.3 christos rc = -1; 659 1.3 christos goto done; 660 1.3 christos } 661 1.3 christos 662 1.3 christos rc = wc->session->begin_transaction(wc->session, NULL); 663 1.3 christos if( rc ){ 664 1.3 christos Debug( LDAP_DEBUG_ANY, 665 1.3 christos "wt_tool_entry_delete: begin_transaction failed: %s (%d)\n", 666 1.3 christos wiredtiger_strerror(rc), rc ); 667 1.3 christos goto done; 668 1.3 christos } 669 1.3 christos 670 1.3 christos /* delete from dn2id */ 671 1.3 christos rc = wt_dn2id_delete( &op, wc, &e->e_nname); 672 1.3 christos if ( rc ) { 673 1.3 christos Debug( LDAP_DEBUG_TRACE, 674 1.3 christos "<== wt_tool_entry_delete: dn2id failed: %s (%d)\n", 675 1.3 christos wiredtiger_strerror(rc), rc ); 676 1.3 christos wc->session->rollback_transaction(wc->session, NULL); 677 1.3 christos goto done; 678 1.3 christos } 679 1.3 christos 680 1.3 christos /* delete indices for old attributes */ 681 1.3 christos rc = wt_index_entry_del( &op, wc, e ); 682 1.3 christos if ( rc ) { 683 1.3 christos Debug( LDAP_DEBUG_TRACE, 684 1.3 christos "<== wt_tool_entry_delete: index delete failed: %s (%d)\n", 685 1.3 christos wiredtiger_strerror(rc), rc ); 686 1.3 christos wc->session->rollback_transaction(wc->session, NULL); 687 1.3 christos goto done; 688 1.3 christos } 689 1.3 christos 690 1.3 christos /* delete from id2entry */ 691 1.3 christos rc = wt_id2entry_delete( &op, wc, e ); 692 1.3 christos if ( rc ) { 693 1.3 christos Debug( LDAP_DEBUG_TRACE, 694 1.3 christos "<== wt_tool_entry_delete: id2entry failed: %s (%d)\n", 695 1.3 christos wiredtiger_strerror(rc), rc ); 696 1.3 christos wc->session->rollback_transaction(wc->session, NULL); 697 1.3 christos goto done; 698 1.3 christos } 699 1.3 christos 700 1.3 christos rc = wc->session->commit_transaction(wc->session, NULL); 701 1.3 christos if( rc != 0 ) { 702 1.3 christos snprintf( text->bv_val, text->bv_len, 703 1.3 christos "txn_commit failed: %s (%d)", 704 1.3 christos wiredtiger_strerror(rc), rc ); 705 1.3 christos Debug( LDAP_DEBUG_ANY, 706 1.3 christos "=> wt_tool_entry_delete: %s\n", 707 1.3 christos text->bv_val ); 708 1.3 christos goto done; 709 1.3 christos } 710 1.3 christos 711 1.3 christos done: 712 1.3 christos /* free entry */ 713 1.3 christos if( e != NULL ) { 714 1.3 christos wt_entry_return( e ); 715 1.3 christos } 716 1.3 christos return rc; 717 1.3 christos } 718 1.3 christos 719 1.3 christos 720 1.1 christos /* 721 1.1 christos * Local variables: 722 1.1 christos * indent-tabs-mode: t 723 1.1 christos * tab-width: 4 724 1.1 christos * c-basic-offset: 4 725 1.1 christos * End: 726 1.1 christos */ 727