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