1 /* $OpenLDAP: pkg/ldap/servers/slapd/slapi/slapi_ext.c,v 1.16.2.3 2008/02/11 23:26:49 kurt Exp $ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 2003-2008 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 get_extension_block(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_hdr
->oh_extensions
;
70 *parent
= ((Operation
*)object
)->o_conn
;
77 if ( *eblock
== NULL
) {
84 static int map_extension_type(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 new_extension(struct slapi_extension_block
*eblock
,
98 int objecttype
, void *object
, void *parent
,
101 slapi_extension_constructor_fnptr constructor
;
103 assert( objecttype
< SLAPI_X_EXT_MAX
);
104 assert( extensionhandle
< registered_extensions
.extensions
[objecttype
].count
);
106 assert( registered_extensions
.extensions
[objecttype
].constructors
!= NULL
);
107 constructor
= registered_extensions
.extensions
[objecttype
].constructors
[extensionhandle
];
109 assert( eblock
->extensions
[extensionhandle
] == NULL
);
111 if ( constructor
!= NULL
) {
112 eblock
->extensions
[extensionhandle
] = (*constructor
)( object
, parent
);
114 eblock
->extensions
[extensionhandle
] = NULL
;
118 static void free_extension(struct slapi_extension_block
*eblock
, int objecttype
, void *object
, void *parent
, int extensionhandle
)
120 slapi_extension_destructor_fnptr destructor
;
122 assert( objecttype
< SLAPI_X_EXT_MAX
);
123 assert( extensionhandle
< registered_extensions
.extensions
[objecttype
].count
);
125 if ( eblock
->extensions
[extensionhandle
] != NULL
) {
126 assert( registered_extensions
.extensions
[objecttype
].destructors
!= NULL
);
127 destructor
= registered_extensions
.extensions
[objecttype
].destructors
[extensionhandle
];
128 if ( destructor
!= NULL
) {
129 (*destructor
)( eblock
->extensions
[extensionhandle
], object
, parent
);
131 eblock
->extensions
[extensionhandle
] = NULL
;
135 void *slapi_get_object_extension(int objecttype
, void *object
, int extensionhandle
)
137 struct slapi_extension_block
*eblock
;
140 if ( get_extension_block( objecttype
, object
, &eblock
, &parent
) != 0 ) {
144 if ( extensionhandle
< registered_extensions
.extensions
[objecttype
].count
) {
145 return eblock
->extensions
[extensionhandle
];
151 void slapi_set_object_extension(int objecttype
, void *object
, int extensionhandle
, void *extension
)
153 struct slapi_extension_block
*eblock
;
156 if ( get_extension_block( objecttype
, object
, &eblock
, &parent
) != 0 ) {
160 if ( extensionhandle
< registered_extensions
.extensions
[objecttype
].count
) {
161 /* free the old one */
162 free_extension( eblock
, objecttype
, object
, parent
, extensionhandle
);
164 /* constructed by caller */
165 eblock
->extensions
[extensionhandle
] = extension
;
169 int slapi_register_object_extension(
170 const char *pluginname
,
171 const char *objectname
,
172 slapi_extension_constructor_fnptr constructor
,
173 slapi_extension_destructor_fnptr destructor
,
175 int *extensionhandle
)
178 slapi_extension_t type
;
179 struct slapi_registered_extension
*re
;
181 ldap_pvt_thread_mutex_lock( ®istered_extensions
.mutex
);
183 rc
= map_extension_type( objectname
, &type
);
185 ldap_pvt_thread_mutex_unlock( ®istered_extensions
.mutex
);
189 *objecttype
= (int)type
;
191 re
= ®istered_extensions
.extensions
[*objecttype
];
193 *extensionhandle
= re
->count
;
196 /* can't add new extensions after objects have been created */
197 ldap_pvt_thread_mutex_unlock( ®istered_extensions
.mutex
);
203 if ( re
->constructors
== NULL
) {
204 re
->constructors
= (slapi_extension_constructor_fnptr
*)slapi_ch_calloc( re
->count
,
205 sizeof( slapi_extension_constructor_fnptr
) );
207 re
->constructors
= (slapi_extension_constructor_fnptr
*)slapi_ch_realloc( (char *)re
->constructors
,
208 re
->count
* sizeof( slapi_extension_constructor_fnptr
) );
210 re
->constructors
[*extensionhandle
] = constructor
;
212 if ( re
->destructors
== NULL
) {
213 re
->destructors
= (slapi_extension_destructor_fnptr
*)slapi_ch_calloc( re
->count
,
214 sizeof( slapi_extension_destructor_fnptr
) );
216 re
->destructors
= (slapi_extension_destructor_fnptr
*)slapi_ch_realloc( (char *)re
->destructors
,
217 re
->count
* sizeof( slapi_extension_destructor_fnptr
) );
219 re
->destructors
[*extensionhandle
] = destructor
;
221 ldap_pvt_thread_mutex_unlock( ®istered_extensions
.mutex
);
226 int slapi_int_create_object_extensions(int objecttype
, void *object
)
229 struct slapi_extension_block
*eblock
;
233 switch ((slapi_extension_t
) objecttype
) {
234 case SLAPI_X_EXT_CONNECTION
:
235 peblock
= &(((Connection
*)object
)->c_extensions
);
238 case SLAPI_X_EXT_OPERATION
:
239 peblock
= &(((Operation
*)object
)->o_hdr
->oh_extensions
);
240 parent
= ((Operation
*)object
)->o_conn
;
249 ldap_pvt_thread_mutex_lock( ®istered_extensions
.mutex
);
250 if ( registered_extensions
.extensions
[objecttype
].active
== 0 ) {
252 * once we've created some extensions, no new extensions can
255 registered_extensions
.extensions
[objecttype
].active
= 1;
257 ldap_pvt_thread_mutex_unlock( ®istered_extensions
.mutex
);
259 eblock
= (struct slapi_extension_block
*)slapi_ch_calloc( 1, sizeof(*eblock
) );
261 if ( registered_extensions
.extensions
[objecttype
].count
) {
262 eblock
->extensions
= (void **)slapi_ch_calloc( registered_extensions
.extensions
[objecttype
].count
, sizeof(void *) );
263 for ( i
= 0; i
< registered_extensions
.extensions
[objecttype
].count
; i
++ ) {
264 new_extension( eblock
, objecttype
, object
, parent
, i
);
267 eblock
->extensions
= NULL
;
275 int slapi_int_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_hdr
->oh_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 free_extension( eblock
, objecttype
, object
, parent
, i
);
303 slapi_ch_free( (void **)&eblock
->extensions
);
306 slapi_ch_free( peblock
);
311 /* for reusable object types */
312 int slapi_int_clear_object_extensions(int objecttype
, void *object
)
315 struct slapi_extension_block
*eblock
;
318 if ( get_extension_block( objecttype
, object
, &eblock
, &parent
) != 0 ) {
322 if ( eblock
->extensions
== NULL
) {
327 for ( i
= registered_extensions
.extensions
[objecttype
].count
- 1; i
>= 0; --i
) {
328 free_extension( eblock
, objecttype
, object
, parent
, i
);
331 for ( i
= 0; i
< registered_extensions
.extensions
[objecttype
].count
; i
++ ) {
332 new_extension( eblock
, objecttype
, object
, parent
, i
);
338 int slapi_int_init_object_extensions(void)
340 memset( ®istered_extensions
, 0, sizeof( registered_extensions
) );
342 if ( ldap_pvt_thread_mutex_init( ®istered_extensions
.mutex
) != 0 ) {
349 #endif /* LDAP_SLAPI */