retrocl.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  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) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * All rights reserved.
  37. * END COPYRIGHT BLOCK **/
  38. /*
  39. * Requires that create_instance.c have added a plugin entry similar to:
  40. dn: cn=Retrocl Plugin,cn=plugins,cn=config
  41. objectclass: top
  42. objectclass: nsSlapdPlugin
  43. objectclass: extensibleObject
  44. cn: RetroCL Plugin
  45. nsslapd-pluginpath: /export2/servers/Hydra-supplier/lib/retrocl-plugin.so
  46. nsslapd-plugininitfunc: retrocl_plugin_init
  47. nsslapd-plugintype: object
  48. nsslapd-pluginenabled: on
  49. nsslapd-plugin-depends-on-type: database
  50. nsslapd-pluginid: retrocl
  51. nsslapd-pluginversion: 5.0b2
  52. nsslapd-pluginvendor: Sun Microsystems, Inc.
  53. nsslapd-plugindescription: Retrocl Plugin
  54. *
  55. */
  56. #include "retrocl.h"
  57. #ifdef _WIN32
  58. int *module_ldap_debug = 0;
  59. void plugin_init_debug_level(int *level_ptr)
  60. {
  61. module_ldap_debug = level_ptr;
  62. }
  63. #endif
  64. void* g_plg_identity [PLUGIN_MAX];
  65. Slapi_Backend *retrocl_be_changelog = NULL;
  66. /* ----------------------------- Retrocl Plugin */
  67. static Slapi_PluginDesc retrocldesc = {"retrocl", PLUGIN_MAGIC_VENDOR_STR, PRODUCTTEXT, "Retrocl Plugin"};
  68. static Slapi_PluginDesc retroclpostopdesc = {"retrocl-postop", PLUGIN_MAGIC_VENDOR_STR, PRODUCTTEXT, "retrocl post-operation plugin"};
  69. static Slapi_PluginDesc retroclinternalpostopdesc = {"retrocl-internalpostop", PLUGIN_MAGIC_VENDOR_STR, PRODUCTTEXT, "retrocl internal post-operation plugin"};
  70. /*
  71. * Function: retrocl_*
  72. *
  73. * Returns: LDAP_
  74. *
  75. * Arguments: Pb of operation
  76. *
  77. * Description: wrappers around retrocl_postob registered as callback
  78. *
  79. */
  80. int retrocl_postop_add (Slapi_PBlock *pb) { return retrocl_postob(pb,OP_ADD);}
  81. int retrocl_postop_delete (Slapi_PBlock *pb) { return retrocl_postob(pb,OP_DELETE);}
  82. int retrocl_postop_modify (Slapi_PBlock *pb) { return retrocl_postob(pb,OP_MODIFY);}
  83. int retrocl_postop_modrdn (Slapi_PBlock *pb) { return retrocl_postob(pb,OP_MODRDN);}
  84. /*
  85. * Function: retrocl_postop_init
  86. *
  87. * Returns: 0/-1
  88. *
  89. * Arguments: Pb
  90. *
  91. * Description: callback function
  92. *
  93. */
  94. int
  95. retrocl_postop_init( Slapi_PBlock *pb )
  96. {
  97. int rc= 0; /* OK */
  98. if( slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01 ) != 0 ||
  99. slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&retroclpostopdesc ) != 0 ||
  100. slapi_pblock_set( pb, SLAPI_PLUGIN_POST_ADD_FN, (void *) retrocl_postop_add ) != 0 ||
  101. slapi_pblock_set( pb, SLAPI_PLUGIN_POST_DELETE_FN, (void *) retrocl_postop_delete ) != 0 ||
  102. slapi_pblock_set( pb, SLAPI_PLUGIN_POST_MODIFY_FN, (void *) retrocl_postop_modify ) != 0 ||
  103. slapi_pblock_set( pb, SLAPI_PLUGIN_POST_MODRDN_FN, (void *) retrocl_postop_modrdn ) != 0 )
  104. {
  105. slapi_log_error( SLAPI_LOG_PLUGIN, RETROCL_PLUGIN_NAME, "retrocl_postop_init failed\n" );
  106. rc= -1;
  107. }
  108. return rc;
  109. }
  110. /*
  111. * Function: retrocl_internalpostop_init
  112. *
  113. * Returns: 0/-1
  114. *
  115. * Arguments: Pb
  116. *
  117. * Description: callback function
  118. *
  119. */
  120. int
  121. retrocl_internalpostop_init( Slapi_PBlock *pb )
  122. {
  123. int rc= 0; /* OK */
  124. if( slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01 ) != 0 ||
  125. slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&retroclinternalpostopdesc ) != 0 ||
  126. slapi_pblock_set( pb, SLAPI_PLUGIN_INTERNAL_POST_ADD_FN, (void *) retrocl_postop_add ) != 0 ||
  127. slapi_pblock_set( pb, SLAPI_PLUGIN_INTERNAL_POST_DELETE_FN, (void *) retrocl_postop_delete ) != 0 ||
  128. slapi_pblock_set( pb, SLAPI_PLUGIN_INTERNAL_POST_MODIFY_FN, (void *) retrocl_postop_modify ) != 0 ||
  129. slapi_pblock_set( pb, SLAPI_PLUGIN_INTERNAL_POST_MODRDN_FN, (void *) retrocl_postop_modrdn ) != 0 )
  130. {
  131. slapi_log_error( SLAPI_LOG_PLUGIN, RETROCL_PLUGIN_NAME, "retrocl_internalpostop_init failed\n" );
  132. rc= -1;
  133. }
  134. return rc;
  135. }
  136. /*
  137. * Function: retrocl_rootdse_init
  138. *
  139. * Returns: LDAP_SUCCESS
  140. *
  141. * Arguments: none
  142. *
  143. * Description: The FE DSE *must* be initialised before we get here.
  144. *
  145. */
  146. static int retrocl_rootdse_init(void)
  147. {
  148. int return_value= LDAP_SUCCESS;
  149. slapi_config_register_callback(SLAPI_OPERATION_SEARCH,DSE_FLAG_PREOP,"",
  150. LDAP_SCOPE_BASE,"(objectclass=*)",
  151. retrocl_rootdse_search,NULL);
  152. return return_value;
  153. }
  154. /*
  155. * Function: retrocl_select_backend
  156. *
  157. * Returns: LDAP_
  158. *
  159. * Arguments: none
  160. *
  161. * Description: simulates an add of the changelog to see if it exists. If not,
  162. * creates it. Then reads the changenumbers. This function should be called
  163. * exactly once at startup.
  164. *
  165. */
  166. static int retrocl_select_backend(void)
  167. {
  168. int err;
  169. Slapi_PBlock *pb;
  170. Slapi_Backend *be = NULL;
  171. Slapi_Entry *referral = NULL;
  172. Slapi_Operation *op = NULL;
  173. char errbuf[BUFSIZ];
  174. pb = slapi_pblock_new();
  175. slapi_pblock_set (pb, SLAPI_PLUGIN_IDENTITY, g_plg_identity[PLUGIN_RETROCL]);
  176. /* This is a simulated operation; no actual add is performed */
  177. op = operation_new(OP_FLAG_INTERNAL);
  178. operation_set_type(op,SLAPI_OPERATION_ADD); /* Ensure be not readonly */
  179. operation_set_target_spec_str(op,RETROCL_CHANGELOG_DN);
  180. slapi_pblock_set(pb,SLAPI_OPERATION, op);
  181. err = slapi_mapping_tree_select(pb,&be,&referral,errbuf);
  182. slapi_entry_free(referral);
  183. operation_free(&op,NULL);
  184. if (err != LDAP_SUCCESS || be == NULL || be == defbackend_get_backend()) {
  185. LDAPDebug(LDAP_DEBUG_TRACE,"Mapping tree select failed (%d) %s.\n",
  186. err,errbuf,0);
  187. /* could not find the backend for cn=changelog, either because
  188. * it doesn't exist
  189. * mapping tree not registered.
  190. */
  191. err = retrocl_create_config();
  192. if (err != LDAP_SUCCESS) return err;
  193. } else {
  194. retrocl_be_changelog = be;
  195. }
  196. retrocl_create_cle();
  197. return retrocl_get_changenumbers();
  198. }
  199. /*
  200. * Function: retrocl_get_config_str
  201. *
  202. * Returns: malloc'ed string which must be freed.
  203. *
  204. * Arguments: attribute type name
  205. *
  206. * Description: reads a single-valued string attr from the plugins' own DSE.
  207. * This is called twice: to obtain the trim max age during startup, and to
  208. * obtain the change log directory. No callback is registered; you cannot
  209. * change the trim max age without restarting the server.
  210. *
  211. */
  212. char *retrocl_get_config_str(const char *attrt)
  213. {
  214. Slapi_Entry **entries;
  215. Slapi_PBlock *pb = NULL;
  216. char *ma;
  217. int rc = 0;
  218. char *dn;
  219. dn = RETROCL_PLUGIN_DN;
  220. pb = slapi_pblock_new();
  221. slapi_search_internal_set_pb (pb, dn, LDAP_SCOPE_BASE, "objectclass=*", NULL, 0, NULL,
  222. NULL, g_plg_identity[PLUGIN_RETROCL] , 0);
  223. slapi_search_internal_pb (pb);
  224. slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
  225. if (rc != 0) {
  226. slapi_pblock_destroy(pb);
  227. return NULL;
  228. }
  229. slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
  230. ma = slapi_entry_attr_get_charptr(entries[0],attrt);
  231. slapi_free_search_results_internal(pb);
  232. slapi_pblock_destroy(pb);
  233. return ma;
  234. }
  235. /*
  236. * Function: retrocl_start
  237. *
  238. * Returns: 0 on success
  239. *
  240. * Arguments: Pb
  241. *
  242. * Description:
  243. *
  244. */
  245. static int retrocl_start (Slapi_PBlock *pb)
  246. {
  247. static int retrocl_started = 0;
  248. int rc = 0;
  249. if (!retrocl_started) {
  250. retrocl_rootdse_init();
  251. rc = retrocl_select_backend();
  252. if (rc == 0) {
  253. retrocl_init_trimming();
  254. } else {
  255. LDAPDebug(LDAP_DEBUG_TRACE,"Couldnt find backend, not trimming retro changelog (%d).\n",rc,0,0);
  256. }
  257. }
  258. retrocl_started = 1;
  259. return rc;
  260. }
  261. /*
  262. * Function: retrocl_stop
  263. *
  264. * Returns: 0
  265. *
  266. * Arguments: Pb
  267. *
  268. * Description: called when the server is shutting down
  269. *
  270. */
  271. static int retrocl_stop (Slapi_PBlock *pb)
  272. {
  273. int rc = 0;
  274. retrocl_stop_trimming();
  275. retrocl_be_changelog = NULL;
  276. retrocl_forget_changenumbers();
  277. return rc;
  278. }
  279. /*
  280. * Function: retrocl_plugin_init
  281. *
  282. * Returns: 0 on successs
  283. *
  284. * Arguments: Pb
  285. *
  286. * Description: main entry point for retrocl
  287. *
  288. */
  289. int
  290. retrocl_plugin_init(Slapi_PBlock *pb)
  291. {
  292. static int legacy_initialised= 0;
  293. int rc = 0;
  294. void *identity = NULL;
  295. slapi_pblock_get (pb, SLAPI_PLUGIN_IDENTITY, &identity);
  296. PR_ASSERT (identity);
  297. g_plg_identity[PLUGIN_RETROCL] = identity;
  298. if (!legacy_initialised) {
  299. rc= slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01 );
  300. rc= slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&retrocldesc );
  301. rc= slapi_pblock_set( pb, SLAPI_PLUGIN_START_FN, (void *) retrocl_start );
  302. rc= slapi_pblock_set( pb, SLAPI_PLUGIN_CLOSE_FN, (void *) retrocl_stop );
  303. rc= slapi_register_plugin("postoperation", 1 /* Enabled */, "retrocl_postop_init", retrocl_postop_init, "Retrocl postoperation plugin", NULL, identity);
  304. rc= slapi_register_plugin("internalpostoperation", 1 /* Enabled */, "retrocl_internalpostop_init", retrocl_internalpostop_init, "Retrocl internal postoperation plugin", NULL, identity);
  305. }
  306. legacy_initialised = 1;
  307. return rc;
  308. }