retrocl_po.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693
  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. #include "retrocl.h"
  13. static int
  14. entry2reple(Slapi_Entry *e, Slapi_Entry *oe, int optype);
  15. static int
  16. mods2reple(Slapi_Entry *e, LDAPMod **ldm);
  17. static int
  18. modrdn2reple(Slapi_Entry *e, const char *newrdn, int deloldrdn, LDAPMod **ldm, const char *newsup);
  19. /******************************/
  20. const char *attr_changenumber = "changenumber";
  21. const char *attr_targetdn = "targetdn";
  22. const char *attr_changetype = "changetype";
  23. const char *attr_newrdn = "newrdn";
  24. const char *attr_deleteoldrdn = "deleteoldrdn";
  25. const char *attr_changes = "changes";
  26. const char *attr_newsuperior = "newsuperior";
  27. const char *attr_changetime = "changetime";
  28. const char *attr_objectclass = "objectclass";
  29. const char *attr_nsuniqueid = "nsuniqueid";
  30. const char *attr_isreplicated = "isreplicated";
  31. /*
  32. * Function: make_changes_string
  33. *
  34. * Returns:
  35. *
  36. * Arguments:
  37. *
  38. * Description:
  39. * loop through the LDAPMod struct and construct the changes attribute/
  40. *
  41. */
  42. static lenstr *
  43. make_changes_string(LDAPMod **ldm, const char **includeattrs)
  44. {
  45. lenstr *l;
  46. int i, j, len;
  47. int skip;
  48. l = lenstr_new();
  49. for (i = 0; ldm[i] != NULL; i++) {
  50. /* If a list of explicit attributes was given, only add those */
  51. if (NULL != includeattrs) {
  52. skip = 1;
  53. for (j = 0; includeattrs[j] != NULL; j++) {
  54. if (strcasecmp(includeattrs[j], ldm[i]->mod_type) == 0) {
  55. skip = 0;
  56. break;
  57. }
  58. }
  59. if (skip) {
  60. continue;
  61. }
  62. }
  63. if (SLAPD_UNHASHED_PW_NOLOG == slapi_config_get_unhashed_pw_switch()) {
  64. if (0 == strcasecmp(ldm[i]->mod_type, PSEUDO_ATTR_UNHASHEDUSERPASSWORD)) {
  65. /* If nsslapd-unhashed-pw-switch == nolog, skip writing it to cl. */
  66. continue;
  67. }
  68. }
  69. switch (ldm[i]->mod_op & ~LDAP_MOD_BVALUES) {
  70. case LDAP_MOD_ADD:
  71. addlenstr(l, "add: ");
  72. addlenstr(l, ldm[i]->mod_type);
  73. addlenstr(l, "\n");
  74. break;
  75. case LDAP_MOD_DELETE:
  76. addlenstr(l, "delete: ");
  77. addlenstr(l, ldm[i]->mod_type);
  78. addlenstr(l, "\n");
  79. break;
  80. case LDAP_MOD_REPLACE:
  81. addlenstr(l, "replace: ");
  82. addlenstr(l, ldm[i]->mod_type);
  83. addlenstr(l, "\n");
  84. break;
  85. }
  86. for (j = 0; ldm[i]->mod_bvalues != NULL &&
  87. ldm[i]->mod_bvalues[j] != NULL;
  88. j++) {
  89. char *buf = NULL;
  90. char *bufp = NULL;
  91. len = strlen(ldm[i]->mod_type);
  92. len = LDIF_SIZE_NEEDED(len,
  93. ldm[i]->mod_bvalues[j]->bv_len) +
  94. 1;
  95. buf = slapi_ch_malloc(len);
  96. bufp = buf;
  97. slapi_ldif_put_type_and_value_with_options(&bufp, ldm[i]->mod_type,
  98. ldm[i]->mod_bvalues[j]->bv_val,
  99. ldm[i]->mod_bvalues[j]->bv_len, 0);
  100. *bufp = '\0';
  101. addlenstr(l, buf);
  102. slapi_ch_free_string(&buf);
  103. }
  104. addlenstr(l, "-\n");
  105. }
  106. return l;
  107. }
  108. /*
  109. * Function: write_replog_db
  110. * Arguments: be - backend to which this change is being applied
  111. * optype - type of LDAP operation being logged
  112. * dn - distinguished name of entry being changed
  113. * log_m - pointer to the actual change operation on a modify
  114. * flag - only used by modrdn operations - value of deleteoldrdn
  115. * curtime - the current time
  116. * Returns: error code
  117. * Description: Given a change, construct an entry which is to be added to the
  118. * changelog database.
  119. */
  120. static int
  121. write_replog_db(
  122. Slapi_PBlock *pb,
  123. int optype,
  124. char *dn,
  125. LDAPMod **log_m,
  126. int flag,
  127. time_t curtime,
  128. Slapi_Entry *log_e,
  129. Slapi_Entry *post_entry,
  130. const char *newrdn,
  131. LDAPMod **modrdn_mods,
  132. const char *newsuperior)
  133. {
  134. Slapi_PBlock *newPb = NULL;
  135. changeNumber changenum;
  136. struct berval *vals[2];
  137. struct berval val;
  138. Slapi_Entry *e;
  139. char chnobuf[22] = {0};
  140. char *edn;
  141. int extensibleObject = 0;
  142. int err = 0;
  143. int ret = LDAP_SUCCESS;
  144. int i;
  145. if (!dn) {
  146. slapi_log_err(SLAPI_LOG_PLUGIN, RETROCL_PLUGIN_NAME, "write_replog_db: NULL dn\n");
  147. return ret;
  148. }
  149. if (post_entry) {
  150. if (!retrocl_entry_in_scope(log_e) && !retrocl_entry_in_scope(post_entry)) {
  151. /* modrdn: entry not in scope, just return... */
  152. return ret;
  153. }
  154. } else {
  155. if (!retrocl_entry_in_scope(log_e)) {
  156. /* entry not in scope, just return... */
  157. return ret;
  158. }
  159. }
  160. PR_Lock(retrocl_internal_lock);
  161. changenum = retrocl_assign_changenumber();
  162. PR_ASSERT(changenum > 0UL);
  163. slapi_log_err(SLAPI_LOG_PLUGIN, RETROCL_PLUGIN_NAME,
  164. "write_replog_db: write change record %lu for dn: \"%s\"\n",
  165. changenum, dn);
  166. /* Construct the dn of this change record */
  167. edn = slapi_ch_smprintf("%s=%lu,%s", attr_changenumber, changenum, RETROCL_CHANGELOG_DN);
  168. /*
  169. * Create the entry struct, and fill in fields common to all types
  170. * of change records.
  171. */
  172. vals[0] = &val;
  173. vals[1] = NULL;
  174. e = slapi_entry_alloc();
  175. slapi_entry_set_dn(e, slapi_ch_strdup(edn));
  176. /* Set the objectclass attribute */
  177. val.bv_val = "top";
  178. val.bv_len = 3;
  179. slapi_entry_add_values(e, "objectclass", vals);
  180. val.bv_val = "changelogentry";
  181. val.bv_len = 14;
  182. slapi_entry_add_values(e, "objectclass", vals);
  183. for (i = 0; i < retrocl_nattributes; i++) {
  184. char *attributeName = retrocl_attributes[i];
  185. char *attributeAlias = retrocl_aliases[i];
  186. if (attributeAlias == NULL) {
  187. attributeAlias = attributeName;
  188. }
  189. if (strcasecmp(attributeName, attr_nsuniqueid) == 0) {
  190. Slapi_Entry *entry = NULL;
  191. const char *uniqueId = NULL;
  192. slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &entry);
  193. if (entry == NULL) {
  194. slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &entry);
  195. }
  196. if (entry == NULL)
  197. continue;
  198. uniqueId = slapi_entry_get_uniqueid(entry);
  199. slapi_log_err(SLAPI_LOG_PLUGIN, RETROCL_PLUGIN_NAME,
  200. "write_replog_db: add %s: \"%s\"\n", attributeAlias, uniqueId);
  201. val.bv_val = (char *)uniqueId;
  202. val.bv_len = strlen(uniqueId);
  203. slapi_entry_add_values(e, attributeAlias, vals);
  204. extensibleObject = 1;
  205. } else if (strcasecmp(attributeName, attr_isreplicated) == 0) {
  206. int isReplicated = 0;
  207. char *attributeValue = NULL;
  208. slapi_pblock_get(pb, SLAPI_IS_REPLICATED_OPERATION, &isReplicated);
  209. attributeValue = isReplicated ? "TRUE" : "FALSE";
  210. slapi_log_err(SLAPI_LOG_PLUGIN, RETROCL_PLUGIN_NAME,
  211. "write_replog_db: add %s: \"%s\"\n", attributeAlias, attributeValue);
  212. val.bv_val = attributeValue;
  213. val.bv_len = strlen(attributeValue);
  214. slapi_entry_add_values(e, attributeAlias, vals);
  215. extensibleObject = 1;
  216. } else {
  217. Slapi_Entry *entry = NULL;
  218. Slapi_ValueSet *valueSet = NULL;
  219. int type_name_disposition = 0;
  220. char *actual_type_name = NULL;
  221. int flags = 0;
  222. int buffer_flags = 0;
  223. slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &entry);
  224. if (entry != NULL) {
  225. slapi_vattr_values_get(entry, attributeName, &valueSet,
  226. &type_name_disposition, &actual_type_name, flags, &buffer_flags);
  227. }
  228. if (valueSet == NULL) {
  229. slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &entry);
  230. if (entry != NULL) {
  231. slapi_vattr_values_get(entry, attributeName, &valueSet,
  232. &type_name_disposition, &actual_type_name, flags, &buffer_flags);
  233. }
  234. }
  235. if (valueSet == NULL)
  236. continue;
  237. slapi_log_err(SLAPI_LOG_PLUGIN, RETROCL_PLUGIN_NAME,
  238. "write_replog_db: add %s\n", attributeAlias);
  239. slapi_entry_add_valueset(e, attributeAlias, valueSet);
  240. slapi_vattr_values_free(&valueSet, &actual_type_name, buffer_flags);
  241. extensibleObject = 1;
  242. }
  243. }
  244. if (extensibleObject) {
  245. val.bv_val = "extensibleObject";
  246. val.bv_len = 16;
  247. slapi_entry_add_values(e, "objectclass", vals);
  248. }
  249. /* Set the changeNumber attribute */
  250. sprintf(chnobuf, "%lu", changenum);
  251. val.bv_val = chnobuf;
  252. val.bv_len = strlen(chnobuf);
  253. slapi_entry_add_values(e, attr_changenumber, vals);
  254. /* Set the targetentrydn attribute */
  255. val.bv_val = dn;
  256. val.bv_len = strlen(dn);
  257. slapi_entry_add_values(e, attr_targetdn, vals);
  258. /* Set the changeTime attribute */
  259. val.bv_val = format_genTime(curtime);
  260. val.bv_len = strlen(val.bv_val);
  261. slapi_entry_add_values(e, attr_changetime, vals);
  262. slapi_ch_free((void **)&val.bv_val);
  263. /*
  264. * Finish constructing the entry. How to do it depends on the type
  265. * of modification being logged.
  266. */
  267. switch (optype) {
  268. case OP_ADD:
  269. if (entry2reple(e, log_e, OP_ADD) != 0) {
  270. err = SLAPI_PLUGIN_FAILURE;
  271. }
  272. break;
  273. case OP_MODIFY:
  274. if (mods2reple(e, log_m) != 0) {
  275. err = SLAPI_PLUGIN_FAILURE;
  276. }
  277. break;
  278. case OP_MODRDN:
  279. if (modrdn2reple(e, newrdn, flag, modrdn_mods, newsuperior) != 0) {
  280. err = SLAPI_PLUGIN_FAILURE;
  281. }
  282. break;
  283. case OP_DELETE:
  284. if (retrocl_log_deleted) {
  285. /* we have to log the full entry */
  286. if (entry2reple(e, log_e, OP_DELETE) != 0) {
  287. err = SLAPI_PLUGIN_FAILURE;
  288. }
  289. } else {
  290. /* Set the changetype attribute */
  291. val.bv_val = "delete";
  292. val.bv_len = 6;
  293. slapi_entry_add_values(e, attr_changetype, vals);
  294. }
  295. break;
  296. default:
  297. slapi_log_err(SLAPI_LOG_ERR, RETROCL_PLUGIN_NAME,
  298. "write_replog_db - Unknown LDAP operation type %d.\n", optype);
  299. err = SLAPI_PLUGIN_FAILURE;
  300. }
  301. /* Call the repl backend to add this entry */
  302. if (0 == err) {
  303. newPb = slapi_pblock_new();
  304. slapi_add_entry_internal_set_pb(newPb, e, NULL /* controls */,
  305. g_plg_identity[PLUGIN_RETROCL],
  306. /* dont leave entry in cache if main oparation is aborted */
  307. SLAPI_OP_FLAG_NEVER_CACHE);
  308. slapi_add_internal_pb(newPb);
  309. slapi_pblock_get(newPb, SLAPI_PLUGIN_INTOP_RESULT, &ret);
  310. slapi_pblock_destroy(newPb);
  311. if (0 != ret) {
  312. slapi_log_err(SLAPI_LOG_ERR, RETROCL_PLUGIN_NAME,
  313. "write_replog_db - An error occured while adding change "
  314. "number %lu, dn = %s: %s. \n",
  315. changenum, edn, ldap_err2string(ret));
  316. retrocl_release_changenumber();
  317. } else {
  318. /* Tell the change numbering system this one's committed to disk */
  319. retrocl_commit_changenumber();
  320. }
  321. } else {
  322. slapi_log_err(SLAPI_LOG_ERR, RETROCL_PLUGIN_NAME,
  323. "write_replog_db - An error occurred while constructing "
  324. "change record number %ld.\n",
  325. changenum);
  326. retrocl_release_changenumber();
  327. ret = err;
  328. }
  329. PR_Unlock(retrocl_internal_lock);
  330. if (NULL != edn) {
  331. slapi_ch_free((void **)&edn);
  332. }
  333. return ret;
  334. }
  335. /*
  336. * Function: entry2reple
  337. * Arguments: e - a partially-constructed Slapi_Entry structure
  338. * oe - the original entry (an entry being added by a client).
  339. * Returns: 0 on success.
  340. * Description: Given an Slapi_Entry struct, construct a changelog entry which will be
  341. * added to the replication database. It is assumed that e points
  342. * to an entry obtained from slapi_entry_alloc().
  343. */
  344. static int
  345. entry2reple(Slapi_Entry *e, Slapi_Entry *oe, int optype)
  346. {
  347. char *p, *estr;
  348. struct berval *vals[2];
  349. struct berval val;
  350. int len;
  351. vals[0] = &val;
  352. vals[1] = NULL;
  353. /* Set the changetype attribute */
  354. if (optype == OP_ADD) {
  355. val.bv_val = "add";
  356. val.bv_len = 3;
  357. } else if (optype == OP_DELETE) {
  358. val.bv_val = "delete";
  359. val.bv_len = 6;
  360. } else {
  361. return (1);
  362. }
  363. slapi_entry_add_values(e, attr_changetype, vals);
  364. estr = slapi_entry2str(oe, &len);
  365. p = estr;
  366. /* Skip over the dn: line */
  367. while ((p = strchr(p, '\n')) != NULL) {
  368. p++;
  369. if (!ldap_utf8isspace(p)) {
  370. break;
  371. }
  372. }
  373. val.bv_val = p;
  374. val.bv_len = len - (p - estr); /* length + terminating \0 */
  375. slapi_entry_add_values(e, attr_changes, vals);
  376. slapi_ch_free_string(&estr);
  377. return 0;
  378. }
  379. /*
  380. * Function: mods2reple
  381. * Arguments: e - a partially-constructed Slapi_Entry structure
  382. * ldm - an array of pointers to LDAPMod structures describing the
  383. * change applied.
  384. * Returns: 0 on success.
  385. * Description: Given a pointer to an LDAPMod struct and a dn, construct
  386. * a new entry which will be added to the replication database.
  387. * It is assumed that e points to an entry obtained from
  388. * slapi_entry_alloc().
  389. */
  390. static int
  391. mods2reple(Slapi_Entry *e, LDAPMod **ldm)
  392. {
  393. struct berval val;
  394. struct berval *vals[2];
  395. lenstr *l;
  396. vals[0] = &val;
  397. vals[1] = NULL;
  398. /* Set the changetype attribute */
  399. val.bv_val = "modify";
  400. val.bv_len = 6;
  401. slapi_entry_add_values(e, "changetype", vals);
  402. if (NULL != ldm) {
  403. l = make_changes_string(ldm, NULL);
  404. if (NULL != l) {
  405. val.bv_val = l->ls_buf;
  406. val.bv_len = l->ls_len + 1; /* string + terminating \0 */
  407. slapi_entry_add_values(e, attr_changes, vals);
  408. lenstr_free(&l);
  409. }
  410. }
  411. return 0;
  412. }
  413. /*
  414. * Function: modrdn2reple
  415. * Arguments: e - a partially-constructed Slapi_Entry structure
  416. * newrdn - the new relative distinguished name for the entry
  417. * deloldrdn - the "deleteoldrdn" flag provided by the client
  418. * ldm - any modifications applied as a side-effect of the modrdn
  419. * Returns: 0 on success
  420. * Description: Given a dn, a new rdn, and a deleteoldrdn flag, construct
  421. * a new entry which will be added to the replication database reflecting a
  422. * completed modrdn operation. The entry has the same form as above.
  423. * It is assumed that e points to an entry obtained from slapi_entry_alloc().
  424. */
  425. static int
  426. modrdn2reple(
  427. Slapi_Entry *e,
  428. const char *newrdn,
  429. int deloldrdn,
  430. LDAPMod **ldm,
  431. const char *newsuperior)
  432. {
  433. struct berval val;
  434. struct berval *vals[2];
  435. lenstr *l;
  436. static const char *lastmodattrs[] = {"modifiersname", "modifytimestamp",
  437. "creatorsname", "createtimestamp",
  438. NULL};
  439. vals[0] = &val;
  440. vals[1] = NULL;
  441. val.bv_val = "modrdn";
  442. val.bv_len = 6;
  443. slapi_entry_add_values(e, attr_changetype, vals);
  444. if (newrdn) {
  445. val.bv_val = (char *)newrdn; /* cast away const */
  446. val.bv_len = strlen(newrdn);
  447. slapi_entry_add_values(e, attr_newrdn, vals);
  448. }
  449. if (deloldrdn == 0) {
  450. val.bv_val = "FALSE";
  451. val.bv_len = 5;
  452. } else {
  453. val.bv_val = "TRUE";
  454. val.bv_len = 4;
  455. }
  456. slapi_entry_add_values(e, attr_deleteoldrdn, vals);
  457. if (newsuperior) {
  458. val.bv_val = (char *)newsuperior; /* cast away const */
  459. val.bv_len = strlen(newsuperior);
  460. slapi_entry_add_values(e, attr_newsuperior, vals);
  461. }
  462. if (NULL != ldm) {
  463. l = make_changes_string(ldm, lastmodattrs);
  464. if (NULL != l) {
  465. if (l->ls_len) {
  466. val.bv_val = l->ls_buf;
  467. val.bv_len = l->ls_len;
  468. slapi_entry_add_values(e, attr_changes, vals);
  469. }
  470. lenstr_free(&l);
  471. }
  472. }
  473. return 0;
  474. }
  475. /*
  476. * Function: retrocl_postob
  477. *
  478. * Returns: 0 on success
  479. *
  480. * Arguments: pblock, optype (add, del, modify etc)
  481. *
  482. * Description: called from retrocl.c op-specific plugins.
  483. *
  484. * Please be aware that operation threads may be scheduled out between their
  485. * being performed inside of the LDBM database and the changelog plugin
  486. * running. For example, suppose MA and MB are two modify operations on the
  487. * same entry. MA may be performed on the LDBM database, and then block
  488. * before the changelog runs. MB then runs against the LDBM database and then
  489. * is written to the changelog. MA starts running. In the changelog, MB will
  490. * appear to have been performed before MA, but in the LDBM database the
  491. * opposite will have occured.
  492. *
  493. *
  494. */
  495. int
  496. retrocl_postob(Slapi_PBlock *pb, int optype)
  497. {
  498. char *dn;
  499. LDAPMod **log_m = NULL;
  500. int flag = 0;
  501. Slapi_Entry *entry = NULL;
  502. Slapi_Entry *post_entry = NULL;
  503. Slapi_Operation *op = NULL;
  504. LDAPMod **modrdn_mods = NULL;
  505. char *newrdn = NULL;
  506. Slapi_DN *newsuperior = NULL;
  507. Slapi_Backend *be = NULL;
  508. time_t curtime;
  509. int rc = SLAPI_PLUGIN_SUCCESS;
  510. /*
  511. * Check to see if the change was made to the replication backend db.
  512. * If so, don't try to log it to the db (otherwise, we'd get in a loop).
  513. */
  514. (void)slapi_pblock_get(pb, SLAPI_BACKEND, &be);
  515. if (be == NULL) {
  516. slapi_log_err(SLAPI_LOG_ERR, RETROCL_PLUGIN_NAME, "retrocl_postob - Backend is not set\n");
  517. return SLAPI_PLUGIN_FAILURE;
  518. }
  519. if (slapi_be_logchanges(be) == 0) {
  520. slapi_log_err(SLAPI_LOG_TRACE, RETROCL_PLUGIN_NAME, "retrocl_postob - Not applying change if not logging\n");
  521. return SLAPI_PLUGIN_SUCCESS;
  522. }
  523. if (retrocl_be_changelog == NULL || be == retrocl_be_changelog) {
  524. slapi_log_err(SLAPI_LOG_TRACE, RETROCL_PLUGIN_NAME, "retrocl_postob - Not applying change if no/cl be\n");
  525. return SLAPI_PLUGIN_SUCCESS;
  526. }
  527. slapi_pblock_get(pb, SLAPI_RESULT_CODE, &rc);
  528. if (rc != LDAP_SUCCESS) {
  529. slapi_log_err(SLAPI_LOG_TRACE, RETROCL_PLUGIN_NAME, "retrocl_postob - Not applying change if op failed %d\n", rc);
  530. /* this could also mean that the changenumber is no longer correct
  531. * set a flag to check at next assignment
  532. */
  533. retrocl_set_check_changenumber();
  534. return SLAPI_PLUGIN_SUCCESS;
  535. }
  536. if (slapi_op_abandoned(pb)) {
  537. slapi_log_err(SLAPI_LOG_PLUGIN, RETROCL_PLUGIN_NAME, "retrocl_postob - Not applying change if op abandoned\n");
  538. return SLAPI_PLUGIN_SUCCESS;
  539. }
  540. curtime = slapi_current_utc_time();
  541. (void)slapi_pblock_get(pb, SLAPI_ORIGINAL_TARGET_DN, &dn);
  542. /* change number could be retrieved from Operation extension stored in
  543. * the pblock, or else it needs to be made dynamically. */
  544. /* get the operation extension and retrieve the change number */
  545. slapi_pblock_get(pb, SLAPI_OPERATION, &op);
  546. if (op == NULL) {
  547. slapi_log_err(SLAPI_LOG_TRACE, RETROCL_PLUGIN_NAME, "retrocl_postob - Not applying change if no op\n");
  548. return SLAPI_PLUGIN_SUCCESS;
  549. }
  550. if (operation_is_flag_set(op, OP_FLAG_TOMBSTONE_ENTRY)) {
  551. slapi_log_err(SLAPI_LOG_TRACE, RETROCL_PLUGIN_NAME, "retrocl_postob - Not applying change for nsTombstone entries\n");
  552. return SLAPI_PLUGIN_SUCCESS;
  553. }
  554. /*
  555. * Start by grabbing the preop entry, ADD will replace it as needed. Getting the entry
  556. * allows up to perform scoping in write_replog_db() for all op types.
  557. */
  558. (void)slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &entry);
  559. switch (optype) {
  560. case OP_MODIFY:
  561. (void)slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &log_m);
  562. break;
  563. case OP_ADD:
  564. /*
  565. * For adds, we want the unnormalized dn, so we can preserve
  566. * spacing, case, when replicating it.
  567. */
  568. (void)slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &entry);
  569. if (NULL != entry) {
  570. dn = slapi_entry_get_dn(entry);
  571. }
  572. break;
  573. case OP_DELETE:
  574. if (retrocl_log_deleted)
  575. (void)slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &entry);
  576. break;
  577. case OP_MODRDN:
  578. /* newrdn is used just for logging; no need to be normalized */
  579. (void)slapi_pblock_get(pb, SLAPI_MODRDN_NEWRDN, &newrdn);
  580. (void)slapi_pblock_get(pb, SLAPI_MODRDN_DELOLDRDN, &flag);
  581. (void)slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &modrdn_mods);
  582. (void)slapi_pblock_get(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &newsuperior);
  583. (void)slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &post_entry);
  584. break;
  585. }
  586. /* check if we should log change to retro changelog, and
  587. * if so, do it here */
  588. if ((rc = write_replog_db(pb, optype, dn, log_m, flag, curtime, entry,
  589. post_entry, newrdn, modrdn_mods, slapi_sdn_get_dn(newsuperior)))) {
  590. slapi_log_err(SLAPI_LOG_ERR, RETROCL_PLUGIN_NAME,
  591. "retrocl_postob - Operation failure [%d]\n", rc);
  592. if (rc < 0) {
  593. rc = LDAP_OPERATIONS_ERROR;
  594. }
  595. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &rc);
  596. rc = SLAPI_PLUGIN_FAILURE;
  597. }
  598. return rc;
  599. }