factory.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  3. * Copyright (C) 2005 Red Hat, Inc.
  4. * All rights reserved.
  5. *
  6. * License: GPL (version 3 or any later version).
  7. * See LICENSE for details.
  8. * END COPYRIGHT BLOCK **/
  9. #ifdef HAVE_CONFIG_H
  10. # include <config.h>
  11. #endif
  12. #include "slap.h"
  13. /*
  14. * This module provides a mechanism for extending core server objects.
  15. * This functionality is provided to plugin writers so that they may
  16. * efficiently pass state information between plugin calls. Typically
  17. * a plugin might register both a pre-op and post-op call. It's very
  18. * convenient for the plugin to associate it's private data with the
  19. * operation object that's passed through the PBlock.
  20. *
  21. * --- An interface is made available to the core server.
  22. *
  23. * int factory_register_type(const char *name, size_t offset)
  24. * void *factory_create_extension(int type,void *object,void *parent)
  25. * void factory_destroy_extension(int type,void *object,void *parent,void **extension)
  26. *
  27. * An object that wishes to make itself available for extension must
  28. * register with the Factory. It passes it's name, say 'Operation',
  29. * and an offset into the structure of where the extension block
  30. * is to be stored. In return a type handle is passed back, which is
  31. * used in place of the name in the creation and destruction calls.
  32. *
  33. * When an object is created, which has registered as extensible, it
  34. * must call the factory_create_extension with its type handle so that
  35. * the extension block can be constructed. A pointer to the block is
  36. * returned that *must* be stored in the object structure at the offset
  37. * declared by the call to factory_register_type.
  38. *
  39. * When an extensible object is destroyed the extension block must also
  40. * be destroyed. The factory_destroy_extension call is provided to
  41. * tidy up and free any extensions created for this object.
  42. *
  43. * --- An interface is made available to the plugins.
  44. *
  45. * int slapi_register_object_extension(
  46. * const char* objectname,
  47. * slapi_extension_constructor_fnptr constructor,
  48. * slapi_extension_destructor_fnptr destructor,
  49. * int *objecttype,
  50. * int *extensionhandle)
  51. * void *slapi_get_object_extension(int objecttype,void *object,int extensionhandle)
  52. *
  53. * When the plugin is initialised it must register its object extensions.
  54. * It must provide the name of the object to be extended, say 'Operation',
  55. * and constructor and destructor functions. These functions are called
  56. * when the object is constructed and destroyed. The extension functions
  57. * would probably allocate some memory and initialise it for its
  58. * own use. The registration function will fail if any objects have already
  59. * been created. This is why the registration *must* happen during plugin
  60. * initialisation. In return the plugin will receive two handles, one for
  61. * the object type, and one for the object extension. These only have meaning
  62. * for the slapi_get_object_extension function.
  63. *
  64. * A plugin retrieves a pointer to its own extension by calling slapi_get_
  65. * object_extension with the object from which the extension is to be
  66. * retrieved. The factory uses the objecttype to find the offset into the
  67. * object of where the extension block is stored. The extension handle is
  68. * then used to find the appropriate extension within the block.
  69. *
  70. * Currently (Oct 98) the only supported objects are Operation and Connection.
  71. *
  72. * This documentation is available here...
  73. *
  74. * http://warp/server/directory-server/hydra/replication/objext.html
  75. */
  76. /* JCM: Could implement simple object leak detection here */
  77. /* ---------------------- Factory Extension ---------------------- */
  78. struct factory_extension
  79. {
  80. const char *pluginname;
  81. slapi_extension_constructor_fnptr constructor;
  82. slapi_extension_destructor_fnptr destructor;
  83. int removed;
  84. };
  85. static struct factory_extension*
  86. new_factory_extension(
  87. const char *pluginname,
  88. slapi_extension_constructor_fnptr constructor,
  89. slapi_extension_destructor_fnptr destructor)
  90. {
  91. struct factory_extension* fe = (struct factory_extension*)slapi_ch_calloc(1, sizeof(struct factory_extension));
  92. fe->pluginname= slapi_ch_strdup(pluginname);
  93. fe->constructor= constructor;
  94. fe->destructor= destructor;
  95. return fe;
  96. }
  97. static void
  98. delete_factory_extension(struct factory_extension **fe)
  99. {
  100. slapi_ch_free( (void **) &((*fe)->pluginname) );
  101. slapi_ch_free( (void **) fe);
  102. }
  103. /* ---------------------- Factory Type ---------------------- */
  104. #define MAX_EXTENSIONS 32
  105. struct factory_type
  106. {
  107. char *name; /* The name of the object that can be extended */
  108. int extension_count; /* The number of extensions registered for this object */
  109. PRLock *extension_lock; /* Protect the array of extensions */
  110. size_t extension_offset; /* The offset into the object where the extension pointer is */
  111. long existence_count; /* Keep track of how many extensions blocks are in existence */
  112. struct factory_extension *extensions[MAX_EXTENSIONS]; /* The extension registered for this object type */
  113. };
  114. static struct factory_type*
  115. new_factory_type(const char *name, size_t offset)
  116. {
  117. struct factory_type* ft= (struct factory_type*)slapi_ch_calloc(1, sizeof(struct factory_type));
  118. ft->name= slapi_ch_strdup(name);
  119. ft->extension_lock = PR_NewLock();
  120. ft->extension_count= 0;
  121. ft->extension_offset= offset;
  122. ft->existence_count= 0;
  123. return ft;
  124. }
  125. static int
  126. factory_type_add_extension(struct factory_type *ft, struct factory_extension *fe)
  127. {
  128. int extensionhandle = -1;
  129. int added = 0;
  130. int i;
  131. PR_Lock(ft->extension_lock);
  132. if(ft->extension_count<MAX_EXTENSIONS)
  133. {
  134. for(i = 0; i < ft->extension_count; i++){
  135. if(strcasecmp(ft->extensions[i]->pluginname,fe->pluginname) == 0){
  136. if(ft->extensions[i]->removed){
  137. /* this extension was previously added, and then removed. Reuse the slot */
  138. delete_factory_extension(&ft->extensions[i]);
  139. extensionhandle = i;
  140. ft->extensions[i] = fe;
  141. added = 1;
  142. break;
  143. }
  144. }
  145. }
  146. if(!added){
  147. extensionhandle= ft->extension_count;
  148. ft->extensions[ft->extension_count]= fe;
  149. ft->extension_count++;
  150. }
  151. }
  152. else
  153. {
  154. LDAPDebug( LDAP_DEBUG_ANY, "ERROR: factory.c: Registration of %s extension by %s failed.\n",
  155. ft->name, fe->pluginname, 0);
  156. LDAPDebug( LDAP_DEBUG_ANY, "ERROR: factory.c: %d extensions already registered. Max is %d\n",
  157. ft->extension_count, MAX_EXTENSIONS, 0);
  158. }
  159. PR_Unlock(ft->extension_lock);
  160. return extensionhandle;
  161. }
  162. static void
  163. factory_type_increment_existence(struct factory_type *ft)
  164. {
  165. ft->existence_count++;
  166. }
  167. static void
  168. factory_type_decrement_existence(struct factory_type *ft)
  169. {
  170. ft->existence_count--;
  171. if(ft->existence_count<0)
  172. {
  173. /* This just shouldn't happen */
  174. LDAPDebug( LDAP_DEBUG_ANY, "ERROR: factory.c: %lu %s object extensions in existence.\n", ft->extension_count, ft->name, 0);
  175. }
  176. }
  177. /* ---------------------- Factory Type Store ---------------------- */
  178. #define MAX_TYPES 16
  179. static PRLock *factory_type_store_lock;
  180. static struct factory_type* factory_type_store[MAX_TYPES];
  181. static int number_of_types= 0;
  182. static void
  183. factory_type_store_init()
  184. {
  185. int i= 0;
  186. factory_type_store_lock= PR_NewLock(); /* JCM - Should really free this at shutdown */
  187. for(i=0;i<MAX_TYPES;i++)
  188. {
  189. factory_type_store[number_of_types]= NULL;
  190. }
  191. }
  192. static int
  193. factory_type_store_add(struct factory_type* ft)
  194. {
  195. int type= number_of_types;
  196. factory_type_store[type]= ft;
  197. number_of_types++;
  198. return type;
  199. }
  200. static struct factory_type*
  201. factory_type_store_get_factory_type(int type)
  202. {
  203. if(type>=0 && type<number_of_types)
  204. {
  205. return factory_type_store[type];
  206. }
  207. else
  208. {
  209. return NULL;
  210. }
  211. }
  212. static int
  213. factory_type_store_name_to_type(const char* name)
  214. {
  215. int i;
  216. for(i=0;i<number_of_types;i++)
  217. {
  218. if(strcasecmp(factory_type_store[i]->name,name)==0)
  219. {
  220. return i;
  221. }
  222. }
  223. return -1;
  224. }
  225. /* ---------------------- Core Server Functions ---------------------- */
  226. /*
  227. * Function for core server usage.
  228. * See documentation at head of file.
  229. */
  230. int
  231. factory_register_type(const char *name, size_t offset)
  232. {
  233. int type= 0;
  234. if(number_of_types==0)
  235. {
  236. factory_type_store_init();
  237. }
  238. PR_Lock(factory_type_store_lock);
  239. if(number_of_types<MAX_TYPES)
  240. {
  241. struct factory_type* ft= new_factory_type(name,offset);
  242. type= factory_type_store_add(ft);
  243. }
  244. else
  245. {
  246. LDAPDebug( LDAP_DEBUG_ANY, "ERROR: factory.c: Registration of %s object failed.\n", name, 0, 0);
  247. LDAPDebug( LDAP_DEBUG_ANY, "ERROR: factory.c: %d objects already registered. Max is %d\n", number_of_types, MAX_TYPES, 0);
  248. type= -1;
  249. }
  250. PR_Unlock(factory_type_store_lock);
  251. return type;
  252. }
  253. /*
  254. * Function for core server usage.
  255. * See documentation at head of file.
  256. */
  257. void *
  258. factory_create_extension(int type,void *object,void *parent)
  259. {
  260. int n;
  261. void **extension= NULL;
  262. struct factory_type* ft= factory_type_store_get_factory_type(type);
  263. if(ft!=NULL)
  264. {
  265. PR_Lock(ft->extension_lock);
  266. if((n = ft->extension_count)>0)
  267. {
  268. int i;
  269. factory_type_increment_existence(ft);
  270. PR_Unlock(ft->extension_lock);
  271. extension= (void**)slapi_ch_calloc(n + 1,sizeof(void*));
  272. for(i=0;i<n;i++)
  273. {
  274. if(ft->extensions[i] == NULL || ft->extensions[i]->removed){
  275. continue;
  276. }
  277. slapi_extension_constructor_fnptr constructor= ft->extensions[i]->constructor;
  278. if(constructor!=NULL)
  279. {
  280. extension[i]= (*constructor)(object,parent);
  281. }
  282. }
  283. }
  284. else
  285. {
  286. /* No extensions registered. That's OK */
  287. PR_Unlock(ft->extension_lock);
  288. }
  289. }
  290. else
  291. {
  292. /* The type wasn't registered. Programming error? */
  293. LDAPDebug( LDAP_DEBUG_ANY, "ERROR: factory.c: Object type handle %d not valid. Object not registered?\n", type, 0, 0);
  294. }
  295. return (void*)extension;
  296. }
  297. /*
  298. * Function for core server usage.
  299. * See documentation at head of file.
  300. */
  301. void
  302. factory_destroy_extension(int type,void *object,void *parent,void **extension)
  303. {
  304. if(extension!=NULL && *extension!=NULL)
  305. {
  306. struct factory_type* ft= factory_type_store_get_factory_type(type);
  307. if(ft!=NULL)
  308. {
  309. int i,n;
  310. PR_Lock(ft->extension_lock);
  311. n=ft->extension_count;
  312. factory_type_decrement_existence(ft);
  313. for(i=0;i<n;i++)
  314. {
  315. slapi_extension_destructor_fnptr destructor;
  316. if(ft->extensions[i] == NULL){
  317. continue;
  318. }
  319. destructor = ft->extensions[i]->destructor;
  320. if(destructor!=NULL)
  321. {
  322. void **extention_array= (void**)(*extension);
  323. (*destructor)(extention_array[i],object,parent);
  324. }
  325. }
  326. PR_Unlock(ft->extension_lock);
  327. }
  328. else
  329. {
  330. /* The type wasn't registered. Programming error? */
  331. LDAPDebug( LDAP_DEBUG_ANY, "ERROR: factory.c: Object type handle %d not valid. Object not registered?\n", type, 0, 0);
  332. }
  333. slapi_ch_free(extension);
  334. }
  335. }
  336. /* ---------------------- Slapi Functions ---------------------- */
  337. /*
  338. * The caller should reset
  339. */
  340. int
  341. slapi_unregister_object_extension(
  342. const char* pluginname,
  343. const char* objectname,
  344. int *objecttype,
  345. int *extensionhandle)
  346. {
  347. struct factory_type* ft;
  348. int rc = 0;
  349. *objecttype = factory_type_store_name_to_type(objectname);
  350. ft = factory_type_store_get_factory_type(*objecttype);
  351. if(ft){
  352. PR_Lock(ft->extension_lock);
  353. ft->extensions[*extensionhandle]->removed = 1;
  354. PR_Unlock(ft->extension_lock);
  355. } else {
  356. /* extension not found */
  357. rc = -1;
  358. }
  359. return rc;
  360. }
  361. /*
  362. * Function for plugin usage.
  363. * See documentation at head of file.
  364. */
  365. int
  366. slapi_register_object_extension(
  367. const char* pluginname,
  368. const char* objectname,
  369. slapi_extension_constructor_fnptr constructor,
  370. slapi_extension_destructor_fnptr destructor,
  371. int *objecttype,
  372. int *extensionhandle)
  373. {
  374. int rc= 0;
  375. struct factory_extension* fe;
  376. struct factory_type* ft;
  377. fe= new_factory_extension(pluginname,constructor, destructor);
  378. *objecttype= factory_type_store_name_to_type(objectname);
  379. ft= factory_type_store_get_factory_type(*objecttype);
  380. if(ft!=NULL)
  381. {
  382. *extensionhandle= factory_type_add_extension(ft,fe);
  383. if(*extensionhandle==-1)
  384. {
  385. delete_factory_extension(&fe);
  386. }
  387. }
  388. else
  389. {
  390. LDAPDebug( LDAP_DEBUG_ANY, "ERROR: factory.c: Plugin %s failed to register extension for object %s.\n", pluginname, objectname, 0);
  391. rc= -1;
  392. delete_factory_extension(&fe);
  393. }
  394. return rc;
  395. }
  396. /*
  397. * Function for plugin usage.
  398. * See documentation at head of file.
  399. */
  400. void *
  401. slapi_get_object_extension(int objecttype,void *object,int extensionhandle)
  402. {
  403. void *object_extension= NULL;
  404. struct factory_type* ft= factory_type_store_get_factory_type(objecttype);
  405. if(ft!=NULL)
  406. {
  407. char *object_base= (char*)object;
  408. void **o_extension= (void**)(object_base + ft->extension_offset);
  409. void **extension_array= (void**)(*o_extension);
  410. if ( extension_array != NULL ) {
  411. object_extension= extension_array[extensionhandle];
  412. }
  413. }
  414. return object_extension;
  415. }
  416. /*
  417. * sometimes a plugin would like to change its extension, too.
  418. */
  419. void
  420. slapi_set_object_extension(int objecttype, void *object, int extensionhandle,
  421. void *extension)
  422. {
  423. struct factory_type *ft = factory_type_store_get_factory_type(objecttype);
  424. if (ft != NULL) {
  425. char *object_base = (char *)object;
  426. void **o_extension = (void **)(object_base + ft->extension_offset);
  427. void **extension_array= (void**)(*o_extension);
  428. if (extension_array != NULL) {
  429. extension_array[extensionhandle] = extension;
  430. }
  431. }
  432. }