urp.c 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430
  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. #ifdef HAVE_CONFIG_H
  39. # include <config.h>
  40. #endif
  41. /*
  42. * urp.c - Update Resolution Procedures
  43. */
  44. #include "slapi-plugin.h"
  45. #include "repl.h"
  46. #include "repl5.h"
  47. #include "urp.h"
  48. extern int slapi_log_urp;
  49. static int urp_add_resolve_parententry (Slapi_PBlock *pb, char *sessionid, Slapi_Entry *entry, Slapi_Entry *parententry, CSN *opcsn);
  50. static int urp_annotate_dn (char *sessionid, const Slapi_Entry *entry, CSN *opcsn, const char *optype);
  51. static int urp_naming_conflict_removal (Slapi_PBlock *pb, char *sessionid, CSN *opcsn, const char *optype);
  52. static int mod_namingconflict_attr (const char *uniqueid, const Slapi_DN *entrysdn, const Slapi_DN *conflictsdn, CSN *opcsn, const char *optype);
  53. static int del_replconflict_attr (const Slapi_Entry *entry, CSN *opcsn, int opflags);
  54. static char *get_dn_plus_uniqueid(char *sessionid,const Slapi_DN *oldsdn,const char *uniqueid);
  55. static int is_suffix_entry (Slapi_PBlock *pb, Slapi_Entry *entry, Slapi_DN **parenddn);
  56. /*
  57. * Return 0 for OK, -1 for Error.
  58. */
  59. int
  60. urp_modify_operation( Slapi_PBlock *pb )
  61. {
  62. Slapi_Entry *modifyentry= NULL;
  63. int op_result= 0;
  64. int rc= 0; /* OK */
  65. char sessionid[REPL_SESSION_ID_SIZE];
  66. CSN *opcsn;
  67. if ( slapi_op_abandoned(pb) )
  68. {
  69. return rc;
  70. }
  71. get_repl_session_id (pb, sessionid, &opcsn);
  72. slapi_pblock_get( pb, SLAPI_MODIFY_EXISTING_ENTRY, &modifyentry );
  73. if(modifyentry!=NULL)
  74. {
  75. /*
  76. * The entry to be modified exists.
  77. * - the entry could be a tombstone... but that's OK.
  78. * - the entry could be glue... that may not be OK. JCMREPL
  79. */
  80. rc= 0; /* OK, Modify the entry */
  81. PROFILE_POINT; /* Modify Conflict; Entry Exists; Apply Modification */
  82. }
  83. else
  84. {
  85. /*
  86. * The entry to be modified could not be found.
  87. */
  88. op_result= LDAP_NO_SUCH_OBJECT;
  89. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
  90. rc = SLAPI_PLUGIN_NOOP; /* Must discard this Modification */
  91. slapi_log_error (slapi_log_urp, sessionid,
  92. "urp_modify: No such entry\n");
  93. PROFILE_POINT; /* Modify Conflict; Entry Does Not Exist; Discard Modification */
  94. }
  95. return rc;
  96. }
  97. /*
  98. * Return 0 for OK,
  99. * -1 for Ignore or Error depending on SLAPI_RESULT_CODE,
  100. * >0 for action code
  101. * Action Code Bit 0: Fetch existing entry.
  102. * Action Code Bit 1: Fetch parent entry.
  103. * The function is called as a be pre-op on consumers.
  104. */
  105. int
  106. urp_add_operation( Slapi_PBlock *pb )
  107. {
  108. Slapi_Entry *existing_uniqueid_entry;
  109. Slapi_Entry *existing_dn_entry;
  110. Slapi_Entry *addentry;
  111. const char *adduniqueid;
  112. CSN *opcsn;
  113. const char *basedn;
  114. char sessionid[REPL_SESSION_ID_SIZE];
  115. int r;
  116. int op_result= 0;
  117. int rc= 0; /* OK */
  118. Slapi_DN *sdn = NULL;
  119. if ( slapi_op_abandoned(pb) )
  120. {
  121. return rc;
  122. }
  123. get_repl_session_id (pb, sessionid, &opcsn);
  124. slapi_pblock_get( pb, SLAPI_ADD_EXISTING_UNIQUEID_ENTRY, &existing_uniqueid_entry );
  125. if (existing_uniqueid_entry!=NULL)
  126. {
  127. /*
  128. * An entry with this uniqueid already exists.
  129. * - It could be a replay of the same Add, or
  130. * - It could be a UUID generation collision, or
  131. */
  132. /*
  133. * This operation won't be replayed. That is, this CSN won't update
  134. * the max csn in RUV. The CSN is left uncommitted in RUV unless an
  135. * error is set to op_result. Just to get rid of this CSN from RUV,
  136. * setting an error to op_result
  137. */
  138. /* op_result = LDAP_SUCCESS; */
  139. slapi_log_error(slapi_log_urp, sessionid,
  140. "urp_add (%s): an entry with this uniqueid already exists.\n",
  141. slapi_entry_get_dn_const(existing_uniqueid_entry));
  142. op_result= LDAP_UNWILLING_TO_PERFORM;
  143. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
  144. rc = SLAPI_PLUGIN_NOOP; /* Ignore this Operation */
  145. PROFILE_POINT; /* Add Conflict; UniqueID Exists; Ignore */
  146. goto bailout;
  147. }
  148. slapi_pblock_get( pb, SLAPI_ADD_ENTRY, &addentry );
  149. slapi_pblock_get( pb, SLAPI_ADD_EXISTING_DN_ENTRY, &existing_dn_entry );
  150. if (existing_dn_entry==NULL) /* The target DN does not exist */
  151. {
  152. /* Check for parent entry... this could be an orphan. */
  153. Slapi_Entry *parententry;
  154. slapi_pblock_get( pb, SLAPI_ADD_PARENT_ENTRY, &parententry );
  155. rc = urp_add_resolve_parententry (pb, sessionid, addentry, parententry, opcsn);
  156. PROFILE_POINT; /* Add Entry */
  157. goto bailout;
  158. }
  159. /*
  160. * Naming conflict: an entry with the target DN already exists.
  161. * Compare the DistinguishedNameCSN of the existing entry
  162. * and the OperationCSN. The smaller CSN wins. The loser changes
  163. * its RDN to uniqueid+baserdn, and adds operational attribute
  164. * ATTR_NSDS5_REPLCONFLIC.
  165. */
  166. basedn = slapi_entry_get_ndn (addentry);
  167. adduniqueid = slapi_entry_get_uniqueid (addentry);
  168. r = csn_compare (entry_get_dncsn(existing_dn_entry), opcsn);
  169. if (r<0)
  170. {
  171. /* Entry to be added is a loser */
  172. char *newdn= get_dn_plus_uniqueid (sessionid, (const Slapi_DN *)addentry, adduniqueid);
  173. if(newdn==NULL)
  174. {
  175. op_result= LDAP_OPERATIONS_ERROR;
  176. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
  177. rc = SLAPI_PLUGIN_NOOP; /* Abort this Operation */
  178. slapi_log_error(slapi_log_urp, sessionid,
  179. "urp_add (%s): Add conflict; Unique ID (%s) already in RDN\n",
  180. basedn, adduniqueid);
  181. PROFILE_POINT; /* Add Conflict; Entry Exists; Unique ID already in RDN - Abort this update. */
  182. }
  183. else
  184. {
  185. /* Add the nsds5ReplConflict attribute in the mods */
  186. Slapi_Attr *attr = NULL;
  187. Slapi_Value **vals = NULL;
  188. Slapi_RDN *rdn;
  189. char buf[BUFSIZ];
  190. #ifdef DEBUG
  191. PR_snprintf(buf, BUFSIZ, "%s (add) %s", REASON_ANNOTATE_DN, basedn);
  192. #else
  193. PR_snprintf(buf, BUFSIZ, "%s %s", REASON_ANNOTATE_DN, basedn);
  194. #endif
  195. if (slapi_entry_attr_find (addentry, ATTR_NSDS5_REPLCONFLICT, &attr) == 0)
  196. {
  197. /* ATTR_NSDS5_REPLCONFLICT exists */
  198. slapi_log_error(SLAPI_LOG_FATAL, sessionid,
  199. "urp_add: New entry has nsds5ReplConflict already\n");
  200. vals = attr_get_present_values (attr); /* this returns a pointer to the contents */
  201. }
  202. if ( vals == NULL || *vals == NULL )
  203. {
  204. /* Add new attribute */
  205. slapi_entry_add_string (addentry, ATTR_NSDS5_REPLCONFLICT, buf);
  206. }
  207. else
  208. {
  209. /*
  210. * Replace old attribute. We don't worry about the index
  211. * change here since the entry is yet to be added.
  212. */
  213. slapi_value_set_string (*vals, buf);
  214. }
  215. /* slapi_pblock_get(pb, SLAPI_ADD_TARGET, &dn); */
  216. slapi_pblock_get(pb, SLAPI_ADD_TARGET_SDN, &sdn);
  217. slapi_sdn_free(&sdn);
  218. slapi_entry_set_normdn(addentry, newdn); /* dn: passin */
  219. sdn = slapi_sdn_dup(slapi_entry_get_sdn_const(addentry));
  220. slapi_pblock_set(pb, SLAPI_ADD_TARGET_SDN, sdn);
  221. rdn = slapi_rdn_new_sdn ( slapi_entry_get_sdn_const(addentry) );
  222. slapi_log_error (slapi_log_urp, sessionid,
  223. "urp_add: Naming conflict ADD. Add %s instead\n",
  224. slapi_rdn_get_rdn(rdn));
  225. slapi_rdn_free(&rdn);
  226. rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_DN_ENTRY);
  227. PROFILE_POINT; /* Add Conflict; Entry Exists; Rename Operation Entry */
  228. }
  229. }
  230. else if(r>0)
  231. {
  232. /* Existing entry is a loser */
  233. if (!urp_annotate_dn(sessionid, existing_dn_entry, opcsn, "ADD"))
  234. {
  235. op_result= LDAP_OPERATIONS_ERROR;
  236. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
  237. slapi_log_error(slapi_log_urp, sessionid,
  238. "urp_add (%s): Entry to be added is a loser; "
  239. "urp_annotate_dn failed.\n", basedn);
  240. rc = SLAPI_PLUGIN_NOOP; /* Ignore this Operation */
  241. }
  242. else
  243. {
  244. /* The backend add code should now search for the existing entry again. */
  245. rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_DN_ENTRY);
  246. rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_PARENT_ENTRY);
  247. }
  248. PROFILE_POINT; /* Add Conflict; Entry Exists; Rename Existing Entry */
  249. }
  250. else /* r==0 */
  251. {
  252. /* The CSN of the Operation and the Entry DN are the same.
  253. * This could only happen if:
  254. * a) There are two replicas with the same ReplicaID.
  255. * b) We've seen the Operation before.
  256. * Let's go with (b) and ignore the little bastard.
  257. */
  258. /*
  259. * This operation won't be replayed. That is, this CSN won't update
  260. * the max csn in RUV. The CSN is left uncommitted in RUV unless an
  261. * error is set to op_result. Just to get rid of this CSN from RUV,
  262. * setting an error to op_result
  263. */
  264. /* op_result = LDAP_SUCCESS; */
  265. slapi_log_error(slapi_log_urp, sessionid,
  266. "urp_add (%s): The CSN of the Operation and the Entry DN are the same.",
  267. slapi_entry_get_dn_const(existing_dn_entry));
  268. op_result= LDAP_UNWILLING_TO_PERFORM;
  269. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
  270. rc = SLAPI_PLUGIN_NOOP; /* Ignore this Operation */
  271. PROFILE_POINT; /* Add Conflict; Entry Exists; Same CSN */
  272. }
  273. bailout:
  274. return rc;
  275. }
  276. /*
  277. * Return 0 for OK, -1 for Error, >0 for action code
  278. * Action Code Bit 0: Fetch existing entry.
  279. * Action Code Bit 1: Fetch parent entry.
  280. */
  281. int
  282. urp_modrdn_operation( Slapi_PBlock *pb )
  283. {
  284. slapi_operation_parameters *op_params = NULL;
  285. Slapi_Entry *parent_entry;
  286. Slapi_Entry *new_parent_entry;
  287. Slapi_DN *newsuperior = NULL;
  288. Slapi_DN *parentdn = NULL;
  289. const Slapi_Entry *target_entry;
  290. Slapi_Entry *existing_entry;
  291. const CSN *target_entry_dncsn;
  292. CSN *opcsn= NULL;
  293. char *op_uniqueid = NULL;
  294. const char *existing_uniqueid = NULL;
  295. const Slapi_DN *target_sdn;
  296. const Slapi_DN *existing_sdn;
  297. char *newrdn;
  298. char sessionid[REPL_SESSION_ID_SIZE];
  299. int r;
  300. int op_result= 0;
  301. int rc= 0; /* OK */
  302. int del_old_replconflict_attr = 0;
  303. if ( slapi_op_abandoned(pb) )
  304. {
  305. return rc;
  306. }
  307. slapi_pblock_get (pb, SLAPI_MODRDN_TARGET_ENTRY, &target_entry);
  308. if(target_entry==NULL)
  309. {
  310. /* An entry can't be found for the Unique Identifier */
  311. op_result= LDAP_NO_SUCH_OBJECT;
  312. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
  313. rc= -1; /* No entry to modrdn */
  314. PROFILE_POINT; /* ModRDN Conflict; Entry does not Exist; Discard ModRDN */
  315. goto bailout;
  316. }
  317. get_repl_session_id (pb, sessionid, &opcsn);
  318. target_entry_dncsn = entry_get_dncsn (target_entry);
  319. if ( csn_compare (target_entry_dncsn, opcsn) >= 0 )
  320. {
  321. /*
  322. * The Operation CSN is not newer than the DN CSN.
  323. * Either we're beaten by another ModRDN or we've applied the op.
  324. */
  325. /* op_result= LDAP_SUCCESS; */
  326. /*
  327. * This operation won't be replayed. That is, this CSN won't update
  328. * the max csn in RUV. The CSN is left uncommitted in RUV unless an
  329. * error is set to op_result. Just to get rid of this CSN from RUV,
  330. * setting an error to op_result
  331. */
  332. slapi_log_error(slapi_log_urp, sessionid,
  333. "urp_modrdn (%s): operation CSN is newer than the DN CSN.\n",
  334. slapi_entry_get_dn_const(target_entry));
  335. op_result= LDAP_UNWILLING_TO_PERFORM;
  336. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
  337. rc = SLAPI_PLUGIN_NOOP; /* Ignore the modrdn */
  338. PROFILE_POINT; /* ModRDN Conflict; Entry with Target DN Exists; OPCSN is not newer. */
  339. goto bailout;
  340. }
  341. /* The DN CSN is older than the Operation CSN. Apply the operation */
  342. target_sdn = slapi_entry_get_sdn_const (target_entry);
  343. /* newrdn is no need to be case-ignored (get_rdn_plus_uniqueid) */
  344. slapi_pblock_get(pb, SLAPI_MODRDN_NEWRDN, &newrdn);
  345. slapi_pblock_get(pb, SLAPI_TARGET_UNIQUEID, &op_uniqueid);
  346. slapi_pblock_get(pb, SLAPI_MODRDN_PARENT_ENTRY, &parent_entry);
  347. slapi_pblock_get(pb, SLAPI_MODRDN_NEWPARENT_ENTRY, &new_parent_entry);
  348. slapi_pblock_get(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &newsuperior);
  349. if ( is_tombstone_entry (target_entry) )
  350. {
  351. /*
  352. * It is a non-trivial task to rename a tombstone.
  353. * This op has been ignored so far by
  354. * setting SLAPI_RESULT_CODE to LDAP_NO_SUCH_OBJECT
  355. * and rc to -1.
  356. */
  357. /* Turn the tombstone to glue before rename it */
  358. /*
  359. op_result = tombstone_to_glue (pb, sessionid, target_entry,
  360. slapi_entry_get_sdn (target_entry), "renameTombstone", opcsn);
  361. */
  362. op_result = LDAP_NO_SUCH_OBJECT;
  363. slapi_log_error(SLAPI_LOG_REPL, sessionid,
  364. "urp_modrdn: target_entry %s is a tombstone; returning LDAP_NO_SUCH_OBJECT.\n",
  365. slapi_entry_get_dn((Slapi_Entry *)target_entry));
  366. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
  367. if (op_result == 0)
  368. {
  369. /*
  370. * Remember to turn this entry back to tombstone in post op.
  371. * We'll just borrow an obsolete pblock type here.
  372. */
  373. slapi_pblock_set (pb, SLAPI_URP_TOMBSTONE_UNIQUEID, slapi_ch_strdup(op_uniqueid));
  374. rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_TARGET_ENTRY);
  375. rc = 0;
  376. }
  377. else
  378. {
  379. slapi_log_error(slapi_log_urp, sessionid,
  380. "urp_modrdn (%s): target entry is a tombstone.\n",
  381. slapi_entry_get_dn_const(target_entry));
  382. rc = SLAPI_PLUGIN_NOOP; /* Ignore the modrdn */
  383. }
  384. PROFILE_POINT; /* ModRDN Conflict; Entry with Target DN Exists; OPCSN is not newer. */
  385. goto bailout;
  386. }
  387. slapi_pblock_get(pb, SLAPI_MODRDN_EXISTING_ENTRY, &existing_entry);
  388. if(existing_entry!=NULL)
  389. {
  390. /*
  391. * An entry with the target DN already exists.
  392. * The smaller dncsn wins. The loser changes its RDN to
  393. * uniqueid+baserdn, and adds operational attribute
  394. * ATTR_NSDS5_REPLCONFLIC
  395. */
  396. existing_uniqueid = slapi_entry_get_uniqueid (existing_entry);
  397. existing_sdn = slapi_entry_get_sdn_const ( existing_entry);
  398. /*
  399. * It used to dismiss the operation if the existing entry is
  400. * the same as the target one.
  401. * But renaming the RDN with the one which only cases are different,
  402. * cn=ABC --> cn=Abc, this case matches. We should go forward the op.
  403. */
  404. if (strcmp(op_uniqueid, existing_uniqueid) == 0) {
  405. op_result= LDAP_SUCCESS;
  406. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
  407. rc = 0; /* Don't ignore the op */
  408. PROFILE_POINT; /* ModRDN Replay */
  409. goto bailout;
  410. }
  411. r= csn_compare ( entry_get_dncsn (existing_entry), opcsn);
  412. if (r == 0)
  413. {
  414. /*
  415. * The CSN of the Operation and the Entry DN are the same
  416. * but the uniqueids are not.
  417. * There might be two replicas with the same ReplicaID.
  418. */
  419. slapi_log_error(slapi_log_urp, sessionid,
  420. "urp_modrdn: Duplicated CSN for different uniqueids [%s][%s]",
  421. existing_uniqueid, op_uniqueid);
  422. op_result= LDAP_OPERATIONS_ERROR;
  423. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
  424. rc = SLAPI_PLUGIN_NOOP; /* Ignore this Operation */
  425. PROFILE_POINT; /* ModRDN Conflict; Duplicated CSN for Different Entries */
  426. goto bailout;
  427. }
  428. if(r<0)
  429. {
  430. /* The target entry is a loser */
  431. char *newrdn_with_uniqueid;
  432. newrdn_with_uniqueid= get_rdn_plus_uniqueid (sessionid, newrdn, op_uniqueid);
  433. if(newrdn_with_uniqueid==NULL)
  434. {
  435. op_result= LDAP_OPERATIONS_ERROR;
  436. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
  437. rc= -1; /* Ignore this Operation */
  438. PROFILE_POINT; /* ModRDN Conflict; Entry with Target DN Exists;
  439. Unique ID already in RDN - Change to Lost and Found entry */
  440. goto bailout;
  441. }
  442. mod_namingconflict_attr (op_uniqueid, target_sdn, existing_sdn, opcsn, "MODRDN");
  443. slapi_pblock_set(pb, SLAPI_MODRDN_NEWRDN, newrdn_with_uniqueid);
  444. slapi_log_error(slapi_log_urp, sessionid,
  445. "urp_modrdn: Naming conflict MODRDN. Rename target entry from %s to %s\n",
  446. newrdn, newrdn_with_uniqueid );
  447. rc= slapi_setbit_int(rc, SLAPI_RTN_BIT_FETCH_EXISTING_DN_ENTRY);
  448. PROFILE_POINT; /* ModRDN Conflict; Entry with Target DN Exists; Rename Operation Entry */
  449. goto bailout;
  450. }
  451. if ( r>0 )
  452. {
  453. /* The existing entry is a loser */
  454. int resolve = urp_annotate_dn (sessionid, existing_entry, opcsn, "MODRDN");
  455. if(!resolve)
  456. {
  457. op_result= LDAP_OPERATIONS_ERROR;
  458. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
  459. rc= -1; /* Abort this Operation */
  460. goto bailout;
  461. }
  462. rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_DN_ENTRY);
  463. rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_NEWPARENT_ENTRY);
  464. if (LDAP_NO_SUCH_OBJECT == resolve) {
  465. /* This means that existing_dn_entry did not really exist!!!
  466. * This indicates that a get_copy_of_entry -> dn2entry returned
  467. * an entry (existing_dn_entry) that was already removed from the ldbm.
  468. * This is bad, because it indicates a dn cache or DB corruption.
  469. * However, as far as the conflict is concerned, this error is harmless:
  470. * if the existing_dn_entry did not exist in the first place, there was no
  471. * conflict!! Return 0 for success to break the ldbm_back_modrdn loop
  472. * and get out of this inexistent conflict resolution ASAP.
  473. */
  474. rc = 0;
  475. }
  476. /* Set flag to remove possible old naming conflict */
  477. del_old_replconflict_attr = 1;
  478. PROFILE_POINT; /* ModRDN Conflict; Entry with Target DN Exists; Rename Entry with Target DN */
  479. goto bailout;
  480. }
  481. }
  482. else
  483. {
  484. /*
  485. * No entry with the target DN exists.
  486. */
  487. /* Set flag to remove possible old naming conflict */
  488. del_old_replconflict_attr = 1;
  489. if(new_parent_entry!=NULL)
  490. {
  491. /* The new superior entry exists */
  492. rc= 0; /* OK, Apply the ModRDN */
  493. PROFILE_POINT; /* ModRDN Conflict; OK */
  494. goto bailout;
  495. }
  496. /* The new superior entry doesn't exist */
  497. slapi_pblock_get(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &newsuperior);
  498. if(newsuperior == NULL)
  499. {
  500. /* (new_parent_entry==NULL && newsuperiordn==NULL)
  501. * This is ok - SLAPI_MODRDN_NEWPARENT_ENTRY will
  502. * only be set if SLAPI_MODRDN_NEWSUPERIOR_SDN was
  503. * suplied by the client. If it wasn't, we're just
  504. * changing the RDN of the entry. In that case,
  505. * if the entry exists, its parent won't change
  506. * when it's renamed, and therefore we can assume
  507. * its parent exists.
  508. */
  509. rc=0;
  510. PROFILE_POINT; /* ModRDN OK */
  511. goto bailout;
  512. }
  513. if((0 == slapi_sdn_compare(slapi_entry_get_sdn(parent_entry),
  514. newsuperior)) ||
  515. is_suffix_dn (pb, newsuperior, &parentdn) )
  516. {
  517. /*
  518. * The new superior is the same as the current one, or
  519. * this entry is a suffix whose parent can be absent.
  520. */
  521. rc= 0; /* OK, Move the entry */
  522. PROFILE_POINT; /* ModRDN Conflict; Absent Target Parent; Create Suffix Entry */
  523. goto bailout;
  524. }
  525. /*
  526. * This entry is not a suffix entry, so the parent entry should exist.
  527. * (This shouldn't happen in a ds5 server)
  528. */
  529. slapi_pblock_get ( pb, SLAPI_OPERATION_PARAMETERS, &op_params );
  530. op_result = create_glue_entry (pb, sessionid, newsuperior,
  531. op_params->p.p_modrdn.modrdn_newsuperior_address.uniqueid, opcsn);
  532. if (LDAP_SUCCESS != op_result)
  533. {
  534. /*
  535. * FATAL ERROR
  536. * We should probably just abort the rename
  537. * this will cause replication divergence requiring
  538. * admin intercession
  539. */
  540. slapi_log_error( SLAPI_LOG_FATAL, sessionid,
  541. "urp_modrdn: Parent %s couldn't be found, nor recreated as a glue entry\n",
  542. slapi_sdn_get_dn(newsuperior) );
  543. op_result= LDAP_OPERATIONS_ERROR;
  544. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
  545. rc = SLAPI_PLUGIN_FAILURE; /* Ignore this Operation */
  546. PROFILE_POINT;
  547. goto bailout;
  548. }
  549. /* The backend add code should now search for the parent again. */
  550. rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_NEWPARENT_ENTRY);
  551. PROFILE_POINT; /* ModRDN Conflict; Absent Target Parent - Change to Lost and Found entry */
  552. goto bailout;
  553. }
  554. bailout:
  555. if ( del_old_replconflict_attr && rc == 0 )
  556. {
  557. del_replconflict_attr (target_entry, opcsn, 0);
  558. }
  559. if ( parentdn )
  560. slapi_sdn_free(&parentdn);
  561. return rc;
  562. }
  563. /*
  564. * Return 0 for OK, -1 for Error
  565. */
  566. int
  567. urp_delete_operation( Slapi_PBlock *pb )
  568. {
  569. const Slapi_Entry *deleteentry;
  570. CSN *opcsn= NULL;
  571. char sessionid[REPL_SESSION_ID_SIZE];
  572. int op_result= 0;
  573. int rc = SLAPI_PLUGIN_SUCCESS; /* OK */
  574. if ( slapi_op_abandoned(pb) )
  575. {
  576. return rc;
  577. }
  578. slapi_pblock_get(pb, SLAPI_DELETE_EXISTING_ENTRY, &deleteentry);
  579. get_repl_session_id (pb, sessionid, &opcsn);
  580. if(deleteentry==NULL) /* uniqueid can't be found */
  581. {
  582. op_result= LDAP_NO_SUCH_OBJECT;
  583. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
  584. rc = SLAPI_PLUGIN_FAILURE; /* Don't apply the Delete */
  585. slapi_log_error(slapi_log_urp, sessionid,
  586. "Entry %s does not exist; returning NO_SUCH_OBJECT.\n",
  587. slapi_entry_get_dn((Slapi_Entry *)deleteentry));
  588. PROFILE_POINT; /* Delete Operation; Entry not exist. */
  589. }
  590. else if(is_tombstone_entry(deleteentry))
  591. {
  592. /* The entry is already a Tombstone, ignore this delete. */
  593. op_result= LDAP_ALREADY_EXISTS;
  594. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
  595. rc = SLAPI_PLUGIN_NOOP; /* Don't apply the Delete */
  596. slapi_log_error(slapi_log_urp, sessionid,
  597. "urp_delete: Entry \"%s\" is already a Tombstone.\n",
  598. slapi_entry_get_dn_const(deleteentry));
  599. PROFILE_POINT; /* Delete Operation; Already a Tombstone. */
  600. }
  601. else /* The entry to be deleted exists and is not a tombstone */
  602. {
  603. get_repl_session_id (pb, sessionid, &opcsn);
  604. /* Check if the entry has children. */
  605. if(!slapi_entry_has_children(deleteentry))
  606. {
  607. /* Remove possible conflict attributes */
  608. del_replconflict_attr (deleteentry, opcsn, 0);
  609. rc = SLAPI_PLUGIN_SUCCESS; /* OK, to delete the entry */
  610. PROFILE_POINT; /* Delete Operation; OK. */
  611. }
  612. else
  613. {
  614. /* Turn this entry into a glue_absent_parent entry */
  615. entry_to_glue(sessionid, deleteentry, REASON_RESURRECT_ENTRY, opcsn);
  616. /* Turn the Delete into a No-Op */
  617. op_result= LDAP_SUCCESS;
  618. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
  619. rc = SLAPI_PLUGIN_NOOP; /* Don't apply the Delete */
  620. slapi_log_error(slapi_log_urp, sessionid,
  621. "urp_delete: Turn entry \"%s\" into a glue_absent_parent entry.\n",
  622. slapi_entry_get_dn_const(deleteentry));
  623. PROFILE_POINT; /* Delete Operation; Entry has children. */
  624. }
  625. }
  626. return rc;
  627. }
  628. int urp_post_modrdn_operation (Slapi_PBlock *pb)
  629. {
  630. CSN *opcsn;
  631. char sessionid[REPL_SESSION_ID_SIZE];
  632. char *tombstone_uniqueid;
  633. Slapi_Entry *postentry;
  634. Slapi_Operation *op;
  635. /*
  636. * Do not abandon the post op - the processed CSN needs to be
  637. * committed to keep the consistency between the changelog
  638. * and the backend DB.
  639. * if ( slapi_op_abandoned(pb) ) return 0;
  640. */
  641. slapi_pblock_get (pb, SLAPI_URP_TOMBSTONE_UNIQUEID, &tombstone_uniqueid );
  642. if (tombstone_uniqueid == NULL)
  643. {
  644. /*
  645. * The entry is not resurrected from tombstone. Hence
  646. * we need to check if any naming conflict with its
  647. * old dn can be resolved.
  648. */
  649. slapi_pblock_get( pb, SLAPI_OPERATION, &op);
  650. if (!operation_is_flag_set(op, OP_FLAG_REPL_FIXUP))
  651. {
  652. get_repl_session_id (pb, sessionid, &opcsn);
  653. urp_naming_conflict_removal (pb, sessionid, opcsn, "MODRDN");
  654. }
  655. }
  656. else
  657. {
  658. /*
  659. * The entry was a resurrected tombstone.
  660. * This could happen when we applied a rename
  661. * to a tombstone to avoid server divergence. Now
  662. * it's time to put the entry back to tombstone.
  663. */
  664. slapi_pblock_get ( pb, SLAPI_ENTRY_POST_OP, &postentry );
  665. if (postentry && strcmp(tombstone_uniqueid, slapi_entry_get_uniqueid(postentry)) == 0)
  666. {
  667. entry_to_tombstone (pb, postentry);
  668. }
  669. slapi_ch_free ((void**)&tombstone_uniqueid);
  670. slapi_pblock_set (pb, SLAPI_URP_TOMBSTONE_UNIQUEID, NULL);
  671. }
  672. return 0;
  673. }
  674. /*
  675. * Conflict removal
  676. */
  677. int
  678. urp_post_delete_operation( Slapi_PBlock *pb )
  679. {
  680. Slapi_Operation *op;
  681. Slapi_Entry *entry;
  682. CSN *opcsn;
  683. char sessionid[REPL_SESSION_ID_SIZE];
  684. int op_result;
  685. /*
  686. * Do not abandon the post op - the processed CSN needs to be
  687. * committed to keep the consistency between the changelog
  688. * and the backend DB
  689. * if ( slapi_op_abandoned(pb) ) return 0;
  690. */
  691. get_repl_session_id (pb, sessionid, &opcsn);
  692. /*
  693. * Conflict removal from the parent entry:
  694. * If the parent is glue and has no more children,
  695. * turn the parent to tombstone
  696. */
  697. slapi_pblock_get ( pb, SLAPI_DELETE_GLUE_PARENT_ENTRY, &entry );
  698. if ( entry != NULL )
  699. {
  700. op_result = entry_to_tombstone ( pb, entry );
  701. if ( op_result == LDAP_SUCCESS )
  702. {
  703. slapi_log_error ( slapi_log_urp, sessionid,
  704. "Tombstoned glue entry %s since it has no more children\n",
  705. slapi_entry_get_dn_const (entry) );
  706. }
  707. }
  708. slapi_pblock_get( pb, SLAPI_OPERATION, &op);
  709. if (!operation_is_flag_set(op, OP_FLAG_REPL_FIXUP))
  710. {
  711. /*
  712. * Conflict removal from the peers of the old dn
  713. */
  714. urp_naming_conflict_removal (pb, sessionid, opcsn, "DEL");
  715. }
  716. return 0;
  717. }
  718. int
  719. urp_fixup_add_entry (Slapi_Entry *e, const char *target_uniqueid, const char *parentuniqueid, CSN *opcsn, int opflags)
  720. {
  721. Slapi_PBlock *newpb;
  722. Slapi_Operation *op;
  723. int op_result;
  724. newpb = slapi_pblock_new ();
  725. /*
  726. * Mark this operation as replicated, so that the front end
  727. * doesn't add extra attributes.
  728. */
  729. slapi_add_entry_internal_set_pb (
  730. newpb,
  731. e, /* entry will be consumed */
  732. NULL, /*Controls*/
  733. repl_get_plugin_identity ( PLUGIN_MULTIMASTER_REPLICATION ),
  734. OP_FLAG_REPLICATED | OP_FLAG_REPL_FIXUP | opflags);
  735. if (target_uniqueid)
  736. {
  737. slapi_pblock_set( newpb, SLAPI_TARGET_UNIQUEID, (void*)target_uniqueid);
  738. }
  739. if (parentuniqueid)
  740. {
  741. struct slapi_operation_parameters *op_params;
  742. slapi_pblock_get( newpb, SLAPI_OPERATION_PARAMETERS, &op_params );
  743. op_params->p.p_add.parentuniqueid = (char*)parentuniqueid; /* Consumes parentuniqueid */
  744. }
  745. slapi_pblock_get ( newpb, SLAPI_OPERATION, &op );
  746. operation_set_csn ( op, opcsn );
  747. slapi_add_internal_pb ( newpb );
  748. slapi_pblock_get ( newpb, SLAPI_PLUGIN_INTOP_RESULT, &op_result );
  749. slapi_pblock_destroy ( newpb );
  750. return op_result;
  751. }
  752. int
  753. urp_fixup_rename_entry (const Slapi_Entry *entry, const char *newrdn, const char *parentuniqueid, int opflags)
  754. {
  755. Slapi_PBlock *newpb;
  756. Slapi_Operation *op;
  757. CSN *opcsn;
  758. int op_result;
  759. newpb = slapi_pblock_new();
  760. /*
  761. * Must mark this operation as replicated,
  762. * so that the frontend doesn't add extra attributes.
  763. */
  764. slapi_rename_internal_set_pb_ext (
  765. newpb,
  766. slapi_entry_get_sdn_const (entry),
  767. newrdn, /*NewRDN*/
  768. NULL, /*NewSuperior*/
  769. 0, /* !Delete Old RDNS */
  770. NULL, /*Controls*/
  771. slapi_entry_get_uniqueid (entry), /*uniqueid*/
  772. repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION),
  773. OP_FLAG_REPLICATED | OP_FLAG_REPL_FIXUP | opflags);
  774. /* set operation csn to the entry's dncsn */
  775. opcsn = (CSN *)entry_get_dncsn (entry);
  776. slapi_pblock_get (newpb, SLAPI_OPERATION, &op);
  777. operation_set_csn (op, opcsn);
  778. if (parentuniqueid)
  779. {
  780. struct slapi_operation_parameters *op_params;
  781. slapi_pblock_get( newpb, SLAPI_OPERATION_PARAMETERS, &op_params );
  782. op_params->p.p_modrdn.modrdn_newsuperior_address.uniqueid = (char*)parentuniqueid;
  783. }
  784. slapi_modrdn_internal_pb(newpb);
  785. slapi_pblock_get(newpb, SLAPI_PLUGIN_INTOP_RESULT, &op_result);
  786. slapi_pblock_destroy(newpb);
  787. return op_result;
  788. }
  789. int
  790. urp_fixup_delete_entry (const char *uniqueid, const char *dn, CSN *opcsn, int opflags)
  791. {
  792. Slapi_PBlock *newpb;
  793. Slapi_Operation *op;
  794. int op_result;
  795. newpb = slapi_pblock_new ();
  796. /*
  797. * Mark this operation as replicated, so that the front end
  798. * doesn't add extra attributes.
  799. */
  800. slapi_delete_internal_set_pb (
  801. newpb,
  802. dn,
  803. NULL, /*Controls*/
  804. uniqueid, /*uniqueid*/
  805. repl_get_plugin_identity ( PLUGIN_MULTIMASTER_REPLICATION ),
  806. OP_FLAG_REPLICATED | OP_FLAG_REPL_FIXUP | opflags );
  807. slapi_pblock_get ( newpb, SLAPI_OPERATION, &op );
  808. operation_set_csn ( op, opcsn );
  809. slapi_delete_internal_pb ( newpb );
  810. slapi_pblock_get ( newpb, SLAPI_PLUGIN_INTOP_RESULT, &op_result );
  811. slapi_pblock_destroy ( newpb );
  812. return op_result;
  813. }
  814. int
  815. urp_fixup_modify_entry (const char *uniqueid, const Slapi_DN *sdn, CSN *opcsn, Slapi_Mods *smods, int opflags)
  816. {
  817. Slapi_PBlock *newpb;
  818. Slapi_Operation *op;
  819. int op_result;
  820. newpb = slapi_pblock_new();
  821. slapi_modify_internal_set_pb_ext (
  822. newpb,
  823. sdn,
  824. slapi_mods_get_ldapmods_byref (smods),
  825. NULL, /* Controls */
  826. uniqueid,
  827. repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION),
  828. OP_FLAG_REPLICATED | OP_FLAG_REPL_FIXUP | opflags);
  829. /* set operation csn */
  830. slapi_pblock_get (newpb, SLAPI_OPERATION, &op);
  831. operation_set_csn (op, opcsn);
  832. /* do modify */
  833. slapi_modify_internal_pb (newpb);
  834. slapi_pblock_get (newpb, SLAPI_PLUGIN_INTOP_RESULT, &op_result);
  835. slapi_pblock_destroy(newpb);
  836. return op_result;
  837. }
  838. static int
  839. urp_add_resolve_parententry (Slapi_PBlock *pb, char *sessionid, Slapi_Entry *entry, Slapi_Entry *parententry, CSN *opcsn)
  840. {
  841. Slapi_DN *parentdn = NULL;
  842. Slapi_RDN *add_rdn = NULL;
  843. char *newdn = NULL;
  844. int ldap_rc;
  845. int rc = 0;
  846. Slapi_DN *sdn = NULL;
  847. if( is_suffix_entry (pb, entry, &parentdn) )
  848. {
  849. /* It's OK for the suffix entry's parent to be absent */
  850. rc= 0;
  851. PROFILE_POINT; /* Add Conflict; Suffix Entry */
  852. goto bailout;
  853. }
  854. /* The entry is not a suffix. */
  855. if(parententry==NULL) /* The parent entry was not found. */
  856. {
  857. /* Create a glue entry to stand in for the absent parent */
  858. slapi_operation_parameters *op_params;
  859. slapi_pblock_get( pb, SLAPI_OPERATION_PARAMETERS, &op_params );
  860. ldap_rc = create_glue_entry (pb, sessionid, parentdn, op_params->p.p_add.parentuniqueid, opcsn);
  861. if ( LDAP_SUCCESS == ldap_rc )
  862. {
  863. /* The backend code should now search for the parent again. */
  864. rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_DN_ENTRY);
  865. rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_PARENT_ENTRY);
  866. PROFILE_POINT; /* Add Conflict; Orphaned Entry; Glue Parent */
  867. }
  868. else
  869. {
  870. /*
  871. * Error. The parent can't be created as a glue entry.
  872. * This will cause replication divergence and will
  873. * require admin intercession
  874. */
  875. ldap_rc= LDAP_OPERATIONS_ERROR;
  876. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_rc);
  877. rc= -1; /* Abort this Operation */
  878. PROFILE_POINT; /* Add Conflict; Orphaned Entry; Impossible to create parent; Refuse Change. */
  879. }
  880. goto bailout;
  881. }
  882. if(is_tombstone_entry(parententry)) /* The parent is a tombstone */
  883. {
  884. /* The parent entry must be resurected from the dead. */
  885. /* parentdn retrieved from entry is not tombstone dn. */
  886. ldap_rc = tombstone_to_glue (pb, sessionid, parententry, parentdn, REASON_RESURRECT_ENTRY, opcsn, NULL);
  887. if ( ldap_rc != LDAP_SUCCESS )
  888. {
  889. ldap_rc= LDAP_OPERATIONS_ERROR;
  890. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_rc);
  891. rc = -1; /* Abort the operation */
  892. }
  893. else
  894. {
  895. /* The backend add code should now search for the parent again. */
  896. rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_DN_ENTRY);
  897. rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_PARENT_ENTRY);
  898. }
  899. PROFILE_POINT; /* Add Conflict; Orphaned Entry; Parent Was Tombstone */
  900. goto bailout;
  901. }
  902. /* The parent is healthy */
  903. /* Now we need to check that the parent has the correct DN */
  904. if (slapi_sdn_isparent(slapi_entry_get_sdn(parententry), slapi_entry_get_sdn(entry)))
  905. {
  906. rc= 0; /* OK, Add the entry */
  907. PROFILE_POINT; /* Add Conflict; Parent Exists */
  908. goto bailout;
  909. }
  910. /*
  911. * Parent entry doesn't have a DN parent to the entry.
  912. * This can happen if parententry was renamed due to
  913. * conflict and the child entry was created before
  914. * replication occured. See defect 530942.
  915. * We need to rename the entry to be child of its parent.
  916. */
  917. add_rdn = slapi_rdn_new_dn(slapi_entry_get_dn_const (entry));
  918. newdn = slapi_dn_plus_rdn(slapi_entry_get_dn_const (parententry), slapi_rdn_get_rdn(add_rdn));
  919. slapi_entry_set_normdn ( entry, newdn );
  920. /* slapi_pblock_get(pb, SLAPI_ADD_TARGET, &dn); */
  921. slapi_pblock_get(pb, SLAPI_ADD_TARGET_SDN, &sdn);
  922. slapi_sdn_free(&sdn);
  923. sdn = slapi_sdn_dup(slapi_entry_get_sdn_const(entry));
  924. slapi_pblock_set(pb, SLAPI_ADD_TARGET_SDN, sdn);
  925. slapi_log_error ( slapi_log_urp, sessionid,
  926. "Parent was renamed. Renamed the child to %s\n", newdn );
  927. rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_DN_ENTRY);
  928. PROFILE_POINT; /* Add Conflict; Parent Renamed; Rename Operation Entry */
  929. bailout:
  930. if (parentdn)
  931. slapi_sdn_free(&parentdn);
  932. slapi_rdn_free(&add_rdn);
  933. return rc;
  934. }
  935. /*
  936. * urp_annotate_dn:
  937. * Returns 0 on failure
  938. * Returns > 0 on success (1 on general conflict resolution success, LDAP_NO_SUCH_OBJECT on no-conflict success)
  939. *
  940. * Use this function to annotate an existing entry only. To annotate
  941. * a new entry (the operation entry) see urp_add_operation.
  942. */
  943. static int
  944. urp_annotate_dn (char *sessionid, const Slapi_Entry *entry, CSN *opcsn, const char *optype)
  945. {
  946. int rc = 0; /* Fail */
  947. int op_result;
  948. char *newrdn;
  949. const char *uniqueid;
  950. const Slapi_DN *basesdn;
  951. const char *basedn;
  952. uniqueid = slapi_entry_get_uniqueid (entry);
  953. basesdn = slapi_entry_get_sdn_const (entry);
  954. basedn = slapi_entry_get_dn_const (entry);
  955. newrdn = get_rdn_plus_uniqueid ( sessionid, basedn, uniqueid );
  956. if(newrdn) {
  957. mod_namingconflict_attr (uniqueid, basesdn, basesdn, opcsn, optype);
  958. slapi_log_error(slapi_log_urp, sessionid,
  959. "urp_annotate_dn: %s --> %s\n", basedn, newrdn);
  960. op_result = urp_fixup_rename_entry ( entry, newrdn, NULL, 0 );
  961. switch(op_result)
  962. {
  963. case LDAP_SUCCESS:
  964. slapi_log_error(slapi_log_urp, sessionid,
  965. "Naming conflict %s. Renamed existing entry to %s\n",
  966. optype, newrdn);
  967. rc = 1;
  968. break;
  969. case LDAP_NO_SUCH_OBJECT:
  970. /* This means that entry did not really exist!!!
  971. * This is clearly indicating that there is a
  972. * get_copy_of_entry -> dn2entry returned
  973. * an entry (entry) that was already removed
  974. * from the ldbm database...
  975. * This is bad, because it clearly indicates
  976. * some kind of db or cache corruption. We need to print
  977. * this fact clearly in the errors log to try
  978. * to solve this corruption one day.
  979. * However, as far as the conflict is concerned,
  980. * this error is completely harmless:
  981. * if thew entry did not exist in the first place,
  982. * there was never a room
  983. * for a conflict!! After fix for 558293, this
  984. * state can't be reproduced anymore (5-Oct-01)
  985. */
  986. slapi_log_error(SLAPI_LOG_FATAL, sessionid,
  987. "Entry %s exists in cache but not in DB\n",
  988. basedn);
  989. rc = LDAP_NO_SUCH_OBJECT;
  990. break;
  991. default:
  992. slapi_log_error(slapi_log_urp, sessionid,
  993. "Failed to annotate %s, err=%d\n",
  994. newrdn, op_result);
  995. }
  996. slapi_ch_free ( (void**)&newrdn );
  997. } else {
  998. slapi_log_error(SLAPI_LOG_FATAL, sessionid,
  999. "Failed to create conflict DN from basedn: %s and uniqueid: %s\n",
  1000. basedn, uniqueid );
  1001. }
  1002. return rc;
  1003. }
  1004. /*
  1005. * An URP Naming Collision helper function. Retrieves a list of entries
  1006. * that have the given dn excluding the unique id of the entry. Any
  1007. * entries returned will be entries that have been added with the same
  1008. * dn, but caused a naming conflict when replicated. The URP to fix
  1009. * this constraint violation is to append the unique id of the entry
  1010. * to its RDN.
  1011. */
  1012. static Slapi_Entry *
  1013. urp_get_min_naming_conflict_entry ( Slapi_PBlock *pb, char *sessionid, CSN *opcsn )
  1014. {
  1015. Slapi_PBlock *newpb = NULL;
  1016. LDAPControl **server_ctrls = NULL;
  1017. Slapi_Entry **entries = NULL;
  1018. Slapi_Entry *min_naming_conflict_entry = NULL;
  1019. const CSN *min_csn = NULL;
  1020. char *filter = NULL;
  1021. char *parent_dn = NULL;
  1022. char *basedn;
  1023. int i = 0;
  1024. int min_i = -1;
  1025. int op_result = LDAP_SUCCESS;
  1026. slapi_pblock_get (pb, SLAPI_URP_NAMING_COLLISION_DN, &basedn);
  1027. if (NULL == basedn || strncmp (basedn, SLAPI_ATTR_UNIQUEID, strlen(SLAPI_ATTR_UNIQUEID)) == 0)
  1028. return NULL;
  1029. slapi_log_error ( SLAPI_LOG_REPL, sessionid,
  1030. "Enter urp_get_min_naming_conflict_entry for %s\n", basedn);
  1031. filter = slapi_filter_sprintf("(%s=%s %s%s)", ATTR_NSDS5_REPLCONFLICT, REASON_ANNOTATE_DN,
  1032. ESC_NEXT_VAL, basedn);
  1033. /* server_ctrls will be freed when newpb is destroyed */
  1034. server_ctrls = (LDAPControl **)slapi_ch_calloc (2, sizeof (LDAPControl *));
  1035. server_ctrls[0] = create_managedsait_control();
  1036. server_ctrls[1] = NULL;
  1037. newpb = slapi_pblock_new();
  1038. parent_dn = slapi_dn_parent (basedn);
  1039. slapi_search_internal_set_pb(newpb,
  1040. parent_dn, /* Base DN */
  1041. LDAP_SCOPE_ONELEVEL,
  1042. filter,
  1043. NULL, /* Attrs */
  1044. 0, /* AttrOnly */
  1045. server_ctrls, /* Controls */
  1046. NULL, /* UniqueID */
  1047. repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION),
  1048. 0);
  1049. slapi_search_internal_pb(newpb);
  1050. slapi_pblock_get(newpb, SLAPI_PLUGIN_INTOP_RESULT, &op_result);
  1051. slapi_pblock_get(newpb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
  1052. if ( (op_result != LDAP_SUCCESS) || (entries == NULL) )
  1053. {
  1054. /* Log a message */
  1055. goto done;
  1056. }
  1057. /* For all entries, get the one with the smallest dn csn */
  1058. for (i = 0; NULL != entries[i]; i++)
  1059. {
  1060. const CSN *dncsn;
  1061. dncsn = entry_get_dncsn(entries[i]);
  1062. if ((dncsn != opcsn) &&
  1063. ((min_csn == NULL) || (csn_compare(dncsn, min_csn) < 0)) &&
  1064. !is_tombstone_entry (entries[i]))
  1065. {
  1066. min_csn = dncsn;
  1067. min_i = i;
  1068. }
  1069. /*
  1070. * If there are too many conflicts, the current urp code has no
  1071. * guarantee for all servers to converge anyway, because the
  1072. * urp and the backend can't be done in one transaction due
  1073. * to either performance or the deadlock problem.
  1074. * Don't sacrifice the performance too much for impossible.
  1075. */
  1076. if (min_csn && i > 5)
  1077. {
  1078. break;
  1079. }
  1080. }
  1081. if (min_csn != NULL) {
  1082. /* Found one entry */
  1083. min_naming_conflict_entry = slapi_entry_dup(entries[min_i]);
  1084. }
  1085. done:
  1086. slapi_ch_free_string(&parent_dn);
  1087. if (filter) {
  1088. PR_smprintf_free(filter);
  1089. }
  1090. slapi_free_search_results_internal(newpb);
  1091. slapi_pblock_destroy(newpb);
  1092. newpb = NULL;
  1093. slapi_log_error ( SLAPI_LOG_REPL, sessionid,
  1094. "Leave urp_get_min_naming_conflict_entry (found %d entries)\n", i);
  1095. return min_naming_conflict_entry;
  1096. }
  1097. /*
  1098. * If an entry is deleted or renamed, a new winner may be
  1099. * chosen from its naming competitors.
  1100. * The entry with the smallest dncsn restores its original DN.
  1101. */
  1102. static int
  1103. urp_naming_conflict_removal ( Slapi_PBlock *pb, char *sessionid, CSN *opcsn, const char *optype )
  1104. {
  1105. Slapi_Entry *min_naming_conflict_entry;
  1106. Slapi_RDN *oldrdn, *newrdn;
  1107. const char *oldrdnstr, *newrdnstr;
  1108. int op_result;
  1109. /*
  1110. * Backend op has set SLAPI_URP_NAMING_COLLISION_DN to the basedn.
  1111. */
  1112. min_naming_conflict_entry = urp_get_min_naming_conflict_entry (pb, sessionid, opcsn);
  1113. if (min_naming_conflict_entry == NULL)
  1114. {
  1115. return 0;
  1116. }
  1117. /* Step 1: Restore the entry's original DN */
  1118. oldrdn = slapi_rdn_new_sdn(slapi_entry_get_sdn_const(min_naming_conflict_entry));
  1119. oldrdnstr = slapi_rdn_get_rdn ( oldrdn );
  1120. /* newrdnstr is the old rdn of the entry minus the nsuniqueid part */
  1121. newrdn = slapi_rdn_new_rdn ( oldrdn );
  1122. slapi_rdn_remove_attr (newrdn, SLAPI_ATTR_UNIQUEID );
  1123. newrdnstr = slapi_rdn_get_rdn ( newrdn );
  1124. /*
  1125. * Set OP_FLAG_ACTION_INVOKE_FOR_REPLOP since this operation
  1126. * is done after DB lock was released. The backend modrdn
  1127. * will acquire the DB lock if it sees this flag.
  1128. */
  1129. op_result = urp_fixup_rename_entry((const Slapi_Entry *)min_naming_conflict_entry, newrdnstr, NULL, OP_FLAG_ACTION_INVOKE_FOR_REPLOP);
  1130. if ( op_result != LDAP_SUCCESS )
  1131. {
  1132. slapi_log_error (slapi_log_urp, sessionid,
  1133. "Failed to restore RDN of %s, err=%d\n", oldrdnstr, op_result);
  1134. goto bailout;
  1135. }
  1136. slapi_log_error (slapi_log_urp, sessionid,
  1137. "Naming conflict removed by %s. RDN of %s was restored\n", optype, oldrdnstr);
  1138. /* Step2: Remove ATTR_NSDS5_REPLCONFLICT from the winning entry */
  1139. /*
  1140. * A fixup op will not invoke urp_modrdn_operation(). Even it does,
  1141. * urp_modrdn_operation() will do nothing because of the same CSN.
  1142. */
  1143. op_result = del_replconflict_attr (min_naming_conflict_entry, opcsn, OP_FLAG_ACTION_INVOKE_FOR_REPLOP);
  1144. if (op_result != LDAP_SUCCESS) {
  1145. slapi_log_error(SLAPI_LOG_REPL, sessionid,
  1146. "Failed to remove nsds5ReplConflict for %s, err=%d\n",
  1147. newrdnstr, op_result);
  1148. }
  1149. bailout:
  1150. slapi_entry_free(min_naming_conflict_entry);
  1151. slapi_rdn_free(&oldrdn);
  1152. slapi_rdn_free(&newrdn);
  1153. return op_result;
  1154. }
  1155. /* The returned value is either null or "uniqueid=<uniqueid>+<basedn>" */
  1156. static char *
  1157. get_dn_plus_uniqueid(char *sessionid, const Slapi_DN *oldsdn, const char *uniqueid)
  1158. {
  1159. Slapi_RDN *rdn = slapi_rdn_new();
  1160. char *newdn = NULL;
  1161. int rc = slapi_rdn_init_all_sdn_ext(rdn, oldsdn, 1);
  1162. if (rc) {
  1163. slapi_log_error(SLAPI_LOG_FATAL, sessionid,
  1164. "Failed to convert %s to RDN\n", slapi_sdn_get_dn(oldsdn));
  1165. goto bail;
  1166. }
  1167. PR_ASSERT(uniqueid!=NULL);
  1168. /* Check if the RDN already contains the Unique ID */
  1169. if (slapi_rdn_is_conflict(rdn)) {
  1170. /* The Unique ID is already in the RDN.
  1171. * This is a highly improbable collision.
  1172. * It suggests that a duplicate UUID was generated.
  1173. * This will cause replication divergence and will
  1174. * require admin intercession
  1175. */
  1176. slapi_log_error(SLAPI_LOG_FATAL, sessionid,
  1177. "Annotated DN %s has naming conflict\n", slapi_sdn_get_dn(oldsdn) );
  1178. }
  1179. else
  1180. {
  1181. char *parentdn = slapi_dn_parent(slapi_sdn_get_dn(oldsdn));
  1182. slapi_rdn_add(rdn, SLAPI_ATTR_UNIQUEID, uniqueid);
  1183. /*
  1184. * using slapi_ch_smprintf is okay since ...
  1185. * uniqueid in rdn is normalized and
  1186. * parentdn is normalized by slapi_sdn_get_dn.
  1187. */
  1188. newdn = slapi_ch_smprintf("%s,%s", slapi_rdn_get_rdn(rdn), parentdn);
  1189. slapi_ch_free_string(&parentdn);
  1190. }
  1191. bail:
  1192. slapi_rdn_free(&rdn);
  1193. return newdn;
  1194. }
  1195. char *
  1196. get_rdn_plus_uniqueid(char *sessionid, const char *olddn, const char *uniqueid)
  1197. {
  1198. char *newrdn = NULL;
  1199. /* Check if the RDN already contains the Unique ID */
  1200. Slapi_DN *sdn = slapi_sdn_new_dn_byval(olddn);
  1201. Slapi_RDN *rdn = slapi_rdn_new();
  1202. int rc = slapi_rdn_init_all_sdn_ext(rdn, sdn, 1);
  1203. if (rc) {
  1204. slapi_log_error(SLAPI_LOG_FATAL, sessionid,
  1205. "Failed to convert %s to RDN\n", olddn);
  1206. goto bail;
  1207. }
  1208. PR_ASSERT(uniqueid!=NULL);
  1209. if (slapi_rdn_is_conflict(rdn)) {
  1210. /* The Unique ID is already in the RDN.
  1211. * This is a highly improbable collision.
  1212. * It suggests that a duplicate UUID was generated.
  1213. * This will cause replication divergence and will
  1214. * require admin intercession
  1215. */
  1216. slapi_log_error(SLAPI_LOG_FATAL, sessionid,
  1217. "Annotated RDN %s has naming conflict\n", olddn);
  1218. }
  1219. else
  1220. {
  1221. slapi_rdn_add(rdn,SLAPI_ATTR_UNIQUEID,uniqueid);
  1222. newrdn = slapi_ch_strdup(slapi_rdn_get_rdn(rdn));
  1223. }
  1224. bail:
  1225. slapi_sdn_free(&sdn);
  1226. slapi_rdn_free(&rdn);
  1227. return newrdn;
  1228. }
  1229. static int
  1230. is_suffix_entry ( Slapi_PBlock *pb, Slapi_Entry *entry, Slapi_DN **parentdn )
  1231. {
  1232. return is_suffix_dn ( pb, slapi_entry_get_sdn(entry), parentdn );
  1233. }
  1234. int
  1235. is_suffix_dn_ext ( Slapi_PBlock *pb, const Slapi_DN *dn, Slapi_DN **parentdn,
  1236. int is_tombstone )
  1237. {
  1238. Slapi_Backend *backend;
  1239. int rc;
  1240. *parentdn = slapi_sdn_new();
  1241. slapi_pblock_get( pb, SLAPI_BACKEND, &backend );
  1242. slapi_sdn_get_backend_parent_ext (dn, *parentdn, backend, is_tombstone);
  1243. /* A suffix entry doesn't have parent dn */
  1244. rc = slapi_sdn_isempty (*parentdn) ? 1 : 0;
  1245. return rc;
  1246. }
  1247. int
  1248. is_suffix_dn ( Slapi_PBlock *pb, const Slapi_DN *dn, Slapi_DN **parentdn )
  1249. {
  1250. return is_suffix_dn_ext ( pb, dn, parentdn, 0 );
  1251. }
  1252. static int
  1253. mod_namingconflict_attr (const char *uniqueid, const Slapi_DN *entrysdn,
  1254. const Slapi_DN *conflictsdn, CSN *opcsn,
  1255. const char *optype)
  1256. {
  1257. Slapi_Mods smods;
  1258. char buf[BUFSIZ];
  1259. int op_result;
  1260. #ifdef DEBUG
  1261. PR_snprintf (buf, sizeof(buf), "%s (%s) %s",
  1262. REASON_ANNOTATE_DN, optype, slapi_sdn_get_dn(conflictsdn));
  1263. #else
  1264. PR_snprintf (buf, sizeof(buf), "%s %s",
  1265. REASON_ANNOTATE_DN, slapi_sdn_get_dn(conflictsdn));
  1266. #endif
  1267. slapi_mods_init (&smods, 2);
  1268. if ( strncmp (slapi_sdn_get_dn(entrysdn), SLAPI_ATTR_UNIQUEID,
  1269. strlen(SLAPI_ATTR_UNIQUEID)) != 0 )
  1270. {
  1271. slapi_mods_add (&smods, LDAP_MOD_ADD, ATTR_NSDS5_REPLCONFLICT, strlen(buf), buf);
  1272. }
  1273. else
  1274. {
  1275. /*
  1276. * If the existing entry is already a naming conflict loser,
  1277. * the following replace operation should result in the
  1278. * replace of the ATTR_NSDS5_REPLCONFLICT index as well.
  1279. */
  1280. slapi_mods_add (&smods, LDAP_MOD_REPLACE, ATTR_NSDS5_REPLCONFLICT, strlen(buf), buf);
  1281. }
  1282. op_result = urp_fixup_modify_entry (uniqueid, entrysdn, opcsn, &smods, 0);
  1283. slapi_mods_done (&smods);
  1284. return op_result;
  1285. }
  1286. static int
  1287. del_replconflict_attr (const Slapi_Entry *entry, CSN *opcsn, int opflags)
  1288. {
  1289. Slapi_Attr *attr;
  1290. int op_result = 0;
  1291. if (slapi_entry_attr_find (entry, ATTR_NSDS5_REPLCONFLICT, &attr) == 0)
  1292. {
  1293. Slapi_Mods smods;
  1294. const char *uniqueid;
  1295. const Slapi_DN *entrysdn;
  1296. uniqueid = slapi_entry_get_uniqueid (entry);
  1297. entrysdn = slapi_entry_get_sdn_const (entry);
  1298. slapi_mods_init (&smods, 2);
  1299. slapi_mods_add (&smods, LDAP_MOD_DELETE, ATTR_NSDS5_REPLCONFLICT, 0, NULL);
  1300. op_result = urp_fixup_modify_entry (uniqueid, entrysdn, opcsn, &smods, opflags);
  1301. slapi_mods_done (&smods);
  1302. }
  1303. return op_result;
  1304. }