sync_init.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright (C) 2013 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. #include "sync.h"
  9. static Slapi_PluginDesc pdesc = {PLUGIN_NAME, VENDOR, DS_PACKAGE_VERSION, "Context Synchronization (RFC4533) plugin"};
  10. static int sync_start(Slapi_PBlock *pb);
  11. static int sync_close(Slapi_PBlock *pb);
  12. static int sync_preop_init(Slapi_PBlock *pb);
  13. static int sync_postop_init(Slapi_PBlock *pb);
  14. static int sync_be_postop_init(Slapi_PBlock *pb);
  15. static int sync_betxn_preop_init(Slapi_PBlock *pb);
  16. static int sync_persist_register_operation_extension(void);
  17. static PRUintn thread_primary_op;
  18. /*
  19. * Destructor for the per-thread primary operation list HEAD node.
  20. * Called by NSPR when a thread exits, to free the HEAD node
  21. * and any remaining linked list entries.
  22. */
  23. static void
  24. sync_thread_primary_op_destructor(void *priv)
  25. {
  26. OPERATION_PL_CTX_T *head = (OPERATION_PL_CTX_T *)priv;
  27. if (head) {
  28. OPERATION_PL_CTX_T *curr_op = head->next;
  29. while (curr_op) {
  30. OPERATION_PL_CTX_T *next = curr_op->next;
  31. slapi_entry_free(curr_op->entry);
  32. slapi_entry_free(curr_op->eprev);
  33. slapi_ch_free((void **)&curr_op);
  34. curr_op = next;
  35. }
  36. slapi_ch_free((void **)&head);
  37. }
  38. }
  39. int
  40. sync_init(Slapi_PBlock *pb)
  41. {
  42. char *plugin_identity = NULL;
  43. int rc = 0;
  44. slapi_log_err(SLAPI_LOG_PLUGIN, SYNC_PLUGIN_SUBSYSTEM,
  45. "--> sync_init\n");
  46. /**
  47. * Store the plugin identity for later use.
  48. * Used for internal operations
  49. */
  50. slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY, &plugin_identity);
  51. PR_ASSERT(plugin_identity);
  52. if (slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION,
  53. SLAPI_PLUGIN_VERSION_01) != 0 ||
  54. slapi_pblock_set(pb, SLAPI_PLUGIN_START_FN,
  55. (void *)sync_start) != 0 ||
  56. slapi_pblock_set(pb, SLAPI_PLUGIN_CLOSE_FN,
  57. (void *)sync_close) != 0 ||
  58. slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION,
  59. (void *)&pdesc) != 0 ||
  60. sync_persist_register_operation_extension()) {
  61. slapi_log_err(SLAPI_LOG_ERR, SYNC_PLUGIN_SUBSYSTEM,
  62. "sync_init - Failed to register plugin\n");
  63. rc = 1;
  64. }
  65. if (rc == 0) {
  66. char *plugin_type = "preoperation";
  67. /* the config change checking post op */
  68. if (slapi_register_plugin(
  69. plugin_type,
  70. 1, /* Enabled */
  71. "sync_init", /* this function desc */
  72. sync_preop_init, /* init func for post op */
  73. SYNC_PREOP_DESC, /* plugin desc */
  74. NULL,
  75. plugin_identity)) {
  76. slapi_log_err(SLAPI_LOG_ERR, SYNC_PLUGIN_SUBSYSTEM,
  77. "sync_init - Failed to register preop plugin\n");
  78. rc = 1;
  79. }
  80. }
  81. if (rc == 0) {
  82. char *plugin_type = "postoperation";
  83. /* the config change checking post op */
  84. if (slapi_register_plugin(plugin_type,
  85. 1, /* Enabled */
  86. "sync_init", /* this function desc */
  87. sync_postop_init, /* init func for post op */
  88. SYNC_POSTOP_DESC, /* plugin desc */
  89. NULL,
  90. plugin_identity)) {
  91. slapi_log_err(SLAPI_LOG_ERR, SYNC_PLUGIN_SUBSYSTEM,
  92. "sync_init - Failed to register postop plugin\n");
  93. rc = 1;
  94. }
  95. }
  96. if (rc == 0) {
  97. char *plugin_type = "betxnpreoperation";
  98. /* the config change checking post op */
  99. if (slapi_register_plugin(plugin_type,
  100. 1, /* Enabled */
  101. "sync_init", /* this function desc */
  102. sync_betxn_preop_init, /* init func for post op */
  103. SYNC_BETXN_PREOP_DESC, /* plugin desc */
  104. NULL,
  105. plugin_identity)) {
  106. slapi_log_err(SLAPI_LOG_ERR, SYNC_PLUGIN_SUBSYSTEM,
  107. "sync_init - Failed to register be_txn_pre_op plugin\n");
  108. rc = 1;
  109. }
  110. }
  111. if (rc == 0) {
  112. char *plugin_type = "bepostoperation";
  113. /* the config change checking post op */
  114. if (slapi_register_plugin(plugin_type,
  115. 1, /* Enabled */
  116. "sync_init", /* this function desc */
  117. sync_be_postop_init, /* init func for be_post op */
  118. SYNC_BE_POSTOP_DESC, /* plugin desc */
  119. NULL,
  120. plugin_identity)) {
  121. slapi_log_err(SLAPI_LOG_ERR, SYNC_PLUGIN_SUBSYSTEM,
  122. "sync_init - Failed to register be_txn_pre_op plugin\n");
  123. rc = 1;
  124. }
  125. }
  126. return (rc);
  127. }
  128. static int
  129. sync_preop_init(Slapi_PBlock *pb)
  130. {
  131. int rc;
  132. rc = slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_SEARCH_FN, (void *)sync_srch_refresh_pre_search);
  133. rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_ENTRY_FN, (void *)sync_srch_refresh_pre_entry);
  134. rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_RESULT_FN, (void *)sync_srch_refresh_pre_result);
  135. rc |= sync_register_operation_extension();
  136. return (rc);
  137. }
  138. static int
  139. sync_postop_init(Slapi_PBlock *pb)
  140. {
  141. int rc;
  142. rc = slapi_pblock_set(pb, SLAPI_PLUGIN_POST_SEARCH_FN, (void *)sync_srch_refresh_post_search);
  143. return (rc);
  144. }
  145. static int
  146. sync_be_postop_init(Slapi_PBlock *pb)
  147. {
  148. int rc;
  149. rc = slapi_pblock_set(pb, SLAPI_PLUGIN_BE_POST_ADD_FN, (void *)sync_add_persist_post_op);
  150. rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_BE_POST_DELETE_FN, (void *)sync_del_persist_post_op);
  151. rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_BE_POST_MODIFY_FN, (void *)sync_mod_persist_post_op);
  152. rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_BE_POST_MODRDN_FN, (void *)sync_modrdn_persist_post_op);
  153. return (rc);
  154. }
  155. static int
  156. sync_betxn_preop_init(Slapi_PBlock *pb)
  157. {
  158. int rc;
  159. rc = slapi_pblock_set(pb, SLAPI_PLUGIN_BE_TXN_PRE_ADD_FN, (void *)sync_update_persist_betxn_pre_op);
  160. rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_BE_TXN_PRE_DELETE_FN, (void *)sync_update_persist_betxn_pre_op);
  161. rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_BE_TXN_PRE_MODIFY_FN, (void *)sync_update_persist_betxn_pre_op);
  162. rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_BE_TXN_PRE_MODRDN_FN, (void *)sync_update_persist_betxn_pre_op);
  163. return (rc);
  164. }
  165. /*
  166. sync_start
  167. --------------
  168. Register the Content Synchronization Control.
  169. Initialize locks and queues for the persitent phase.
  170. */
  171. static int
  172. sync_start(Slapi_PBlock *pb)
  173. {
  174. int argc;
  175. char **argv;
  176. Slapi_Entry *e = NULL;
  177. PRBool allow_openldap_compat = PR_FALSE;
  178. slapi_register_supported_control(LDAP_CONTROL_SYNC,
  179. SLAPI_OPERATION_SEARCH);
  180. slapi_log_err(SLAPI_LOG_PLUGIN, SYNC_PLUGIN_SUBSYSTEM,
  181. "--> sync_start\n");
  182. if (slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &e) != 0) {
  183. slapi_log_err(SLAPI_LOG_PLUGIN, SYNC_PLUGIN_SUBSYSTEM, " sync_start, no config found, that's okay 👍\n");
  184. }
  185. if (e) {
  186. /* Do we allow openldap sync? */
  187. Slapi_Attr *chattr = NULL;
  188. if (slapi_entry_attr_find(e, SYNC_ALLOW_OPENLDAP_COMPAT, &chattr) == 0) {
  189. Slapi_Value *sval = NULL;
  190. slapi_attr_first_value(chattr, &sval);
  191. const struct berval *value = slapi_value_get_berval(sval);
  192. if (NULL != value && NULL != value->bv_val && '\0' != value->bv_val[0]) {
  193. if (strcasecmp(value->bv_val, "on") == 0) {
  194. allow_openldap_compat = PR_TRUE;
  195. }
  196. }
  197. }
  198. }
  199. sync_register_allow_openldap_compat(allow_openldap_compat);
  200. if (slapi_pblock_get(pb, SLAPI_PLUGIN_ARGC, &argc) != 0 ||
  201. slapi_pblock_get(pb, SLAPI_PLUGIN_ARGV, &argv) != 0) {
  202. slapi_log_err(SLAPI_LOG_ERR, SYNC_PLUGIN_SUBSYSTEM,
  203. "sync_start - Unable to get arguments\n");
  204. return (-1);
  205. }
  206. /* It registers a per thread 'thread_primary_op' variable that is
  207. * a list of pending operations. For simple operation, this list
  208. * only contains one operation. For nested, the list contains the operations
  209. * in the order that they were applied
  210. */
  211. PR_NewThreadPrivateIndex(&thread_primary_op, sync_thread_primary_op_destructor);
  212. sync_persist_initialize(argc, argv);
  213. return (0);
  214. }
  215. /*
  216. sync_close
  217. --------------
  218. Free locks and queues allocated.
  219. */
  220. static int
  221. sync_close(Slapi_PBlock *pb __attribute__((unused)))
  222. {
  223. sync_persist_terminate_all();
  224. sync_unregister_operation_entension();
  225. return (0);
  226. }
  227. /* Return the head of the operations list
  228. * the head is the primary operation.
  229. * The list is private to that thread and contains
  230. * all nested operations applied by the thread.
  231. */
  232. OPERATION_PL_CTX_T *
  233. get_thread_primary_op(void)
  234. {
  235. OPERATION_PL_CTX_T *head = NULL;
  236. head = (OPERATION_PL_CTX_T *)PR_GetThreadPrivate(thread_primary_op);
  237. if (head == NULL) {
  238. /* if it was not initialized set it to zero */
  239. head = (OPERATION_PL_CTX_T *) slapi_ch_calloc(1, sizeof(OPERATION_PL_CTX_T));
  240. head->flags = OPERATION_PL_HEAD;
  241. PR_SetThreadPrivate(thread_primary_op, head);
  242. }
  243. return head->next;
  244. }
  245. /* It is set with a non NULL op when this is a primary operation
  246. * else it set to NULL when the all pending list has be flushed.
  247. * The list is flushed when no more operations (in that list) are
  248. * pending (OPERATION_PL_PENDING).
  249. */
  250. void
  251. set_thread_primary_op(OPERATION_PL_CTX_T *op)
  252. {
  253. OPERATION_PL_CTX_T *head;
  254. head = (OPERATION_PL_CTX_T *) PR_GetThreadPrivate(thread_primary_op);
  255. if (head == NULL) {
  256. /* if it was not initialized set it to zero */
  257. head = (OPERATION_PL_CTX_T *) slapi_ch_calloc(1, sizeof(OPERATION_PL_CTX_T));
  258. head->flags = OPERATION_PL_HEAD;
  259. PR_SetThreadPrivate(thread_primary_op, (void *) head);
  260. }
  261. head->next = op;
  262. }
  263. /* The following definitions are used for the operation pending list
  264. * (used by sync_repl). To retrieve a specific operation in the pending
  265. * list, the operation extension contains the index of the operation in
  266. * the pending list
  267. */
  268. static int sync_persist_extension_type; /* initialized in sync_persist_register_operation_extension */
  269. static int sync_persist_extension_handle; /* initialized in sync_persist_register_operation_extension */
  270. op_ext_ident_t *
  271. sync_persist_get_operation_extension(Slapi_PBlock *pb)
  272. {
  273. Slapi_Operation *op;
  274. op_ext_ident_t *ident;
  275. slapi_pblock_get(pb, SLAPI_OPERATION, &op);
  276. ident = slapi_get_object_extension(sync_persist_extension_type, op,
  277. sync_persist_extension_handle);
  278. slapi_log_err(SLAPI_LOG_PLUGIN, SYNC_PLUGIN_SUBSYSTEM, "sync_persist_get_operation_extension operation (op=0x%lx) -> %d\n",
  279. (ulong) op, ident ? ident->idx_pl : -1);
  280. return (op_ext_ident_t *) ident;
  281. }
  282. void
  283. sync_persist_set_operation_extension(Slapi_PBlock *pb, op_ext_ident_t *op_ident)
  284. {
  285. Slapi_Operation *op;
  286. slapi_pblock_get(pb, SLAPI_OPERATION, &op);
  287. slapi_log_err(SLAPI_LOG_PLUGIN, SYNC_PLUGIN_SUBSYSTEM, "sync_persist_set_operation_extension operation (op=0x%lx) -> %d\n",
  288. (ulong) op, op_ident ? op_ident->idx_pl : -1);
  289. slapi_set_object_extension(sync_persist_extension_type, op,
  290. sync_persist_extension_handle, (void *)op_ident);
  291. }
  292. /* operation extension constructor */
  293. static void *
  294. sync_persist_operation_extension_constructor(void *object __attribute__((unused)), void *parent __attribute__((unused)))
  295. {
  296. /* we only set the extension value explicitly in sync_update_persist_betxn_pre_op */
  297. return NULL; /* we don't set anything in the ctor */
  298. }
  299. /* consumer operation extension destructor */
  300. static void
  301. sync_persist_operation_extension_destructor(void *ext, void *object __attribute__((unused)), void *parent __attribute__((unused)))
  302. {
  303. op_ext_ident_t *op_ident = (op_ext_ident_t *)ext;
  304. slapi_ch_free((void **)&op_ident);
  305. }
  306. static int
  307. sync_persist_register_operation_extension(void)
  308. {
  309. return slapi_register_object_extension(SYNC_PLUGIN_SUBSYSTEM,
  310. SLAPI_EXT_OPERATION,
  311. sync_persist_operation_extension_constructor,
  312. sync_persist_operation_extension_destructor,
  313. &sync_persist_extension_type,
  314. &sync_persist_extension_handle);
  315. }