summaryrefslogtreecommitdiffstats
path: root/ldap/servers/slapd/back-ldbm/ldbm_delete.c
diff options
context:
space:
mode:
Diffstat (limited to 'ldap/servers/slapd/back-ldbm/ldbm_delete.c')
-rw-r--r--ldap/servers/slapd/back-ldbm/ldbm_delete.c107
1 files changed, 97 insertions, 10 deletions
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
index 74d8de8e..97873003 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
@@ -49,7 +49,7 @@ int
ldbm_back_delete( Slapi_PBlock *pb )
{
backend *be;
- ldbm_instance *inst;
+ ldbm_instance *inst = NULL;
struct ldbminfo *li = NULL;
struct backentry *e = NULL;
struct backentry *tombstone = NULL;
@@ -63,7 +63,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
int disk_full = 0;
int parent_found = 0;
modify_context parent_modify_c = {0};
- int rc;
+ int rc = 0;
int ldap_result_code= LDAP_SUCCESS;
char *ldap_result_message= NULL;
Slapi_DN sdn;
@@ -99,6 +99,18 @@ ldbm_back_delete( Slapi_PBlock *pb )
slapi_log_error (SLAPI_LOG_TRACE, "ldbm_back_delete", "enter conn=%" NSPRIu64 " op=%d\n", pb->pb_conn->c_connid, operation->o_opid);
}
+ if (NULL == addr)
+ {
+ goto error_return;
+ }
+ ldap_result_code = slapi_dn_syntax_check(pb, addr->dn, 1);
+ if (ldap_result_code)
+ {
+ ldap_result_code = LDAP_INVALID_DN_SYNTAX;
+ slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message);
+ goto error_return;
+ }
+
is_fixup_operation = operation_is_flag_set(operation, OP_FLAG_REPL_FIXUP);
is_ruv = operation_is_flag_set(operation, OP_FLAG_REPL_RUV);
delete_tombstone_entry = operation_is_flag_set(operation, OP_FLAG_TOMBSTONE_ENTRY);
@@ -163,6 +175,11 @@ ldbm_back_delete( Slapi_PBlock *pb )
*/
ldap_result_code= get_copy_of_entry(pb, addr, &txn,
SLAPI_DELETE_EXISTING_ENTRY, !is_replicated_operation);
+ if(ldap_result_code==LDAP_OPERATIONS_ERROR ||
+ ldap_result_code==LDAP_INVALID_DN_SYNTAX)
+ {
+ goto error_return;
+ }
slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);
if(plugin_call_plugins(pb, SLAPI_PLUGIN_BE_PRE_DELETE_FN)==-1)
{
@@ -336,6 +353,16 @@ ldbm_back_delete( Slapi_PBlock *pb )
}
tombstone = backentry_dup( e );
slapi_entry_set_dn(tombstone->ep_entry,tombstone_dn); /* Consumes DN */
+ if (entryrdn_get_switch()) /* subtree-rename: on */
+ {
+ Slapi_RDN *srdn = slapi_entry_get_srdn(tombstone->ep_entry);
+ char *tombstone_rdn =
+ compute_entry_tombstone_rdn(slapi_entry_get_rdn_const(e->ep_entry),
+ childuniqueid);
+ /* e_srdn has "uniaqueid=..., <ORIG RDN>" */
+ slapi_rdn_replace_rdn(srdn, tombstone_rdn);
+ slapi_ch_free_string(&tombstone_rdn);
+ }
/* Set tombstone flag on ep_entry */
slapi_entry_set_flag(tombstone->ep_entry, SLAPI_ENTRY_FLAG_TOMBSTONE);
@@ -403,6 +430,11 @@ ldbm_back_delete( Slapi_PBlock *pb )
* entry. We change the DN, add objectclass=tombstone, and record
* the UniqueID of the parent entry.
*/
+ /* Note: cache_add (tombstone) fails since the original entry having
+ * the same ID is already in the cache. Thus, we have to add it
+ * tentatively for now, then cache_add again when the original
+ * entry is removed from the cache.
+ */
retval = id2entry_add( be, tombstone, &txn );
if (DB_LOCK_DEADLOCK == retval) {
LDAPDebug( LDAP_DEBUG_ARGS, "delete 1 DB_LOCK_DEADLOCK\n", 0, 0, 0 );
@@ -416,7 +448,9 @@ ldbm_back_delete( Slapi_PBlock *pb )
ldap_result_code= LDAP_OPERATIONS_ERROR;
goto error_return;
}
- tombstone_in_cache = 1;
+ if (cache_add_tentative( &inst->inst_cache, tombstone, NULL) == 0) {
+ tombstone_in_cache = 1;
+ }
}
else
{
@@ -566,6 +600,26 @@ ldbm_back_delete( Slapi_PBlock *pb )
goto error_return;
}
}
+ if (entryrdn_get_switch()) /* subtree-rename: on */
+ {
+ retval =
+ entryrdn_index_entry(be, tombstone, BE_INDEX_ADD, &txn);
+ if (DB_LOCK_DEADLOCK == retval) {
+ LDAPDebug0Args( LDAP_DEBUG_ARGS,
+ "delete (adding entryrdn) DB_LOCK_DEADLOCK\n");
+ /* Retry txn */
+ continue;
+ }
+ if (0 != retval) {
+ LDAPDebug2Args( LDAP_DEBUG_TRACE,
+ "delete (adding entryrdn) failed, err=%d %s\n",
+ retval,
+ (msg = dblayer_strerror( retval )) ? msg : "" );
+ if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ goto error_return;
+ }
+ }
} /* create_tombstone_entry */
else if (delete_tombstone_entry)
{
@@ -662,6 +716,26 @@ ldbm_back_delete( Slapi_PBlock *pb )
goto error_return;
}
}
+ if (entryrdn_get_switch()) /* subtree-rename: on */
+ {
+ retval =
+ entryrdn_index_entry(be, tombstone, BE_INDEX_DEL, &txn);
+ if (DB_LOCK_DEADLOCK == retval) {
+ LDAPDebug0Args( LDAP_DEBUG_ARGS,
+ "delete (deleting entryrdn) DB_LOCK_DEADLOCK\n");
+ /* Retry txn */
+ continue;
+ }
+ if (0 != retval) {
+ LDAPDebug2Args( LDAP_DEBUG_TRACE,
+ "delete (deleting entryrdn) failed, err=%d %s\n",
+ retval,
+ (msg = dblayer_strerror( retval )) ? msg : "" );
+ if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ goto error_return;
+ }
+ }
} /* delete_tombstone_entry */
if (parent_found) {
@@ -721,9 +795,16 @@ ldbm_back_delete( Slapi_PBlock *pb )
}
/* delete from cache and clean up */
- cache_remove(&inst->inst_cache, e);
+ CACHE_REMOVE(&inst->inst_cache, e);
cache_unlock_entry( &inst->inst_cache, e );
- cache_return( &inst->inst_cache, &e );
+ CACHE_RETURN( &inst->inst_cache, &e );
+ if (tombstone_in_cache) {
+ if (CACHE_ADD( &inst->inst_cache, tombstone, NULL ) == 0) {
+ tombstone_in_cache = 1;
+ } else {
+ tombstone_in_cache = 0;
+ }
+ }
if (parent_found)
{
/* Replace the old parent entry with the newly modified one */
@@ -737,11 +818,11 @@ ldbm_back_delete( Slapi_PBlock *pb )
error_return:
if (e!=NULL) {
cache_unlock_entry( &inst->inst_cache, e );
- cache_return( &inst->inst_cache, &e );
+ CACHE_RETURN( &inst->inst_cache, &e );
}
if (tombstone_in_cache)
{
- cache_remove( &inst->inst_cache, tombstone );
+ CACHE_REMOVE( &inst->inst_cache, tombstone );
}
else
{
@@ -761,13 +842,19 @@ error_return:
else
rc= SLAPI_FAIL_GENERAL;
- /* It is specifically OK to make this call even when no transaction was in progress */
- dblayer_txn_abort(li,&txn); /* abort crashes in case disk full */
+ /* It is safer not to abort when the transaction is not started. */
+ if (retry_count > 0) {
+ dblayer_txn_abort(li,&txn); /* abort crashes in case disk full */
+ }
common_return:
if (tombstone_in_cache)
{
- cache_return( &inst->inst_cache, &tombstone );
+ CACHE_RETURN( &inst->inst_cache, &tombstone );
+ }
+ else
+ {
+ backentry_free( &tombstone );
}
/*