2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 2003-2005 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>
40 * We only support two types -- connection and operation extensions.
41 * Define more types in slapi.h
45 struct slapi_registered_extension_set {
46 ldap_pvt_thread_mutex_t mutex;
47 struct slapi_registered_extension {
50 slapi_extension_constructor_fnptr *constructors;
51 slapi_extension_destructor_fnptr *destructors;
52 } extensions[SLAPI_X_EXT_MAX];
53 } registered_extensions;
55 /* per-object state */
56 struct slapi_extension_block {
60 static int get_extension_block(int objecttype, void *object, struct slapi_extension_block **eblock, void **parent)
62 switch ((slapi_extension_t) objecttype) {
63 case SLAPI_X_EXT_CONNECTION:
64 *eblock = ((Connection *)object)->c_extensions;
67 case SLAPI_X_EXT_OPERATION:
68 *eblock = ((Operation *)object)->o_extensions;
69 *parent = ((Operation *)object)->o_conn;
76 if ( *eblock == NULL ) {
83 static int map_extension_type(const char *objectname, slapi_extension_t *type)
85 if ( strcasecmp( objectname, SLAPI_EXT_CONNECTION ) == 0 ) {
86 *type = SLAPI_X_EXT_CONNECTION;
87 } else if ( strcasecmp( objectname, SLAPI_EXT_OPERATION ) == 0 ) {
88 *type = SLAPI_X_EXT_OPERATION;
96 static void new_extension(struct slapi_extension_block *eblock,
97 int objecttype, void *object, void *parent,
100 slapi_extension_constructor_fnptr constructor;
102 assert( objecttype < SLAPI_X_EXT_MAX );
103 assert( extensionhandle < registered_extensions.extensions[objecttype].count );
105 assert( registered_extensions.extensions[objecttype].constructors != NULL );
106 constructor = registered_extensions.extensions[objecttype].constructors[extensionhandle];
108 assert( eblock->extensions[extensionhandle] == NULL );
110 if ( constructor != NULL ) {
111 eblock->extensions[extensionhandle] = (*constructor)( object, parent );
113 eblock->extensions[extensionhandle] = NULL;
117 static void free_extension(struct slapi_extension_block *eblock, int objecttype, void *object, void *parent, int extensionhandle )
119 slapi_extension_destructor_fnptr destructor;
121 assert( objecttype < SLAPI_X_EXT_MAX );
122 assert( extensionhandle < registered_extensions.extensions[objecttype].count );
124 if ( eblock->extensions[extensionhandle] != NULL ) {
125 assert( registered_extensions.extensions[objecttype].destructors != NULL );
126 destructor = registered_extensions.extensions[objecttype].destructors[extensionhandle];
127 if ( destructor != NULL ) {
128 (*destructor)( eblock->extensions[extensionhandle], object, parent );
130 eblock->extensions[extensionhandle] = NULL;
133 #endif /* LDAP_SLAPI */
135 void *slapi_get_object_extension(int objecttype, void *object, int extensionhandle)
138 struct slapi_extension_block *eblock;
141 if ( get_extension_block( objecttype, object, &eblock, &parent ) != 0 ) {
145 if ( extensionhandle < registered_extensions.extensions[objecttype].count ) {
146 return eblock->extensions[extensionhandle];
152 #endif /* LDAP_SLAPI */
155 void slapi_set_object_extension(int objecttype, void *object, int extensionhandle, void *extension)
158 struct slapi_extension_block *eblock;
161 if ( get_extension_block( objecttype, object, &eblock, &parent ) != 0 ) {
165 if ( extensionhandle < registered_extensions.extensions[objecttype].count ) {
166 /* free the old one */
167 free_extension( eblock, objecttype, object, parent, extensionhandle );
169 /* constructed by caller */
170 eblock->extensions[extensionhandle] = extension;
172 #endif /* LDAP_SLAPI */
175 int slapi_register_object_extension(
176 const char *pluginname,
177 const char *objectname,
178 slapi_extension_constructor_fnptr constructor,
179 slapi_extension_destructor_fnptr destructor,
181 int *extensionhandle)
185 slapi_extension_t type;
186 struct slapi_registered_extension *re;
188 ldap_pvt_thread_mutex_lock( ®istered_extensions.mutex );
190 rc = map_extension_type( objectname, &type );
192 ldap_pvt_thread_mutex_unlock( ®istered_extensions.mutex );
196 *objecttype = (int)type;
198 re = ®istered_extensions.extensions[*objecttype];
200 *extensionhandle = re->count;
203 /* can't add new extensions after objects have been created */
204 ldap_pvt_thread_mutex_unlock( ®istered_extensions.mutex );
210 if ( re->constructors == NULL ) {
211 re->constructors = (slapi_extension_constructor_fnptr *)slapi_ch_calloc( re->count,
212 sizeof( slapi_extension_constructor_fnptr ) );
214 re->constructors = (slapi_extension_constructor_fnptr *)slapi_ch_realloc( (char *)re->constructors,
215 re->count * sizeof( slapi_extension_constructor_fnptr ) );
217 re->constructors[*extensionhandle] = constructor;
219 if ( re->destructors == NULL ) {
220 re->destructors = (slapi_extension_destructor_fnptr *)slapi_ch_calloc( re->count,
221 sizeof( slapi_extension_destructor_fnptr ) );
223 re->destructors = (slapi_extension_destructor_fnptr *)slapi_ch_realloc( (char *)re->destructors,
224 re->count * sizeof( slapi_extension_destructor_fnptr ) );
226 re->destructors[*extensionhandle] = destructor;
228 ldap_pvt_thread_mutex_unlock( ®istered_extensions.mutex );
233 #endif /* LDAP_SLAPI */
236 int slapi_int_create_object_extensions(int objecttype, void *object)
240 struct slapi_extension_block *eblock;
244 switch ((slapi_extension_t) objecttype) {
245 case SLAPI_X_EXT_CONNECTION:
246 peblock = &(((Connection *)object)->c_extensions);
249 case SLAPI_X_EXT_OPERATION:
250 peblock = &(((Operation *)object)->o_extensions);
251 parent = ((Operation *)object)->o_conn;
260 ldap_pvt_thread_mutex_lock( ®istered_extensions.mutex );
261 if ( registered_extensions.extensions[objecttype].active == 0 ) {
263 * once we've created some extensions, no new extensions can
266 registered_extensions.extensions[objecttype].active = 1;
268 ldap_pvt_thread_mutex_unlock( ®istered_extensions.mutex );
270 eblock = (struct slapi_extension_block *)slapi_ch_calloc( 1, sizeof(*eblock) );
272 if ( registered_extensions.extensions[objecttype].count ) {
273 eblock->extensions = (void **)slapi_ch_calloc( registered_extensions.extensions[objecttype].count, sizeof(void *) );
274 for ( i = 0; i < registered_extensions.extensions[objecttype].count; i++ ) {
275 new_extension( eblock, objecttype, object, parent, i );
278 eblock->extensions = NULL;
289 int slapi_int_free_object_extensions(int objecttype, void *object)
293 struct slapi_extension_block *eblock;
297 switch ((slapi_extension_t) objecttype) {
298 case SLAPI_X_EXT_CONNECTION:
299 peblock = &(((Connection *)object)->c_extensions);
302 case SLAPI_X_EXT_OPERATION:
303 peblock = &(((Operation *)object)->o_extensions);
304 parent = ((Operation *)object)->o_conn;
311 eblock = (struct slapi_extension_block *)*peblock;
313 if ( eblock->extensions != NULL ) {
314 for ( i = registered_extensions.extensions[objecttype].count - 1; i >= 0; --i ) {
315 free_extension( eblock, objecttype, object, parent, i );
318 slapi_ch_free( (void **)&eblock->extensions );
321 slapi_ch_free( peblock );
329 /* for reusable object types */
330 int slapi_int_clear_object_extensions(int objecttype, void *object)
334 struct slapi_extension_block *eblock;
337 if ( get_extension_block( objecttype, object, &eblock, &parent ) != 0 ) {
341 if ( eblock->extensions == NULL ) {
346 for ( i = registered_extensions.extensions[objecttype].count - 1; i >= 0; --i ) {
347 free_extension( eblock, objecttype, object, parent, i );
350 for ( i = 0; i < registered_extensions.extensions[objecttype].count; i++ ) {
351 new_extension( eblock, objecttype, object, parent, i );
360 int slapi_int_init_object_extensions(void)
363 memset( ®istered_extensions, 0, sizeof( registered_extensions ) );
365 if ( ldap_pvt_thread_mutex_init( ®istered_extensions.mutex ) != 0 ) {