ldbm_delete.c 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
  37. * All rights reserved.
  38. * END COPYRIGHT BLOCK **/
  39. #ifdef HAVE_CONFIG_H
  40. # include <config.h>
  41. #endif
  42. /* delete.c - ldbm backend delete routine */
  43. #include "back-ldbm.h"
  44. #define DEL_SET_ERROR(rc, error, count) \
  45. { \
  46. (rc) = (error); \
  47. (count) = RETRY_TIMES; /* otherwise, the transaction may not be aborted */ \
  48. }
  49. int
  50. ldbm_back_delete( Slapi_PBlock *pb )
  51. {
  52. backend *be;
  53. ldbm_instance *inst = NULL;
  54. struct ldbminfo *li = NULL;
  55. struct backentry *e = NULL;
  56. struct backentry *tombstone = NULL;
  57. struct backentry *original_tombstone = NULL;
  58. char *dn = NULL;
  59. back_txn txn;
  60. back_txnid parent_txn;
  61. int retval = -1;
  62. char *msg;
  63. char *errbuf = NULL;
  64. int retry_count = 0;
  65. int disk_full = 0;
  66. int parent_found = 0;
  67. int ruv_c_init = 0;
  68. modify_context parent_modify_c = {0};
  69. modify_context ruv_c = {0};
  70. int rc = 0;
  71. int ldap_result_code= LDAP_SUCCESS;
  72. char *ldap_result_message= NULL;
  73. Slapi_DN sdn;
  74. Slapi_DN *sdnp = NULL;
  75. char *e_uniqueid = NULL;
  76. Slapi_DN nscpEntrySDN;
  77. int dblock_acquired= 0;
  78. Slapi_Operation *operation;
  79. CSN *opcsn = NULL;
  80. int is_fixup_operation = 0;
  81. int is_ruv = 0; /* True if the current entry is RUV */
  82. int is_replicated_operation= 0;
  83. int is_tombstone_entry = 0; /* True if the current entry is alreday a tombstone */
  84. int delete_tombstone_entry = 0; /* We must remove the given tombstone entry from the DB */
  85. int create_tombstone_entry = 0; /* We perform a "regular" LDAP delete but since we use */
  86. /* replication, we must create a new tombstone entry */
  87. int tombstone_in_cache = 0;
  88. entry_address *addr;
  89. int addordel_flags = 0; /* passed to index_addordel */
  90. char *entryusn_str = NULL;
  91. Slapi_Entry *orig_entry = NULL;
  92. Slapi_DN parentsdn;
  93. int opreturn = 0;
  94. int free_delete_existing_entry = 0;
  95. slapi_pblock_get( pb, SLAPI_BACKEND, &be);
  96. slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &li );
  97. slapi_pblock_get( pb, SLAPI_DELETE_TARGET_SDN, &sdnp );
  98. slapi_pblock_get( pb, SLAPI_TARGET_ADDRESS, &addr);
  99. slapi_pblock_get( pb, SLAPI_TXN, (void**)&parent_txn );
  100. slapi_pblock_get( pb, SLAPI_OPERATION, &operation );
  101. slapi_pblock_get( pb, SLAPI_IS_REPLICATED_OPERATION, &is_replicated_operation );
  102. /* sdn needs to be initialized before "goto *_return */
  103. slapi_sdn_init(&sdn);
  104. slapi_sdn_init(&nscpEntrySDN);
  105. /* dblayer_txn_init needs to be called before "goto error_return" */
  106. dblayer_txn_init(li,&txn);
  107. /* the calls to perform searches require the parent txn if any
  108. so set txn to the parent_txn until we begin the child transaction */
  109. if (parent_txn) {
  110. txn.back_txn_txn = parent_txn;
  111. } else {
  112. parent_txn = txn.back_txn_txn;
  113. slapi_pblock_set( pb, SLAPI_TXN, parent_txn );
  114. }
  115. if (pb->pb_conn)
  116. {
  117. slapi_log_error (SLAPI_LOG_TRACE, "ldbm_back_delete", "enter conn=%" NSPRIu64 " op=%d\n", pb->pb_conn->c_connid, operation->o_opid);
  118. }
  119. if (NULL == addr)
  120. {
  121. /* retval is -1 */
  122. goto error_return;
  123. }
  124. ldap_result_code = slapi_dn_syntax_check(pb, slapi_sdn_get_dn(sdnp), 1);
  125. if (ldap_result_code)
  126. {
  127. ldap_result_code = LDAP_INVALID_DN_SYNTAX;
  128. slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message);
  129. /* retval is -1 */
  130. goto error_return;
  131. }
  132. is_fixup_operation = operation_is_flag_set(operation, OP_FLAG_REPL_FIXUP);
  133. is_ruv = operation_is_flag_set(operation, OP_FLAG_REPL_RUV);
  134. delete_tombstone_entry = operation_is_flag_set(operation, OP_FLAG_TOMBSTONE_ENTRY);
  135. inst = (ldbm_instance *) be->be_instance_info;
  136. if (NULL == sdnp) {
  137. slapi_sdn_init_normdn_byref(&sdn, dn);
  138. sdnp = &sdn;
  139. }
  140. /* The dblock serializes writes to the database,
  141. * which reduces deadlocking in the db code,
  142. * which means that we run faster.
  143. *
  144. * But, this lock is re-enterant for the fixup
  145. * operations that the URP code in the Replication
  146. * plugin generates.
  147. */
  148. if(SERIALLOCK(li) && !operation_is_flag_set(operation,OP_FLAG_REPL_FIXUP))
  149. {
  150. dblayer_lock_backend(be);
  151. dblock_acquired= 1;
  152. }
  153. /*
  154. * We are about to pass the last abandon test, so from now on we are
  155. * committed to finish this operation. Set status to "will complete"
  156. * before we make our last abandon check to avoid race conditions in
  157. * the code that processes abandon operations.
  158. */
  159. if (operation) {
  160. operation->o_status = SLAPI_OP_STATUS_WILL_COMPLETE;
  161. }
  162. if ( slapi_op_abandoned( pb ) ) {
  163. /* retval is -1 */
  164. goto error_return;
  165. }
  166. /* find and lock the entry we are about to modify */
  167. if ( (e = find_entry2modify( pb, be, addr, &txn )) == NULL )
  168. {
  169. ldap_result_code= LDAP_NO_SUCH_OBJECT;
  170. /* retval is -1 */
  171. goto error_return; /* error result sent by find_entry2modify() */
  172. }
  173. if ( slapi_entry_has_children( e->ep_entry ) )
  174. {
  175. ldap_result_code= LDAP_NOT_ALLOWED_ON_NONLEAF;
  176. /* retval is -1 */
  177. goto error_return;
  178. }
  179. /* Don't call pre-op for Tombstone entries */
  180. if (!delete_tombstone_entry)
  181. {
  182. int rc = 0;
  183. /*
  184. * Some present state information is passed through the PBlock to the
  185. * backend pre-op plugin. To ensure a consistent snapshot of this state
  186. * we wrap the reading of the entry with the dblock.
  187. */
  188. ldap_result_code= get_copy_of_entry(pb, addr, &txn,
  189. SLAPI_DELETE_EXISTING_ENTRY, !is_replicated_operation);
  190. free_delete_existing_entry = 1;
  191. if(ldap_result_code==LDAP_OPERATIONS_ERROR ||
  192. ldap_result_code==LDAP_INVALID_DN_SYNTAX)
  193. {
  194. /* restore original entry so the front-end delete code can free it */
  195. /* retval is -1 */
  196. goto error_return;
  197. }
  198. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);
  199. rc = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_PRE_DELETE_FN);
  200. if (rc == -1)
  201. {
  202. /*
  203. * Plugin indicated some kind of failure,
  204. * or that this Operation became a No-Op.
  205. */
  206. if (!ldap_result_code) {
  207. slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code);
  208. }
  209. /* restore original entry so the front-end delete code can free it */
  210. slapi_pblock_get( pb, SLAPI_PLUGIN_OPRETURN, &opreturn );
  211. if (!opreturn) {
  212. slapi_pblock_set( pb, SLAPI_PLUGIN_OPRETURN, ldap_result_code ? &ldap_result_code : &rc );
  213. }
  214. /* retval is -1 */
  215. goto error_return;
  216. }
  217. /* the flag could be set in a preop plugin (e.g., USN) */
  218. delete_tombstone_entry = operation_is_flag_set(operation,
  219. OP_FLAG_TOMBSTONE_ENTRY);
  220. }
  221. /*
  222. * Sanity check to avoid to delete a non-tombstone or to tombstone again
  223. * a tombstone entry. This should not happen (see bug 561003).
  224. */
  225. is_tombstone_entry = slapi_entry_flag_is_set(e->ep_entry, SLAPI_ENTRY_FLAG_TOMBSTONE);
  226. if (delete_tombstone_entry) {
  227. PR_ASSERT(is_tombstone_entry);
  228. if (!is_tombstone_entry) {
  229. slapi_log_error(SLAPI_LOG_FATAL, "ldbm_back_delete",
  230. "Attempt to delete a non-tombstone entry %s\n", dn);
  231. delete_tombstone_entry = 0;
  232. }
  233. } else {
  234. PR_ASSERT(!is_tombstone_entry);
  235. if (is_tombstone_entry) {
  236. slapi_log_error(SLAPI_LOG_FATAL, "ldbm_back_delete",
  237. "Attempt to Tombstone again a tombstone entry %s\n", dn);
  238. delete_tombstone_entry = 1;
  239. }
  240. }
  241. /*
  242. * If a CSN is set, we need to tombstone the entry,
  243. * rather than deleting it outright.
  244. */
  245. opcsn = operation_get_csn (operation);
  246. if (!delete_tombstone_entry)
  247. {
  248. if ((opcsn == NULL) && !is_fixup_operation && operation->o_csngen_handler)
  249. {
  250. /*
  251. * Current op is a user request. Opcsn will be assigned
  252. * by entry_assign_operation_csn() if the dn is in an
  253. * updatable replica.
  254. */
  255. opcsn = entry_assign_operation_csn ( pb, e->ep_entry, NULL );
  256. }
  257. if (opcsn != NULL)
  258. {
  259. if (!is_fixup_operation)
  260. {
  261. entry_set_maxcsn (e->ep_entry, opcsn);
  262. }
  263. }
  264. /*
  265. * We are dealing with replication and if we haven't been called to
  266. * remove a tombstone, then it's because we want to create a new one.
  267. */
  268. if ( slapi_operation_get_replica_attr (pb, operation, "nsds5ReplicaTombstonePurgeInterval",
  269. &create_tombstone_entry) == 0 )
  270. {
  271. create_tombstone_entry = (create_tombstone_entry < 0) ? 0 : 1;
  272. }
  273. }
  274. #if DEBUG
  275. slapi_log_error(SLAPI_LOG_REPL, "ldbm_back_delete",
  276. "entry: %s - flags: delete %d is_tombstone_entry %d create %d \n",
  277. dn, delete_tombstone_entry, is_tombstone_entry, create_tombstone_entry);
  278. #endif
  279. /* Save away a copy of the entry, before modifications */
  280. slapi_pblock_set( pb, SLAPI_ENTRY_PRE_OP, slapi_entry_dup( e->ep_entry ));
  281. /* JCMACL - Shouldn't the access check be before the has children check...
  282. * otherwise we're revealing the fact that an entry exists and has children */
  283. ldap_result_code = plugin_call_acl_plugin (pb, e->ep_entry, NULL, NULL, SLAPI_ACL_DELETE,
  284. ACLPLUGIN_ACCESS_DEFAULT, &errbuf );
  285. if ( ldap_result_code != LDAP_SUCCESS )
  286. {
  287. ldap_result_message= errbuf;
  288. /* retval is -1 */
  289. goto error_return;
  290. }
  291. /*
  292. * Get the entry's parent. We do this here because index_read
  293. * seems to deadlock the database when dblayer_txn_begin is
  294. * called.
  295. */
  296. slapi_sdn_init(&parentsdn);
  297. slapi_sdn_get_backend_parent_ext(sdnp, &parentsdn, pb->pb_backend, is_tombstone_entry);
  298. if ( !slapi_sdn_isempty(&parentsdn) )
  299. {
  300. struct backentry *parent = NULL;
  301. entry_address parent_addr;
  302. parent_addr.sdn = &parentsdn;
  303. parent_addr.uniqueid = NULL;
  304. parent = find_entry2modify_only_ext(pb, be, &parent_addr,
  305. TOMBSTONE_INCLUDED, &txn);
  306. if (NULL != parent) {
  307. int isglue;
  308. size_t haschildren = 0;
  309. int op = PARENTUPDATE_DEL;
  310. /* Unfortunately findentry doesn't tell us whether it just
  311. * didn't find the entry, or if there was an error, so we
  312. * have to assume that the parent wasn't found */
  313. parent_found = 1;
  314. /* Modify the parent in memory */
  315. modify_init(&parent_modify_c,parent);
  316. if (create_tombstone_entry) {
  317. op |= PARENTUPDATE_CREATE_TOMBSTONE;
  318. } else if (delete_tombstone_entry) {
  319. op |= PARENTUPDATE_DELETE_TOMBSTONE;
  320. }
  321. retval = parent_update_on_childchange(&parent_modify_c,
  322. op, &haschildren);
  323. /* The modify context now contains info needed later */
  324. if (0 != retval) {
  325. ldap_result_code= LDAP_OPERATIONS_ERROR;
  326. goto error_return;
  327. }
  328. /*
  329. * Replication urp_post_delete will delete the parent entry
  330. * if it is a glue entry without any more children.
  331. * Those urp condition checkings are done here to
  332. * save unnecessary entry dup.
  333. */
  334. isglue = slapi_entry_attr_hasvalue (parent_modify_c.new_entry->ep_entry,
  335. SLAPI_ATTR_OBJECTCLASS, "glue");
  336. if ( opcsn && parent_modify_c.new_entry && !haschildren && isglue)
  337. {
  338. slapi_pblock_set ( pb, SLAPI_DELETE_GLUE_PARENT_ENTRY,
  339. slapi_entry_dup (parent_modify_c.new_entry->ep_entry) );
  340. }
  341. }
  342. }
  343. slapi_sdn_done(&parentsdn);
  344. if(create_tombstone_entry)
  345. {
  346. /*
  347. * The entry is not removed from the disk when we tombstone an
  348. * entry. We change the DN, add objectclass=tombstone, and record
  349. * the UniqueID of the parent entry.
  350. */
  351. const char *childuniqueid= slapi_entry_get_uniqueid(e->ep_entry);
  352. const char *parentuniqueid= NULL;
  353. char *tombstone_dn = compute_entry_tombstone_dn(slapi_entry_get_dn(e->ep_entry),
  354. childuniqueid);
  355. Slapi_Value *tomb_value;
  356. slapi_sdn_set_ndn_byval(&nscpEntrySDN, slapi_sdn_get_ndn(slapi_entry_get_sdn(e->ep_entry)));
  357. /* Copy the entry unique_id for URP conflict checking */
  358. e_uniqueid = slapi_ch_strdup(childuniqueid);
  359. if(parent_modify_c.old_entry!=NULL)
  360. {
  361. /* The suffix entry has no parent */
  362. parentuniqueid= slapi_entry_get_uniqueid(parent_modify_c.old_entry->ep_entry);
  363. }
  364. tombstone = backentry_dup( e );
  365. slapi_entry_set_dn(tombstone->ep_entry,tombstone_dn); /* Consumes DN */
  366. if (entryrdn_get_switch()) /* subtree-rename: on */
  367. {
  368. Slapi_RDN *srdn = slapi_entry_get_srdn(tombstone->ep_entry);
  369. char *tombstone_rdn =
  370. compute_entry_tombstone_rdn(slapi_entry_get_rdn_const(e->ep_entry),
  371. childuniqueid);
  372. /* e_srdn has "uniaqueid=..., <ORIG RDN>" */
  373. slapi_rdn_replace_rdn(srdn, tombstone_rdn);
  374. slapi_ch_free_string(&tombstone_rdn);
  375. }
  376. /* Set tombstone flag on ep_entry */
  377. slapi_entry_set_flag(tombstone->ep_entry, SLAPI_ENTRY_FLAG_TOMBSTONE);
  378. if(parentuniqueid!=NULL)
  379. {
  380. /* The suffix entry has no parent */
  381. slapi_entry_add_string(tombstone->ep_entry, SLAPI_ATTR_VALUE_PARENT_UNIQUEID, parentuniqueid);
  382. }
  383. slapi_entry_add_string(tombstone->ep_entry, SLAPI_ATTR_NSCP_ENTRYDN, slapi_sdn_get_ndn(&nscpEntrySDN));
  384. tomb_value = slapi_value_new_string(SLAPI_ATTR_VALUE_TOMBSTONE);
  385. value_update_csn(tomb_value, CSN_TYPE_VALUE_UPDATED,
  386. operation_get_csn(operation));
  387. slapi_entry_add_value(tombstone->ep_entry, SLAPI_ATTR_OBJECTCLASS, tomb_value);
  388. slapi_value_free(&tomb_value);
  389. /* XXXggood above used to be: slapi_entry_add_string(tombstone->ep_entry, SLAPI_ATTR_OBJECTCLASS, SLAPI_ATTR_VALUE_TOMBSTONE); */
  390. /* JCMREPL - Add a description of what's going on? */
  391. if ( (original_tombstone = backentry_dup( tombstone )) == NULL ) {
  392. ldap_result_code= LDAP_OPERATIONS_ERROR;
  393. goto error_return;
  394. }
  395. }
  396. if (!is_ruv && !is_fixup_operation && !delete_tombstone_entry) {
  397. ruv_c_init = ldbm_txn_ruv_modify_context( pb, &ruv_c );
  398. if (-1 == ruv_c_init) {
  399. LDAPDebug( LDAP_DEBUG_ANY,
  400. "ldbm_back_delete: ldbm_txn_ruv_modify_context "
  401. "failed to construct RUV modify context\n",
  402. 0, 0, 0);
  403. ldap_result_code= LDAP_OPERATIONS_ERROR;
  404. retval = 0;
  405. goto error_return;
  406. }
  407. }
  408. /*
  409. * So, we believe that no code up till here actually added anything
  410. * to the persistent store. From now on, we're transacted
  411. */
  412. txn.back_txn_txn = NULL; /* ready to create the child transaction */
  413. for (retry_count = 0; retry_count < RETRY_TIMES; retry_count++) {
  414. if (txn.back_txn_txn && (txn.back_txn_txn != parent_txn)) {
  415. Slapi_Entry *ent = NULL;
  416. dblayer_txn_abort(li,&txn);
  417. slapi_pblock_set(pb, SLAPI_TXN, parent_txn);
  418. /* reset original entry */
  419. slapi_pblock_get( pb, SLAPI_DELETE_EXISTING_ENTRY, &ent );
  420. if (ent && free_delete_existing_entry) {
  421. slapi_entry_free(ent);
  422. slapi_pblock_set( pb, SLAPI_DELETE_EXISTING_ENTRY, NULL );
  423. }
  424. slapi_pblock_set( pb, SLAPI_DELETE_EXISTING_ENTRY, slapi_entry_dup( e->ep_entry ) );
  425. free_delete_existing_entry = 1; /* must free the dup */
  426. if (create_tombstone_entry) {
  427. slapi_sdn_set_ndn_byval(&nscpEntrySDN, slapi_sdn_get_ndn(slapi_entry_get_sdn(e->ep_entry)));
  428. }
  429. /* reset tombstone entry */
  430. if (original_tombstone) {
  431. if (tombstone_in_cache) {
  432. CACHE_REMOVE(&inst->inst_cache, tombstone);
  433. CACHE_RETURN(&inst->inst_cache, &tombstone);
  434. tombstone_in_cache = 0;
  435. } else {
  436. backentry_free(&tombstone);
  437. }
  438. tombstone = original_tombstone;
  439. if ( (original_tombstone = backentry_dup( tombstone )) == NULL ) {
  440. ldap_result_code= LDAP_OPERATIONS_ERROR;
  441. goto error_return;
  442. }
  443. }
  444. /* We're re-trying */
  445. LDAPDebug0Args(LDAP_DEBUG_BACKLDBM,
  446. "Delete Retrying Transaction\n");
  447. #ifndef LDBM_NO_BACKOFF_DELAY
  448. {
  449. PRIntervalTime interval;
  450. interval = PR_MillisecondsToInterval(slapi_rand() % 100);
  451. DS_Sleep(interval);
  452. }
  453. #endif
  454. }
  455. retval = dblayer_txn_begin(li,parent_txn,&txn);
  456. if (0 != retval) {
  457. if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
  458. ldap_result_code= LDAP_OPERATIONS_ERROR;
  459. goto error_return;
  460. }
  461. /* stash the transaction */
  462. slapi_pblock_set(pb, SLAPI_TXN, txn.back_txn_txn);
  463. /* call the transaction pre delete plugins just after creating
  464. * the transaction */
  465. /* these should not need to modify the entry to be deleted -
  466. if for some reason they ever do, do not use e->ep_entry since
  467. it could be in the cache and referenced by other search threads -
  468. instead, have them modify a copy of the entry */
  469. retval = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_PRE_DELETE_FN);
  470. if (retval) {
  471. LDAPDebug1Arg( LDAP_DEBUG_TRACE,
  472. "SLAPI_PLUGIN_BE_TXN_PRE_DELETE_FN plugin "
  473. "returned error code %d\n", retval );
  474. if (!ldap_result_code) {
  475. slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code);
  476. }
  477. if (!opreturn) {
  478. slapi_pblock_get( pb, SLAPI_PLUGIN_OPRETURN, &opreturn );
  479. }
  480. if (!opreturn) {
  481. slapi_pblock_set( pb, SLAPI_PLUGIN_OPRETURN,
  482. ldap_result_code ?
  483. &ldap_result_code : &retval );
  484. }
  485. goto error_return;
  486. }
  487. if(create_tombstone_entry)
  488. {
  489. slapi_pblock_get( pb, SLAPI_DELETE_BEPREOP_ENTRY, &orig_entry );
  490. /* this is ok because no other threads should be accessing
  491. the tombstone entry */
  492. slapi_pblock_set( pb, SLAPI_DELETE_BEPREOP_ENTRY,
  493. tombstone->ep_entry );
  494. rc = plugin_call_plugins(pb,
  495. SLAPI_PLUGIN_BE_TXN_PRE_DELETE_TOMBSTONE_FN);
  496. if (rc == -1) {
  497. /*
  498. * Plugin indicated some kind of failure,
  499. * or that this Operation became a No-Op.
  500. */
  501. if (!ldap_result_code) {
  502. slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code);
  503. }
  504. /* restore original entry so the front-end delete code
  505. * can free it */
  506. slapi_pblock_get( pb, SLAPI_PLUGIN_OPRETURN, &opreturn );
  507. if (!opreturn) {
  508. slapi_pblock_set( pb, SLAPI_PLUGIN_OPRETURN,
  509. ldap_result_code ?
  510. &ldap_result_code : &rc );
  511. }
  512. /* retval is -1 */
  513. goto error_return;
  514. }
  515. slapi_pblock_set( pb, SLAPI_DELETE_BEPREOP_ENTRY, orig_entry );
  516. orig_entry = NULL;
  517. /*
  518. * The entry is not removed from the disk when we tombstone an
  519. * entry. We change the DN, add objectclass=tombstone, and record
  520. * the UniqueID of the parent entry.
  521. */
  522. /* Note: cache_add (tombstone) fails since the original entry having
  523. * the same ID is already in the cache. Thus, we have to add it
  524. * tentatively for now, then cache_add again when the original
  525. * entry is removed from the cache.
  526. */
  527. if (cache_add_tentative( &inst->inst_cache, tombstone, NULL) == 0) {
  528. tombstone_in_cache = 1;
  529. } else if (!(tombstone->ep_state & ENTRY_STATE_NOTINCACHE)) {
  530. LDAPDebug1Arg(LDAP_DEBUG_CACHE,
  531. "id2entry_add tombstone (%s) is in cache\n",
  532. slapi_entry_get_dn(tombstone->ep_entry));
  533. tombstone_in_cache = 1;
  534. }
  535. retval = id2entry_add( be, tombstone, &txn );
  536. if (DB_LOCK_DEADLOCK == retval) {
  537. LDAPDebug( LDAP_DEBUG_ARGS, "delete 1 DB_LOCK_DEADLOCK\n", 0, 0, 0 );
  538. /* Abort and re-try */
  539. continue;
  540. }
  541. if (0 != retval) {
  542. LDAPDebug( LDAP_DEBUG_ANY, "id2entry_add failed, err=%d %s\n",
  543. retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
  544. if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
  545. DEL_SET_ERROR(ldap_result_code,
  546. LDAP_OPERATIONS_ERROR, retry_count);
  547. goto error_return;
  548. }
  549. }
  550. else
  551. {
  552. /* delete the entry from disk */
  553. retval = id2entry_delete( be, e, &txn );
  554. if (DB_LOCK_DEADLOCK == retval)
  555. {
  556. LDAPDebug( LDAP_DEBUG_ARGS, "delete 2 DEADLOCK\n", 0, 0, 0 );
  557. /* Retry txn */
  558. continue;
  559. }
  560. if (retval != 0 ) {
  561. if (retval == DB_RUNRECOVERY ||
  562. LDBM_OS_ERR_IS_DISKFULL(retval)) {
  563. disk_full = 1;
  564. }
  565. DEL_SET_ERROR(ldap_result_code,
  566. LDAP_OPERATIONS_ERROR, retry_count);
  567. goto error_return;
  568. }
  569. }
  570. /* delete from attribute indexes */
  571. addordel_flags = BE_INDEX_DEL|BE_INDEX_PRESENCE|BE_INDEX_EQUALITY;
  572. if (delete_tombstone_entry)
  573. {
  574. addordel_flags |= BE_INDEX_TOMBSTONE; /* tell index code we are deleting a tombstone */
  575. }
  576. retval = index_addordel_entry( be, e, addordel_flags, &txn );
  577. if (DB_LOCK_DEADLOCK == retval)
  578. {
  579. LDAPDebug( LDAP_DEBUG_ARGS, "delete 1 DEADLOCK\n", 0, 0, 0 );
  580. /* Retry txn */
  581. continue;
  582. }
  583. if (retval != 0) {
  584. LDAPDebug( LDAP_DEBUG_TRACE, "index_del_entry failed\n", 0, 0, 0 );
  585. DEL_SET_ERROR(ldap_result_code, LDAP_OPERATIONS_ERROR, retry_count);
  586. goto error_return;
  587. }
  588. if(create_tombstone_entry)
  589. {
  590. /*
  591. * The tombstone entry is removed from all attribute indexes
  592. * above, but we want it to remain in the nsUniqueID and nscpEntryDN indexes
  593. * and for objectclass=tombstone.
  594. */
  595. retval = index_addordel_string(be, SLAPI_ATTR_OBJECTCLASS,
  596. SLAPI_ATTR_VALUE_TOMBSTONE,
  597. tombstone->ep_id,BE_INDEX_ADD, &txn);
  598. if (DB_LOCK_DEADLOCK == retval) {
  599. LDAPDebug( LDAP_DEBUG_ARGS,
  600. "delete (adding %s) DB_LOCK_DEADLOCK\n",
  601. SLAPI_ATTR_VALUE_TOMBSTONE, 0, 0 );
  602. /* Retry txn */
  603. continue;
  604. }
  605. if (0 != retval) {
  606. LDAPDebug( LDAP_DEBUG_TRACE,
  607. "delete (adding %s) failed, err=%d %s\n",
  608. SLAPI_ATTR_VALUE_TOMBSTONE, retval,
  609. (msg = dblayer_strerror( retval )) ? msg : "" );
  610. if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
  611. DEL_SET_ERROR(ldap_result_code,
  612. LDAP_OPERATIONS_ERROR, retry_count);
  613. goto error_return;
  614. }
  615. retval = index_addordel_string(be, SLAPI_ATTR_UNIQUEID,
  616. slapi_entry_get_uniqueid(tombstone->ep_entry),
  617. tombstone->ep_id,BE_INDEX_ADD,&txn);
  618. if (DB_LOCK_DEADLOCK == retval) {
  619. LDAPDebug( LDAP_DEBUG_ARGS,
  620. "delete (adding %s) DB_LOCK_DEADLOCK\n",
  621. SLAPI_ATTR_UNIQUEID, 0, 0 );
  622. /* Retry txn */
  623. continue;
  624. }
  625. if (0 != retval) {
  626. LDAPDebug( LDAP_DEBUG_TRACE,
  627. "delete (adding %s) failed, err=%d %s\n",
  628. SLAPI_ATTR_UNIQUEID, retval,
  629. (msg = dblayer_strerror( retval )) ? msg : "" );
  630. if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
  631. DEL_SET_ERROR(ldap_result_code,
  632. LDAP_OPERATIONS_ERROR, retry_count);
  633. goto error_return;
  634. }
  635. retval = index_addordel_string(be, SLAPI_ATTR_NSCP_ENTRYDN,
  636. slapi_sdn_get_ndn(&nscpEntrySDN),
  637. tombstone->ep_id, BE_INDEX_ADD, &txn);
  638. if (DB_LOCK_DEADLOCK == retval) {
  639. LDAPDebug( LDAP_DEBUG_ARGS,
  640. "delete (adding %s) DB_LOCK_DEADLOCK\n",
  641. SLAPI_ATTR_NSCP_ENTRYDN, 0, 0 );
  642. /* Retry txn */
  643. continue;
  644. }
  645. if (0 != retval) {
  646. LDAPDebug( LDAP_DEBUG_TRACE,
  647. "delete (adding %s) failed, err=%d %s\n",
  648. SLAPI_ATTR_NSCP_ENTRYDN, retval,
  649. (msg = dblayer_strerror( retval )) ? msg : "" );
  650. if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
  651. DEL_SET_ERROR(ldap_result_code,
  652. LDAP_OPERATIONS_ERROR, retry_count);
  653. goto error_return;
  654. }
  655. /* add a new usn to the entryusn index */
  656. entryusn_str = slapi_entry_attr_get_charptr(tombstone->ep_entry,
  657. SLAPI_ATTR_ENTRYUSN);
  658. if (entryusn_str) {
  659. retval = index_addordel_string(be, SLAPI_ATTR_ENTRYUSN,
  660. entryusn_str, tombstone->ep_id, BE_INDEX_ADD, &txn);
  661. slapi_ch_free_string(&entryusn_str);
  662. if (DB_LOCK_DEADLOCK == retval) {
  663. LDAPDebug( LDAP_DEBUG_ARGS,
  664. "delete (adding %s) DB_LOCK_DEADLOCK\n",
  665. SLAPI_ATTR_ENTRYUSN, 0, 0 );
  666. /* Retry txn */
  667. continue;
  668. }
  669. if (0 != retval) {
  670. LDAPDebug( LDAP_DEBUG_TRACE,
  671. "delete (adding %s) failed, err=%d %s\n",
  672. SLAPI_ATTR_ENTRYUSN, retval,
  673. (msg = dblayer_strerror( retval )) ? msg : "" );
  674. if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
  675. DEL_SET_ERROR(ldap_result_code,
  676. LDAP_OPERATIONS_ERROR, retry_count);
  677. goto error_return;
  678. }
  679. }
  680. if (entryrdn_get_switch()) /* subtree-rename: on */
  681. {
  682. Slapi_Attr *attr;
  683. Slapi_Value **svals;
  684. /* To maintain tombstonenumsubordinates,
  685. * parentid is needed for tombstone, as well. */
  686. slapi_entry_attr_find(tombstone->ep_entry, LDBM_PARENTID_STR,
  687. &attr);
  688. if (attr) {
  689. svals = attr_get_present_values(attr);
  690. retval = index_addordel_values_sv(be, LDBM_PARENTID_STR,
  691. svals, NULL, e->ep_id,
  692. BE_INDEX_ADD, &txn);
  693. if (DB_LOCK_DEADLOCK == retval) {
  694. LDAPDebug0Args( LDAP_DEBUG_ARGS,
  695. "delete (updating " LDBM_PARENTID_STR ") DB_LOCK_DEADLOCK\n");
  696. /* Retry txn */
  697. continue;
  698. }
  699. if ( retval ) {
  700. LDAPDebug( LDAP_DEBUG_TRACE,
  701. "delete (deleting %s) failed, err=%d %s\n",
  702. LDBM_PARENTID_STR, retval,
  703. (msg = dblayer_strerror( retval )) ? msg : "" );
  704. if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
  705. DEL_SET_ERROR(ldap_result_code,
  706. LDAP_OPERATIONS_ERROR, retry_count);
  707. goto error_return;
  708. }
  709. }
  710. retval = entryrdn_index_entry(be, e, BE_INDEX_DEL, &txn);
  711. if (DB_LOCK_DEADLOCK == retval) {
  712. LDAPDebug0Args( LDAP_DEBUG_ARGS,
  713. "delete (deleting entryrdn) DB_LOCK_DEADLOCK\n");
  714. /* Retry txn */
  715. continue;
  716. }
  717. if (0 != retval) {
  718. LDAPDebug2Args( LDAP_DEBUG_TRACE,
  719. "delete (deleting entryrdn) failed, err=%d %s\n",
  720. retval,
  721. (msg = dblayer_strerror( retval )) ? msg : "" );
  722. if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
  723. DEL_SET_ERROR(ldap_result_code,
  724. LDAP_OPERATIONS_ERROR, retry_count);
  725. goto error_return;
  726. }
  727. retval = entryrdn_index_entry(be, tombstone, BE_INDEX_ADD, &txn);
  728. if (DB_LOCK_DEADLOCK == retval) {
  729. LDAPDebug0Args( LDAP_DEBUG_ARGS,
  730. "adding (adding tombstone entryrdn) DB_LOCK_DEADLOCK\n");
  731. /* Retry txn */
  732. continue;
  733. }
  734. if (0 != retval) {
  735. LDAPDebug2Args( LDAP_DEBUG_TRACE,
  736. "adding (adding tombstone entryrdn) failed, err=%d %s\n",
  737. retval,
  738. (msg = dblayer_strerror( retval )) ? msg : "" );
  739. if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
  740. DEL_SET_ERROR(ldap_result_code,
  741. LDAP_OPERATIONS_ERROR, retry_count);
  742. goto error_return;
  743. }
  744. }
  745. } /* create_tombstone_entry */
  746. else if (delete_tombstone_entry)
  747. {
  748. /*
  749. * We need to remove the Tombstone entry from the remaining indexes:
  750. * objectclass=nsTombstone, nsUniqueID, nscpEntryDN
  751. */
  752. char *nscpedn = NULL;
  753. retval = index_addordel_string(be, SLAPI_ATTR_OBJECTCLASS,
  754. SLAPI_ATTR_VALUE_TOMBSTONE, e->ep_id,
  755. BE_INDEX_DEL, &txn);
  756. if (DB_LOCK_DEADLOCK == retval) {
  757. LDAPDebug( LDAP_DEBUG_ARGS,
  758. "delete (deleting %s) DB_LOCK_DEADLOCK\n",
  759. SLAPI_ATTR_VALUE_TOMBSTONE, 0, 0 );
  760. /* Retry txn */
  761. continue;
  762. }
  763. if (0 != retval) {
  764. LDAPDebug( LDAP_DEBUG_TRACE,
  765. "delete (deleting %s) failed, err=%d %s\n",
  766. SLAPI_ATTR_VALUE_TOMBSTONE, retval,
  767. (msg = dblayer_strerror( retval )) ? msg : "" );
  768. if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
  769. DEL_SET_ERROR(ldap_result_code,
  770. LDAP_OPERATIONS_ERROR, retry_count);
  771. goto error_return;
  772. }
  773. retval = index_addordel_string(be, SLAPI_ATTR_UNIQUEID,
  774. slapi_entry_get_uniqueid(e->ep_entry),
  775. e->ep_id, BE_INDEX_DEL, &txn);
  776. if (DB_LOCK_DEADLOCK == retval) {
  777. LDAPDebug( LDAP_DEBUG_ARGS,
  778. "delete (deleting %s) DB_LOCK_DEADLOCK\n",
  779. SLAPI_ATTR_UNIQUEID, 0, 0 );
  780. /* Retry txn */
  781. continue;
  782. }
  783. if (0 != retval) {
  784. LDAPDebug( LDAP_DEBUG_TRACE,
  785. "delete (deleting %s) failed, err=%d %s\n",
  786. SLAPI_ATTR_UNIQUEID, retval,
  787. (msg = dblayer_strerror( retval )) ? msg : "" );
  788. if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
  789. DEL_SET_ERROR(ldap_result_code,
  790. LDAP_OPERATIONS_ERROR, retry_count);
  791. goto error_return;
  792. }
  793. nscpedn = slapi_entry_attr_get_charptr(e->ep_entry,
  794. SLAPI_ATTR_NSCP_ENTRYDN);
  795. if (nscpedn) {
  796. retval = index_addordel_string(be, SLAPI_ATTR_NSCP_ENTRYDN,
  797. nscpedn, e->ep_id, BE_INDEX_DEL, &txn);
  798. slapi_ch_free((void **)&nscpedn);
  799. if (DB_LOCK_DEADLOCK == retval) {
  800. LDAPDebug( LDAP_DEBUG_ARGS,
  801. "delete (deleting %s) DB_LOCK_DEADLOCK\n",
  802. SLAPI_ATTR_NSCP_ENTRYDN, 0, 0 );
  803. /* Retry txn */
  804. continue;
  805. }
  806. if (0 != retval) {
  807. LDAPDebug( LDAP_DEBUG_TRACE,
  808. "delete (deleting %s) failed, err=%d %s\n",
  809. SLAPI_ATTR_NSCP_ENTRYDN, retval,
  810. (msg = dblayer_strerror( retval )) ? msg : "" );
  811. if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
  812. DEL_SET_ERROR(ldap_result_code,
  813. LDAP_OPERATIONS_ERROR, retry_count);
  814. goto error_return;
  815. }
  816. }
  817. /* delete usn from the entryusn index */
  818. entryusn_str = slapi_entry_attr_get_charptr(e->ep_entry,
  819. SLAPI_ATTR_ENTRYUSN);
  820. if (entryusn_str) {
  821. retval = index_addordel_string(be, SLAPI_ATTR_ENTRYUSN,
  822. entryusn_str, e->ep_id,
  823. BE_INDEX_DEL|BE_INDEX_EQUALITY, &txn);
  824. slapi_ch_free_string(&entryusn_str);
  825. if (DB_LOCK_DEADLOCK == retval) {
  826. LDAPDebug( LDAP_DEBUG_ARGS,
  827. "delete (deleting %s) DB_LOCK_DEADLOCK\n",
  828. SLAPI_ATTR_ENTRYUSN, 0, 0 );
  829. /* Retry txn */
  830. continue;
  831. }
  832. if (0 != retval) {
  833. LDAPDebug( LDAP_DEBUG_TRACE,
  834. "delete (deleting %s) failed, err=%d %s\n",
  835. SLAPI_ATTR_ENTRYUSN, retval,
  836. (msg = dblayer_strerror( retval )) ? msg : "" );
  837. if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
  838. DEL_SET_ERROR(ldap_result_code,
  839. LDAP_OPERATIONS_ERROR, retry_count);
  840. goto error_return;
  841. }
  842. }
  843. if (entryrdn_get_switch()) /* subtree-rename: on */
  844. {
  845. retval = entryrdn_index_entry(be, e, BE_INDEX_DEL, &txn);
  846. if (DB_LOCK_DEADLOCK == retval) {
  847. LDAPDebug0Args( LDAP_DEBUG_ARGS,
  848. "delete (deleting entryrdn) DB_LOCK_DEADLOCK\n");
  849. /* Retry txn */
  850. continue;
  851. }
  852. if (0 != retval) {
  853. LDAPDebug2Args( LDAP_DEBUG_TRACE,
  854. "delete (deleting entryrdn) failed, err=%d %s\n",
  855. retval,
  856. (msg = dblayer_strerror( retval )) ? msg : "" );
  857. if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
  858. DEL_SET_ERROR(ldap_result_code,
  859. LDAP_OPERATIONS_ERROR, retry_count);
  860. goto error_return;
  861. }
  862. }
  863. } /* delete_tombstone_entry */
  864. if (parent_found) {
  865. /* Push out the db modifications from the parent entry */
  866. retval = modify_update_all(be,pb,&parent_modify_c,&txn);
  867. if (DB_LOCK_DEADLOCK == retval)
  868. {
  869. LDAPDebug( LDAP_DEBUG_ARGS, "del 4 DEADLOCK\n", 0, 0, 0 );
  870. /* Retry txn */
  871. continue;
  872. }
  873. if (0 != retval) {
  874. LDAPDebug( LDAP_DEBUG_TRACE, "delete 3 BAD, err=%d %s\n",
  875. retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
  876. if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
  877. DEL_SET_ERROR(ldap_result_code,
  878. LDAP_OPERATIONS_ERROR, retry_count);
  879. goto error_return;
  880. }
  881. }
  882. /*
  883. * first check if searchentry needs to be removed
  884. * Remove the entry from the Virtual List View indexes.
  885. */
  886. if (!delete_tombstone_entry && !is_ruv &&
  887. !vlv_delete_search_entry(pb,e->ep_entry,inst)) {
  888. retval = vlv_update_all_indexes(&txn, be, pb, e, NULL);
  889. if (DB_LOCK_DEADLOCK == retval)
  890. {
  891. LDAPDebug( LDAP_DEBUG_ARGS, "delete DEADLOCK vlv_update_index\n", 0, 0, 0 );
  892. /* Retry txn */
  893. continue;
  894. }
  895. if (retval != 0 ) {
  896. if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
  897. DEL_SET_ERROR(ldap_result_code,
  898. LDAP_OPERATIONS_ERROR, retry_count);
  899. goto error_return;
  900. }
  901. }
  902. if (ruv_c_init) {
  903. retval = modify_update_all( be, pb, &ruv_c, &txn );
  904. if (DB_LOCK_DEADLOCK == retval) {
  905. /* Abort and re-try */
  906. continue;
  907. }
  908. if (0 != retval) {
  909. LDAPDebug( LDAP_DEBUG_ANY,
  910. "modify_update_all failed, err=%d %s\n", retval,
  911. (msg = dblayer_strerror( retval )) ? msg : "", 0 );
  912. if (LDBM_OS_ERR_IS_DISKFULL(retval))
  913. disk_full = 1;
  914. ldap_result_code= LDAP_OPERATIONS_ERROR;
  915. goto error_return;
  916. }
  917. }
  918. if (retval == 0 ) {
  919. break;
  920. }
  921. }
  922. if (retry_count == RETRY_TIMES) {
  923. /* Failed */
  924. LDAPDebug( LDAP_DEBUG_ANY, "Retry count exceeded in delete\n", 0, 0, 0 );
  925. ldap_result_code= LDAP_BUSY;
  926. retval = -1;
  927. goto error_return;
  928. }
  929. /* call the transaction post delete plugins just before the commit */
  930. if (plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_POST_DELETE_FN)) {
  931. LDAPDebug0Args( LDAP_DEBUG_ANY, "SLAPI_PLUGIN_BE_TXN_POST_DELETE_FN plugin "
  932. "returned error code\n" );
  933. if (!ldap_result_code) {
  934. slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code);
  935. }
  936. if (!ldap_result_code) {
  937. LDAPDebug0Args( LDAP_DEBUG_ANY, "SLAPI_PLUGIN_BE_TXN_POST_DELETE_FN plugin "
  938. "returned error code but did not set SLAPI_RESULT_CODE\n" );
  939. ldap_result_code = LDAP_OPERATIONS_ERROR;
  940. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);
  941. }
  942. if (!opreturn) {
  943. slapi_pblock_get( pb, SLAPI_PLUGIN_OPRETURN, &opreturn );
  944. }
  945. if (!retval) {
  946. retval = -1;
  947. }
  948. if (!opreturn) {
  949. slapi_pblock_set( pb, SLAPI_PLUGIN_OPRETURN, &retval );
  950. }
  951. goto error_return;
  952. }
  953. retval = dblayer_txn_commit(li,&txn);
  954. /* after commit - txn is no longer valid - replace SLAPI_TXN with parent */
  955. slapi_pblock_set(pb, SLAPI_TXN, parent_txn);
  956. if (0 != retval)
  957. {
  958. if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
  959. ldap_result_code= LDAP_OPERATIONS_ERROR;
  960. goto error_return;
  961. }
  962. /* delete from cache and clean up */
  963. if (e) {
  964. CACHE_REMOVE(&inst->inst_cache, e);
  965. cache_unlock_entry(&inst->inst_cache, e);
  966. CACHE_RETURN(&inst->inst_cache, &e);
  967. e = NULL;
  968. }
  969. if (parent_found)
  970. {
  971. /* Replace the old parent entry with the newly modified one */
  972. modify_switch_entries( &parent_modify_c,be);
  973. }
  974. if (ruv_c_init) {
  975. if (modify_switch_entries(&ruv_c, be) != 0 ) {
  976. ldap_result_code= LDAP_OPERATIONS_ERROR;
  977. LDAPDebug( LDAP_DEBUG_ANY,
  978. "ldbm_back_delete: modify_switch_entries failed\n", 0, 0, 0);
  979. retval = -1;
  980. goto error_return;
  981. }
  982. }
  983. rc= 0;
  984. goto common_return;
  985. error_return:
  986. if (tombstone_in_cache)
  987. {
  988. CACHE_REMOVE( &inst->inst_cache, tombstone );
  989. CACHE_RETURN( &inst->inst_cache, &tombstone );
  990. tombstone = NULL;
  991. tombstone_in_cache = 0;
  992. }
  993. else
  994. {
  995. backentry_free( &tombstone );
  996. }
  997. if (retval == DB_RUNRECOVERY) {
  998. dblayer_remember_disk_filled(li);
  999. ldbm_nasty("Delete",79,retval);
  1000. disk_full = 1;
  1001. }
  1002. if (disk_full) {
  1003. rc= return_on_disk_full(li);
  1004. goto diskfull_return;
  1005. }
  1006. else
  1007. rc= SLAPI_FAIL_GENERAL;
  1008. /* It is safer not to abort when the transaction is not started. */
  1009. if (txn.back_txn_txn && (txn.back_txn_txn != parent_txn)) {
  1010. /* make sure SLAPI_RESULT_CODE and SLAPI_PLUGIN_OPRETURN are set */
  1011. int val = 0;
  1012. slapi_pblock_get(pb, SLAPI_RESULT_CODE, &val);
  1013. if (!val) {
  1014. if (!ldap_result_code) {
  1015. ldap_result_code = LDAP_OPERATIONS_ERROR;
  1016. }
  1017. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);
  1018. }
  1019. slapi_pblock_get( pb, SLAPI_PLUGIN_OPRETURN, &val );
  1020. if (!val) {
  1021. opreturn = retval;
  1022. slapi_pblock_set( pb, SLAPI_PLUGIN_OPRETURN, &retval );
  1023. }
  1024. /* call the transaction post delete plugins just before the commit */
  1025. if (plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_POST_DELETE_FN)) {
  1026. LDAPDebug1Arg( LDAP_DEBUG_ANY, "SLAPI_PLUGIN_BE_TXN_POST_DELETE_FN plugin "
  1027. "returned error code %d\n", retval );
  1028. if (!ldap_result_code) {
  1029. slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code);
  1030. }
  1031. if (!opreturn) {
  1032. slapi_pblock_get( pb, SLAPI_PLUGIN_OPRETURN, &opreturn );
  1033. }
  1034. if (!opreturn) {
  1035. slapi_pblock_set( pb, SLAPI_PLUGIN_OPRETURN, ldap_result_code ? &ldap_result_code : &retval );
  1036. }
  1037. }
  1038. dblayer_txn_abort(li,&txn); /* abort crashes in case disk full */
  1039. /* txn is no longer valid - reset the txn pointer to the parent */
  1040. slapi_pblock_set(pb, SLAPI_TXN, parent_txn);
  1041. }
  1042. common_return:
  1043. if (orig_entry) {
  1044. /* NOTE: #define SLAPI_DELETE_BEPREOP_ENTRY SLAPI_ENTRY_PRE_OP */
  1045. /* so if orig_entry is NULL, we will wipe out SLAPI_ENTRY_PRE_OP
  1046. for the post op plugins */
  1047. slapi_pblock_set( pb, SLAPI_DELETE_BEPREOP_ENTRY, orig_entry );
  1048. }
  1049. if (tombstone_in_cache)
  1050. {
  1051. CACHE_RETURN( &inst->inst_cache, &tombstone );
  1052. tombstone = NULL;
  1053. tombstone_in_cache = 0;
  1054. }
  1055. else
  1056. {
  1057. backentry_free( &tombstone );
  1058. }
  1059. /* result code could be used in the bepost plugin functions. */
  1060. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);
  1061. /*
  1062. * The bepostop is called even if the operation fails,
  1063. * but not if the operation is purging tombstones.
  1064. */
  1065. if (!delete_tombstone_entry) {
  1066. plugin_call_plugins (pb, SLAPI_PLUGIN_BE_POST_DELETE_FN);
  1067. }
  1068. /* Need to return to cache after post op plugins are called */
  1069. if (retval) { /* error case */
  1070. if (e) {
  1071. cache_unlock_entry( &inst->inst_cache, e );
  1072. CACHE_RETURN( &inst->inst_cache, &e );
  1073. }
  1074. }
  1075. if (ruv_c_init) {
  1076. modify_term(&ruv_c, be);
  1077. }
  1078. diskfull_return:
  1079. if(ldap_result_code!=-1)
  1080. {
  1081. slapi_send_ldap_result( pb, ldap_result_code, NULL, ldap_result_message, 0, NULL );
  1082. }
  1083. modify_term(&parent_modify_c,be);
  1084. if(dblock_acquired)
  1085. {
  1086. dblayer_unlock_backend(be);
  1087. }
  1088. if (rc == 0 && opcsn && !is_fixup_operation && !delete_tombstone_entry)
  1089. {
  1090. /* URP Naming Collision
  1091. * When an entry is deleted by a replicated delete operation
  1092. * we must check for entries that have had a naming collision
  1093. * with this entry. Now that this name has been given up, one
  1094. * of those entries can take over the name.
  1095. */
  1096. slapi_pblock_set(pb, SLAPI_URP_NAMING_COLLISION_DN, slapi_ch_strdup (dn));
  1097. }
  1098. if (free_delete_existing_entry) {
  1099. done_with_pblock_entry(pb, SLAPI_DELETE_EXISTING_ENTRY);
  1100. } else { /* owned by someone else */
  1101. slapi_pblock_set(pb, SLAPI_DELETE_EXISTING_ENTRY, NULL);
  1102. }
  1103. backentry_free(&original_tombstone);
  1104. slapi_ch_free((void**)&errbuf);
  1105. slapi_sdn_done(&sdn);
  1106. slapi_sdn_done(&nscpEntrySDN);
  1107. slapi_ch_free_string(&e_uniqueid);
  1108. if (pb->pb_conn)
  1109. {
  1110. slapi_log_error (SLAPI_LOG_TRACE, "ldbm_back_delete", "leave conn=%" NSPRIu64 " op=%d\n", pb->pb_conn->c_connid, operation->o_opid);
  1111. }
  1112. return rc;
  1113. }