2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 2003 The OpenLDAP Foundation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted only as authorized by the OpenLDAP
11 * A copy of this license is available in the file LICENSE in the
12 * top-level directory of the distribution or, alternatively, at
13 * <http://www.OpenLDAP.org/license.html>.
15 /* (C) Copyright PADL Software Pty Ltd. 2003
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that this notice is preserved
18 * and that due credit is given to PADL Software Pty Ltd. This software
19 * is provided ``as is'' without express or implied warranty.
22 * This work was initially developed by Luke Howard for inclusion
23 * in OpenLDAP Software.
28 #include <ac/string.h>
29 #include <ac/stdarg.h>
31 #include <ac/unistd.h>
41 * We only support two types -- connection and operation extensions.
42 * Define more types in slapi.h
46 struct slapi_registered_extension_set {
47 ldap_pvt_thread_mutex_t mutex;
48 struct slapi_registered_extension {
51 slapi_extension_constructor_fnptr *constructors;
52 slapi_extension_destructor_fnptr *destructors;
53 } extensions[SLAPI_X_EXT_MAX];
54 } registered_extensions;
56 /* per-object state */
57 struct slapi_extension_block {
61 static int getExtensionBlock(int objecttype, void *object, struct slapi_extension_block **eblock, void **parent)
63 switch ((slapi_extension_t) objecttype) {
64 case SLAPI_X_EXT_CONNECTION:
65 *eblock = ((Connection *)object)->c_extensions;
68 case SLAPI_X_EXT_OPERATION:
69 *eblock = ((Operation *)object)->o_extensions;
70 *parent = ((Operation *)object)->o_conn;
77 if ( *eblock == NULL ) {
84 static int mapExtensionType(const char *objectname, slapi_extension_t *type)
86 if ( strcasecmp( objectname, SLAPI_EXT_CONNECTION ) == 0 ) {
87 *type = SLAPI_X_EXT_CONNECTION;
88 } else if ( strcasecmp( objectname, SLAPI_EXT_OPERATION ) == 0 ) {
89 *type = SLAPI_X_EXT_OPERATION;
97 static void newExtension(struct slapi_extension_block *eblock, int objecttype, void *object, void *parent, int extensionhandle )
99 slapi_extension_constructor_fnptr constructor;
101 assert( objecttype < SLAPI_X_EXT_MAX );
102 assert( extensionhandle < registered_extensions.extensions[objecttype].count );
104 assert( registered_extensions.extensions[objecttype].constructors != NULL );
105 constructor = registered_extensions.extensions[objecttype].constructors[extensionhandle];
107 assert( eblock->extensions[extensionhandle] == NULL );
109 if ( constructor != NULL ) {
110 eblock->extensions[extensionhandle] = (*constructor)( object, parent );
112 eblock->extensions[extensionhandle] = NULL;
116 static void freeExtension(struct slapi_extension_block *eblock, int objecttype, void *object, void *parent, int extensionhandle )
118 slapi_extension_destructor_fnptr destructor;
120 assert( objecttype < SLAPI_X_EXT_MAX );
121 assert( extensionhandle < registered_extensions.extensions[objecttype].count );
123 if ( eblock->extensions[extensionhandle] != NULL ) {
124 assert( registered_extensions.extensions[objecttype].destructors != NULL );
125 destructor = registered_extensions.extensions[objecttype].destructors[extensionhandle];
126 if ( destructor != NULL ) {
127 (*destructor)( eblock->extensions[extensionhandle], object, parent );
129 eblock->extensions[extensionhandle] = NULL;
132 #endif /* LDAP_SLAPI */
134 void *slapi_get_object_extension(int objecttype, void *object, int extensionhandle)
137 struct slapi_extension_block *eblock;
140 if ( getExtensionBlock( objecttype, object, &eblock, &parent ) != 0 ) {
144 if ( extensionhandle < registered_extensions.extensions[objecttype].count ) {
145 return eblock->extensions[extensionhandle];
151 #endif /* LDAP_SLAPI */
154 void slapi_set_object_extension(int objecttype, void *object, int extensionhandle, void *extension)
157 struct slapi_extension_block *eblock;
160 if ( getExtensionBlock( objecttype, object, &eblock, &parent ) != 0 ) {
164 if ( extensionhandle < registered_extensions.extensions[objecttype].count ) {
165 /* free the old one */
166 freeExtension( eblock, objecttype, object, parent, extensionhandle );
168 /* constructed by caller */
169 eblock->extensions[extensionhandle] = extension;
171 #endif /* LDAP_SLAPI */
174 int slapi_register_object_extension(
175 const char *pluginname,
176 const char *objectname,
177 slapi_extension_constructor_fnptr constructor,
178 slapi_extension_destructor_fnptr destructor,
180 int *extensionhandle)
184 slapi_extension_t type;
185 struct slapi_registered_extension *re;
187 ldap_pvt_thread_mutex_lock( ®istered_extensions.mutex );
189 rc = mapExtensionType( objectname, &type );
191 ldap_pvt_thread_mutex_unlock( ®istered_extensions.mutex );
195 *objecttype = (int)type;
197 re = ®istered_extensions.extensions[*objecttype];
199 *extensionhandle = re->count;
202 /* can't add new extensions after objects have been created */
203 ldap_pvt_thread_mutex_unlock( ®istered_extensions.mutex );
209 if ( re->constructors == NULL ) {
210 re->constructors = (slapi_extension_constructor_fnptr *)slapi_ch_calloc( re->count,
211 sizeof( slapi_extension_constructor_fnptr ) );
213 re->constructors = (slapi_extension_constructor_fnptr *)slapi_ch_realloc( (char *)re->constructors,
214 re->count * sizeof( slapi_extension_constructor_fnptr ) );
216 re->constructors[*extensionhandle] = constructor;
218 if ( re->destructors == NULL ) {
219 re->destructors = (slapi_extension_destructor_fnptr *)slapi_ch_calloc( re->count,
220 sizeof( slapi_extension_destructor_fnptr ) );
222 re->destructors = (slapi_extension_destructor_fnptr *)slapi_ch_realloc( (char *)re->destructors,
223 re->count * sizeof( slapi_extension_destructor_fnptr ) );
225 re->destructors[*extensionhandle] = destructor;
227 ldap_pvt_thread_mutex_unlock( ®istered_extensions.mutex );
232 #endif /* LDAP_SLAPI */
235 int slapi_x_create_object_extensions(int objecttype, void *object)
239 struct slapi_extension_block *eblock;
243 switch ((slapi_extension_t) objecttype) {
244 case SLAPI_X_EXT_CONNECTION:
245 peblock = &(((Connection *)object)->c_extensions);
248 case SLAPI_X_EXT_OPERATION:
249 peblock = &(((Operation *)object)->o_extensions);
250 parent = ((Operation *)object)->o_conn;
259 ldap_pvt_thread_mutex_lock( ®istered_extensions.mutex );
260 if ( registered_extensions.extensions[objecttype].active == 0 ) {
262 * once we've created some extensions, no new extensions can
265 registered_extensions.extensions[objecttype].active = 1;
267 ldap_pvt_thread_mutex_unlock( ®istered_extensions.mutex );
269 eblock = (struct slapi_extension_block *)slapi_ch_calloc( 1, sizeof(*eblock) );
271 if ( registered_extensions.extensions[objecttype].count ) {
272 eblock->extensions = (void **)slapi_ch_calloc( registered_extensions.extensions[objecttype].count, sizeof(void *) );
273 for ( i = 0; i < registered_extensions.extensions[objecttype].count; i++ ) {
274 newExtension( eblock, objecttype, object, parent, i );
277 eblock->extensions = NULL;
288 int slapi_x_free_object_extensions(int objecttype, void *object)
292 struct slapi_extension_block *eblock;
296 switch ((slapi_extension_t) objecttype) {
297 case SLAPI_X_EXT_CONNECTION:
298 peblock = &(((Connection *)object)->c_extensions);
301 case SLAPI_X_EXT_OPERATION:
302 peblock = &(((Operation *)object)->o_extensions);
303 parent = ((Operation *)object)->o_conn;
310 eblock = (struct slapi_extension_block *)*peblock;
312 if ( eblock->extensions != NULL ) {
313 for ( i = registered_extensions.extensions[objecttype].count - 1; i >= 0; --i ) {
314 freeExtension( eblock, objecttype, object, parent, i );
317 slapi_ch_free( (void **)&eblock->extensions );
320 slapi_ch_free( peblock );
328 /* for reusable object types */
329 int slapi_x_clear_object_extensions(int objecttype, void *object)
333 struct slapi_extension_block *eblock;
336 if ( getExtensionBlock( objecttype, object, &eblock, &parent ) != 0 ) {
340 if ( eblock->extensions == NULL ) {
345 for ( i = registered_extensions.extensions[objecttype].count - 1; i >= 0; --i ) {
346 freeExtension( eblock, objecttype, object, parent, i );
349 for ( i = 0; i < registered_extensions.extensions[objecttype].count; i++ ) {
350 newExtension( eblock, objecttype, object, parent, i );
359 int slapi_x_init_object_extensions(void)
362 memset( ®istered_extensions, 0, sizeof( registered_extensions ) );
364 if ( ldap_pvt_thread_mutex_init( ®istered_extensions.mutex ) != 0 ) {