urp.c 44 KB

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