usn.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2009 Red Hat, Inc.
  35. * All rights reserved.
  36. * END COPYRIGHT BLOCK **/
  37. #ifdef HAVE_CONFIG_H
  38. # include <config.h>
  39. #endif
  40. #include "usn.h"
  41. static Slapi_PluginDesc pdesc = {
  42. "USN", VENDOR, DS_PACKAGE_VERSION,
  43. "USN (Update Sequence Number) plugin" };
  44. static CSNGen *_usn_csngen = NULL;
  45. static void *_usn_identity = NULL;
  46. static int usn_preop_init(Slapi_PBlock *pb);
  47. static int usn_bepreop_init(Slapi_PBlock *pb);
  48. static int usn_bepostop_init(Slapi_PBlock *pb);
  49. static int usn_rootdse_init();
  50. static int usn_preop_delete(Slapi_PBlock *pb);
  51. static int usn_bepreop_add(Slapi_PBlock *pb);
  52. static int usn_bepreop_delete(Slapi_PBlock *pb);
  53. static int usn_bepreop_modify(Slapi_PBlock *pb);
  54. static int usn_bepostop(Slapi_PBlock *pb);
  55. static int usn_bepostop_delete (Slapi_PBlock *pb);
  56. static int usn_bepostop_modify (Slapi_PBlock *pb);
  57. static int usn_start(Slapi_PBlock *pb);
  58. static int usn_close(Slapi_PBlock *pb);
  59. static int usn_get_attr(Slapi_PBlock *pb, const char* type, void *value);
  60. static int usn_rootdse_search(Slapi_PBlock *pb, Slapi_Entry* e,
  61. Slapi_Entry* entryAfter, int *returncode, char *returntext, void *arg);
  62. static int g_plugin_started = 0;
  63. /*
  64. * Register USN plugin
  65. * Note: USN counter initialization is done in the backend (ldbm_usn_init).
  66. */
  67. int
  68. usn_init(Slapi_PBlock *pb)
  69. {
  70. int rc = 0;
  71. void *identity = NULL;
  72. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  73. "--> usn_init\n");
  74. slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY, &identity);
  75. /* slapi_register_plugin always returns SUCCESS (0) */
  76. if (slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION,
  77. SLAPI_PLUGIN_VERSION_01) != 0 ||
  78. slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION,
  79. (void *)&pdesc) != 0) {
  80. slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
  81. "usn_init: failed to register version & description\n");
  82. rc = -1;
  83. goto bail;
  84. }
  85. if (slapi_pblock_set(pb, SLAPI_PLUGIN_START_FN,
  86. (void *)usn_start) != 0 ||
  87. slapi_pblock_set(pb, SLAPI_PLUGIN_CLOSE_FN,
  88. (void *)usn_close) != 0 ) {
  89. slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
  90. "usn_init: failed to register close callback & task\n");
  91. rc = -1;
  92. goto bail;
  93. }
  94. rc = slapi_register_plugin("preoperation", 1 /* Enabled */,
  95. "usn_preop_init", usn_preop_init,
  96. "USN preoperation plugin", NULL, identity);
  97. rc |= slapi_register_plugin("bepreoperation", 1 /* Enabled */,
  98. "usn_bepreop_init", usn_bepreop_init,
  99. "USN bepreoperation plugin", NULL, identity);
  100. rc |= slapi_register_plugin("bepostoperation", 1 /* Enabled */,
  101. "usn_bepostop_init", usn_bepostop_init,
  102. "USN bepostoperation plugin", NULL, identity);
  103. usn_set_identity(identity);
  104. bail:
  105. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  106. "<-- usn_init\n");
  107. return rc;
  108. }
  109. static int
  110. usn_preop_init(Slapi_PBlock *pb)
  111. {
  112. int rc = 0;
  113. /* set up csn generator for tombstone */
  114. _usn_csngen = csngen_new(USN_CSNGEN_ID, NULL);
  115. if (NULL == _usn_csngen) {
  116. slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
  117. "usn_preop_init: csngen_new failed\n");
  118. rc = -1;
  119. }
  120. if (slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_DELETE_FN,
  121. (void *)usn_preop_delete) != 0) {
  122. slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
  123. "usn_preop_init: failed to register preop plugin\n");
  124. rc = -1;
  125. }
  126. return rc;
  127. }
  128. static int
  129. usn_bepreop_init(Slapi_PBlock *pb)
  130. {
  131. int rc = 0;
  132. if (slapi_pblock_set(pb, SLAPI_PLUGIN_BE_PRE_ADD_FN,
  133. (void *)usn_bepreop_add) != 0 ||
  134. slapi_pblock_set(pb, SLAPI_PLUGIN_BE_PRE_DELETE_FN,
  135. (void *)usn_bepreop_delete) != 0 ||
  136. slapi_pblock_set(pb, SLAPI_PLUGIN_BE_PRE_MODIFY_FN,
  137. (void *)usn_bepreop_modify) != 0 ||
  138. slapi_pblock_set(pb, SLAPI_PLUGIN_BE_PRE_MODRDN_FN,
  139. (void *)usn_bepreop_modify) != 0) {
  140. slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
  141. "usn_bepreop_init: failed to register bepreop plugin\n");
  142. rc = -1;
  143. }
  144. return rc;
  145. }
  146. static int
  147. usn_bepostop_init(Slapi_PBlock *pb)
  148. {
  149. int rc = 0;
  150. if (slapi_pblock_set(pb, SLAPI_PLUGIN_BE_POST_ADD_FN,
  151. (void *)usn_bepostop) != 0 ||
  152. slapi_pblock_set(pb, SLAPI_PLUGIN_BE_POST_DELETE_FN,
  153. (void *)usn_bepostop_delete) != 0 ||
  154. slapi_pblock_set(pb, SLAPI_PLUGIN_BE_POST_MODIFY_FN,
  155. (void *)usn_bepostop_modify) != 0 ||
  156. slapi_pblock_set(pb, SLAPI_PLUGIN_BE_POST_MODRDN_FN,
  157. (void *)usn_bepostop) != 0) {
  158. slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
  159. "usn_bepostop_init: failed to register bepostop plugin\n");
  160. rc = -1;
  161. }
  162. return rc;
  163. }
  164. static int
  165. usn_rootdse_init()
  166. {
  167. int rc = -1;
  168. if (slapi_config_register_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP,
  169. "", LDAP_SCOPE_BASE, "(objectclass=*)",
  170. usn_rootdse_search, NULL)) {
  171. rc = 0;
  172. }
  173. return rc;
  174. }
  175. /*
  176. * usn_start: usn_rootdse_init -- set rootdse callback to aggregate in rootDSE
  177. * usn_cleanup_start -- initialize USN tombstone cleanup task
  178. */
  179. static int
  180. usn_start(Slapi_PBlock *pb)
  181. {
  182. int rc = 0;
  183. Slapi_Value *value;
  184. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM, "--> usn_start\n");
  185. rc = usn_rootdse_init();
  186. rc |= usn_cleanup_start(pb);
  187. if (rc) {
  188. goto bail;
  189. }
  190. if (0) { /* Not executed; test code for slapi_get_plugin_default_config */
  191. Slapi_ValueSet *vs = NULL;
  192. Slapi_Value *v = NULL;
  193. int i;
  194. slapi_get_plugin_default_config("nsds5ReplicatedAttributeList", &vs);
  195. if (vs) {
  196. for (i = slapi_valueset_first_value(vs, &v);
  197. i != -1;
  198. i = slapi_valueset_next_value(vs, i, &v)) {
  199. slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
  200. "nsds5ReplicatedAttributeList: %s\n",
  201. slapi_value_get_string(v));
  202. }
  203. }
  204. slapi_valueset_free(vs);
  205. }
  206. /* add nsds5ReplicatedAttributeList: (objectclass=*) $ EXCLUDE entryusn
  207. * to cn=plugin default config,cn=config */
  208. value = slapi_value_new_string("(objectclass=*) $ EXCLUDE entryusn");
  209. rc = slapi_set_plugin_default_config("nsds5ReplicatedAttributeList", value);
  210. slapi_value_free(&value);
  211. g_plugin_started = 1;
  212. bail:
  213. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  214. "<-- usn_start (rc: %d)\n", rc);
  215. return rc;
  216. }
  217. /*
  218. * usn_close: release the csn generator used to convert an entry to tombstone
  219. */
  220. static int
  221. usn_close(Slapi_PBlock *pb)
  222. {
  223. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM, "--> usn_close\n");
  224. csngen_free(&_usn_csngen);
  225. g_plugin_started = 0;
  226. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM, "<-- usn_close\n");
  227. return 0;
  228. }
  229. /*
  230. * usn_preop_delete -- set params to turn the entry to tombstone
  231. */
  232. static int
  233. usn_preop_delete(Slapi_PBlock *pb)
  234. {
  235. int rc = 0;
  236. CSN *csn = NULL;
  237. CSN *orig_csn = NULL;
  238. Slapi_Operation *op = NULL;
  239. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  240. "--> usn_preop_delete\n");
  241. slapi_pblock_get(pb, SLAPI_OPERATION, &op);
  242. orig_csn = operation_get_csn(op);
  243. if (NULL == orig_csn) {
  244. /*
  245. * No other plugins hasn't set csn yet, so let's set USN's csn.
  246. * If other plugin overrides csn and replica_attr_handler, that's fine.
  247. */
  248. rc = csngen_new_csn(_usn_csngen, &csn, PR_FALSE /* notify */);
  249. if (CSN_SUCCESS != rc) {
  250. slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
  251. "usn_preop_delete: csngen_new failed (%d)\n", rc);
  252. csn_free(&csn);
  253. goto bail;
  254. }
  255. operation_set_csn(op, csn);
  256. slapi_operation_set_replica_attr_handler(op, (void *)usn_get_attr);
  257. }
  258. bail:
  259. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  260. "<-- usn_preop_delete\n");
  261. return rc;
  262. }
  263. #define KEEP_PREV_USN 1
  264. static void
  265. _usn_add_next_usn(Slapi_Entry *e, Slapi_Backend *be, int flags)
  266. {
  267. struct berval usn_berval = {0};
  268. Slapi_Attr* attr = NULL;
  269. if (NULL == be->be_usn_counter) {
  270. /* USN plugin is not enabled */
  271. return;
  272. }
  273. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  274. "--> _usn_add_next_usn\n");
  275. /* add next USN to the entry; "be" contains the usn counter */
  276. usn_berval.bv_val = slapi_ch_smprintf("%" NSPRIu64,
  277. slapi_counter_get_value(be->be_usn_counter));
  278. usn_berval.bv_len = strlen(usn_berval.bv_val);
  279. slapi_entry_attr_find(e, SLAPI_ATTR_ENTRYUSN, &attr);
  280. if (NULL == attr) { /* ENTRYUSN does not exist; add it */
  281. Slapi_Value *usn_value = slapi_value_new_berval(&usn_berval);
  282. slapi_entry_add_value(e, SLAPI_ATTR_ENTRYUSN, usn_value);
  283. slapi_value_free(&usn_value);
  284. } else { /* ENTRYUSN exists; replace it */
  285. struct berval *new_bvals[2];
  286. struct berval **prev_values = NULL;
  287. if (KEEP_PREV_USN == flags) {
  288. if (0 == slapi_attr_get_bervals_copy(attr, &prev_values)) {
  289. slapi_entry_add_values(e,
  290. SLAPI_ATTR_ENTRYUSN_PREV, prev_values);
  291. ber_bvecfree(prev_values);
  292. }
  293. }
  294. new_bvals[0] = &usn_berval;
  295. new_bvals[1] = NULL;
  296. slapi_entry_attr_replace(e, SLAPI_ATTR_ENTRYUSN, new_bvals);
  297. }
  298. slapi_ch_free_string(&usn_berval.bv_val);
  299. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  300. "<-- _usn_add_next_usn\n");
  301. return;
  302. }
  303. static int
  304. _usn_mod_next_usn(LDAPMod ***mods, Slapi_Backend *be)
  305. {
  306. Slapi_Mods smods = {0};
  307. struct berval *bvals[2];
  308. struct berval usn_berval = {0};
  309. char counter_buf[USN_COUNTER_BUF_LEN];
  310. if (NULL == be->be_usn_counter) {
  311. /* USN plugin is not enabled */
  312. return LDAP_UNWILLING_TO_PERFORM;
  313. }
  314. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  315. "--> _usn_mod_next_usn\n");
  316. /* add next USN to the mods; "be" contains the usn counter */
  317. usn_berval.bv_val = counter_buf;
  318. PR_snprintf(usn_berval.bv_val, USN_COUNTER_BUF_LEN, "%" NSPRIu64,
  319. slapi_counter_get_value(be->be_usn_counter));
  320. usn_berval.bv_len = strlen(usn_berval.bv_val);
  321. bvals[0] = &usn_berval;
  322. bvals[1] = NULL;
  323. slapi_mods_init_passin(&smods, *mods);
  324. /* bvals is duplicated by ber_bvdup in slapi_mods_add_modbvps */
  325. slapi_mods_add_modbvps(&smods, LDAP_MOD_REPLACE | LDAP_MOD_BVALUES,
  326. SLAPI_ATTR_ENTRYUSN, bvals);
  327. *mods = slapi_mods_get_ldapmods_passout(&smods);
  328. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  329. "<-- _usn_mod_next_usn\n");
  330. return LDAP_SUCCESS;
  331. }
  332. /*
  333. * usn_bepreop_add - add next USN to the entry to be added
  334. */
  335. static int
  336. usn_bepreop_add(Slapi_PBlock *pb)
  337. {
  338. Slapi_Entry *e = NULL;
  339. Slapi_Backend *be = NULL;
  340. int rc = LDAP_SUCCESS;
  341. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  342. "--> usn_bepreop_add\n");
  343. /* add next USN to the entry; "be" contains the usn counter */
  344. slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &e);
  345. if (NULL == e) {
  346. rc = LDAP_NO_SUCH_OBJECT;
  347. goto bail;
  348. }
  349. slapi_pblock_get(pb, SLAPI_BACKEND, &be);
  350. if (NULL == be) {
  351. rc = LDAP_PARAM_ERROR;
  352. goto bail;
  353. }
  354. _usn_add_next_usn(e, be, 0);
  355. bail:
  356. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  357. "<-- usn_bepreop_add\n");
  358. return rc;
  359. }
  360. /*
  361. * usn_bepreop_delete -- add/replace next USN to the entry
  362. * bepreop_delete is not called if the entry is tombstone
  363. */
  364. static int
  365. usn_bepreop_delete(Slapi_PBlock *pb)
  366. {
  367. Slapi_Entry *e = NULL;
  368. Slapi_Backend *be = NULL;
  369. int rc = LDAP_SUCCESS;
  370. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  371. "--> usn_bepreop_delete\n");
  372. /* add next USN to the entry; "be" contains the usn counter */
  373. slapi_pblock_get(pb, SLAPI_DELETE_BEPREOP_ENTRY, &e);
  374. if (NULL == e) {
  375. rc = LDAP_NO_SUCH_OBJECT;
  376. goto bail;
  377. }
  378. slapi_pblock_get(pb, SLAPI_BACKEND, &be);
  379. if (NULL == be) {
  380. rc = LDAP_PARAM_ERROR;
  381. goto bail;
  382. }
  383. if (e->e_flags & SLAPI_ENTRY_FLAG_TOMBSTONE) {
  384. Slapi_Operation *op = NULL;
  385. slapi_pblock_get(pb, SLAPI_OPERATION, &op);
  386. slapi_operation_set_flag(op, OP_FLAG_TOMBSTONE_ENTRY);
  387. } else {
  388. _usn_add_next_usn(e, be, KEEP_PREV_USN);
  389. }
  390. bail:
  391. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  392. "<-- usn_bepreop_delete\n");
  393. return rc;
  394. }
  395. /*
  396. * usn_bepreop_modify - add/replace next USN to the mods;
  397. * shared by modify and modrdn
  398. */
  399. static int
  400. usn_bepreop_modify (Slapi_PBlock *pb)
  401. {
  402. LDAPMod **mods = NULL;
  403. Slapi_Backend *be = NULL;
  404. int rc = LDAP_SUCCESS;
  405. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  406. "--> usn_bepreop_modify\n");
  407. /* add/replace next USN to the mods; "be" contains the usn counter */
  408. slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods);
  409. slapi_pblock_get(pb, SLAPI_BACKEND, &be);
  410. if (NULL == be) {
  411. rc = LDAP_PARAM_ERROR;
  412. goto bail;
  413. }
  414. if (LDAP_SUCCESS == _usn_mod_next_usn(&mods, be)) {
  415. slapi_pblock_set(pb, SLAPI_MODIFY_MODS, mods);
  416. }
  417. bail:
  418. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  419. "<-- usn_bepreop_modify\n");
  420. return rc;
  421. }
  422. /* count up the counter */
  423. static int
  424. usn_bepostop (Slapi_PBlock *pb)
  425. {
  426. int rc = -1;
  427. Slapi_Backend *be = NULL;
  428. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  429. "--> usn_bepostop\n");
  430. /* if op is not successful, don't increment the counter */
  431. slapi_pblock_get(pb, SLAPI_RESULT_CODE, &rc);
  432. if (LDAP_SUCCESS != rc) {
  433. goto bail;
  434. }
  435. slapi_pblock_get(pb, SLAPI_BACKEND, &be);
  436. if (NULL == be) {
  437. rc = LDAP_PARAM_ERROR;
  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 = -1;
  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. goto bail;
  462. }
  463. slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods);
  464. for (i = 0; mods && mods[i]; i++) {
  465. if (0 == strcasecmp(mods[i]->mod_type, SLAPI_ATTR_ENTRYUSN)) {
  466. if (mods[i]->mod_op & LDAP_MOD_IGNORE) {
  467. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  468. "usn_bepostop_mod: MOD_IGNORE detected\n");
  469. goto bail; /* conflict occurred.
  470. skip incrementing the counter. */
  471. } else {
  472. break;
  473. }
  474. }
  475. }
  476. slapi_pblock_get(pb, SLAPI_BACKEND, &be);
  477. if (NULL == be) {
  478. rc = LDAP_PARAM_ERROR;
  479. goto bail;
  480. }
  481. if (be->be_usn_counter) {
  482. slapi_counter_increment(be->be_usn_counter);
  483. }
  484. bail:
  485. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  486. "<-- usn_bepostop_mod\n");
  487. return rc;
  488. }
  489. /* count up the counter */
  490. /* if the op is delete and the op was not successful, remove preventryusn */
  491. static int
  492. usn_bepostop_delete (Slapi_PBlock *pb)
  493. {
  494. int rc = -1;
  495. Slapi_Backend *be = NULL;
  496. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  497. "--> usn_bepostop\n");
  498. /* if op is not successful, don't increment the counter */
  499. slapi_pblock_get(pb, SLAPI_RESULT_CODE, &rc);
  500. if (LDAP_SUCCESS != rc) {
  501. Slapi_Entry *e = NULL;
  502. slapi_pblock_get(pb, SLAPI_DELETE_BEPOSTOP_ENTRY, &e);
  503. if (NULL == e) {
  504. rc = LDAP_NO_SUCH_OBJECT;
  505. goto bail;
  506. }
  507. /* okay to return the rc from slapi_entry_delete_values */
  508. rc = slapi_entry_delete_values(e, SLAPI_ATTR_ENTRYUSN_PREV, NULL);
  509. goto bail;
  510. }
  511. slapi_pblock_get(pb, SLAPI_BACKEND, &be);
  512. if (NULL == be) {
  513. rc = LDAP_PARAM_ERROR;
  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 */
  587. PR_snprintf(usn_berval.bv_val, USN_COUNTER_BUF_LEN, "%" NSPRI64 "d",
  588. slapi_counter_get_value(be->be_usn_counter)-1);
  589. usn_berval.bv_len = strlen(usn_berval.bv_val);
  590. slapi_entry_attr_replace(e, attr, vals);
  591. }
  592. } else {
  593. /* nsslapd-entryusn-global: off (default) */
  594. /* root dse shows ...
  595. * lastusn;<backend>: <num> */
  596. PR_snprintf(attr, USN_LAST_USN_ATTR_CORE_LEN + 2, "%s;", USN_LAST_USN);
  597. attr_subp = attr + USN_LAST_USN_ATTR_CORE_LEN + 1;
  598. for (be = slapi_get_first_backend(&cookie); be;
  599. be = slapi_get_next_backend(cookie)) {
  600. if (NULL == be->be_usn_counter) {
  601. /* no counter == not a db backend */
  602. continue;
  603. }
  604. /* get a next USN counter from be_usn_counter;
  605. * then minus 1 from it */
  606. PR_snprintf(usn_berval.bv_val, USN_COUNTER_BUF_LEN, "%" NSPRI64 "d",
  607. slapi_counter_get_value(be->be_usn_counter)-1);
  608. usn_berval.bv_len = strlen(usn_berval.bv_val);
  609. if (USN_LAST_USN_ATTR_CORE_LEN+strlen(be->be_name)+2 > attr_len) {
  610. attr_len *= 2;
  611. attr = (char *)slapi_ch_realloc(attr, attr_len);
  612. attr_subp = attr + USN_LAST_USN_ATTR_CORE_LEN;
  613. }
  614. PR_snprintf(attr_subp, attr_len - USN_LAST_USN_ATTR_CORE_LEN,
  615. "%s", be->be_name);
  616. slapi_entry_attr_replace(e, attr, vals);
  617. }
  618. }
  619. slapi_ch_free_string(&cookie);
  620. slapi_ch_free_string(&attr);
  621. slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM,
  622. "<-- usn_rootdse_search\n");
  623. return SLAPI_DSE_CALLBACK_OK;
  624. }
  625. int
  626. usn_is_started()
  627. {
  628. return g_plugin_started;
  629. }