1 /* modrdn.c - bdb backend modrdn routine */
4 * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
5 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
11 #include <ac/string.h>
17 bdb_modrdn( Operation *op, SlapReply *rs )
19 struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
20 AttributeDescription *children = slap_schema.si_ad_children;
21 AttributeDescription *entry = slap_schema.si_ad_entry;
22 struct berval p_dn, p_ndn;
23 struct berval new_dn = {0, NULL}, new_ndn = {0, NULL};
27 EntryInfo *ei = NULL, *eip = NULL, *nei = NULL, *neip = NULL;
28 /* LDAP v2 supporting correct attribute handling. */
29 LDAPRDN new_rdn = NULL;
30 LDAPRDN old_rdn = NULL;
31 char textbuf[SLAP_TEXT_BUFLEN];
32 size_t textlen = sizeof textbuf;
33 DB_TXN *ltid = NULL, *lt2;
34 struct bdb_op_info opinfo;
39 Entry *np = NULL; /* newSuperior Entry */
40 struct berval *np_dn = NULL; /* newSuperior dn */
41 struct berval *np_ndn = NULL; /* newSuperior ndn */
42 struct berval *new_parent_dn = NULL; /* np_dn, p_dn, or NULL */
44 /* Used to interface with bdb_modify_internal() */
45 Modifications *mod = NULL; /* Used to delete old rdn */
47 int manageDSAit = get_manageDSAit( op );
50 DB_LOCK lock, plock, nplock;
56 LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS];
60 struct psid_entry *pm_list, *pm_prev;
67 LDAP_LOG ( OPERATION, ENTRY, "==>bdb_modrdn(%s,%s,%s)\n",
68 op->o_req_dn.bv_val,op->oq_modrdn.rs_newrdn.bv_val,
69 op->oq_modrdn.rs_newSup ? op->oq_modrdn.rs_newSup->bv_val : "NULL" );
71 Debug( LDAP_DEBUG_TRACE, "==>bdb_modrdn(%s,%s,%s)\n",
72 op->o_req_dn.bv_val,op->oq_modrdn.rs_newrdn.bv_val,
73 op->oq_modrdn.rs_newSup ? op->oq_modrdn.rs_newSup->bv_val : "NULL" );
77 retry: /* transaction retry */
79 bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e);
83 bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
87 bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, np);
91 LDAP_LOG ( OPERATION, DETAIL1, "==>bdb_modrdn: retrying...\n", 0, 0, 0);
93 Debug( LDAP_DEBUG_TRACE, "==>bdb_modrdn: retrying...\n", 0, 0, 0 );
95 pm_list = LDAP_LIST_FIRST(&op->o_pm_list);
96 while ( pm_list != NULL ) {
97 LDAP_LIST_REMOVE ( pm_list, ps_link );
99 pm_list = LDAP_LIST_NEXT ( pm_list, ps_link );
103 rs->sr_err = TXN_ABORT( ltid );
105 op->o_private = NULL;
106 op->o_do_not_cache = opinfo.boi_acl_cache;
107 if( rs->sr_err != 0 ) {
108 rs->sr_err = LDAP_OTHER;
109 rs->sr_text = "internal error";
112 ldap_pvt_thread_yield();
113 bdb_trans_backoff( ++num_retries );
116 /* begin transaction */
117 rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, NULL, <id,
118 bdb->bi_db_opflags );
120 if( rs->sr_err != 0 ) {
122 LDAP_LOG ( OPERATION, ERR,
123 "==>bdb_modrdn: txn_begin failed: %s (%d)\n",
124 db_strerror(rs->sr_err), rs->sr_err, 0 );
126 Debug( LDAP_DEBUG_TRACE,
127 "bdb_delete: txn_begin failed: %s (%d)\n",
128 db_strerror(rs->sr_err), rs->sr_err, 0 );
130 rs->sr_err = LDAP_OTHER;
131 rs->sr_text = "internal error";
135 locker = TXN_ID ( ltid );
137 opinfo.boi_bdb = op->o_bd;
138 opinfo.boi_txn = ltid;
139 opinfo.boi_locker = locker;
141 opinfo.boi_acl_cache = op->o_do_not_cache;
142 op->o_private = &opinfo;
145 rs->sr_err = bdb_dn2entry( op, ltid, &op->o_req_ndn, &ei, 1,
148 switch( rs->sr_err ) {
152 case DB_LOCK_DEADLOCK:
153 case DB_LOCK_NOTGRANTED:
156 rs->sr_text = "ldap server busy";
159 rs->sr_err = LDAP_OTHER;
160 rs->sr_text = "internal error";
165 /* FIXME: dn2entry() should return non-glue entry */
166 if (( rs->sr_err == DB_NOTFOUND ) || ( !manageDSAit && e && is_entry_glue( e ))) {
168 rs->sr_matched = ch_strdup( e->e_dn );
169 rs->sr_ref = is_entry_referral( e )
170 ? get_entry_referrals( op, e )
172 bdb_unlocked_cache_return_entry_r( &bdb->bi_cache, e);
176 BerVarray deref = NULL;
177 if ( !LDAP_STAILQ_EMPTY( &op->o_bd->be_syncinfo )) {
179 LDAP_STAILQ_FOREACH( si, &op->o_bd->be_syncinfo, si_next ) {
181 ber_dupbv( &tmpbv, &si->si_provideruri_bv[0] );
182 ber_bvarray_add( &deref, &tmpbv );
185 deref = default_referral;
187 rs->sr_ref = referral_rewrite( deref, NULL, &op->o_req_dn,
188 LDAP_SCOPE_DEFAULT );
191 rs->sr_err = LDAP_REFERRAL;
192 send_ldap_result( op, rs );
194 ber_bvarray_free( rs->sr_ref );
195 free( (char *)rs->sr_matched );
197 rs->sr_matched = NULL;
202 if ( get_assert( op ) &&
203 ( test_filter( op, e, get_assertion( op )) != LDAP_COMPARE_TRUE ))
205 rs->sr_err = LDAP_ASSERTION_FAILED;
209 /* check write on old entry */
210 rs->sr_err = access_allowed( op, e, entry, NULL, ACL_WRITE, NULL );
211 if ( ! rs->sr_err ) {
212 switch( opinfo.boi_err ) {
213 case DB_LOCK_DEADLOCK:
214 case DB_LOCK_NOTGRANTED:
219 LDAP_LOG ( OPERATION, ERR,
220 "==>bdb_modrdn: no access to entry\n", 0, 0, 0 );
222 Debug( LDAP_DEBUG_TRACE, "no access to entry\n", 0,
225 rs->sr_text = "no write access to old entry";
226 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
231 rs->sr_err = bdb_cache_children( op, ltid, e );
232 if ( rs->sr_err != DB_NOTFOUND ) {
233 switch( rs->sr_err ) {
234 case DB_LOCK_DEADLOCK:
235 case DB_LOCK_NOTGRANTED:
239 LDAP_LOG ( OPERATION, DETAIL1,
240 "<=- bdb_modrdn: non-leaf %s\n", op->o_req_dn.bv_val, 0, 0 );
242 Debug(LDAP_DEBUG_ARGS,
243 "<=- bdb_modrdn: non-leaf %s\n",
244 op->o_req_dn.bv_val, 0, 0);
246 rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
247 rs->sr_text = "subtree rename not supported";
251 LDAP_LOG ( OPERATION, ERR,
252 "<=- bdb_modrdn: has_children failed %s (%d)\n",
253 db_strerror(rs->sr_err), rs->sr_err, 0 );
255 Debug(LDAP_DEBUG_ARGS,
256 "<=- bdb_modrdn: has_children failed: %s (%d)\n",
257 db_strerror(rs->sr_err), rs->sr_err, 0 );
259 rs->sr_err = LDAP_OTHER;
260 rs->sr_text = "internal error";
264 ei->bei_state |= CACHE_ENTRY_NO_KIDS;
266 if (!manageDSAit && is_entry_referral( e ) ) {
267 /* parent is a referral, don't allow add */
268 rs->sr_ref = get_entry_referrals( op, e );
271 LDAP_LOG ( OPERATION, DETAIL1,
272 "==>bdb_modrdn: entry %s is referral \n", e->e_dn, 0, 0 );
274 Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: entry %s is referral\n",
278 rs->sr_err = LDAP_REFERRAL,
279 rs->sr_matched = e->e_name.bv_val;
280 send_ldap_result( op, rs );
282 ber_bvarray_free( rs->sr_ref );
284 rs->sr_matched = NULL;
288 if ( be_issuffix( op->o_bd, &e->e_nname ) ) {
289 p_ndn = slap_empty_bv;
291 dnParent( &e->e_nname, &p_ndn );
294 if ( p_ndn.bv_len != 0 ) {
295 /* Make sure parent entry exist and we can write its
298 eip = ei->bei_parent;
299 rs->sr_err = bdb_cache_find_id( op, ltid,
300 eip->bei_id, &eip, 0, locker, &plock );
302 switch( rs->sr_err ) {
306 case DB_LOCK_DEADLOCK:
307 case DB_LOCK_NOTGRANTED:
310 rs->sr_text = "ldap server busy";
313 rs->sr_err = LDAP_OTHER;
314 rs->sr_text = "internal error";
321 LDAP_LOG ( OPERATION, ERR,
322 "==>bdb_modrdn: parent does not exist\n", 0, 0, 0 );
324 Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: parent does not exist\n",
327 rs->sr_err = LDAP_OTHER;
328 rs->sr_text = "old entry's parent does not exist";
332 /* check parent for "children" acl */
333 rs->sr_err = access_allowed( op, p,
334 children, NULL, ACL_WRITE, NULL );
336 if ( ! rs->sr_err ) {
337 switch( opinfo.boi_err ) {
338 case DB_LOCK_DEADLOCK:
339 case DB_LOCK_NOTGRANTED:
343 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
345 LDAP_LOG ( OPERATION, ERR,
346 "==>bdb_modrdn: no access to parent\n", 0, 0, 0 );
348 Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
351 rs->sr_text = "no write access to old parent's children";
356 LDAP_LOG ( OPERATION, DETAIL1,
357 "==>bdb_modrdn: wr to children %s is OK\n", p_ndn.bv_val, 0, 0 );
359 Debug( LDAP_DEBUG_TRACE,
360 "bdb_modrdn: wr to children of entry %s OK\n",
361 p_ndn.bv_val, 0, 0 );
364 if ( p_ndn.bv_val == slap_empty_bv.bv_val ) {
365 p_dn = slap_empty_bv;
367 dnParent( &e->e_name, &p_dn );
371 LDAP_LOG ( OPERATION, DETAIL1,
372 "==>bdb_modrdn: parent dn=%s\n", p_dn.bv_val, 0, 0 );
374 Debug( LDAP_DEBUG_TRACE,
375 "bdb_modrdn: parent dn=%s\n",
380 /* no parent, modrdn entry directly under root */
381 isroot = be_isroot( op->o_bd, &op->o_ndn );
383 if ( be_issuffix( op->o_bd, (struct berval *)&slap_empty_bv )
384 || be_isupdate( op->o_bd, &op->o_ndn ) ) {
386 p = (Entry *)&slap_entry_root;
388 /* check parent for "children" acl */
389 rs->sr_err = access_allowed( op, p,
390 children, NULL, ACL_WRITE, NULL );
394 if ( ! rs->sr_err ) {
395 switch( opinfo.boi_err ) {
396 case DB_LOCK_DEADLOCK:
397 case DB_LOCK_NOTGRANTED:
401 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
403 LDAP_LOG ( OPERATION, ERR,
404 "==>bdb_modrdn: no access to parent\n", 0, 0, 0 );
406 Debug( LDAP_DEBUG_TRACE,
407 "no access to parent\n",
410 rs->sr_text = "no write access to old parent";
415 LDAP_LOG ( OPERATION, DETAIL1,
416 "==>bdb_modrdn: wr to children of entry \"%s\" OK\n",
419 Debug( LDAP_DEBUG_TRACE,
420 "bdb_modrdn: wr to children of entry \"\" OK\n",
428 LDAP_LOG ( OPERATION, DETAIL1,
429 "==>bdb_modrdn: parent dn=\"\" \n", 0, 0, 0 );
431 Debug( LDAP_DEBUG_TRACE,
432 "bdb_modrdn: parent dn=\"\"\n",
438 LDAP_LOG ( OPERATION, ERR,
439 "==>bdb_modrdn: no parent, not root &\"\" is not "
440 "suffix\n", 0, 0, 0 );
442 Debug( LDAP_DEBUG_TRACE,
443 "bdb_modrdn: no parent, not root "
444 "& \"\" is not suffix\n",
447 rs->sr_text = "no write access to old parent";
448 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
454 new_parent_dn = &p_dn; /* New Parent unless newSuperior given */
456 if ( op->oq_modrdn.rs_newSup != NULL ) {
458 LDAP_LOG ( OPERATION, DETAIL1,
459 "==>bdb_modrdn: new parent \"%s\" requested...\n",
460 op->oq_modrdn.rs_newSup->bv_val, 0, 0 );
462 Debug( LDAP_DEBUG_TRACE,
463 "bdb_modrdn: new parent \"%s\" requested...\n",
464 op->oq_modrdn.rs_newSup->bv_val, 0, 0 );
467 /* newSuperior == oldParent? */
468 if( dn_match( &p_ndn, op->oq_modrdn.rs_nnewSup ) ) {
470 LDAP_LOG( BACK_BDB, INFO, "bdb_back_modrdn: "
471 "new parent \"%s\" same as the old parent \"%s\"\n",
472 op->oq_modrdn.rs_newSup->bv_val, p_dn.bv_val, 0 );
474 Debug( LDAP_DEBUG_TRACE, "bdb_back_modrdn: "
475 "new parent \"%s\" same as the old parent \"%s\"\n",
476 op->oq_modrdn.rs_newSup->bv_val, p_dn.bv_val, 0 );
478 op->oq_modrdn.rs_newSup = NULL; /* ignore newSuperior */
482 if ( op->oq_modrdn.rs_newSup != NULL ) {
483 if ( op->oq_modrdn.rs_newSup->bv_len ) {
484 np_dn = op->oq_modrdn.rs_newSup;
485 np_ndn = op->oq_modrdn.rs_nnewSup;
487 /* newSuperior == oldParent?, if so ==> ERROR */
488 /* newSuperior == entry being moved?, if so ==> ERROR */
489 /* Get Entry with dn=newSuperior. Does newSuperior exist? */
491 rs->sr_err = bdb_dn2entry( op, ltid, np_ndn,
492 &neip, 0, locker, &nplock );
494 switch( rs->sr_err ) {
495 case 0: np = neip->bei_e;
498 case DB_LOCK_DEADLOCK:
499 case DB_LOCK_NOTGRANTED:
502 rs->sr_text = "ldap server busy";
505 rs->sr_err = LDAP_OTHER;
506 rs->sr_text = "internal error";
512 LDAP_LOG ( OPERATION, DETAIL1,
513 "==>bdb_modrdn: newSup(ndn=%s) not here!\n",
514 np_ndn->bv_val, 0, 0 );
516 Debug( LDAP_DEBUG_TRACE,
517 "bdb_modrdn: newSup(ndn=%s) not here!\n",
518 np_ndn->bv_val, 0, 0);
520 rs->sr_text = "new superior not found";
521 rs->sr_err = LDAP_OTHER;
526 LDAP_LOG ( OPERATION, DETAIL1,
527 "==>bdb_modrdn: wr to new parent OK np=%p, id=%ld\n",
528 (void *) np, (long) np->e_id, 0 );
530 Debug( LDAP_DEBUG_TRACE,
531 "bdb_modrdn: wr to new parent OK np=%p, id=%ld\n",
532 (void *) np, (long) np->e_id, 0 );
535 /* check newSuperior for "children" acl */
536 rs->sr_err = access_allowed( op, np, children,
537 NULL, ACL_WRITE, NULL );
540 switch( opinfo.boi_err ) {
541 case DB_LOCK_DEADLOCK:
542 case DB_LOCK_NOTGRANTED:
547 LDAP_LOG ( OPERATION, DETAIL1,
548 "==>bdb_modrdn: no wr to newSup children\n", 0, 0, 0 );
550 Debug( LDAP_DEBUG_TRACE,
551 "bdb_modrdn: no wr to newSup children\n",
554 rs->sr_text = "no write access to new superior's children";
555 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
560 if ( is_entry_alias( np ) ) {
561 /* parent is an alias, don't allow add */
563 LDAP_LOG ( OPERATION, DETAIL1,
564 "==>bdb_modrdn: entry is alias\n", 0, 0, 0 );
566 Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: entry is alias\n",
569 rs->sr_text = "new superior is an alias";
570 rs->sr_err = LDAP_ALIAS_PROBLEM;
575 if ( is_entry_referral( np ) ) {
576 /* parent is a referral, don't allow add */
578 LDAP_LOG ( OPERATION, DETAIL1,
579 "==>bdb_modrdn: entry is referral\n", 0, 0, 0 );
581 Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: entry is referral\n",
584 rs->sr_text = "new superior is a referral";
585 rs->sr_err = LDAP_OTHER;
590 if ( isroot == -1 ) {
591 isroot = be_isroot( op->o_bd, &op->o_ndn );
596 /* no parent, modrdn entry directly under root */
598 if ( be_issuffix( op->o_bd, (struct berval *)&slap_empty_bv )
599 || be_isupdate( op->o_bd, &op->o_ndn ) ) {
600 np = (Entry *)&slap_entry_root;
602 /* check parent for "children" acl */
603 rs->sr_err = access_allowed( op, np,
604 children, NULL, ACL_WRITE, NULL );
608 if ( ! rs->sr_err ) {
609 switch( opinfo.boi_err ) {
610 case DB_LOCK_DEADLOCK:
611 case DB_LOCK_NOTGRANTED:
615 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
617 LDAP_LOG ( OPERATION, ERR,
618 "==>bdb_modrdn: no access to superior\n", 0, 0, 0 );
620 Debug( LDAP_DEBUG_TRACE,
621 "no access to new superior\n",
624 rs->sr_text = "no write access to new superior's children";
629 LDAP_LOG ( OPERATION, DETAIL1,
630 "bdb_modrdn: wr to children entry \"\" OK\n", 0, 0, 0 );
632 Debug( LDAP_DEBUG_TRACE,
633 "bdb_modrdn: wr to children of entry \"\" OK\n",
639 LDAP_LOG ( OPERATION, ERR,
640 "bdb_modrdn: new superior=\"\", not root & \"\" "
641 "is not suffix\n", 0, 0, 0 );
643 Debug( LDAP_DEBUG_TRACE,
644 "bdb_modrdn: new superior=\"\", not root "
645 "& \"\" is not suffix\n",
648 rs->sr_text = "no write access to new superior's children";
649 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
655 LDAP_LOG ( OPERATION, DETAIL1,
656 "bdb_modrdn: new superior=\"\"\n", 0, 0, 0 );
658 Debug( LDAP_DEBUG_TRACE,
659 "bdb_modrdn: new superior=\"\"\n",
665 LDAP_LOG ( OPERATION, DETAIL1,
666 "bdb_modrdn: wr to new parent's children OK\n", 0, 0, 0 );
668 Debug( LDAP_DEBUG_TRACE,
669 "bdb_modrdn: wr to new parent's children OK\n",
673 new_parent_dn = np_dn;
676 /* Build target dn and make sure target entry doesn't exist already. */
677 if (!new_dn.bv_val) build_new_dn( &new_dn, new_parent_dn, &op->oq_modrdn.rs_newrdn, NULL );
679 if (!new_ndn.bv_val) {
680 struct berval bv = {0, NULL};
681 dnNormalize( 0, NULL, NULL, &new_dn, &bv, op->o_tmpmemctx );
682 ber_dupbv( &new_ndn, &bv );
686 LDAP_LOG ( OPERATION, RESULTS,
687 "bdb_modrdn: new ndn=%s\n", new_ndn.bv_val, 0, 0 );
689 Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: new ndn=%s\n",
690 new_ndn.bv_val, 0, 0 );
694 /* Shortcut the search */
695 nei = neip ? neip : eip;
696 rs->sr_err = bdb_cache_find_ndn ( op, ltid, &new_ndn, &nei );
697 if ( nei ) bdb_cache_entryinfo_unlock( nei );
698 switch( rs->sr_err ) {
699 case DB_LOCK_DEADLOCK:
700 case DB_LOCK_NOTGRANTED:
705 rs->sr_err = LDAP_ALREADY_EXISTS;
708 rs->sr_err = LDAP_OTHER;
709 rs->sr_text = "internal error";
713 /* Get attribute type and attribute value of our new rdn, we will
714 * need to add that to our new entry
716 if ( !new_rdn && ldap_bv2rdn_x( &op->oq_modrdn.rs_newrdn, &new_rdn, (char **)&rs->sr_text,
717 LDAP_DN_FORMAT_LDAP, op->o_tmpmemctx ) )
720 LDAP_LOG ( OPERATION, ERR,
721 "bdb_modrdn: can't figure out "
722 "type(s)/values(s) of newrdn\n",
725 Debug( LDAP_DEBUG_TRACE,
726 "bdb_modrdn: can't figure out "
727 "type(s)/values(s) of newrdn\n",
730 rs->sr_err = LDAP_INVALID_DN_SYNTAX;
731 rs->sr_text = "unknown type(s) used in RDN";
736 LDAP_LOG ( OPERATION, RESULTS,
737 "bdb_modrdn: new_rdn_type=\"%s\", "
738 "new_rdn_val=\"%s\"\n",
739 new_rdn[ 0 ]->la_attr.bv_val,
740 new_rdn[ 0 ]->la_value.bv_val, 0 );
742 Debug( LDAP_DEBUG_TRACE,
743 "bdb_modrdn: new_rdn_type=\"%s\", "
744 "new_rdn_val=\"%s\"\n",
745 new_rdn[ 0 ]->la_attr.bv_val,
746 new_rdn[ 0 ]->la_value.bv_val, 0 );
749 if ( op->oq_modrdn.rs_deleteoldrdn ) {
750 if ( !old_rdn && ldap_bv2rdn_x( &op->o_req_dn, &old_rdn, (char **)&rs->sr_text,
751 LDAP_DN_FORMAT_LDAP, op->o_tmpmemctx ) )
754 LDAP_LOG ( OPERATION, ERR,
755 "bdb_modrdn: can't figure out "
756 "type(s)/values(s) of old_rdn\n",
759 Debug( LDAP_DEBUG_TRACE,
760 "bdb_modrdn: can't figure out "
761 "the old_rdn type(s)/value(s)\n",
764 rs->sr_err = LDAP_OTHER;
765 rs->sr_text = "cannot parse RDN from old DN";
770 /* prepare modlist of modifications from old/new rdn */
772 rs->sr_err = slap_modrdn2mods( op, rs, e, old_rdn, new_rdn, &mod );
773 if ( rs->sr_err != LDAP_SUCCESS ) {
778 if( op->o_preread ) {
779 if( slap_read_controls( op, rs, e,
780 &slap_pre_read_bv, &ctrls[num_ctrls] ) )
783 LDAP_LOG ( OPERATION, DETAIL1,
784 "<=- bdb_modrdn: post-read failed!\n", 0, 0, 0 );
786 Debug( LDAP_DEBUG_TRACE,
787 "<=- bdb_modrdn: post-read failed!\n", 0, 0, 0 );
791 ctrls[++num_ctrls] = NULL;
792 op->o_preread = 0; /* prevent redo on retry */
795 /* nested transaction */
796 rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, ltid, <2,
797 bdb->bi_db_opflags );
799 if( rs->sr_err != 0 ) {
801 LDAP_LOG ( OPERATION, ERR,
802 "bdb_modrdn: txn_begin(2) failed: %s (%d)\n", db_strerror(rs->sr_err), rs->sr_err, 0 );
804 Debug( LDAP_DEBUG_TRACE,
805 "bdb_modrdn: txn_begin(2) failed: %s (%d)\n",
806 db_strerror(rs->sr_err), rs->sr_err, 0 );
808 rs->sr_err = LDAP_OTHER;
809 rs->sr_text = "internal error";
818 rs->sr_err = bdb_dn2id_delete( op, lt2, eip, e );
819 if ( rs->sr_err != 0 ) {
821 LDAP_LOG ( OPERATION, ERR,
822 "<=- bdb_modrdn: dn2id del failed: %s (%d)\n",
823 db_strerror(rs->sr_err), rs->sr_err, 0 );
825 Debug(LDAP_DEBUG_TRACE,
826 "<=- bdb_modrdn: dn2id del failed: %s (%d)\n",
827 db_strerror(rs->sr_err), rs->sr_err, 0 );
829 switch( rs->sr_err ) {
830 case DB_LOCK_DEADLOCK:
831 case DB_LOCK_NOTGRANTED:
834 rs->sr_err = LDAP_OTHER;
835 rs->sr_text = "DN index delete fail";
839 /* Binary format uses a single contiguous block, cannot
840 * free individual fields. But if a previous modrdn has
841 * already happened, must free the names. The frees are
842 * done in bdb_cache_modrdn().
844 if( e->e_nname.bv_val < e->e_bv.bv_val || e->e_nname.bv_val >
845 e->e_bv.bv_val + e->e_bv.bv_len ) {
846 e->e_name.bv_val = NULL;
847 e->e_nname.bv_val = NULL;
850 e->e_nname = new_ndn;
851 new_dn.bv_val = NULL;
852 new_ndn.bv_val = NULL;
855 rs->sr_err = bdb_dn2id_add( op, lt2, neip ? neip : eip, e );
856 if ( rs->sr_err != 0 ) {
858 LDAP_LOG ( OPERATION, ERR,
859 "<=- bdb_modrdn: dn2id add failed: %s (%d)\n",
860 db_strerror(rs->sr_err), rs->sr_err, 0 );
862 Debug(LDAP_DEBUG_TRACE,
863 "<=- bdb_modrdn: dn2id add failed: %s (%d)\n",
864 db_strerror(rs->sr_err), rs->sr_err, 0 );
866 switch( rs->sr_err ) {
867 case DB_LOCK_DEADLOCK:
868 case DB_LOCK_NOTGRANTED:
871 rs->sr_err = LDAP_OTHER;
872 rs->sr_text = "DN index add failed";
876 if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop && !op->o_no_psearch ) {
877 LDAP_LIST_FOREACH ( ps_list, &bdb->bi_psearch_list, o_ps_link ) {
878 bdb_psearch( op, rs, ps_list, e, LDAP_PSEARCH_BY_PREMODIFY );
883 rs->sr_err = bdb_modify_internal( op, lt2, &mod[0], e,
884 &rs->sr_text, textbuf, textlen );
886 if( rs->sr_err != LDAP_SUCCESS ) {
888 LDAP_LOG ( OPERATION, ERR,
889 "<=- bdb_modrdn: modify failed: %s (%d)\n",
890 db_strerror(rs->sr_err), rs->sr_err, 0 );
892 Debug(LDAP_DEBUG_TRACE,
893 "<=- bdb_modrdn: modify failed: %s (%d)\n",
894 db_strerror(rs->sr_err), rs->sr_err, 0 );
896 if ( ( rs->sr_err == LDAP_INSUFFICIENT_ACCESS ) && opinfo.boi_err ) {
897 rs->sr_err = opinfo.boi_err;
899 switch( rs->sr_err ) {
900 case DB_LOCK_DEADLOCK:
901 case DB_LOCK_NOTGRANTED:
907 if( op->o_postread ) {
908 if( slap_read_controls( op, rs, e,
909 &slap_post_read_bv, &ctrls[num_ctrls] ) )
912 LDAP_LOG ( OPERATION, DETAIL1,
913 "<=- bdb_modrdn: post-read failed!\n", 0, 0, 0 );
915 Debug( LDAP_DEBUG_TRACE,
916 "<=- bdb_modrdn: post-read failed!\n", 0, 0, 0 );
920 ctrls[++num_ctrls] = NULL;
921 op->o_postread = 0; /* prevent redo on retry */
922 /* FIXME: should read entry on the last retry */
926 rs->sr_err = bdb_id2entry_update( op->o_bd, lt2, e );
927 if ( rs->sr_err != 0 ) {
929 LDAP_LOG ( OPERATION, ERR,
930 "<=- bdb_modrdn: id2entry failed: %s (%d)\n",
931 db_strerror(rs->sr_err), rs->sr_err, 0 );
933 Debug(LDAP_DEBUG_TRACE,
934 "<=- bdb_modrdn: id2entry failed: %s (%d)\n",
935 db_strerror(rs->sr_err), rs->sr_err, 0 );
937 switch( rs->sr_err ) {
938 case DB_LOCK_DEADLOCK:
939 case DB_LOCK_NOTGRANTED:
942 rs->sr_err = LDAP_OTHER;
943 rs->sr_text = "entry update failed";
946 if ( TXN_COMMIT( lt2, 0 ) != 0 ) {
947 rs->sr_err = LDAP_OTHER;
948 rs->sr_text = "txn_commit(2) failed";
952 if ( LDAP_STAILQ_EMPTY( &op->o_bd->be_syncinfo )) {
953 rc = bdb_csn_commit( op, rs, ltid, ei, &suffix_ei,
954 &ctxcsn_e, &ctxcsn_added, locker );
964 if(( rs->sr_err=TXN_ABORT( ltid )) != 0 ) {
965 rs->sr_text = "txn_abort (no-op) failed";
968 rs->sr_err = LDAP_SUCCESS;
972 char gid[DB_XIDDATASIZE];
974 memset( gid, 0, sizeof(gid) );
975 snprintf( gid, sizeof( gid ), "%s-%08lx-%08lx",
976 bdb_uuid.bv_val, (long) op->o_connid, (long) op->o_opid );
978 if(( rs->sr_err=TXN_PREPARE( ltid, gid )) != 0 ) {
979 rs->sr_text = "txn_prepare failed";
981 bdb_cache_modrdn( save, &op->orr_nnewrdn, e, neip,
982 bdb->bi_dbenv, locker, &lock );
984 if ( LDAP_STAILQ_EMPTY( &op->o_bd->be_syncinfo )) {
985 if ( ctxcsn_added ) {
986 bdb_cache_add( bdb, suffix_ei, ctxcsn_e,
987 (struct berval *)&slap_ldapsync_cn_bv, locker );
991 if(( rs->sr_err=TXN_COMMIT( ltid, 0 )) != 0 ) {
992 rs->sr_text = "txn_commit failed";
994 rs->sr_err = LDAP_SUCCESS;
1000 op->o_private = NULL;
1002 if( rs->sr_err != LDAP_SUCCESS ) {
1004 LDAP_LOG ( OPERATION, RESULTS, "bdb_modrdn: %s : %s (%d)\n",
1005 rs->sr_text, db_strerror(rs->sr_err), rs->sr_err );
1007 Debug( LDAP_DEBUG_TRACE, "bdb_add: %s : %s (%d)\n",
1008 rs->sr_text, db_strerror(rs->sr_err), rs->sr_err );
1010 rs->sr_err = LDAP_OTHER;
1012 goto return_results;
1016 LDAP_LOG ( OPERATION, RESULTS,
1017 "bdb_modrdn: rdn modified%s id=%08lx dn=\"%s\"\n",
1018 op->o_noop ? " (no-op)" : "", e->e_id, e->e_dn );
1020 Debug(LDAP_DEBUG_TRACE,
1021 "bdb_modrdn: rdn modified%s id=%08lx dn=\"%s\"\n",
1022 op->o_noop ? " (no-op)" : "", e->e_id, e->e_dn );
1025 if( num_ctrls ) rs->sr_ctrls = ctrls;
1028 send_ldap_result( op, rs );
1030 if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop ) {
1031 /* Loop through in-scope entries for each psearch spec */
1032 LDAP_LIST_FOREACH ( ps_list, &bdb->bi_psearch_list, o_ps_link ) {
1033 bdb_psearch( op, rs, ps_list, e, LDAP_PSEARCH_BY_MODIFY );
1035 pm_list = LDAP_LIST_FIRST(&op->o_pm_list);
1036 while ( pm_list != NULL ) {
1037 bdb_psearch(op, rs, pm_list->ps_op,
1038 e, LDAP_PSEARCH_BY_SCOPEOUT);
1040 LDAP_LIST_REMOVE ( pm_list, ps_link );
1041 pm_list = LDAP_LIST_NEXT ( pm_list, ps_link );
1046 if( rs->sr_err == LDAP_SUCCESS && bdb->bi_txn_cp ) {
1047 ldap_pvt_thread_yield();
1048 TXN_CHECKPOINT( bdb->bi_dbenv,
1049 bdb->bi_txn_cp_kbyte, bdb->bi_txn_cp_min, 0 );
1053 if( new_dn.bv_val != NULL ) free( new_dn.bv_val );
1054 if( new_ndn.bv_val != NULL ) free( new_ndn.bv_val );
1056 /* LDAP v2 supporting correct attribute handling. */
1057 if ( new_rdn != NULL ) {
1058 ldap_rdnfree_x( new_rdn, op->o_tmpmemctx );
1060 if ( old_rdn != NULL ) {
1061 ldap_rdnfree_x( old_rdn, op->o_tmpmemctx );
1065 for (; mod; mod=tmp ) {
1066 tmp = mod->sml_next;
1067 /* slap_modrdn2mods does things one way,
1068 * slap_mods_opattrs does it differently
1070 if ( mod->sml_op != SLAP_MOD_SOFTADD &&
1071 mod->sml_op != LDAP_MOD_DELETE ) break;
1072 if ( mod->sml_nvalues ) free( mod->sml_nvalues[0].bv_val );
1075 slap_mods_free( mod );
1078 /* LDAP v3 Support */
1080 /* free new parent and reader lock */
1081 bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, np);
1085 /* free parent and reader lock */
1086 bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
1091 bdb_unlocked_cache_return_entry_w( &bdb->bi_cache, e);
1094 if( ltid != NULL ) {
1095 pm_list = LDAP_LIST_FIRST(&op->o_pm_list);
1096 while ( pm_list != NULL ) {
1097 LDAP_LIST_REMOVE ( pm_list, ps_link );
1099 pm_list = LDAP_LIST_NEXT ( pm_list, ps_link );
1103 op->o_private = NULL;
1106 return ( ( rs->sr_err == LDAP_SUCCESS ) ? noop : rs->sr_err );