X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fback-bdb%2Fmodrdn.c;h=749f6571deefbf33906fd52d3e7475a4218ae1e9;hb=82c1b0d1f0a27e374961c910473f549878e81e24;hp=f1d58647f8faa3e1a5ee9c471de67e117f2a1818;hpb=73af07e062025e294345278b9dd6735bd46677da;p=openldap diff --git a/servers/slapd/back-bdb/modrdn.c b/servers/slapd/back-bdb/modrdn.c index f1d58647f8..749f6571de 100644 --- a/servers/slapd/back-bdb/modrdn.c +++ b/servers/slapd/back-bdb/modrdn.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2000-2003 The OpenLDAP Foundation. + * Copyright 2000-2004 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -58,8 +58,6 @@ bdb_modrdn( Operation *op, SlapReply *rs ) u_int32_t locker = 0; DB_LOCK lock, plock, nplock; - int noop = 0; - int num_retries = 0; LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS]; @@ -72,6 +70,9 @@ bdb_modrdn( Operation *op, SlapReply *rs ) Entry *ctxcsn_e; int ctxcsn_added = 0; + int parent_is_glue = 0; + int parent_is_leaf = 0; + #ifdef NEW_LOGGING LDAP_LOG ( OPERATION, ENTRY, "==>bdb_modrdn(%s,%s,%s)\n", op->o_req_dn.bv_val,op->oq_modrdn.rs_newrdn.bv_val, @@ -118,6 +119,8 @@ retry: /* transaction retry */ rs->sr_text = "internal error"; goto return_results; } + parent_is_glue = 0; + parent_is_leaf = 0; ldap_pvt_thread_yield(); bdb_trans_backoff( ++num_retries ); } @@ -172,7 +175,9 @@ retry: /* transaction retry */ e = ei->bei_e; /* FIXME: dn2entry() should return non-glue entry */ - if (( rs->sr_err == DB_NOTFOUND ) || ( !manageDSAit && e && is_entry_glue( e ))) { + if (( rs->sr_err == DB_NOTFOUND ) || + ( !manageDSAit && e && is_entry_glue( e ))) + { if( e != NULL ) { rs->sr_matched = ch_strdup( e->e_dn ); rs->sr_ref = is_entry_referral( e ) @@ -272,6 +277,7 @@ retry: /* transaction retry */ } ei->bei_state |= CACHE_ENTRY_NO_KIDS; #endif + if (!manageDSAit && is_entry_referral( e ) ) { /* parent is a referral, don't allow add */ rs->sr_ref = get_entry_referrals( op, e ); @@ -387,10 +393,10 @@ retry: /* transaction retry */ } else { /* no parent, modrdn entry directly under root */ - isroot = be_isroot( op->o_bd, &op->o_ndn ); + isroot = be_isroot( op ); if ( ! isroot ) { if ( be_issuffix( op->o_bd, (struct berval *)&slap_empty_bv ) - || be_isupdate( op->o_bd, &op->o_ndn ) ) { + || be_shadow_update( op ) ) { p = (Entry *)&slap_entry_root; @@ -597,7 +603,7 @@ retry: /* transaction retry */ } else { if ( isroot == -1 ) { - isroot = be_isroot( op->o_bd, &op->o_ndn ); + isroot = be_isroot( op ); } np_dn = NULL; @@ -605,7 +611,7 @@ retry: /* transaction retry */ /* no parent, modrdn entry directly under root */ if ( ! isroot ) { if ( be_issuffix( op->o_bd, (struct berval *)&slap_empty_bv ) - || be_isupdate( op->o_bd, &op->o_ndn ) ) { + || be_isupdate( op ) ) { np = (Entry *)&slap_entry_root; /* check parent for "children" acl */ @@ -630,7 +636,8 @@ retry: /* transaction retry */ "no access to new superior\n", 0, 0, 0 ); #endif - rs->sr_text = "no write access to new superior's children"; + rs->sr_text = + "no write access to new superior's children"; goto return_results; } @@ -683,7 +690,9 @@ retry: /* transaction retry */ } /* Build target dn and make sure target entry doesn't exist already. */ - if (!new_dn.bv_val) build_new_dn( &new_dn, new_parent_dn, &op->oq_modrdn.rs_newrdn, NULL ); + if (!new_dn.bv_val) { + build_new_dn( &new_dn, new_parent_dn, &op->oq_modrdn.rs_newrdn, NULL ); + } if (!new_ndn.bv_val) { struct berval bv = {0, NULL}; @@ -699,7 +708,6 @@ retry: /* transaction retry */ new_ndn.bv_val, 0, 0 ); #endif - /* Shortcut the search */ nei = neip ? neip : eip; rs->sr_err = bdb_cache_find_ndn ( op, ltid, &new_ndn, &nei ); @@ -722,8 +730,8 @@ retry: /* transaction retry */ /* Get attribute type and attribute value of our new rdn, we will * need to add that to our new entry */ - if ( !new_rdn && ldap_bv2rdn_x( &op->oq_modrdn.rs_newrdn, &new_rdn, (char **)&rs->sr_text, - LDAP_DN_FORMAT_LDAP, op->o_tmpmemctx ) ) + if ( !new_rdn && ldap_bv2rdn_x( &op->oq_modrdn.rs_newrdn, &new_rdn, + (char **)&rs->sr_text, LDAP_DN_FORMAT_LDAP, op->o_tmpmemctx ) ) { #ifdef NEW_LOGGING LDAP_LOG ( OPERATION, ERR, @@ -743,21 +751,17 @@ retry: /* transaction retry */ #ifdef NEW_LOGGING LDAP_LOG ( OPERATION, RESULTS, - "bdb_modrdn: new_rdn_type=\"%s\", " - "new_rdn_val=\"%s\"\n", - new_rdn[ 0 ]->la_attr.bv_val, - new_rdn[ 0 ]->la_value.bv_val, 0 ); + "bdb_modrdn: new_rdn_type=\"%s\", new_rdn_val=\"%s\"\n", + new_rdn[ 0 ]->la_attr.bv_val, new_rdn[ 0 ]->la_value.bv_val, 0 ); #else Debug( LDAP_DEBUG_TRACE, - "bdb_modrdn: new_rdn_type=\"%s\", " - "new_rdn_val=\"%s\"\n", - new_rdn[ 0 ]->la_attr.bv_val, - new_rdn[ 0 ]->la_value.bv_val, 0 ); + "bdb_modrdn: new_rdn_type=\"%s\", new_rdn_val=\"%s\"\n", + new_rdn[ 0 ]->la_attr.bv_val, new_rdn[ 0 ]->la_value.bv_val, 0 ); #endif if ( op->oq_modrdn.rs_deleteoldrdn ) { - if ( !old_rdn && ldap_bv2rdn_x( &op->o_req_dn, &old_rdn, (char **)&rs->sr_text, - LDAP_DN_FORMAT_LDAP, op->o_tmpmemctx ) ) + if ( !old_rdn && ldap_bv2rdn_x( &op->o_req_dn, &old_rdn, + (char **)&rs->sr_text, LDAP_DN_FORMAT_LDAP, op->o_tmpmemctx ) ) { #ifdef NEW_LOGGING LDAP_LOG ( OPERATION, ERR, @@ -802,13 +806,13 @@ retry: /* transaction retry */ } /* nested transaction */ - rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, ltid, <2, - bdb->bi_db_opflags ); + rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, ltid, <2, bdb->bi_db_opflags ); rs->sr_text = NULL; if( rs->sr_err != 0 ) { #ifdef NEW_LOGGING LDAP_LOG ( OPERATION, ERR, - "bdb_modrdn: txn_begin(2) failed: %s (%d)\n", db_strerror(rs->sr_err), rs->sr_err, 0 ); + "bdb_modrdn: txn_begin(2) failed: %s (%d)\n", + db_strerror(rs->sr_err), rs->sr_err, 0 ); #else Debug( LDAP_DEBUG_TRACE, "bdb_modrdn: txn_begin(2) failed: %s (%d)\n", @@ -850,8 +854,9 @@ retry: /* transaction retry */ * already happened, must free the names. The frees are * done in bdb_cache_modrdn(). */ - if( e->e_nname.bv_val < e->e_bv.bv_val || e->e_nname.bv_val > - e->e_bv.bv_val + e->e_bv.bv_len ) { + if( e->e_nname.bv_val < e->e_bv.bv_val || + e->e_nname.bv_val > e->e_bv.bv_val + e->e_bv.bv_len ) + { e->e_name.bv_val = NULL; e->e_nname.bv_val = NULL; } @@ -893,7 +898,6 @@ retry: /* transaction retry */ /* modify entry */ rs->sr_err = bdb_modify_internal( op, lt2, &mod[0], e, &rs->sr_text, textbuf, textlen ); - if( rs->sr_err != LDAP_SUCCESS ) { #ifdef NEW_LOGGING LDAP_LOG ( OPERATION, ERR, @@ -954,6 +958,39 @@ retry: /* transaction retry */ rs->sr_text = "entry update failed"; goto return_results; } + + bdb_cache_find_id( op, lt2, eip->bei_id, &eip, 0, locker, &plock ); + if ( eip ) p = eip->bei_e; + if ( p_ndn.bv_len != 0 ) { + parent_is_glue = is_entry_glue(p); + rs->sr_err = bdb_cache_children( op, lt2, p ); + if ( rs->sr_err != DB_NOTFOUND ) { + switch( rs->sr_err ) { + case DB_LOCK_DEADLOCK: + case DB_LOCK_NOTGRANTED: + goto retry; + case 0: + break; + default: +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, ERR, + "<=- bdb_modrdn: has_children failed %s (%d)\n", + db_strerror(rs->sr_err), rs->sr_err, 0 ); +#else + Debug(LDAP_DEBUG_ARGS, + "<=- bdb_modrdn: has_children failed: %s (%d)\n", + db_strerror(rs->sr_err), rs->sr_err, 0 ); +#endif + rs->sr_err = LDAP_OTHER; + rs->sr_text = "internal error"; + goto return_results; + } + parent_is_leaf = 1; + } + bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p); + p = NULL; + } + if ( TXN_COMMIT( lt2, 0 ) != 0 ) { rs->sr_err = LDAP_OTHER; rs->sr_text = "txn_commit(2) failed"; @@ -975,13 +1012,18 @@ retry: /* transaction retry */ if(( rs->sr_err=TXN_ABORT( ltid )) != 0 ) { rs->sr_text = "txn_abort (no-op) failed"; } else { - noop = 1; rs->sr_err = LDAP_SUCCESS; + goto return_results; } } else { - bdb_cache_modrdn( save, &op->orr_nnewrdn, e, neip, + rc = bdb_cache_modrdn( save, &op->orr_nnewrdn, e, neip, bdb->bi_dbenv, locker, &lock ); + switch( rc ) { + case DB_LOCK_DEADLOCK: + case DB_LOCK_NOTGRANTED: + goto retry; + } if ( LDAP_STAILQ_EMPTY( &op->o_bd->be_syncinfo )) { if ( ctxcsn_added ) { @@ -990,7 +1032,7 @@ retry: /* transaction retry */ } } - if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop ) { + if ( rs->sr_err == LDAP_SUCCESS ) { /* Loop through in-scope entries for each psearch spec */ ldap_pvt_thread_rdwr_rlock( &bdb->bi_pslist_rwlock ); LDAP_LIST_FOREACH ( ps_list, &bdb->bi_psearch_list, o_ps_link ) { @@ -1034,11 +1076,13 @@ retry: /* transaction retry */ #ifdef NEW_LOGGING LDAP_LOG ( OPERATION, RESULTS, "bdb_modrdn: rdn modified%s id=%08lx dn=\"%s\"\n", - op->o_noop ? " (no-op)" : "", e->e_id, e->e_dn ); + op->o_noop ? " (no-op)" : "", + e->e_id, e->e_dn ); #else Debug(LDAP_DEBUG_TRACE, "bdb_modrdn: rdn modified%s id=%08lx dn=\"%s\"\n", - op->o_noop ? " (no-op)" : "", e->e_id, e->e_dn ); + op->o_noop ? " (no-op)" : "", + e->e_id, e->e_dn ); #endif rs->sr_text = NULL; if( num_ctrls ) rs->sr_ctrls = ctrls; @@ -1051,6 +1095,10 @@ return_results: TXN_CHECKPOINT( bdb->bi_dbenv, bdb->bi_txn_cp_kbyte, bdb->bi_txn_cp_min, 0 ); } + + if ( rs->sr_err == LDAP_SUCCESS && parent_is_glue && parent_is_leaf ) { + op->o_delete_glue_parent = 1; + } done: if( new_dn.bv_val != NULL ) free( new_dn.bv_val ); @@ -1106,5 +1154,5 @@ done: op->o_private = NULL; } - return ( ( rs->sr_err == LDAP_SUCCESS ) ? noop : rs->sr_err ); + return rs->sr_err; }