]> git.sur5r.net Git - openldap/blob - servers/slapd/slapi/slapi_ext.c
ITS#2846 - make veryclean
[openldap] / servers / slapd / slapi / slapi_ext.c
1 /* $OpenLDAP$/
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 2003 The OpenLDAP Foundation.
5  * All rights reserved.
6  *
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.
10  *
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>.
14  */
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.
20  */
21 /* ACKNOWLEDGEMENTS:
22  * This work was initially developed by Luke Howard for inclusion
23  * in OpenLDAP Software.
24  */
25
26 #include "portable.h"
27
28 #include <ac/string.h>
29 #include <ac/stdarg.h>
30 #include <ac/ctype.h>
31 #include <ac/unistd.h>
32 #include <ldap_pvt.h>
33
34 #include <slap.h>
35 #include <slapi.h>
36
37 #ifdef LDAP_SLAPI
38 /*
39  * Object extensions
40  *
41  * We only support two types -- connection and operation extensions.
42  * Define more types in slapi.h
43  */
44
45 /* global state */
46 struct slapi_registered_extension_set {
47         ldap_pvt_thread_mutex_t mutex;
48         struct slapi_registered_extension {
49                 int active;
50                 int count;
51                 slapi_extension_constructor_fnptr *constructors;
52                 slapi_extension_destructor_fnptr *destructors;
53         } extensions[SLAPI_X_EXT_MAX];
54 } registered_extensions;
55
56 /* per-object state */
57 struct slapi_extension_block {
58         void **extensions;
59 };
60
61 static int getExtensionBlock(int objecttype, void *object, struct slapi_extension_block **eblock, void **parent)
62 {
63         switch ((slapi_extension_t) objecttype) {
64         case SLAPI_X_EXT_CONNECTION:
65                 *eblock = ((Connection *)object)->c_extensions;
66                 *parent = NULL;
67                 break;  
68         case SLAPI_X_EXT_OPERATION:
69                 *eblock = ((Operation *)object)->o_extensions;
70                 *parent = ((Operation *)object)->o_conn;
71                 break;  
72         default:
73                 return -1;
74                 break;
75         }
76
77         if ( *eblock == NULL ) {
78                 return -1;
79         }
80
81         return 0;
82 }
83
84 static int mapExtensionType(const char *objectname, slapi_extension_t *type)
85 {
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;
90         } else {
91                 return -1;
92         }
93
94         return 0;
95 }
96
97 static void newExtension(struct slapi_extension_block *eblock, int objecttype, void *object, void *parent, int extensionhandle )
98 {
99         slapi_extension_constructor_fnptr constructor;
100
101         assert( objecttype < SLAPI_X_EXT_MAX );
102         assert( extensionhandle < registered_extensions.extensions[objecttype].count );
103
104         assert( registered_extensions.extensions[objecttype].constructors != NULL );
105         constructor = registered_extensions.extensions[objecttype].constructors[extensionhandle];
106
107         assert( eblock->extensions[extensionhandle] == NULL );
108
109         if ( constructor != NULL ) {
110                 eblock->extensions[extensionhandle] = (*constructor)( object, parent );
111         } else {
112                 eblock->extensions[extensionhandle] = NULL;
113         }
114 }
115
116 static void freeExtension(struct slapi_extension_block *eblock, int objecttype, void *object, void *parent, int extensionhandle )
117 {
118         slapi_extension_destructor_fnptr destructor;
119
120         assert( objecttype < SLAPI_X_EXT_MAX );
121         assert( extensionhandle < registered_extensions.extensions[objecttype].count );
122
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 );
128                 }
129                 eblock->extensions[extensionhandle] = NULL;
130         }
131 }
132 #endif /* LDAP_SLAPI */
133
134 void *slapi_get_object_extension(int objecttype, void *object, int extensionhandle)
135 {
136 #ifdef LDAP_SLAPI
137         struct slapi_extension_block *eblock;
138         void *parent;
139
140         if ( getExtensionBlock( objecttype, object, &eblock, &parent ) != 0 ) {
141                 return NULL;
142         }
143
144         if ( extensionhandle < registered_extensions.extensions[objecttype].count ) {
145                 return eblock->extensions[extensionhandle];
146         }
147
148         return NULL;
149 #else
150         return NULL;
151 #endif /* LDAP_SLAPI */
152 }
153
154 void slapi_set_object_extension(int objecttype, void *object, int extensionhandle, void *extension)
155 {
156 #ifdef LDAP_SLAPI
157         struct slapi_extension_block *eblock;
158         void *parent;
159
160         if ( getExtensionBlock( objecttype, object, &eblock, &parent ) != 0 ) {
161                 return;
162         }
163
164         if ( extensionhandle < registered_extensions.extensions[objecttype].count ) {
165                 /* free the old one */
166                 freeExtension( eblock, objecttype, object, parent, extensionhandle );
167
168                 /* constructed by caller */
169                 eblock->extensions[extensionhandle] = extension;
170         }
171 #endif /* LDAP_SLAPI */
172 }
173
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,
179         int *objecttype,
180         int *extensionhandle)
181 {
182 #ifdef LDAP_SLAPI
183         int rc;
184         slapi_extension_t type;
185         struct slapi_registered_extension *re;
186
187         ldap_pvt_thread_mutex_lock( &registered_extensions.mutex );
188
189         rc = mapExtensionType( objectname, &type );
190         if ( rc != 0 ) {
191                 ldap_pvt_thread_mutex_unlock( &registered_extensions.mutex );
192                 return rc;
193         }
194
195         *objecttype = (int)type;
196
197         re = &registered_extensions.extensions[*objecttype];
198
199         *extensionhandle = re->count;
200
201         if ( re->active ) {
202                 /* can't add new extensions after objects have been created */
203                 ldap_pvt_thread_mutex_unlock( &registered_extensions.mutex );
204                 return -1;
205         }
206
207         re->count++;
208
209         if ( re->constructors == NULL ) {
210                 re->constructors = (slapi_extension_constructor_fnptr *)slapi_ch_calloc( re->count,
211                         sizeof( slapi_extension_constructor_fnptr ) );
212         } else {
213                 re->constructors = (slapi_extension_constructor_fnptr *)slapi_ch_realloc( (char *)re->constructors,
214                         re->count * sizeof( slapi_extension_constructor_fnptr ) );
215         }
216         re->constructors[*extensionhandle] = constructor;
217
218         if ( re->destructors == NULL ) {
219                 re->destructors = (slapi_extension_destructor_fnptr *)slapi_ch_calloc( re->count,
220                         sizeof( slapi_extension_destructor_fnptr ) );
221         } else {
222                 re->destructors = (slapi_extension_destructor_fnptr *)slapi_ch_realloc( (char *)re->destructors,
223                         re->count * sizeof( slapi_extension_destructor_fnptr ) );
224         }
225         re->destructors[*extensionhandle] = destructor;
226
227         ldap_pvt_thread_mutex_unlock( &registered_extensions.mutex );
228
229         return 0;
230 #else
231         return -1;
232 #endif /* LDAP_SLAPI */
233 }
234
235 int slapi_x_create_object_extensions(int objecttype, void *object)
236 {
237 #ifdef LDAP_SLAPI
238         int i, rc;
239         struct slapi_extension_block *eblock;
240         void **peblock;
241         void *parent;
242
243         switch ((slapi_extension_t) objecttype) {
244         case SLAPI_X_EXT_CONNECTION:
245                 peblock = &(((Connection *)object)->c_extensions);
246                 parent = NULL;
247                 break;  
248         case SLAPI_X_EXT_OPERATION:
249                 peblock = &(((Operation *)object)->o_extensions);
250                 parent = ((Operation *)object)->o_conn;
251                 break;
252         default:
253                 return -1;
254                 break;
255         }
256
257         *peblock = NULL;
258
259         ldap_pvt_thread_mutex_lock( &registered_extensions.mutex );
260         if ( registered_extensions.extensions[objecttype].active == 0 ) {
261                 /*
262                  * once we've created some extensions, no new extensions can
263                  * be registered.
264                  */
265                 registered_extensions.extensions[objecttype].active = 1;
266         }
267         ldap_pvt_thread_mutex_unlock( &registered_extensions.mutex );
268
269         eblock = (struct slapi_extension_block *)slapi_ch_calloc( 1, sizeof(*eblock) );
270
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 );
275                 }
276         } else {
277                 eblock->extensions = NULL;
278         }
279
280         *peblock = eblock;
281
282         return 0;
283 #else
284         return -1;
285 #endif
286 }
287
288 int slapi_x_free_object_extensions(int objecttype, void *object)
289 {
290 #ifdef LDAP_SLAPI
291         int i, rc;
292         struct slapi_extension_block *eblock;
293         void **peblock;
294         void *parent;
295
296         switch ((slapi_extension_t) objecttype) {
297         case SLAPI_X_EXT_CONNECTION:
298                 peblock = &(((Connection *)object)->c_extensions);
299                 parent = NULL;
300                 break;  
301         case SLAPI_X_EXT_OPERATION:
302                 peblock = &(((Operation *)object)->o_extensions);
303                 parent = ((Operation *)object)->o_conn;
304                 break;  
305         default:
306                 return -1;
307                 break;
308         }
309
310         eblock = (struct slapi_extension_block *)*peblock;
311
312         if ( eblock->extensions != NULL ) {
313                 for ( i = registered_extensions.extensions[objecttype].count - 1; i >= 0; --i ) {
314                         freeExtension( eblock, objecttype, object, parent, i );
315                 }
316
317                 slapi_ch_free( (void **)&eblock->extensions );
318         }
319
320         slapi_ch_free( peblock );
321
322         return 0;
323 #else
324         return -1;
325 #endif
326 }
327
328 /* for reusable object types */
329 int slapi_x_clear_object_extensions(int objecttype, void *object)
330 {
331 #ifdef LDAP_SLAPI
332         int i, rc;
333         struct slapi_extension_block *eblock;
334         void *parent;
335
336         if ( getExtensionBlock( objecttype, object, &eblock, &parent ) != 0 ) {
337                 return -1;
338         }
339
340         if ( eblock->extensions == NULL ) {
341                 /* no extensions */
342                 return 0;
343         }
344
345         for ( i = registered_extensions.extensions[objecttype].count - 1; i >= 0; --i ) {
346                 freeExtension( eblock, objecttype, object, parent, i );
347         }
348
349         for ( i = 0; i < registered_extensions.extensions[objecttype].count; i++ ) {
350                 newExtension( eblock, objecttype, object, parent, i );
351         }
352
353         return 0;
354 #else
355         return -1;
356 #endif
357 }
358
359 int slapi_x_init_object_extensions(void)
360 {
361 #ifdef LDAP_SLAPI
362         memset( &registered_extensions, 0, sizeof( registered_extensions ) );
363
364         if ( ldap_pvt_thread_mutex_init( &registered_extensions.mutex ) != 0 ) {
365                 return -1;
366         }
367
368         return 0;
369 #else
370         return -1;
371 #endif
372 }