usn.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright (C) 2009 Red Hat, Inc.
  3. * All rights reserved.
  4. *
  5. * License: GPL (version 3 or any later version).
  6. * See LICENSE for details.
  7. * END COPYRIGHT BLOCK **/
  8. #ifdef HAVE_CONFIG_H
  9. # include <config.h>
  10. #endif
  11. #include "usn.h"
  12. static Slapi_PluginDesc pdesc = {
  13. "USN", VENDOR, DS_PACKAGE_VERSION,
  14. "USN (Update Sequence Number) plugin" };
  15. static void *_usn_identity = NULL;
  16. static int usn_preop_init(Slapi_PBlock *pb);
  17. static int usn_bepreop_init(Slapi_PBlock *pb);
  18. static int usn_betxnpreop_init(Slapi_PBlock *pb);
  19. static int usn_bepostop_init(Slapi_PBlock *pb);
  20. static int usn_rootdse_init(Slapi_PBlock *pb);
  21. static int usn_preop_delete(Slapi_PBlock *pb);
  22. static int usn_bepreop_modify(Slapi_PBlock *pb);
  23. static int usn_betxnpreop_add(Slapi_PBlock *pb);
  24. static int usn_betxnpreop_delete(Slapi_PBlock *pb);
  25. static int usn_bepostop(Slapi_PBlock *pb);
  26. static int usn_bepostop_delete (Slapi_PBlock *pb);
  27. static int usn_bepostop_modify (Slapi_PBlock *pb);
  28. static int usn_start(Slapi_PBlock *pb);
  29. static int usn_close(Slapi_PBlock *pb);
  30. static int usn_get_attr(Slapi_PBlock *pb, const char* type, void *value);
  31. static int usn_rootdse_search(Slapi_PBlock *pb, Slapi_Entry* e,
  32. Slapi_Entry* entryAfter, int *returncode, char *returntext, void *arg);
  33. /*
  34. * Register USN plugin
  35. * Note: USN counter initialization is done in the backend (ldbm_usn_init).
  36. */
  37. int
  38. usn_init(Slapi_PBlock *pb)
  39. {
  40. int rc = 0;
  41. void *identity = NULL;
  42. Slapi_Entry *plugin_entry = NULL;
  43. int is_betxn = 0;
  44. const char *plugintype;
  45. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  46. "--> usn_init\n");
  47. slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY, &identity);
  48. if ((slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_ENTRY, &plugin_entry) == 0) &&
  49. plugin_entry) {
  50. is_betxn = slapi_entry_attr_get_bool(plugin_entry,
  51. "nsslapd-pluginbetxn");
  52. }
  53. /* slapi_register_plugin always returns SUCCESS (0) */
  54. if (slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION,
  55. SLAPI_PLUGIN_VERSION_01) != 0 ||
  56. slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION,
  57. (void *)&pdesc) != 0) {
  58. slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
  59. "usn_init: failed to register version & description\n");
  60. rc = -1;
  61. goto bail;
  62. }
  63. if (slapi_pblock_set(pb, SLAPI_PLUGIN_START_FN,
  64. (void *)usn_start) != 0 ||
  65. slapi_pblock_set(pb, SLAPI_PLUGIN_CLOSE_FN,
  66. (void *)usn_close) != 0 ) {
  67. slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
  68. "usn_init: failed to register close callback & task\n");
  69. rc = -1;
  70. goto bail;
  71. }
  72. /* usn_preop_init: plugintype is preoperation (not be/betxn) */
  73. plugintype = "preoperation";
  74. rc = slapi_register_plugin(plugintype, 1 /* Enabled */,
  75. "usn_preop_init", usn_preop_init,
  76. "USN preoperation plugin", NULL, identity);
  77. /* usn_bepreop_init: plugintype is bepreoperation (not betxn) */
  78. plugintype = "bepreoperation";
  79. rc |= slapi_register_plugin(plugintype, 1 /* Enabled */,
  80. "usn_bepreop_init", usn_bepreop_init,
  81. "USN bepreoperation plugin", NULL, identity);
  82. /* usn_bepreop_init: plugintype is betxnpreoperation */
  83. plugintype = "betxnpreoperation";
  84. rc |= slapi_register_plugin(plugintype, 1 /* Enabled */,
  85. "usn_betxnpreop_init", usn_betxnpreop_init,
  86. "USN betxnpreoperation plugin", NULL, identity);
  87. plugintype = "bepostoperation";
  88. if (is_betxn) {
  89. plugintype = "betxnpostoperation";
  90. }
  91. rc |= slapi_register_plugin(plugintype, 1 /* Enabled */,
  92. "usn_bepostop_init", usn_bepostop_init,
  93. "USN bepostoperation plugin", NULL, identity);
  94. usn_set_identity(identity);
  95. bail:
  96. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  97. "<-- usn_init\n");
  98. return rc;
  99. }
  100. /* This ops must be preop not be/betxn */
  101. static int
  102. usn_preop_init(Slapi_PBlock *pb)
  103. {
  104. int rc = SLAPI_PLUGIN_SUCCESS;
  105. int predel = SLAPI_PLUGIN_PRE_DELETE_FN;
  106. if (slapi_pblock_set(pb, predel, (void *)usn_preop_delete) != 0) {
  107. slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
  108. "usn_preop_init: failed to register preop plugin\n");
  109. rc = SLAPI_PLUGIN_FAILURE;
  110. }
  111. return rc;
  112. }
  113. static int
  114. usn_bepreop_init(Slapi_PBlock *pb)
  115. {
  116. int rc = SLAPI_PLUGIN_SUCCESS;
  117. int premod = SLAPI_PLUGIN_BE_PRE_MODIFY_FN;
  118. int premdn = SLAPI_PLUGIN_BE_PRE_MODRDN_FN;
  119. /* usn_bepreop functions are called at BE_PRE_OP timing,
  120. * not at BE_TXN_PREOP */
  121. /* modify/modrdn updates mods which is evaluated before the
  122. * transaction start */
  123. if ((slapi_pblock_set(pb, premod, (void *)usn_bepreop_modify) != 0) ||
  124. (slapi_pblock_set(pb, premdn, (void *)usn_bepreop_modify) != 0)) {
  125. slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
  126. "usn_bepreop_init: failed to register bepreop plugin\n");
  127. rc = SLAPI_PLUGIN_FAILURE;
  128. }
  129. return rc;
  130. }
  131. static int
  132. usn_betxnpreop_init(Slapi_PBlock *pb)
  133. {
  134. int rc = SLAPI_PLUGIN_SUCCESS;
  135. int preadd = SLAPI_PLUGIN_BE_TXN_PRE_ADD_FN;
  136. int predel = SLAPI_PLUGIN_BE_TXN_PRE_DELETE_TOMBSTONE_FN;
  137. if ((slapi_pblock_set(pb, preadd, (void *)usn_betxnpreop_add) != 0) ||
  138. (slapi_pblock_set(pb, predel, (void *)usn_betxnpreop_delete) != 0)) {
  139. slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
  140. "usn_betxnpreop_init: failed to register betxnpreop plugin\n");
  141. rc = SLAPI_PLUGIN_FAILURE;
  142. }
  143. return rc;
  144. }
  145. static int
  146. usn_bepostop_init(Slapi_PBlock *pb)
  147. {
  148. int rc = SLAPI_PLUGIN_SUCCESS;
  149. Slapi_Entry *plugin_entry = NULL;
  150. char *plugin_type = NULL;
  151. int postadd = SLAPI_PLUGIN_BE_POST_ADD_FN;
  152. int postmod = SLAPI_PLUGIN_BE_POST_MODIFY_FN;
  153. int postmdn = SLAPI_PLUGIN_BE_POST_MODRDN_FN;
  154. int postdel = SLAPI_PLUGIN_BE_POST_DELETE_FN;
  155. if ((slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_ENTRY, &plugin_entry) == 0) &&
  156. plugin_entry &&
  157. (plugin_type = slapi_entry_attr_get_charptr(plugin_entry,
  158. "nsslapd-plugintype")) &&
  159. plugin_type && strstr(plugin_type, "betxn")) {
  160. postadd = SLAPI_PLUGIN_BE_TXN_POST_ADD_FN;
  161. postmod = SLAPI_PLUGIN_BE_TXN_POST_MODIFY_FN;
  162. postmdn = SLAPI_PLUGIN_BE_TXN_POST_MODRDN_FN;
  163. postdel = SLAPI_PLUGIN_BE_TXN_POST_DELETE_FN;
  164. }
  165. slapi_ch_free_string(&plugin_type);
  166. if ((slapi_pblock_set(pb, postadd, (void *)usn_bepostop) != 0) ||
  167. (slapi_pblock_set(pb, postdel, (void *)usn_bepostop_delete) != 0) ||
  168. (slapi_pblock_set(pb, postmod, (void *)usn_bepostop_modify) != 0) ||
  169. (slapi_pblock_set(pb, postmdn, (void *)usn_bepostop) != 0)) {
  170. slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
  171. "usn_bepostop_init: failed to register bepostop plugin\n");
  172. rc = SLAPI_PLUGIN_FAILURE;
  173. }
  174. return rc;
  175. }
  176. static int
  177. usn_rootdse_init(Slapi_PBlock *pb)
  178. {
  179. int rc = SLAPI_PLUGIN_FAILURE;
  180. if (slapi_config_register_callback_plugin(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP | DSE_FLAG_PLUGIN,
  181. "", LDAP_SCOPE_BASE, "(objectclass=*)",
  182. usn_rootdse_search, NULL, pb)) {
  183. rc = SLAPI_PLUGIN_SUCCESS;
  184. }
  185. return rc;
  186. }
  187. /*
  188. * usn_start: usn_rootdse_init -- set rootdse callback to aggregate in rootDSE
  189. * usn_cleanup_start -- initialize USN tombstone cleanup task
  190. */
  191. static int
  192. usn_start(Slapi_PBlock *pb)
  193. {
  194. int rc = SLAPI_PLUGIN_SUCCESS;
  195. Slapi_Value *value;
  196. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM, "--> usn_start\n");
  197. rc = usn_rootdse_init(pb);
  198. rc |= usn_cleanup_start(pb);
  199. if (rc) {
  200. rc = SLAPI_PLUGIN_FAILURE;
  201. goto bail;
  202. }
  203. if (0) { /* Not executed; test code for slapi_get_plugin_default_config */
  204. Slapi_ValueSet *vs = NULL;
  205. Slapi_Value *v = NULL;
  206. int i;
  207. slapi_get_plugin_default_config("nsds5ReplicatedAttributeList", &vs);
  208. if (vs) {
  209. for (i = slapi_valueset_first_value(vs, &v);
  210. i != -1;
  211. i = slapi_valueset_next_value(vs, i, &v)) {
  212. slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
  213. "nsds5ReplicatedAttributeList: %s\n",
  214. slapi_value_get_string(v));
  215. }
  216. }
  217. slapi_valueset_free(vs);
  218. }
  219. /* add nsds5ReplicatedAttributeList: (objectclass=*) $ EXCLUDE entryusn
  220. * to cn=plugin default config,cn=config */
  221. value = slapi_value_new_string("(objectclass=*) $ EXCLUDE entryusn");
  222. if (slapi_set_plugin_default_config("nsds5ReplicatedAttributeList", value)) {
  223. rc = SLAPI_PLUGIN_FAILURE;
  224. }
  225. slapi_value_free(&value);
  226. bail:
  227. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  228. "<-- usn_start (rc: %d)\n", rc);
  229. return rc;
  230. }
  231. static int
  232. usn_close(Slapi_PBlock *pb)
  233. {
  234. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM, "--> usn_close\n");
  235. usn_cleanup_close();
  236. slapi_config_remove_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP,
  237. "", LDAP_SCOPE_BASE, "(objectclass=*)", usn_rootdse_search);
  238. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM, "<-- usn_close\n");
  239. return SLAPI_PLUGIN_SUCCESS;
  240. }
  241. /*
  242. * usn_preop_delete -- set params to turn the entry to tombstone
  243. */
  244. static int
  245. usn_preop_delete(Slapi_PBlock *pb)
  246. {
  247. Slapi_Operation *op = NULL;
  248. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  249. "--> usn_preop_delete\n");
  250. slapi_pblock_get(pb, SLAPI_OPERATION, &op);
  251. if (NULL == op) {
  252. slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
  253. "<-- usn_preop_delete failed; no operation.\n");
  254. return SLAPI_PLUGIN_FAILURE;
  255. }
  256. slapi_operation_set_replica_attr_handler(op, (void *)usn_get_attr);
  257. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  258. "<-- usn_preop_delete\n");
  259. return SLAPI_PLUGIN_SUCCESS;
  260. }
  261. static void
  262. _usn_add_next_usn(Slapi_Entry *e, Slapi_Backend *be)
  263. {
  264. struct berval usn_berval = {0};
  265. Slapi_Attr* attr = NULL;
  266. if (NULL == be->be_usn_counter) {
  267. /* USN plugin is not enabled */
  268. return;
  269. }
  270. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  271. "--> _usn_add_next_usn\n");
  272. /* add next USN to the entry; "be" contains the usn counter */
  273. usn_berval.bv_val = slapi_ch_smprintf("%" NSPRIu64,
  274. slapi_counter_get_value(be->be_usn_counter));
  275. usn_berval.bv_len = strlen(usn_berval.bv_val);
  276. slapi_entry_attr_find(e, SLAPI_ATTR_ENTRYUSN, &attr);
  277. if (NULL == attr) { /* ENTRYUSN does not exist; add it */
  278. Slapi_Value *usn_value = slapi_value_new_berval(&usn_berval);
  279. slapi_entry_add_value(e, SLAPI_ATTR_ENTRYUSN, usn_value);
  280. slapi_value_free(&usn_value);
  281. } else { /* ENTRYUSN exists; replace it */
  282. struct berval *new_bvals[2];
  283. new_bvals[0] = &usn_berval;
  284. new_bvals[1] = NULL;
  285. slapi_entry_attr_replace(e, SLAPI_ATTR_ENTRYUSN, new_bvals);
  286. }
  287. slapi_ch_free_string(&usn_berval.bv_val);
  288. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  289. "<-- _usn_add_next_usn\n");
  290. return;
  291. }
  292. static int
  293. _usn_mod_next_usn(LDAPMod ***mods, Slapi_Backend *be)
  294. {
  295. Slapi_Mods smods = {0};
  296. struct berval *bvals[2];
  297. struct berval usn_berval = {0};
  298. char counter_buf[USN_COUNTER_BUF_LEN];
  299. if (NULL == be->be_usn_counter) {
  300. /* USN plugin is not enabled */
  301. return LDAP_UNWILLING_TO_PERFORM;
  302. }
  303. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  304. "--> _usn_mod_next_usn\n");
  305. /* add next USN to the mods; "be" contains the usn counter */
  306. usn_berval.bv_val = counter_buf;
  307. PR_snprintf(usn_berval.bv_val, USN_COUNTER_BUF_LEN, "%" NSPRIu64,
  308. slapi_counter_get_value(be->be_usn_counter));
  309. usn_berval.bv_len = strlen(usn_berval.bv_val);
  310. bvals[0] = &usn_berval;
  311. bvals[1] = NULL;
  312. slapi_mods_init_passin(&smods, *mods);
  313. /* bvals is duplicated by ber_bvdup in slapi_mods_add_modbvps */
  314. slapi_mods_add_modbvps(&smods, LDAP_MOD_REPLACE | LDAP_MOD_BVALUES,
  315. SLAPI_ATTR_ENTRYUSN, bvals);
  316. *mods = slapi_mods_get_ldapmods_passout(&smods);
  317. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  318. "<-- _usn_mod_next_usn\n");
  319. return LDAP_SUCCESS;
  320. }
  321. /*
  322. * usn_betxnpreop_add - add next USN to the entry to be added
  323. */
  324. static int
  325. usn_betxnpreop_add(Slapi_PBlock *pb)
  326. {
  327. Slapi_Entry *e = NULL;
  328. Slapi_Backend *be = NULL;
  329. int rc = SLAPI_PLUGIN_SUCCESS;
  330. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  331. "--> usn_betxnpreop_add\n");
  332. /* add next USN to the entry; "be" contains the usn counter */
  333. slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &e);
  334. if (NULL == e) {
  335. rc = LDAP_NO_SUCH_OBJECT;
  336. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &rc);
  337. rc = SLAPI_PLUGIN_FAILURE;
  338. goto bail;
  339. }
  340. slapi_pblock_get(pb, SLAPI_BACKEND, &be);
  341. if (NULL == be) {
  342. rc = LDAP_PARAM_ERROR;
  343. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &rc);
  344. rc = SLAPI_PLUGIN_FAILURE;
  345. goto bail;
  346. }
  347. _usn_add_next_usn(e, be);
  348. bail:
  349. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  350. "<-- usn_betxnpreop_add\n");
  351. return rc;
  352. }
  353. /*
  354. * usn_betxnpreop_delete -- add/replace next USN to the entry
  355. * bepreop_delete is not called if the entry is tombstone
  356. */
  357. static int
  358. usn_betxnpreop_delete(Slapi_PBlock *pb)
  359. {
  360. Slapi_Entry *e = NULL;
  361. Slapi_Backend *be = NULL;
  362. int rc = SLAPI_PLUGIN_SUCCESS;
  363. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  364. "--> usn_betxnpreop_delete\n");
  365. /* add next USN to the entry; "be" contains the usn counter */
  366. slapi_pblock_get(pb, SLAPI_DELETE_BEPREOP_ENTRY, &e);
  367. if (NULL == e) {
  368. rc = LDAP_NO_SUCH_OBJECT;
  369. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &rc);
  370. rc = SLAPI_PLUGIN_FAILURE;
  371. goto bail;
  372. }
  373. slapi_pblock_get(pb, SLAPI_BACKEND, &be);
  374. if (NULL == be) {
  375. rc = LDAP_PARAM_ERROR;
  376. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &rc);
  377. rc = SLAPI_PLUGIN_FAILURE;
  378. goto bail;
  379. }
  380. _usn_add_next_usn(e, be);
  381. bail:
  382. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  383. "<-- usn_betxnpreop_delete\n");
  384. return rc;
  385. }
  386. /*
  387. * usn_bepreop_modify - add/replace next USN to the mods;
  388. * shared by modify and modrdn
  389. * Note: bepreop should not return other than LDAP_SUCCESS.
  390. */
  391. static int
  392. usn_bepreop_modify (Slapi_PBlock *pb)
  393. {
  394. LDAPMod **mods = NULL;
  395. Slapi_Backend *be = NULL;
  396. int rc = SLAPI_PLUGIN_SUCCESS;
  397. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  398. "--> usn_bepreop_modify\n");
  399. /* add/replace next USN to the mods; "be" contains the usn counter */
  400. slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods);
  401. slapi_pblock_get(pb, SLAPI_BACKEND, &be);
  402. if (NULL == be) {
  403. slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
  404. "usn_bepreop_modify: no backend.\n");
  405. rc = LDAP_PARAM_ERROR;
  406. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &rc);
  407. rc = SLAPI_PLUGIN_FAILURE;
  408. goto bail;
  409. }
  410. if (LDAP_SUCCESS == _usn_mod_next_usn(&mods, be)) {
  411. slapi_pblock_set(pb, SLAPI_MODIFY_MODS, mods);
  412. }
  413. bail:
  414. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  415. "<-- usn_bepreop_modify\n");
  416. return rc;
  417. }
  418. /* count up the counter */
  419. static int
  420. usn_bepostop (Slapi_PBlock *pb)
  421. {
  422. int rc = SLAPI_PLUGIN_FAILURE;
  423. Slapi_Backend *be = NULL;
  424. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  425. "--> usn_bepostop\n");
  426. /* if op is not successful, don't increment the counter */
  427. slapi_pblock_get(pb, SLAPI_RESULT_CODE, &rc);
  428. if (LDAP_SUCCESS != rc) {
  429. /* no plugin failure */
  430. rc = SLAPI_PLUGIN_SUCCESS;
  431. goto bail;
  432. }
  433. slapi_pblock_get(pb, SLAPI_BACKEND, &be);
  434. if (NULL == be) {
  435. rc = LDAP_PARAM_ERROR;
  436. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &rc);
  437. rc = SLAPI_PLUGIN_FAILURE;
  438. goto bail;
  439. }
  440. if (be->be_usn_counter) {
  441. slapi_counter_increment(be->be_usn_counter);
  442. }
  443. bail:
  444. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  445. "<-- usn_bepostop\n");
  446. return rc;
  447. }
  448. /* count up the counter */
  449. static int
  450. usn_bepostop_modify (Slapi_PBlock *pb)
  451. {
  452. int rc = SLAPI_PLUGIN_FAILURE;
  453. Slapi_Backend *be = NULL;
  454. LDAPMod **mods = NULL;
  455. int i;
  456. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  457. "--> usn_bepostop_mod\n");
  458. /* if op is not successful, don't increment the counter */
  459. slapi_pblock_get(pb, SLAPI_RESULT_CODE, &rc);
  460. if (LDAP_SUCCESS != rc) {
  461. /* no plugin failure */
  462. rc = SLAPI_PLUGIN_SUCCESS;
  463. goto bail;
  464. }
  465. slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods);
  466. for (i = 0; mods && mods[i]; i++) {
  467. if (0 == strcasecmp(mods[i]->mod_type, SLAPI_ATTR_ENTRYUSN)) {
  468. if (mods[i]->mod_op & LDAP_MOD_IGNORE) {
  469. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  470. "usn_bepostop_mod: MOD_IGNORE detected\n");
  471. goto bail; /* conflict occurred.
  472. skip incrementing the counter. */
  473. } else {
  474. break;
  475. }
  476. }
  477. }
  478. slapi_pblock_get(pb, SLAPI_BACKEND, &be);
  479. if (NULL == be) {
  480. rc = LDAP_PARAM_ERROR;
  481. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &rc);
  482. rc = SLAPI_PLUGIN_FAILURE;
  483. goto bail;
  484. }
  485. if (be->be_usn_counter) {
  486. slapi_counter_increment(be->be_usn_counter);
  487. }
  488. bail:
  489. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  490. "<-- usn_bepostop_mod\n");
  491. return rc;
  492. }
  493. /* count up the counter */
  494. /* if the op is delete and the op was not successful, remove preventryusn */
  495. static int
  496. usn_bepostop_delete (Slapi_PBlock *pb)
  497. {
  498. int rc = SLAPI_PLUGIN_FAILURE;
  499. Slapi_Backend *be = NULL;
  500. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  501. "--> usn_bepostop\n");
  502. /* if op is not successful, don't increment the counter */
  503. slapi_pblock_get(pb, SLAPI_RESULT_CODE, &rc);
  504. if (LDAP_SUCCESS != rc) {
  505. /* no plugin failure */
  506. rc = SLAPI_PLUGIN_SUCCESS;
  507. goto bail;
  508. }
  509. slapi_pblock_get(pb, SLAPI_BACKEND, &be);
  510. if (NULL == be) {
  511. rc = LDAP_PARAM_ERROR;
  512. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &rc);
  513. rc = SLAPI_PLUGIN_FAILURE;
  514. goto bail;
  515. }
  516. if (be->be_usn_counter) {
  517. slapi_counter_increment(be->be_usn_counter);
  518. }
  519. bail:
  520. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  521. "<-- usn_bepostop\n");
  522. return rc;
  523. }
  524. /* mimic replication to turn on create_tombstone_entry */
  525. static int
  526. usn_get_attr(Slapi_PBlock *pb, const char* type, void *value)
  527. {
  528. if (0 == strcasecmp(type, "nsds5ReplicaTombstonePurgeInterval")) {
  529. *(int *)value = 1;
  530. } else {
  531. *(int *)value = 0;
  532. }
  533. return 0;
  534. }
  535. void
  536. usn_set_identity(void *identity)
  537. {
  538. _usn_identity = identity;
  539. }
  540. void *
  541. usn_get_identity()
  542. {
  543. return _usn_identity;
  544. }
  545. /*
  546. * usn_rootdse_search -- callback for the search on root DSN
  547. * add lastusn value per backend
  548. *
  549. * example:
  550. * ldapsearch -b "" -s base "(objectclass=*)" lastusn
  551. * dn:
  552. * lastusn;userroot: 72
  553. * lastusn;testbackend: 15
  554. */
  555. static int
  556. usn_rootdse_search(Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* entryAfter,
  557. int *returncode, char *returntext, void *arg)
  558. {
  559. char *cookie = NULL;
  560. Slapi_Backend *be;
  561. struct berval *vals[2];
  562. struct berval usn_berval;
  563. vals[0] = &usn_berval;
  564. vals[1] = NULL;
  565. char counter_buf[USN_COUNTER_BUF_LEN];
  566. int attr_len = 64; /* length of lastusn;<backend_name> */
  567. char *attr = (char *)slapi_ch_malloc(attr_len);
  568. char *attr_subp = NULL;
  569. int isglobal = config_get_entryusn_global();
  570. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  571. "--> usn_rootdse_search\n");
  572. usn_berval.bv_val = counter_buf;
  573. if (isglobal) {
  574. /* nsslapd-entryusn-global: on*/
  575. /* root dse shows ...
  576. * lastusn: <num> */
  577. PR_snprintf(attr, USN_LAST_USN_ATTR_CORE_LEN + 1, "%s", USN_LAST_USN);
  578. for (be = slapi_get_first_backend(&cookie); be;
  579. be = slapi_get_next_backend(cookie)) {
  580. if (be->be_usn_counter) {
  581. break;
  582. }
  583. }
  584. if (be && be->be_usn_counter) {
  585. /* get a next USN counter from be_usn_counter;
  586. * then minus 1 from it (except if be_usn_counter has value 0) */
  587. if (slapi_counter_get_value(be->be_usn_counter)) {
  588. PR_snprintf(usn_berval.bv_val, USN_COUNTER_BUF_LEN, "%" NSPRIu64,
  589. slapi_counter_get_value(be->be_usn_counter)-1);
  590. } else {
  591. PR_snprintf(usn_berval.bv_val, USN_COUNTER_BUF_LEN, "-1");
  592. }
  593. usn_berval.bv_len = strlen(usn_berval.bv_val);
  594. slapi_entry_attr_replace(e, attr, vals);
  595. }
  596. } else {
  597. /* nsslapd-entryusn-global: off (default) */
  598. /* root dse shows ...
  599. * lastusn;<backend>: <num> */
  600. PR_snprintf(attr, USN_LAST_USN_ATTR_CORE_LEN + 2, "%s;", USN_LAST_USN);
  601. attr_subp = attr + USN_LAST_USN_ATTR_CORE_LEN + 1;
  602. for (be = slapi_get_first_backend(&cookie); be;
  603. be = slapi_get_next_backend(cookie)) {
  604. if (NULL == be->be_usn_counter) {
  605. /* no counter == not a db backend */
  606. continue;
  607. }
  608. /* get a next USN counter from be_usn_counter;
  609. * then minus 1 from it (except if be_usn_counter has value 0) */
  610. if (slapi_counter_get_value(be->be_usn_counter)) {
  611. PR_snprintf(usn_berval.bv_val, USN_COUNTER_BUF_LEN, "%" NSPRIu64,
  612. slapi_counter_get_value(be->be_usn_counter)-1);
  613. } else {
  614. PR_snprintf(usn_berval.bv_val, USN_COUNTER_BUF_LEN, "-1");
  615. }
  616. usn_berval.bv_len = strlen(usn_berval.bv_val);
  617. if (USN_LAST_USN_ATTR_CORE_LEN+strlen(be->be_name)+2 > attr_len) {
  618. attr_len *= 2;
  619. attr = (char *)slapi_ch_realloc(attr, attr_len);
  620. attr_subp = attr + USN_LAST_USN_ATTR_CORE_LEN;
  621. }
  622. PR_snprintf(attr_subp, attr_len - USN_LAST_USN_ATTR_CORE_LEN,
  623. "%s", be->be_name);
  624. slapi_entry_attr_replace(e, attr, vals);
  625. }
  626. }
  627. slapi_ch_free_string(&cookie);
  628. slapi_ch_free_string(&attr);
  629. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  630. "<-- usn_rootdse_search\n");
  631. return SLAPI_DSE_CALLBACK_OK;
  632. }