X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fback-bdb%2Fdelete.c;h=dfa50bed0a638fdf007d94823ebc39fcef1c7399;hb=37d65aed6e108ba43e158121086df6ce0076bd85;hp=5e70633adf88749fb1990fb76656cc09e342c260;hpb=7dcb68f6fa4bcdb3fbd883d9149ec4c23713d1c9;p=openldap diff --git a/servers/slapd/back-bdb/delete.c b/servers/slapd/back-bdb/delete.c index 5e70633adf..dfa50bed0a 100644 --- a/servers/slapd/back-bdb/delete.c +++ b/servers/slapd/back-bdb/delete.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2000-2005 The OpenLDAP Foundation. + * Copyright 2000-2008 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -38,7 +38,7 @@ bdb_delete( Operation *op, SlapReply *rs ) struct bdb_op_info opinfo = {0}; ID eid; - u_int32_t locker = 0; + BDB_LOCKER locker = 0; DB_LOCK lock, plock; int num_retries = 0; @@ -52,13 +52,55 @@ bdb_delete( Operation *op, SlapReply *rs ) int parent_is_glue = 0; int parent_is_leaf = 0; - ctrls[num_ctrls] = 0; +#ifdef LDAP_X_TXN + int settle = 0; +#endif Debug( LDAP_DEBUG_ARGS, "==> " LDAP_XSTRING(bdb_delete) ": %s\n", op->o_req_dn.bv_val, 0, 0 ); +#ifdef LDAP_X_TXN + if( op->o_txnSpec ) { + /* acquire connection lock */ + ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex ); + if( op->o_conn->c_txn == CONN_TXN_INACTIVE ) { + rs->sr_text = "invalid transaction identifier"; + rs->sr_err = LDAP_X_TXN_ID_INVALID; + goto txnReturn; + } else if( op->o_conn->c_txn == CONN_TXN_SETTLE ) { + settle=1; + goto txnReturn; + } + + if( op->o_conn->c_txn_backend == NULL ) { + op->o_conn->c_txn_backend = op->o_bd; + + } else if( op->o_conn->c_txn_backend != op->o_bd ) { + rs->sr_text = "transaction cannot span multiple database contexts"; + rs->sr_err = LDAP_AFFECTS_MULTIPLE_DSAS; + goto txnReturn; + } + + /* insert operation into transaction */ + + rs->sr_text = "transaction specified"; + rs->sr_err = LDAP_X_TXN_SPECIFY_OKAY; + +txnReturn: + /* release connection lock */ + ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex ); + + if( !settle ) { + send_ldap_result( op, rs ); + return rs->sr_err; + } + } +#endif + + ctrls[num_ctrls] = 0; + /* allocate CSN */ - if ( !SLAP_SHADOW( op->o_bd )) { + if ( BER_BVISNULL( &op->o_csn ) ) { struct berval csn; char csnbuf[LDAP_LUTIL_CSNSTR_BUFSIZE]; @@ -95,7 +137,6 @@ retry: /* transaction retry */ } parent_is_glue = 0; parent_is_leaf = 0; - ldap_pvt_thread_yield(); bdb_trans_backoff( ++num_retries ); } @@ -116,7 +157,6 @@ retry: /* transaction retry */ opinfo.boi_bdb = op->o_bd; opinfo.boi_txn = ltid; - opinfo.boi_locker = locker; opinfo.boi_err = 0; opinfo.boi_acl_cache = op->o_do_not_cache; op->o_private = &opinfo; @@ -310,7 +350,11 @@ retry: /* transaction retry */ Debug( LDAP_DEBUG_TRACE, "<=- " LDAP_XSTRING(bdb_delete) ": pre-read " "failed!\n", 0, 0, 0 ); - goto return_results; + if ( op->o_preread & SLAP_CONTROL_CRITICAL ) { + /* FIXME: is it correct to abort + * operation if control fails? */ + goto return_results; + } } } @@ -327,6 +371,9 @@ retry: /* transaction retry */ goto return_results; } + BDB_LOG_PRINTF( bdb->bi_dbenv, lt2, "slapd Starting delete %s(%d)", + e->e_nname.bv_val, e->e_id ); + /* Can't do it if we have kids */ rs->sr_err = bdb_cache_children( op, lt2, e ); if( rs->sr_err != DB_NOTFOUND ) { @@ -369,34 +416,55 @@ retry: /* transaction retry */ goto return_results; } - /* delete from id2entry */ - rs->sr_err = bdb_id2entry_delete( op->o_bd, lt2, e ); - if ( rs->sr_err != 0 ) { + /* delete indices for old attributes */ + rs->sr_err = bdb_index_entry_del( op, lt2, e ); + if ( rs->sr_err != LDAP_SUCCESS ) { Debug(LDAP_DEBUG_TRACE, - "<=- " LDAP_XSTRING(bdb_delete) ": id2entry failed: " + "<=- " LDAP_XSTRING(bdb_delete) ": index failed: " "%s (%d)\n", db_strerror(rs->sr_err), rs->sr_err, 0 ); switch( rs->sr_err ) { case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: goto retry; } - rs->sr_text = "entry delete failed"; + rs->sr_text = "entry index delete failed"; rs->sr_err = LDAP_OTHER; goto return_results; } - /* delete indices for old attributes */ - rs->sr_err = bdb_index_entry_del( op, lt2, e ); + /* fixup delete CSN */ + if ( !SLAP_SHADOW( op->o_bd )) { + struct berval vals[2]; + + assert( !BER_BVISNULL( &op->o_csn ) ); + vals[0] = op->o_csn; + BER_BVZERO( &vals[1] ); + rs->sr_err = bdb_index_values( op, lt2, slap_schema.si_ad_entryCSN, + vals, 0, SLAP_INDEX_ADD_OP ); if ( rs->sr_err != LDAP_SUCCESS ) { + switch( rs->sr_err ) { + case DB_LOCK_DEADLOCK: + case DB_LOCK_NOTGRANTED: + goto retry; + } + rs->sr_text = "entryCSN index update failed"; + rs->sr_err = LDAP_OTHER; + goto return_results; + } + } + + /* delete from id2entry */ + rs->sr_err = bdb_id2entry_delete( op->o_bd, lt2, e ); + if ( rs->sr_err != 0 ) { Debug( LDAP_DEBUG_TRACE, - "<=- " LDAP_XSTRING(bdb_delete) ": index failed: " + "<=- " LDAP_XSTRING(bdb_delete) ": id2entry failed: " "%s (%d)\n", db_strerror(rs->sr_err), rs->sr_err, 0 ); switch( rs->sr_err ) { case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: goto retry; } - rs->sr_text = "entry index delete failed"; + rs->sr_text = "entry delete failed"; rs->sr_err = LDAP_OTHER; goto return_results; } @@ -426,6 +494,9 @@ retry: /* transaction retry */ p = NULL; } + BDB_LOG_PRINTF( bdb->bi_dbenv, lt2, "slapd Commit1 delete %s(%d)", + e->e_nname.bv_val, e->e_id ); + if ( TXN_COMMIT( lt2, 0 ) != 0 ) { rs->sr_err = LDAP_OTHER; rs->sr_text = "txn_commit(2) failed"; @@ -446,12 +517,16 @@ retry: /* transaction retry */ if ( ( rs->sr_err = TXN_ABORT( ltid ) ) != 0 ) { rs->sr_text = "txn_abort (no-op) failed"; } else { - rs->sr_err = LDAP_NO_OPERATION; + rs->sr_err = LDAP_X_NO_OPERATION; + ltid = NULL; goto return_results; } } else { - rc = bdb_cache_delete( &bdb->bi_cache, e, bdb->bi_dbenv, - locker, &lock ); + + BDB_LOG_PRINTF( bdb->bi_dbenv, ltid, "slapd Cache delete %s(%d)", + e->e_nname.bv_val, e->e_id ); + + rc = bdb_cache_delete( bdb, e, locker, &lock ); switch( rc ) { case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: @@ -463,6 +538,9 @@ retry: /* transaction retry */ ltid = NULL; op->o_private = NULL; + BDB_LOG_PRINTF( bdb->bi_dbenv, NULL, "slapd Committed delete %s(%d)", + e->e_nname.bv_val, e->e_id ); + if( rs->sr_err != 0 ) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_delete) ": txn_%s failed: %s (%d)\n", @@ -502,20 +580,18 @@ return_results: if( ltid != NULL ) { TXN_ABORT( ltid ); - op->o_private = NULL; } + op->o_private = NULL; send_ldap_result( op, rs ); - if ( !SLAP_SHADOW( op->o_bd )) - slap_graduate_commit_csn( op ); + slap_graduate_commit_csn( op ); - if( preread_ctrl != NULL ) { + if( preread_ctrl != NULL && (*preread_ctrl) != NULL ) { slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx ); slap_sl_free( *preread_ctrl, op->o_tmpmemctx ); } - if( rs->sr_err == LDAP_SUCCESS && bdb->bi_txn_cp ) { - ldap_pvt_thread_yield(); + if( rs->sr_err == LDAP_SUCCESS && bdb->bi_txn_cp_kbyte ) { TXN_CHECKPOINT( bdb->bi_dbenv, bdb->bi_txn_cp_kbyte, bdb->bi_txn_cp_min, 0 ); }