X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fback-bdb%2Fmodrdn.c;h=749f6571deefbf33906fd52d3e7475a4218ae1e9;hb=82c1b0d1f0a27e374961c910473f549878e81e24;hp=39c6d3249ac35586eacbb38c9b89e13d0803be9f;hpb=593ce2def41f612c650be74cafde22be228330e8;p=openldap diff --git a/servers/slapd/back-bdb/modrdn.c b/servers/slapd/back-bdb/modrdn.c index 39c6d3249a..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; } @@ -883,15 +888,16 @@ retry: /* transaction retry */ } if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop && !op->o_no_psearch ) { + ldap_pvt_thread_rdwr_rlock( &bdb->bi_pslist_rwlock ); LDAP_LIST_FOREACH ( ps_list, &bdb->bi_psearch_list, o_ps_link ) { bdb_psearch( op, rs, ps_list, e, LDAP_PSEARCH_BY_PREMODIFY ); } + ldap_pvt_thread_rdwr_runlock( &bdb->bi_pslist_rwlock ); } /* 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, @@ -952,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"; @@ -973,36 +1012,49 @@ 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 { - char gid[DB_XIDDATASIZE]; - - memset( gid, 0, sizeof(gid) ); - snprintf( gid, sizeof( gid ), "%s-%08lx-%08lx", - bdb_uuid.bv_val, (long) op->o_connid, (long) op->o_opid ); - - if(( rs->sr_err=TXN_PREPARE( ltid, gid )) != 0 ) { - rs->sr_text = "txn_prepare failed"; - } else { - bdb_cache_modrdn( save, &op->orr_nnewrdn, e, neip, - bdb->bi_dbenv, locker, &lock ); + 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 ) { - bdb_cache_add( bdb, suffix_ei, ctxcsn_e, - (struct berval *)&slap_ldapsync_cn_bv, locker ); - } + if ( LDAP_STAILQ_EMPTY( &op->o_bd->be_syncinfo )) { + if ( ctxcsn_added ) { + bdb_cache_add( bdb, suffix_ei, ctxcsn_e, + (struct berval *)&slap_ldapsync_cn_bv, locker ); } + } - if(( rs->sr_err=TXN_COMMIT( ltid, 0 )) != 0 ) { - rs->sr_text = "txn_commit failed"; - } else { - rs->sr_err = LDAP_SUCCESS; + 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 ) { + bdb_psearch( op, rs, ps_list, e, LDAP_PSEARCH_BY_MODIFY ); + } + ldap_pvt_thread_rdwr_runlock( &bdb->bi_pslist_rwlock ); + pm_list = LDAP_LIST_FIRST(&op->o_pm_list); + while ( pm_list != NULL ) { + bdb_psearch(op, rs, pm_list->ps_op, + e, LDAP_PSEARCH_BY_SCOPEOUT); + pm_prev = pm_list; + LDAP_LIST_REMOVE ( pm_list, ps_link ); + pm_list = LDAP_LIST_NEXT ( pm_list, ps_link ); + ch_free( pm_prev ); } } + + if(( rs->sr_err=TXN_COMMIT( ltid, 0 )) != 0 ) { + rs->sr_text = "txn_commit failed"; + } else { + rs->sr_err = LDAP_SUCCESS; + } } ltid = NULL; @@ -1024,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; @@ -1036,27 +1090,15 @@ retry: /* transaction retry */ return_results: send_ldap_result( op, rs ); - if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop ) { - /* Loop through in-scope entries for each psearch spec */ - LDAP_LIST_FOREACH ( ps_list, &bdb->bi_psearch_list, o_ps_link ) { - bdb_psearch( op, rs, ps_list, e, LDAP_PSEARCH_BY_MODIFY ); - } - pm_list = LDAP_LIST_FIRST(&op->o_pm_list); - while ( pm_list != NULL ) { - bdb_psearch(op, rs, pm_list->ps_op, - e, LDAP_PSEARCH_BY_SCOPEOUT); - pm_prev = pm_list; - LDAP_LIST_REMOVE ( pm_list, ps_link ); - pm_list = LDAP_LIST_NEXT ( pm_list, ps_link ); - ch_free( pm_prev ); - } - } - if( rs->sr_err == LDAP_SUCCESS && bdb->bi_txn_cp ) { ldap_pvt_thread_yield(); 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 ); @@ -1112,5 +1154,5 @@ done: op->o_private = NULL; } - return ( ( rs->sr_err == LDAP_SUCCESS ) ? noop : rs->sr_err ); + return rs->sr_err; }