test_repl_session_plugin.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  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) 2010 Red Hat, Inc.
  35. * All rights reserved.
  36. * END COPYRIGHT BLOCK **/
  37. #include "slapi-plugin.h"
  38. #include "repl-session-plugin.h"
  39. #include <string.h>
  40. #define REPL_SESSION_v1_0_GUID "210D7559-566B-41C6-9B03-5523BDF30880"
  41. static char *test_repl_session_plugin_name = "test_repl_session_api";
  42. /*
  43. * Plugin identifiers
  44. */
  45. static Slapi_PluginDesc test_repl_session_pdesc = {
  46. "test-repl-session-plugin",
  47. "Test Vendor",
  48. "1.0",
  49. "test replication session plugin"
  50. };
  51. static Slapi_ComponentId *test_repl_session_plugin_id = NULL;
  52. /*
  53. * Replication Session Callbacks
  54. */
  55. /*
  56. * This is called on a master when a replication agreement is
  57. * initialized at startup. A cookie can be allocated at this
  58. * time which is passed to other callbacks on the master side.
  59. */
  60. static void *
  61. test_repl_session_plugin_agmt_init_cb(const Slapi_DN *repl_subtree)
  62. {
  63. char *cookie = NULL;
  64. slapi_log_error(SLAPI_LOG_FATAL, test_repl_session_plugin_name,
  65. "test_repl_session_plugin_init_cb() called for suffix \"%s\".\n",
  66. slapi_sdn_get_ndn(repl_subtree));
  67. /* allocate a string and set as the cookie */
  68. cookie = slapi_ch_smprintf("cookie test");
  69. slapi_log_error(SLAPI_LOG_FATAL, test_repl_session_plugin_name,
  70. "test_repl_session_plugin_init_cb(): Setting cookie: \"%s\".\n",
  71. cookie);
  72. return cookie;
  73. }
  74. /*
  75. * This is called on a master when we are about to acquire a
  76. * replica. This callback can allocate some extra data to
  77. * be sent to the replica in the start replication request.
  78. * This memory will be free'd by the replication plug-in
  79. * after it is sent. A guid string must be set that is to
  80. * be used by the receiving side to ensure that the data is
  81. * from the same replication session plug-in.
  82. *
  83. * Returning non-0 will abort the replication session. This
  84. * results in the master going into incremental backoff mode.
  85. */
  86. static int
  87. test_repl_session_plugin_pre_acquire_cb(void *cookie, const Slapi_DN *repl_subtree,
  88. int is_total, char **data_guid, struct berval **data)
  89. {
  90. int rc = 0;
  91. slapi_log_error(SLAPI_LOG_FATAL, test_repl_session_plugin_name,
  92. "test_repl_session_plugin_pre_acquire_cb() called for suffix \"%s\", "
  93. "is_total: \"%s\", cookie: \"%s\".\n", slapi_sdn_get_ndn(repl_subtree),
  94. is_total ? "TRUE" : "FALSE", cookie ? (char *)cookie : "NULL");
  95. /* allocate some data to be sent to the replica */
  96. *data_guid = slapi_ch_smprintf("test-guid");
  97. *data = (struct berval *)slapi_ch_malloc(sizeof(struct berval));
  98. (*data)->bv_val = slapi_ch_smprintf("test-data");
  99. (*data)->bv_len = strlen((*data)->bv_val) + 1;
  100. slapi_log_error(SLAPI_LOG_FATAL, test_repl_session_plugin_name,
  101. "test_repl_session_plugin_pre_acquire_cb() sending data: guid: \"%s\" data: \"%s\".\n",
  102. *data_guid, (*data)->bv_val);
  103. return rc;
  104. }
  105. /*
  106. * This is called on a replica when we are about to reply to
  107. * a start replication request from a master. This callback
  108. * can allocate some extra data to be sent to the master in
  109. * the start replication response. This memory will be free'd
  110. * by the replication plug-in after it is sent. A guid string
  111. * must be set that is to be used by the receiving side to ensure
  112. * that the data is from the same replication session plug-in.
  113. *
  114. * Returning non-0 will abort the replication session. This
  115. * results in the master going into incremental backoff mode.
  116. */
  117. static int
  118. test_repl_session_plugin_reply_acquire_cb(const char *repl_subtree, int is_total,
  119. char **data_guid, struct berval **data)
  120. {
  121. int rc = 0;
  122. slapi_log_error(SLAPI_LOG_FATAL, test_repl_session_plugin_name,
  123. "test_repl_session_plugin_reply_acquire_cb() called for suffix \"%s\", is_total: \"%s\".\n",
  124. repl_subtree, is_total ? "TRUE" : "FALSE");
  125. /* allocate some data to be sent to the master */
  126. *data_guid = slapi_ch_smprintf("test-reply-guid");
  127. *data = (struct berval *)slapi_ch_malloc(sizeof(struct berval));
  128. (*data)->bv_val = slapi_ch_smprintf("test-reply-data");
  129. (*data)->bv_len = strlen((*data)->bv_val) + 1;
  130. slapi_log_error(SLAPI_LOG_FATAL, test_repl_session_plugin_name,
  131. "test_repl_session_plugin_reply_acquire_cb() sending data: guid: \"%s\" data: \"%s\".\n",
  132. *data_guid, (*data)->bv_val);
  133. return rc;
  134. }
  135. /*
  136. * This is called on a master when it receives a reply to a
  137. * start replication extop that we sent to a replica. Any
  138. * extra data sent by a replication session callback on the
  139. * replica will be set here as the data parameter. The data_guid
  140. * should be checked first to ensure that the sending side is
  141. * using the same replication session plug-in before making any
  142. * assumptions about the contents of the data parameter. You
  143. * should not free data_guid or data. The replication plug-in
  144. * will take care of freeing this memory.
  145. *
  146. * Returning non-0 will abort the replication session. This
  147. * results in the master going into incremental backoff mode.
  148. */
  149. static int
  150. test_repl_session_plugin_post_acquire_cb(void *cookie, const Slapi_DN *repl_subtree, int is_total,
  151. const char *data_guid, const struct berval *data)
  152. {
  153. int rc = 0;
  154. slapi_log_error(SLAPI_LOG_FATAL, test_repl_session_plugin_name,
  155. "test_repl_session_plugin_post_acquire_cb() called for suffix \"%s\", "
  156. "is_total: \"%s\" cookie: \"%s\".\n", slapi_sdn_get_ndn(repl_subtree),
  157. is_total ? "TRUE" : "FALSE", cookie ? (char *)cookie : "NULL");
  158. /* log any extra data that was sent from the replica */
  159. if (data_guid && data) {
  160. slapi_log_error(SLAPI_LOG_FATAL, test_repl_session_plugin_name,
  161. "test_repl_session_plugin_post_acquire_cb() received data: guid: \"%s\" data: \"%s\".\n",
  162. data_guid, data->bv_val);
  163. }
  164. return rc;
  165. }
  166. /*
  167. * This is called on a replica when it receives a start replication
  168. * extended operation from a master. If the replication session
  169. * plug-in on the master sent any extra data, it will be set here
  170. * as the data parameter. The data_guid should be checked first to
  171. * ensure that the sending side is using the same replication session
  172. * plug-in before making any assumptions about the contents of the
  173. * data parameter. You should not free data_guid or data. The
  174. * replication plug-in will take care of freeing this memory.
  175. *
  176. * Returning non-0 will abort the replication session. This
  177. * results in the master going into incremental backoff mode.
  178. */
  179. static int
  180. test_repl_session_plugin_recv_acquire_cb(const char *repl_subtree, int is_total,
  181. const char *data_guid, const struct berval *data)
  182. {
  183. int rc = 0;
  184. slapi_log_error(SLAPI_LOG_FATAL, test_repl_session_plugin_name,
  185. "test_repl_session_plugin_recv_acquire_cb() called for suffix \"%s\", is_total: \"%s\".\n",
  186. repl_subtree, is_total ? "TRUE" : "FALSE");
  187. /* log any extra data that was sent from the master */
  188. if (data_guid && data) {
  189. slapi_log_error(SLAPI_LOG_FATAL, test_repl_session_plugin_name,
  190. "test_repl_session_plugin_recv_acquire_cb() received data: guid: \"%s\" data: \"%s\".\n",
  191. data_guid, data->bv_val);
  192. }
  193. return rc;
  194. }
  195. /*
  196. * This is called on a master when a replication agreement is
  197. * destroyed. Any cookie allocated when the agreement was initialized
  198. * should be free'd here.
  199. */
  200. static void
  201. test_repl_session_plugin_destroy_cb(void *cookie, const Slapi_DN *repl_subtree)
  202. {
  203. slapi_log_error(SLAPI_LOG_FATAL, test_repl_session_plugin_name,
  204. "test_repl_session_plugin_destroy_cb() called for suffix \"%s\".\n",
  205. slapi_sdn_get_ndn(repl_subtree));
  206. /* free cookie */
  207. slapi_ch_free_string((char **)&cookie);
  208. return;
  209. }
  210. /*
  211. * Callback list for registering API
  212. */
  213. static void *test_repl_session_api[] = {
  214. NULL, /* reserved for api broker use, must be zero */
  215. test_repl_session_plugin_agmt_init_cb,
  216. test_repl_session_plugin_pre_acquire_cb,
  217. test_repl_session_plugin_reply_acquire_cb,
  218. test_repl_session_plugin_post_acquire_cb,
  219. test_repl_session_plugin_recv_acquire_cb,
  220. test_repl_session_plugin_destroy_cb
  221. };
  222. /*
  223. * Plug-in framework functions
  224. */
  225. static int
  226. test_repl_session_plugin_start(Slapi_PBlock *pb)
  227. {
  228. slapi_log_error(SLAPI_LOG_PLUGIN, test_repl_session_plugin_name,
  229. "--> test_repl_session_plugin_start -- begin\n");
  230. slapi_log_error(SLAPI_LOG_PLUGIN, test_repl_session_plugin_name,
  231. "<-- test_repl_session_plugin_start -- end\n");
  232. return 0;
  233. }
  234. static int
  235. test_repl_session_plugin_close(Slapi_PBlock *pb)
  236. {
  237. slapi_log_error(SLAPI_LOG_PLUGIN, test_repl_session_plugin_name,
  238. "--> test_repl_session_plugin_close -- begin\n");
  239. slapi_apib_unregister(REPL_SESSION_v1_0_GUID);
  240. slapi_log_error(SLAPI_LOG_PLUGIN, test_repl_session_plugin_name,
  241. "<-- test_repl_session_plugin_close -- end\n");
  242. return 0;
  243. }
  244. int test_repl_session_plugin_init(Slapi_PBlock *pb)
  245. {
  246. slapi_log_error(SLAPI_LOG_PLUGIN, test_repl_session_plugin_name,
  247. "--> test_repl_session_plugin_init -- begin\n");
  248. if ( slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION,
  249. SLAPI_PLUGIN_VERSION_01 ) != 0 ||
  250. slapi_pblock_set(pb, SLAPI_PLUGIN_START_FN,
  251. (void *) test_repl_session_plugin_start ) != 0 ||
  252. slapi_pblock_set(pb, SLAPI_PLUGIN_CLOSE_FN,
  253. (void *) test_repl_session_plugin_close ) != 0 ||
  254. slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION,
  255. (void *)&test_repl_session_pdesc ) != 0 )
  256. {
  257. slapi_log_error( SLAPI_LOG_FATAL, test_repl_session_plugin_name,
  258. "<-- test_repl_session_plugin_init -- failed to register plugin -- end\n");
  259. return -1;
  260. }
  261. if( slapi_apib_register(REPL_SESSION_v1_0_GUID, test_repl_session_api) ) {
  262. slapi_log_error( SLAPI_LOG_FATAL, test_repl_session_plugin_name,
  263. "<-- test_repl_session_plugin_start -- failed to register repl_session api -- end\n");
  264. return -1;
  265. }
  266. /* Retrieve and save the plugin identity to later pass to
  267. internal operations */
  268. if (slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY, &test_repl_session_plugin_id) != 0) {
  269. slapi_log_error(SLAPI_LOG_FATAL, test_repl_session_plugin_name,
  270. "<-- test_repl_session_plugin_init -- failed to retrieve plugin identity -- end\n");
  271. return -1;
  272. }
  273. slapi_log_error( SLAPI_LOG_PLUGIN, test_repl_session_plugin_name,
  274. "<-- test_repl_session_plugin_init -- end\n");
  275. return 0;
  276. }
  277. /*
  278. dn: cn=Test Replication Session API,cn=plugins,cn=config
  279. objectclass: top
  280. objectclass: nsSlapdPlugin
  281. objectclass: extensibleObject
  282. cn: Test Replication Session API
  283. nsslapd-pluginpath: libtestreplsession-plugin
  284. nsslapd-plugininitfunc: test_repl_session_plugin_init
  285. nsslapd-plugintype: preoperation
  286. nsslapd-pluginenabled: on
  287. nsslapd-plugin-depends-on-type: database
  288. nsslapd-plugin-depends-on-named: Multimaster Replication Plugin
  289. */