1 /* modrdn.c - bdb backend modrdn routine */
2 /* $OpenLDAP: pkg/ldap/servers/slapd/back-bdb/modrdn.c,v 1.185.2.11 2008/05/01 21:39:35 quanah Exp $ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 2000-2008 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 bdb_modrdn( Operation
*op
, SlapReply
*rs
)
27 struct bdb_info
*bdb
= (struct bdb_info
*) op
->o_bd
->be_private
;
28 AttributeDescription
*children
= slap_schema
.si_ad_children
;
29 AttributeDescription
*entry
= slap_schema
.si_ad_entry
;
30 struct berval p_dn
, p_ndn
;
31 struct berval new_dn
= {0, NULL
}, new_ndn
= {0, NULL
};
34 EntryInfo
*ei
= NULL
, *eip
= NULL
, *nei
= NULL
, *neip
= NULL
;
35 /* LDAP v2 supporting correct attribute handling. */
36 char textbuf
[SLAP_TEXT_BUFLEN
];
37 size_t textlen
= sizeof textbuf
;
38 DB_TXN
*ltid
= NULL
, *lt2
;
39 struct bdb_op_info opinfo
= {0};
42 Entry
*np
= NULL
; /* newSuperior Entry */
43 struct berval
*np_dn
= NULL
; /* newSuperior dn */
44 struct berval
*np_ndn
= NULL
; /* newSuperior ndn */
45 struct berval
*new_parent_dn
= NULL
; /* np_dn, p_dn, or NULL */
47 int manageDSAit
= get_manageDSAit( op
);
49 BDB_LOCKER locker
= 0;
50 DB_LOCK lock
, plock
, nplock
;
54 LDAPControl
**preread_ctrl
= NULL
;
55 LDAPControl
**postread_ctrl
= NULL
;
56 LDAPControl
*ctrls
[SLAP_MAX_RESPONSE_CONTROLS
];
61 int parent_is_glue
= 0;
62 int parent_is_leaf
= 0;
68 Debug( LDAP_DEBUG_TRACE
, "==>" LDAP_XSTRING(bdb_modrdn
) "(%s,%s,%s)\n",
69 op
->o_req_dn
.bv_val
,op
->oq_modrdn
.rs_newrdn
.bv_val
,
70 op
->oq_modrdn
.rs_newSup
? op
->oq_modrdn
.rs_newSup
->bv_val
: "NULL" );
74 /* acquire connection lock */
75 ldap_pvt_thread_mutex_lock( &op
->o_conn
->c_mutex
);
76 if( op
->o_conn
->c_txn
== CONN_TXN_INACTIVE
) {
77 rs
->sr_text
= "invalid transaction identifier";
78 rs
->sr_err
= LDAP_X_TXN_ID_INVALID
;
80 } else if( op
->o_conn
->c_txn
== CONN_TXN_SETTLE
) {
85 if( op
->o_conn
->c_txn_backend
== NULL
) {
86 op
->o_conn
->c_txn_backend
= op
->o_bd
;
88 } else if( op
->o_conn
->c_txn_backend
!= op
->o_bd
) {
89 rs
->sr_text
= "transaction cannot span multiple database contexts";
90 rs
->sr_err
= LDAP_AFFECTS_MULTIPLE_DSAS
;
94 /* insert operation into transaction */
96 rs
->sr_text
= "transaction specified";
97 rs
->sr_err
= LDAP_X_TXN_SPECIFY_OKAY
;
100 /* release connection lock */
101 ldap_pvt_thread_mutex_unlock( &op
->o_conn
->c_mutex
);
104 send_ldap_result( op
, rs
);
110 ctrls
[num_ctrls
] = NULL
;
112 slap_mods_opattrs( op
, &op
->orr_modlist
, 1 );
115 retry
: /* transaction retry */
116 if ( dummy
.e_attrs
) {
117 attrs_free( dummy
.e_attrs
);
118 dummy
.e_attrs
= NULL
;
121 bdb_unlocked_cache_return_entry_w(&bdb
->bi_cache
, e
);
125 bdb_unlocked_cache_return_entry_r(&bdb
->bi_cache
, p
);
129 bdb_unlocked_cache_return_entry_r(&bdb
->bi_cache
, np
);
132 Debug( LDAP_DEBUG_TRACE
, "==>" LDAP_XSTRING(bdb_modrdn
)
133 ": retrying...\n", 0, 0, 0 );
135 rs
->sr_err
= TXN_ABORT( ltid
);
137 LDAP_SLIST_REMOVE( &op
->o_extra
, &opinfo
.boi_oe
, OpExtra
, oe_next
);
138 opinfo
.boi_oe
.oe_key
= NULL
;
139 op
->o_do_not_cache
= opinfo
.boi_acl_cache
;
140 if( rs
->sr_err
!= 0 ) {
141 rs
->sr_err
= LDAP_OTHER
;
142 rs
->sr_text
= "internal error";
145 if ( op
->o_abandon
) {
146 rs
->sr_err
= SLAPD_ABANDON
;
151 bdb_trans_backoff( ++num_retries
);
154 /* begin transaction */
155 rs
->sr_err
= TXN_BEGIN( bdb
->bi_dbenv
, NULL
, <id
,
156 bdb
->bi_db_opflags
);
158 if( rs
->sr_err
!= 0 ) {
159 Debug( LDAP_DEBUG_TRACE
,
160 LDAP_XSTRING(bdb_modrdn
) ": txn_begin failed: "
161 "%s (%d)\n", db_strerror(rs
->sr_err
), rs
->sr_err
, 0 );
162 rs
->sr_err
= LDAP_OTHER
;
163 rs
->sr_text
= "internal error";
167 locker
= TXN_ID ( ltid
);
169 opinfo
.boi_oe
.oe_key
= bdb
;
170 opinfo
.boi_txn
= ltid
;
172 opinfo
.boi_acl_cache
= op
->o_do_not_cache
;
173 LDAP_SLIST_INSERT_HEAD( &op
->o_extra
, &opinfo
.boi_oe
, oe_next
);
176 rs
->sr_err
= bdb_dn2entry( op
, ltid
, &op
->o_req_ndn
, &ei
, 1,
179 switch( rs
->sr_err
) {
183 case DB_LOCK_DEADLOCK
:
184 case DB_LOCK_NOTGRANTED
:
187 rs
->sr_text
= "ldap server busy";
190 rs
->sr_err
= LDAP_OTHER
;
191 rs
->sr_text
= "internal error";
196 /* FIXME: dn2entry() should return non-glue entry */
197 if (( rs
->sr_err
== DB_NOTFOUND
) ||
198 ( !manageDSAit
&& e
&& is_entry_glue( e
)))
201 rs
->sr_matched
= ch_strdup( e
->e_dn
);
202 rs
->sr_ref
= is_entry_referral( e
)
203 ? get_entry_referrals( op
, e
)
205 bdb_unlocked_cache_return_entry_r( &bdb
->bi_cache
, e
);
209 rs
->sr_ref
= referral_rewrite( default_referral
, NULL
,
210 &op
->o_req_dn
, LDAP_SCOPE_DEFAULT
);
213 rs
->sr_err
= LDAP_REFERRAL
;
214 send_ldap_result( op
, rs
);
216 ber_bvarray_free( rs
->sr_ref
);
217 free( (char *)rs
->sr_matched
);
219 rs
->sr_matched
= NULL
;
224 if ( get_assert( op
) &&
225 ( test_filter( op
, e
, get_assertion( op
)) != LDAP_COMPARE_TRUE
))
227 rs
->sr_err
= LDAP_ASSERTION_FAILED
;
231 /* check write on old entry */
232 rs
->sr_err
= access_allowed( op
, e
, entry
, NULL
, ACL_WRITE
, NULL
);
233 if ( ! rs
->sr_err
) {
234 switch( opinfo
.boi_err
) {
235 case DB_LOCK_DEADLOCK
:
236 case DB_LOCK_NOTGRANTED
:
240 Debug( LDAP_DEBUG_TRACE
, "no access to entry\n", 0,
242 rs
->sr_text
= "no write access to old entry";
243 rs
->sr_err
= LDAP_INSUFFICIENT_ACCESS
;
248 rs
->sr_err
= bdb_cache_children( op
, ltid
, e
);
249 if ( rs
->sr_err
!= DB_NOTFOUND
) {
250 switch( rs
->sr_err
) {
251 case DB_LOCK_DEADLOCK
:
252 case DB_LOCK_NOTGRANTED
:
255 Debug(LDAP_DEBUG_ARGS
,
256 "<=- " LDAP_XSTRING(bdb_modrdn
)
258 op
->o_req_dn
.bv_val
, 0, 0);
259 rs
->sr_err
= LDAP_NOT_ALLOWED_ON_NONLEAF
;
260 rs
->sr_text
= "subtree rename not supported";
263 Debug(LDAP_DEBUG_ARGS
,
264 "<=- " LDAP_XSTRING(bdb_modrdn
)
265 ": has_children failed: %s (%d)\n",
266 db_strerror(rs
->sr_err
), rs
->sr_err
, 0 );
267 rs
->sr_err
= LDAP_OTHER
;
268 rs
->sr_text
= "internal error";
272 ei
->bei_state
|= CACHE_ENTRY_NO_KIDS
;
275 if (!manageDSAit
&& is_entry_referral( e
) ) {
276 /* parent is a referral, don't allow add */
277 rs
->sr_ref
= get_entry_referrals( op
, e
);
279 Debug( LDAP_DEBUG_TRACE
, LDAP_XSTRING(bdb_modrdn
)
280 ": entry %s is referral\n", e
->e_dn
, 0, 0 );
282 rs
->sr_err
= LDAP_REFERRAL
,
283 rs
->sr_matched
= e
->e_name
.bv_val
;
284 send_ldap_result( op
, rs
);
286 ber_bvarray_free( rs
->sr_ref
);
288 rs
->sr_matched
= NULL
;
292 if ( be_issuffix( op
->o_bd
, &e
->e_nname
) ) {
293 #ifdef BDB_MULTIPLE_SUFFIXES
294 /* Allow renaming one suffix entry to another */
295 p_ndn
= slap_empty_bv
;
297 /* There can only be one suffix entry */
298 rs
->sr_err
= LDAP_NAMING_VIOLATION
;
299 rs
->sr_text
= "cannot rename suffix entry";
303 dnParent( &e
->e_nname
, &p_ndn
);
306 eip
= ei
->bei_parent
;
307 if ( eip
&& eip
->bei_id
) {
308 /* Make sure parent entry exist and we can write its
311 rs
->sr_err
= bdb_cache_find_id( op
, ltid
,
312 eip
->bei_id
, &eip
, 0, locker
, &plock
);
314 switch( rs
->sr_err
) {
318 case DB_LOCK_DEADLOCK
:
319 case DB_LOCK_NOTGRANTED
:
322 rs
->sr_text
= "ldap server busy";
325 rs
->sr_err
= LDAP_OTHER
;
326 rs
->sr_text
= "internal error";
332 Debug( LDAP_DEBUG_TRACE
, LDAP_XSTRING(bdb_modrdn
)
333 ": parent does not exist\n", 0, 0, 0);
334 rs
->sr_err
= LDAP_OTHER
;
335 rs
->sr_text
= "old entry's parent does not exist";
339 p
= (Entry
*)&slap_entry_root
;
342 /* check parent for "children" acl */
343 rs
->sr_err
= access_allowed( op
, p
,
345 op
->oq_modrdn
.rs_newSup
== NULL
?
346 ACL_WRITE
: ACL_WDEL
,
352 if ( ! rs
->sr_err
) {
353 switch( opinfo
.boi_err
) {
354 case DB_LOCK_DEADLOCK
:
355 case DB_LOCK_NOTGRANTED
:
359 rs
->sr_err
= LDAP_INSUFFICIENT_ACCESS
;
360 Debug( LDAP_DEBUG_TRACE
, "no access to parent\n", 0,
362 rs
->sr_text
= "no write access to old parent's children";
366 Debug( LDAP_DEBUG_TRACE
,
367 LDAP_XSTRING(bdb_modrdn
) ": wr to children "
368 "of entry %s OK\n", p_ndn
.bv_val
, 0, 0 );
370 if ( p_ndn
.bv_val
== slap_empty_bv
.bv_val
) {
371 p_dn
= slap_empty_bv
;
373 dnParent( &e
->e_name
, &p_dn
);
376 Debug( LDAP_DEBUG_TRACE
,
377 LDAP_XSTRING(bdb_modrdn
) ": parent dn=%s\n",
380 new_parent_dn
= &p_dn
; /* New Parent unless newSuperior given */
382 if ( op
->oq_modrdn
.rs_newSup
!= NULL
) {
383 Debug( LDAP_DEBUG_TRACE
,
384 LDAP_XSTRING(bdb_modrdn
)
385 ": new parent \"%s\" requested...\n",
386 op
->oq_modrdn
.rs_newSup
->bv_val
, 0, 0 );
388 /* newSuperior == oldParent? */
389 if( dn_match( &p_ndn
, op
->oq_modrdn
.rs_nnewSup
) ) {
390 Debug( LDAP_DEBUG_TRACE
, "bdb_back_modrdn: "
391 "new parent \"%s\" same as the old parent \"%s\"\n",
392 op
->oq_modrdn
.rs_newSup
->bv_val
, p_dn
.bv_val
, 0 );
393 op
->oq_modrdn
.rs_newSup
= NULL
; /* ignore newSuperior */
397 /* There's a BDB_MULTIPLE_SUFFIXES case here that this code doesn't
398 * support. E.g., two suffixes dc=foo,dc=com and dc=bar,dc=net.
399 * We do not allow modDN
403 * and we probably should. But since MULTIPLE_SUFFIXES is deprecated
404 * I'm ignoring this problem for now.
406 if ( op
->oq_modrdn
.rs_newSup
!= NULL
) {
407 if ( op
->oq_modrdn
.rs_newSup
->bv_len
) {
408 np_dn
= op
->oq_modrdn
.rs_newSup
;
409 np_ndn
= op
->oq_modrdn
.rs_nnewSup
;
411 /* newSuperior == oldParent? - checked above */
412 /* newSuperior == entry being moved?, if so ==> ERROR */
413 if ( dnIsSuffix( np_ndn
, &e
->e_nname
)) {
414 rs
->sr_err
= LDAP_NO_SUCH_OBJECT
;
415 rs
->sr_text
= "new superior not found";
418 /* Get Entry with dn=newSuperior. Does newSuperior exist? */
420 rs
->sr_err
= bdb_dn2entry( op
, ltid
, np_ndn
,
421 &neip
, 0, locker
, &nplock
);
423 switch( rs
->sr_err
) {
424 case 0: np
= neip
->bei_e
;
427 case DB_LOCK_DEADLOCK
:
428 case DB_LOCK_NOTGRANTED
:
431 rs
->sr_text
= "ldap server busy";
434 rs
->sr_err
= LDAP_OTHER
;
435 rs
->sr_text
= "internal error";
440 Debug( LDAP_DEBUG_TRACE
,
441 LDAP_XSTRING(bdb_modrdn
)
442 ": newSup(ndn=%s) not here!\n",
443 np_ndn
->bv_val
, 0, 0);
444 rs
->sr_text
= "new superior not found";
445 rs
->sr_err
= LDAP_NO_SUCH_OBJECT
;
449 Debug( LDAP_DEBUG_TRACE
,
450 LDAP_XSTRING(bdb_modrdn
)
451 ": wr to new parent OK np=%p, id=%ld\n",
452 (void *) np
, (long) np
->e_id
, 0 );
454 /* check newSuperior for "children" acl */
455 rs
->sr_err
= access_allowed( op
, np
, children
,
456 NULL
, ACL_WADD
, NULL
);
459 switch( opinfo
.boi_err
) {
460 case DB_LOCK_DEADLOCK
:
461 case DB_LOCK_NOTGRANTED
:
465 Debug( LDAP_DEBUG_TRACE
,
466 LDAP_XSTRING(bdb_modrdn
)
467 ": no wr to newSup children\n",
469 rs
->sr_text
= "no write access to new superior's children";
470 rs
->sr_err
= LDAP_INSUFFICIENT_ACCESS
;
474 if ( is_entry_alias( np
) ) {
475 /* parent is an alias, don't allow add */
476 Debug( LDAP_DEBUG_TRACE
,
477 LDAP_XSTRING(bdb_modrdn
)
478 ": entry is alias\n",
480 rs
->sr_text
= "new superior is an alias";
481 rs
->sr_err
= LDAP_ALIAS_PROBLEM
;
485 if ( is_entry_referral( np
) ) {
486 /* parent is a referral, don't allow add */
487 Debug( LDAP_DEBUG_TRACE
,
488 LDAP_XSTRING(bdb_modrdn
)
489 ": entry is referral\n",
491 rs
->sr_text
= "new superior is a referral";
492 rs
->sr_err
= LDAP_OTHER
;
499 /* no parent, modrdn entry directly under root */
500 if ( be_issuffix( op
->o_bd
, (struct berval
*)&slap_empty_bv
)
501 || be_isupdate( op
) ) {
502 np
= (Entry
*)&slap_entry_root
;
504 /* check parent for "children" acl */
505 rs
->sr_err
= access_allowed( op
, np
,
506 children
, NULL
, ACL_WADD
, NULL
);
510 if ( ! rs
->sr_err
) {
511 switch( opinfo
.boi_err
) {
512 case DB_LOCK_DEADLOCK
:
513 case DB_LOCK_NOTGRANTED
:
517 rs
->sr_err
= LDAP_INSUFFICIENT_ACCESS
;
518 Debug( LDAP_DEBUG_TRACE
,
519 "no access to new superior\n",
522 "no write access to new superior's children";
528 Debug( LDAP_DEBUG_TRACE
,
529 LDAP_XSTRING(bdb_modrdn
)
530 ": wr to new parent's children OK\n",
533 new_parent_dn
= np_dn
;
536 /* Build target dn and make sure target entry doesn't exist already. */
537 if (!new_dn
.bv_val
) {
538 build_new_dn( &new_dn
, new_parent_dn
, &op
->oq_modrdn
.rs_newrdn
, NULL
);
541 if (!new_ndn
.bv_val
) {
542 struct berval bv
= {0, NULL
};
543 dnNormalize( 0, NULL
, NULL
, &new_dn
, &bv
, op
->o_tmpmemctx
);
544 ber_dupbv( &new_ndn
, &bv
);
545 /* FIXME: why not call dnNormalize() w/o ctx? */
546 op
->o_tmpfree( bv
.bv_val
, op
->o_tmpmemctx
);
549 Debug( LDAP_DEBUG_TRACE
, LDAP_XSTRING(bdb_modrdn
) ": new ndn=%s\n",
550 new_ndn
.bv_val
, 0, 0 );
552 /* Shortcut the search */
553 nei
= neip
? neip
: eip
;
554 rs
->sr_err
= bdb_cache_find_ndn ( op
, locker
, &new_ndn
, &nei
);
555 if ( nei
) bdb_cache_entryinfo_unlock( nei
);
556 switch( rs
->sr_err
) {
557 case DB_LOCK_DEADLOCK
:
558 case DB_LOCK_NOTGRANTED
:
563 /* Allow rename to same DN */
566 rs
->sr_err
= LDAP_ALREADY_EXISTS
;
569 rs
->sr_err
= LDAP_OTHER
;
570 rs
->sr_text
= "internal error";
574 assert( op
->orr_modlist
!= NULL
);
576 if( op
->o_preread
) {
577 if( preread_ctrl
== NULL
) {
578 preread_ctrl
= &ctrls
[num_ctrls
++];
579 ctrls
[num_ctrls
] = NULL
;
581 if( slap_read_controls( op
, rs
, e
,
582 &slap_pre_read_bv
, preread_ctrl
) )
584 Debug( LDAP_DEBUG_TRACE
,
585 "<=- " LDAP_XSTRING(bdb_modrdn
)
586 ": pre-read failed!\n", 0, 0, 0 );
587 if ( op
->o_preread
& SLAP_CONTROL_CRITICAL
) {
588 /* FIXME: is it correct to abort
589 * operation if control fails? */
595 /* nested transaction */
596 rs
->sr_err
= TXN_BEGIN( bdb
->bi_dbenv
, ltid
, <2
, bdb
->bi_db_opflags
);
598 if( rs
->sr_err
!= 0 ) {
599 Debug( LDAP_DEBUG_TRACE
,
600 LDAP_XSTRING(bdb_modrdn
)
601 ": txn_begin(2) failed: %s (%d)\n",
602 db_strerror(rs
->sr_err
), rs
->sr_err
, 0 );
603 rs
->sr_err
= LDAP_OTHER
;
604 rs
->sr_text
= "internal error";
609 rs
->sr_err
= bdb_dn2id_delete( op
, lt2
, eip
, e
);
610 if ( rs
->sr_err
!= 0 ) {
611 Debug(LDAP_DEBUG_TRACE
,
612 "<=- " LDAP_XSTRING(bdb_modrdn
)
613 ": dn2id del failed: %s (%d)\n",
614 db_strerror(rs
->sr_err
), rs
->sr_err
, 0 );
615 switch( rs
->sr_err
) {
616 case DB_LOCK_DEADLOCK
:
617 case DB_LOCK_NOTGRANTED
:
620 rs
->sr_err
= LDAP_OTHER
;
621 rs
->sr_text
= "DN index delete fail";
625 /* copy the entry, then override some fields */
627 dummy
.e_name
= new_dn
;
628 dummy
.e_nname
= new_ndn
;
629 dummy
.e_attrs
= NULL
;
632 rs
->sr_err
= bdb_dn2id_add( op
, lt2
, neip
? neip
: eip
, &dummy
);
633 if ( rs
->sr_err
!= 0 ) {
634 Debug(LDAP_DEBUG_TRACE
,
635 "<=- " LDAP_XSTRING(bdb_modrdn
)
636 ": dn2id add failed: %s (%d)\n",
637 db_strerror(rs
->sr_err
), rs
->sr_err
, 0 );
638 switch( rs
->sr_err
) {
639 case DB_LOCK_DEADLOCK
:
640 case DB_LOCK_NOTGRANTED
:
643 rs
->sr_err
= LDAP_OTHER
;
644 rs
->sr_text
= "DN index add failed";
648 dummy
.e_attrs
= e
->e_attrs
;
651 rs
->sr_err
= bdb_modify_internal( op
, lt2
, op
->orr_modlist
, &dummy
,
652 &rs
->sr_text
, textbuf
, textlen
);
653 if( rs
->sr_err
!= LDAP_SUCCESS
) {
654 Debug(LDAP_DEBUG_TRACE
,
655 "<=- " LDAP_XSTRING(bdb_modrdn
)
656 ": modify failed: %s (%d)\n",
657 db_strerror(rs
->sr_err
), rs
->sr_err
, 0 );
658 if ( ( rs
->sr_err
== LDAP_INSUFFICIENT_ACCESS
) && opinfo
.boi_err
) {
659 rs
->sr_err
= opinfo
.boi_err
;
661 if ( dummy
.e_attrs
== e
->e_attrs
) dummy
.e_attrs
= NULL
;
662 switch( rs
->sr_err
) {
663 case DB_LOCK_DEADLOCK
:
664 case DB_LOCK_NOTGRANTED
:
671 rs
->sr_err
= bdb_id2entry_update( op
->o_bd
, lt2
, &dummy
);
672 if ( rs
->sr_err
!= 0 ) {
673 Debug(LDAP_DEBUG_TRACE
,
674 "<=- " LDAP_XSTRING(bdb_modrdn
)
675 ": id2entry failed: %s (%d)\n",
676 db_strerror(rs
->sr_err
), rs
->sr_err
, 0 );
677 switch( rs
->sr_err
) {
678 case DB_LOCK_DEADLOCK
:
679 case DB_LOCK_NOTGRANTED
:
682 rs
->sr_err
= LDAP_OTHER
;
683 rs
->sr_text
= "entry update failed";
687 if ( p_ndn
.bv_len
!= 0 ) {
688 parent_is_glue
= is_entry_glue(p
);
689 rs
->sr_err
= bdb_cache_children( op
, lt2
, p
);
690 if ( rs
->sr_err
!= DB_NOTFOUND
) {
691 switch( rs
->sr_err
) {
692 case DB_LOCK_DEADLOCK
:
693 case DB_LOCK_NOTGRANTED
:
698 Debug(LDAP_DEBUG_ARGS
,
699 "<=- " LDAP_XSTRING(bdb_modrdn
)
700 ": has_children failed: %s (%d)\n",
701 db_strerror(rs
->sr_err
), rs
->sr_err
, 0 );
702 rs
->sr_err
= LDAP_OTHER
;
703 rs
->sr_text
= "internal error";
708 bdb_unlocked_cache_return_entry_r(&bdb
->bi_cache
, p
);
712 if ( TXN_COMMIT( lt2
, 0 ) != 0 ) {
713 rs
->sr_err
= LDAP_OTHER
;
714 rs
->sr_text
= "txn_commit(2) failed";
718 if( op
->o_postread
) {
719 if( postread_ctrl
== NULL
) {
720 postread_ctrl
= &ctrls
[num_ctrls
++];
721 ctrls
[num_ctrls
] = NULL
;
723 if( slap_read_controls( op
, rs
, &dummy
,
724 &slap_post_read_bv
, postread_ctrl
) )
726 Debug( LDAP_DEBUG_TRACE
,
727 "<=- " LDAP_XSTRING(bdb_modrdn
)
728 ": post-read failed!\n", 0, 0, 0 );
729 if ( op
->o_postread
& SLAP_CONTROL_CRITICAL
) {
730 /* FIXME: is it correct to abort
731 * operation if control fails? */
738 if(( rs
->sr_err
=TXN_ABORT( ltid
)) != 0 ) {
739 rs
->sr_text
= "txn_abort (no-op) failed";
741 rs
->sr_err
= LDAP_X_NO_OPERATION
;
743 /* Only free attrs if they were dup'd. */
744 if ( dummy
.e_attrs
== e
->e_attrs
) dummy
.e_attrs
= NULL
;
749 rc
= bdb_cache_modrdn( bdb
, e
, &op
->orr_nnewrdn
, &dummy
, neip
,
752 case DB_LOCK_DEADLOCK
:
753 case DB_LOCK_NOTGRANTED
:
756 dummy
.e_attrs
= NULL
;
757 new_dn
.bv_val
= NULL
;
758 new_ndn
.bv_val
= NULL
;
760 if(( rs
->sr_err
=TXN_COMMIT( ltid
, 0 )) != 0 ) {
761 rs
->sr_text
= "txn_commit failed";
763 rs
->sr_err
= LDAP_SUCCESS
;
768 LDAP_SLIST_REMOVE( &op
->o_extra
, &opinfo
.boi_oe
, OpExtra
, oe_next
);
769 opinfo
.boi_oe
.oe_key
= NULL
;
771 if( rs
->sr_err
!= LDAP_SUCCESS
) {
772 Debug( LDAP_DEBUG_TRACE
,
773 LDAP_XSTRING(bdb_modrdn
) ": %s : %s (%d)\n",
774 rs
->sr_text
, db_strerror(rs
->sr_err
), rs
->sr_err
);
775 rs
->sr_err
= LDAP_OTHER
;
780 Debug(LDAP_DEBUG_TRACE
,
781 LDAP_XSTRING(bdb_modrdn
)
782 ": rdn modified%s id=%08lx dn=\"%s\"\n",
783 op
->o_noop
? " (no-op)" : "",
784 dummy
.e_id
, op
->o_req_dn
.bv_val
);
786 if( num_ctrls
) rs
->sr_ctrls
= ctrls
;
789 if ( dummy
.e_attrs
) {
790 attrs_free( dummy
.e_attrs
);
792 send_ldap_result( op
, rs
);
794 if( rs
->sr_err
== LDAP_SUCCESS
&& bdb
->bi_txn_cp_kbyte
) {
795 TXN_CHECKPOINT( bdb
->bi_dbenv
,
796 bdb
->bi_txn_cp_kbyte
, bdb
->bi_txn_cp_min
, 0 );
799 if ( rs
->sr_err
== LDAP_SUCCESS
&& parent_is_glue
&& parent_is_leaf
) {
800 op
->o_delete_glue_parent
= 1;
804 slap_graduate_commit_csn( op
);
806 if( new_dn
.bv_val
!= NULL
) free( new_dn
.bv_val
);
807 if( new_ndn
.bv_val
!= NULL
) free( new_ndn
.bv_val
);
809 /* LDAP v3 Support */
811 /* free new parent and reader lock */
812 bdb_unlocked_cache_return_entry_r(&bdb
->bi_cache
, np
);
816 /* free parent and reader lock */
817 bdb_unlocked_cache_return_entry_r(&bdb
->bi_cache
, p
);
822 bdb_unlocked_cache_return_entry_w( &bdb
->bi_cache
, e
);
828 if ( opinfo
.boi_oe
.oe_key
) {
829 LDAP_SLIST_REMOVE( &op
->o_extra
, &opinfo
.boi_oe
, OpExtra
, oe_next
);
832 if( preread_ctrl
!= NULL
&& (*preread_ctrl
) != NULL
) {
833 slap_sl_free( (*preread_ctrl
)->ldctl_value
.bv_val
, op
->o_tmpmemctx
);
834 slap_sl_free( *preread_ctrl
, op
->o_tmpmemctx
);
836 if( postread_ctrl
!= NULL
&& (*postread_ctrl
) != NULL
) {
837 slap_sl_free( (*postread_ctrl
)->ldctl_value
.bv_val
, op
->o_tmpmemctx
);
838 slap_sl_free( *postread_ctrl
, op
->o_tmpmemctx
);