urp_tombstone.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  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. * All rights reserved.
  37. * END COPYRIGHT BLOCK **/
  38. /*
  39. * urp_tombstone.c - Update Resolution Procedures - Tombstones
  40. */
  41. #include "slapi-plugin.h"
  42. #include "repl5.h"
  43. #include "urp.h"
  44. extern int slapi_log_urp;
  45. /*
  46. * Check if the entry is a tombstone.
  47. */
  48. int
  49. is_tombstone_entry(const Slapi_Entry* entry)
  50. {
  51. int flag;
  52. /* LP: This doesn't work very well with entries that we tombstone ourself */
  53. flag = slapi_entry_flag_is_set (entry, SLAPI_ENTRY_FLAG_TOMBSTONE);
  54. if (flag == 0)
  55. {
  56. /* This is slow */
  57. flag = slapi_entry_attr_hasvalue(entry, SLAPI_ATTR_OBJECTCLASS, SLAPI_ATTR_VALUE_TOMBSTONE);
  58. }
  59. return flag;
  60. }
  61. PRBool
  62. get_tombstone_csn(const Slapi_Entry *entry, const CSN **delcsn)
  63. {
  64. PRBool ists = PR_FALSE;
  65. if (is_tombstone_entry(entry)) {
  66. ists = PR_TRUE;
  67. *delcsn = _get_deletion_csn((Slapi_Entry *)entry); /* cast away const */
  68. }
  69. return ists;
  70. }
  71. static int
  72. tombstone_to_glue_resolve_parent (
  73. Slapi_PBlock *pb,
  74. const char *sessionid,
  75. const Slapi_DN *parentdn,
  76. const char *parentuniqueid,
  77. CSN *opcsn)
  78. {
  79. /* Let's have a look at the parent of this entry... */
  80. if(!slapi_sdn_isempty(parentdn) && parentuniqueid!=NULL)
  81. {
  82. int op_result;
  83. Slapi_PBlock *newpb= slapi_pblock_new();
  84. slapi_search_internal_set_pb(
  85. newpb,
  86. slapi_sdn_get_dn(parentdn), /* JCM - This DN just identifies the backend to be searched. */
  87. LDAP_SCOPE_BASE,
  88. "objectclass=*",
  89. NULL, /*attrs*/
  90. 0, /*attrsonly*/
  91. NULL, /*Controls*/
  92. parentuniqueid, /*uniqueid*/
  93. repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION),
  94. 0);
  95. slapi_search_internal_pb(newpb);
  96. slapi_pblock_get(newpb, SLAPI_PLUGIN_INTOP_RESULT, &op_result);
  97. switch(op_result)
  98. {
  99. case LDAP_SUCCESS:
  100. {
  101. Slapi_Entry **entries= NULL;
  102. /* OK, the tombstone entry parent exists. Is it also a tombstone? */
  103. slapi_pblock_get(newpb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
  104. if(entries!=NULL && entries[0]!=NULL)
  105. {
  106. if(is_tombstone_entry(entries[0]))
  107. {
  108. tombstone_to_glue (pb, sessionid, entries[0], parentdn, REASON_RESURRECT_ENTRY, opcsn);
  109. }
  110. }
  111. else
  112. {
  113. /* JCM - Couldn't find the entry! */
  114. }
  115. }
  116. break;
  117. default:
  118. /* So, the tombstone entry had a parent... but it's gone. */
  119. /* That's probably a bad thing. */
  120. break;
  121. }
  122. slapi_free_search_results_internal (newpb);
  123. slapi_pblock_destroy(newpb);
  124. }
  125. return 0;
  126. }
  127. /*
  128. * Convert a tombstone into a glue entry.
  129. */
  130. int
  131. tombstone_to_glue (
  132. Slapi_PBlock *pb,
  133. const char *sessionid,
  134. Slapi_Entry *tombstoneentry,
  135. const Slapi_DN *tombstonedn,
  136. const char *reason,
  137. CSN *opcsn)
  138. {
  139. Slapi_DN *parentdn;
  140. char *parentuniqueid;
  141. const char *tombstoneuniqueid;
  142. Slapi_Entry *addingentry;
  143. const char *addingdn;
  144. int op_result;
  145. /* JCMREPL
  146. * Nothing logged to the 5.0 Change Log
  147. * Add is logged to the 4.0 Change Log - Core server Add code
  148. * must attach the entry to the Operation
  149. */
  150. /* Resurrect the parent entry first */
  151. /* JCM - This DN calculation is odd. It could resolve to NULL
  152. * which won't help us identify the correct backend to search.
  153. */
  154. is_suffix_dn (pb, tombstonedn, &parentdn);
  155. parentuniqueid= slapi_entry_attr_get_charptr (tombstoneentry,
  156. SLAPI_ATTR_VALUE_PARENT_UNIQUEID); /* Allocated */
  157. tombstone_to_glue_resolve_parent (pb, sessionid, parentdn, parentuniqueid, opcsn);
  158. slapi_sdn_free(&parentdn);
  159. /* Submit an Add operation to turn the tombstone entry into glue. */
  160. /*
  161. * The tombstone is stored with an invalid DN, we must fix this.
  162. */
  163. addingentry = slapi_entry_dup(tombstoneentry);
  164. addingdn = slapi_sdn_get_dn(tombstonedn);
  165. slapi_entry_set_dn(addingentry,slapi_ch_strdup(addingdn)); /* consumes DN */
  166. if (!slapi_entry_attr_hasvalue(addingentry, ATTR_NSDS5_REPLCONFLICT, reason))
  167. {
  168. /* Add the reason of turning it to glue - The backend code will use it*/
  169. slapi_entry_add_string(addingentry, ATTR_NSDS5_REPLCONFLICT, reason);
  170. }
  171. tombstoneuniqueid= slapi_entry_get_uniqueid(tombstoneentry);
  172. op_result = urp_fixup_add_entry (addingentry, tombstoneuniqueid, parentuniqueid, opcsn, OP_FLAG_RESURECT_ENTRY);
  173. if (op_result == LDAP_SUCCESS)
  174. {
  175. slapi_log_error (slapi_log_urp, repl_plugin_name,
  176. "%s: Resurrected tombstone %s to glue reason '%s'\n", sessionid, addingdn, reason);
  177. }
  178. else
  179. {
  180. slapi_log_error (SLAPI_LOG_FATAL, repl_plugin_name,
  181. "%s: Can't resurrect tombstone %s to glue reason '%s', error=%d\n",
  182. sessionid, addingdn, reason, op_result);
  183. }
  184. slapi_entry_free (addingentry);
  185. return op_result;
  186. }
  187. int
  188. entry_to_tombstone ( Slapi_PBlock *pb, Slapi_Entry *entry )
  189. {
  190. Slapi_Operation *op;
  191. Slapi_Mods smods;
  192. CSN *opcsn;
  193. const char *uniqueid;
  194. int op_result = LDAP_SUCCESS;
  195. slapi_pblock_get ( pb, SLAPI_OPERATION, &op );
  196. opcsn = operation_get_csn ( op );
  197. uniqueid = slapi_entry_get_uniqueid ( entry );
  198. slapi_mods_init ( &smods, 2 );
  199. /* Remove objectclass=glue */
  200. slapi_mods_add ( &smods, LDAP_MOD_DELETE, SLAPI_ATTR_OBJECTCLASS, strlen("glue"), "glue");
  201. /* Remove any URP conflict since a tombstone shouldn't
  202. * be retrieved later for conflict removal.
  203. */
  204. slapi_mods_add ( &smods, LDAP_MOD_DELETE, ATTR_NSDS5_REPLCONFLICT, 0, NULL );
  205. op_result = urp_fixup_modify_entry (uniqueid, slapi_entry_get_dn_const (entry), opcsn, &smods, 0);
  206. slapi_mods_done ( &smods );
  207. /*
  208. * Delete the entry.
  209. */
  210. if ( op_result == LDAP_SUCCESS )
  211. {
  212. /*
  213. * Using internal delete operation since it would go
  214. * through the urp operations and trigger the recursive
  215. * fixup if applicable.
  216. */
  217. op_result = urp_fixup_delete_entry (uniqueid, slapi_entry_get_dn_const (entry), opcsn, 0);
  218. }
  219. return op_result;
  220. }