2 * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
3 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6 * Portions Copyright IBM Corp. 1997,2002-2003
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted only as authorized by the OpenLDAP
9 * Public License, version 2.7 or later.
14 #include <ac/string.h>
15 #include <ac/stdarg.h>
17 #include <ac/unistd.h>
27 * We only support two types -- connection and operation extensions.
28 * Define more types in slapi.h
32 struct slapi_registered_extension_set {
33 ldap_pvt_thread_mutex_t mutex;
34 struct slapi_registered_extension {
37 slapi_extension_constructor_fnptr *constructors;
38 slapi_extension_destructor_fnptr *destructors;
39 } extensions[SLAPI_X_EXT_MAX];
40 } registered_extensions;
42 /* per-object state */
43 struct slapi_extension_block {
47 static int getExtensionBlock(int objecttype, void *object, struct slapi_extension_block **eblock, void **parent)
49 switch ((slapi_extension_t) objecttype) {
50 case SLAPI_X_EXT_CONNECTION:
51 *eblock = ((Connection *)object)->c_extensions;
54 case SLAPI_X_EXT_OPERATION:
55 *eblock = ((Operation *)object)->o_extensions;
56 *parent = ((Operation *)object)->o_conn;
63 if ( *eblock == NULL ) {
70 static int mapExtensionType(const char *objectname, slapi_extension_t *type)
72 if ( strcasecmp( objectname, SLAPI_EXT_CONNECTION ) == 0 ) {
73 *type = SLAPI_X_EXT_CONNECTION;
74 } else if ( strcasecmp( objectname, SLAPI_EXT_OPERATION ) == 0 ) {
75 *type = SLAPI_X_EXT_OPERATION;
83 static void newExtension(struct slapi_extension_block *eblock, int objecttype, void *object, void *parent, int extensionhandle )
85 slapi_extension_constructor_fnptr constructor;
87 assert( objecttype < SLAPI_X_EXT_MAX );
88 assert( extensionhandle < registered_extensions.extensions[objecttype].count );
90 assert( registered_extensions.extensions[objecttype].constructors != NULL );
91 constructor = registered_extensions.extensions[objecttype].constructors[extensionhandle];
93 assert( eblock->extensions[extensionhandle] == NULL );
95 if ( constructor != NULL ) {
96 eblock->extensions[extensionhandle] = (*constructor)( object, parent );
98 eblock->extensions[extensionhandle] = NULL;
102 static void freeExtension(struct slapi_extension_block *eblock, int objecttype, void *object, void *parent, int extensionhandle )
104 slapi_extension_destructor_fnptr destructor;
106 assert( objecttype < SLAPI_X_EXT_MAX );
107 assert( extensionhandle < registered_extensions.extensions[objecttype].count );
109 if ( eblock->extensions[extensionhandle] != NULL ) {
110 assert( registered_extensions.extensions[objecttype].destructors != NULL );
111 destructor = registered_extensions.extensions[objecttype].destructors[extensionhandle];
112 if ( destructor != NULL ) {
113 (*destructor)( eblock->extensions[extensionhandle], object, parent );
115 eblock->extensions[extensionhandle] = NULL;
118 #endif /* LDAP_SLAPI */
120 void *slapi_get_object_extension(int objecttype, void *object, int extensionhandle)
123 struct slapi_extension_block *eblock;
126 if ( getExtensionBlock( objecttype, object, &eblock, &parent ) != 0 ) {
130 if ( extensionhandle < registered_extensions.extensions[objecttype].count ) {
131 return eblock->extensions[extensionhandle];
137 #endif /* LDAP_SLAPI */
140 void slapi_set_object_extension(int objecttype, void *object, int extensionhandle, void *extension)
143 struct slapi_extension_block *eblock;
146 if ( getExtensionBlock( objecttype, object, &eblock, &parent ) != 0 ) {
150 if ( extensionhandle < registered_extensions.extensions[objecttype].count ) {
151 /* free the old one */
152 freeExtension( eblock, objecttype, object, parent, extensionhandle );
154 /* constructed by caller */
155 eblock->extensions[extensionhandle] = extension;
157 #endif /* LDAP_SLAPI */
160 int slapi_register_object_extension(
161 const char *pluginname,
162 const char *objectname,
163 slapi_extension_constructor_fnptr constructor,
164 slapi_extension_destructor_fnptr destructor,
166 int *extensionhandle)
170 slapi_extension_t type;
171 struct slapi_registered_extension *re;
173 ldap_pvt_thread_mutex_lock( ®istered_extensions.mutex );
175 rc = mapExtensionType( objectname, &type );
177 ldap_pvt_thread_mutex_unlock( ®istered_extensions.mutex );
181 *objecttype = (int)type;
183 re = ®istered_extensions.extensions[*objecttype];
185 *extensionhandle = re->count;
188 /* can't add new extensions after objects have been created */
189 ldap_pvt_thread_mutex_unlock( ®istered_extensions.mutex );
195 if ( re->constructors == NULL ) {
196 re->constructors = (slapi_extension_constructor_fnptr *)slapi_ch_calloc( re->count,
197 sizeof( slapi_extension_constructor_fnptr ) );
199 re->constructors = (slapi_extension_constructor_fnptr *)slapi_ch_realloc( (char *)re->constructors,
200 re->count * sizeof( slapi_extension_constructor_fnptr ) );
202 re->constructors[*extensionhandle] = constructor;
204 if ( re->destructors == NULL ) {
205 re->destructors = (slapi_extension_destructor_fnptr *)slapi_ch_calloc( re->count,
206 sizeof( slapi_extension_destructor_fnptr ) );
208 re->destructors = (slapi_extension_destructor_fnptr *)slapi_ch_realloc( (char *)re->destructors,
209 re->count * sizeof( slapi_extension_destructor_fnptr ) );
211 re->destructors[*extensionhandle] = destructor;
213 ldap_pvt_thread_mutex_unlock( ®istered_extensions.mutex );
218 #endif /* LDAP_SLAPI */
221 int slapi_x_create_object_extensions(int objecttype, void *object)
225 struct slapi_extension_block *eblock;
229 switch ((slapi_extension_t) objecttype) {
230 case SLAPI_X_EXT_CONNECTION:
231 peblock = &(((Connection *)object)->c_extensions);
234 case SLAPI_X_EXT_OPERATION:
235 peblock = &(((Operation *)object)->o_extensions);
236 parent = ((Operation *)object)->o_conn;
245 ldap_pvt_thread_mutex_lock( ®istered_extensions.mutex );
246 if ( registered_extensions.extensions[objecttype].active == 0 ) {
248 * once we've created some extensions, no new extensions can
251 registered_extensions.extensions[objecttype].active = 1;
253 ldap_pvt_thread_mutex_unlock( ®istered_extensions.mutex );
255 eblock = (struct slapi_extension_block *)slapi_ch_calloc( 1, sizeof(*eblock) );
257 if ( registered_extensions.extensions[objecttype].count ) {
258 eblock->extensions = (void **)slapi_ch_calloc( registered_extensions.extensions[objecttype].count, sizeof(void *) );
259 for ( i = 0; i < registered_extensions.extensions[objecttype].count; i++ ) {
260 newExtension( eblock, objecttype, object, parent, i );
263 eblock->extensions = NULL;
274 int slapi_x_free_object_extensions(int objecttype, void *object)
278 struct slapi_extension_block *eblock;
282 switch ((slapi_extension_t) objecttype) {
283 case SLAPI_X_EXT_CONNECTION:
284 peblock = &(((Connection *)object)->c_extensions);
287 case SLAPI_X_EXT_OPERATION:
288 peblock = &(((Operation *)object)->o_extensions);
289 parent = ((Operation *)object)->o_conn;
296 eblock = (struct slapi_extension_block *)*peblock;
298 if ( eblock->extensions != NULL ) {
299 for ( i = registered_extensions.extensions[objecttype].count - 1; i >= 0; --i ) {
300 freeExtension( eblock, objecttype, object, parent, i );
303 slapi_ch_free( (void **)&eblock->extensions );
306 slapi_ch_free( peblock );
314 /* for reusable object types */
315 int slapi_x_clear_object_extensions(int objecttype, void *object)
319 struct slapi_extension_block *eblock;
322 if ( getExtensionBlock( objecttype, object, &eblock, &parent ) != 0 ) {
326 if ( eblock->extensions == NULL ) {
331 for ( i = registered_extensions.extensions[objecttype].count - 1; i >= 0; --i ) {
332 freeExtension( eblock, objecttype, object, parent, i );
335 for ( i = 0; i < registered_extensions.extensions[objecttype].count; i++ ) {
336 newExtension( eblock, objecttype, object, parent, i );
345 int slapi_x_init_object_extensions(void)
348 memset( ®istered_extensions, 0, sizeof( registered_extensions ) );
350 if ( ldap_pvt_thread_mutex_init( ®istered_extensions.mutex ) != 0 ) {