Back to index

openldap  2.4.31
slapi_ext.c
Go to the documentation of this file.
00001 /* $OpenLDAP$ */
00002 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00003  *
00004  * Copyright 2003-2012 The OpenLDAP Foundation.
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted only as authorized by the OpenLDAP
00009  * Public License.
00010  *
00011  * A copy of this license is available in the file LICENSE in the
00012  * top-level directory of the distribution or, alternatively, at
00013  * <http://www.OpenLDAP.org/license.html>.
00014  */
00015 /* (C) Copyright PADL Software Pty Ltd. 2003
00016  * Redistribution and use in source and binary forms, with or without
00017  * modification, are permitted provided that this notice is preserved
00018  * and that due credit is given to PADL Software Pty Ltd. This software
00019  * is provided ``as is'' without express or implied warranty.
00020  */
00021 /* ACKNOWLEDGEMENTS:
00022  * This work was initially developed by Luke Howard for inclusion
00023  * in OpenLDAP Software.
00024  */
00025 
00026 #include "portable.h"
00027 
00028 #include <ac/string.h>
00029 #include <ac/stdarg.h>
00030 #include <ac/ctype.h>
00031 #include <ac/unistd.h>
00032 
00033 #ifdef LDAP_SLAPI
00034 
00035 #include <slap.h>
00036 #include <slapi.h>
00037 
00038 /*
00039  * Object extensions
00040  *
00041  * We only support two types -- connection and operation extensions.
00042  * Define more types in slapi.h
00043  */
00044 
00045 /* global state */
00046 struct slapi_registered_extension_set {
00047        ldap_pvt_thread_mutex_t mutex;
00048        struct slapi_registered_extension {
00049               int active;
00050               int count;
00051               slapi_extension_constructor_fnptr *constructors;
00052               slapi_extension_destructor_fnptr *destructors;
00053        } extensions[SLAPI_X_EXT_MAX];
00054 } registered_extensions;
00055 
00056 /* per-object state */
00057 struct slapi_extension_block {
00058        void **extensions;
00059 };
00060 
00061 static int get_extension_block(int objecttype, void *object, struct slapi_extension_block **eblock, void **parent)
00062 {
00063        switch ((slapi_extension_t) objecttype) {
00064        case SLAPI_X_EXT_CONNECTION:
00065               *eblock = ((Connection *)object)->c_extensions;
00066               *parent = NULL;
00067               break; 
00068        case SLAPI_X_EXT_OPERATION:
00069               *eblock = ((Operation *)object)->o_hdr->oh_extensions;
00070               *parent = ((Operation *)object)->o_conn;
00071               break; 
00072        default:
00073               return -1;
00074               break;
00075        }
00076 
00077        if ( *eblock == NULL ) {
00078               return -1;
00079        }
00080 
00081        return 0;
00082 }
00083 
00084 static int map_extension_type(const char *objectname, slapi_extension_t *type)
00085 {
00086        if ( strcasecmp( objectname, SLAPI_EXT_CONNECTION ) == 0 ) {
00087               *type = SLAPI_X_EXT_CONNECTION;
00088        } else if ( strcasecmp( objectname, SLAPI_EXT_OPERATION ) == 0 ) {
00089               *type = SLAPI_X_EXT_OPERATION;
00090        } else {
00091               return -1;
00092        }
00093 
00094        return 0;
00095 }
00096 
00097 static void new_extension(struct slapi_extension_block *eblock,
00098        int objecttype, void *object, void *parent,
00099        int extensionhandle )
00100 {
00101        slapi_extension_constructor_fnptr constructor;
00102 
00103        assert( objecttype < SLAPI_X_EXT_MAX );
00104        assert( extensionhandle < registered_extensions.extensions[objecttype].count );
00105 
00106        assert( registered_extensions.extensions[objecttype].constructors != NULL );
00107        constructor = registered_extensions.extensions[objecttype].constructors[extensionhandle];
00108 
00109        assert( eblock->extensions[extensionhandle] == NULL );
00110 
00111        if ( constructor != NULL ) {
00112               eblock->extensions[extensionhandle] = (*constructor)( object, parent );
00113        } else {
00114               eblock->extensions[extensionhandle] = NULL;
00115        }
00116 }
00117 
00118 static void free_extension(struct slapi_extension_block *eblock, int objecttype, void *object, void *parent, int extensionhandle )
00119 {
00120        slapi_extension_destructor_fnptr destructor;
00121 
00122        assert( objecttype < SLAPI_X_EXT_MAX );
00123        assert( extensionhandle < registered_extensions.extensions[objecttype].count );
00124 
00125        if ( eblock->extensions[extensionhandle] != NULL ) {
00126               assert( registered_extensions.extensions[objecttype].destructors != NULL );
00127               destructor = registered_extensions.extensions[objecttype].destructors[extensionhandle];
00128               if ( destructor != NULL ) {
00129                      (*destructor)( eblock->extensions[extensionhandle], object, parent );
00130               }
00131               eblock->extensions[extensionhandle] = NULL;
00132        }
00133 }
00134 
00135 void *slapi_get_object_extension(int objecttype, void *object, int extensionhandle)
00136 {
00137        struct slapi_extension_block *eblock;
00138        void *parent;
00139 
00140        if ( get_extension_block( objecttype, object, &eblock, &parent ) != 0 ) {
00141               return NULL;
00142        }
00143 
00144        if ( extensionhandle < registered_extensions.extensions[objecttype].count ) {
00145               return eblock->extensions[extensionhandle];
00146        }
00147 
00148        return NULL;
00149 }
00150 
00151 void slapi_set_object_extension(int objecttype, void *object, int extensionhandle, void *extension)
00152 {
00153        struct slapi_extension_block *eblock;
00154        void *parent;
00155 
00156        if ( get_extension_block( objecttype, object, &eblock, &parent ) != 0 ) {
00157               return;
00158        }
00159 
00160        if ( extensionhandle < registered_extensions.extensions[objecttype].count ) {
00161               /* free the old one */
00162               free_extension( eblock, objecttype, object, parent, extensionhandle );
00163 
00164               /* constructed by caller */
00165               eblock->extensions[extensionhandle] = extension;
00166        }
00167 }
00168 
00169 int slapi_register_object_extension(
00170        const char *pluginname,
00171        const char *objectname,
00172        slapi_extension_constructor_fnptr constructor,
00173        slapi_extension_destructor_fnptr destructor,
00174        int *objecttype,
00175        int *extensionhandle)
00176 {
00177        int rc;
00178        slapi_extension_t type;
00179        struct slapi_registered_extension *re;
00180 
00181        ldap_pvt_thread_mutex_lock( &registered_extensions.mutex );
00182 
00183        rc = map_extension_type( objectname, &type );
00184        if ( rc != 0 ) {
00185               ldap_pvt_thread_mutex_unlock( &registered_extensions.mutex );
00186               return rc;
00187        }
00188 
00189        *objecttype = (int)type;
00190 
00191        re = &registered_extensions.extensions[*objecttype];
00192 
00193        *extensionhandle = re->count;
00194 
00195        if ( re->active ) {
00196               /* can't add new extensions after objects have been created */
00197               ldap_pvt_thread_mutex_unlock( &registered_extensions.mutex );
00198               return -1;
00199        }
00200 
00201        re->count++;
00202 
00203        if ( re->constructors == NULL ) {
00204               re->constructors = (slapi_extension_constructor_fnptr *)slapi_ch_calloc( re->count,
00205                      sizeof( slapi_extension_constructor_fnptr ) );
00206        } else {
00207               re->constructors = (slapi_extension_constructor_fnptr *)slapi_ch_realloc( (char *)re->constructors,
00208                      re->count * sizeof( slapi_extension_constructor_fnptr ) );
00209        }
00210        re->constructors[*extensionhandle] = constructor;
00211 
00212        if ( re->destructors == NULL ) {
00213               re->destructors = (slapi_extension_destructor_fnptr *)slapi_ch_calloc( re->count,
00214                      sizeof( slapi_extension_destructor_fnptr ) );
00215        } else {
00216               re->destructors = (slapi_extension_destructor_fnptr *)slapi_ch_realloc( (char *)re->destructors,
00217                      re->count * sizeof( slapi_extension_destructor_fnptr ) );
00218        }
00219        re->destructors[*extensionhandle] = destructor;
00220 
00221        ldap_pvt_thread_mutex_unlock( &registered_extensions.mutex );
00222 
00223        return 0;
00224 }
00225 
00226 int slapi_int_create_object_extensions(int objecttype, void *object)
00227 {
00228        int i;
00229        struct slapi_extension_block *eblock;
00230        void **peblock;
00231        void *parent;
00232 
00233        switch ((slapi_extension_t) objecttype) {
00234        case SLAPI_X_EXT_CONNECTION:
00235               peblock = &(((Connection *)object)->c_extensions);
00236               parent = NULL;
00237               break; 
00238        case SLAPI_X_EXT_OPERATION:
00239               peblock = &(((Operation *)object)->o_hdr->oh_extensions);
00240               parent = ((Operation *)object)->o_conn;
00241               break;
00242        default:
00243               return -1;
00244               break;
00245        }
00246 
00247        *peblock = NULL;
00248 
00249        ldap_pvt_thread_mutex_lock( &registered_extensions.mutex );
00250        if ( registered_extensions.extensions[objecttype].active == 0 ) {
00251               /*
00252                * once we've created some extensions, no new extensions can
00253                * be registered.
00254                */
00255               registered_extensions.extensions[objecttype].active = 1;
00256        }
00257        ldap_pvt_thread_mutex_unlock( &registered_extensions.mutex );
00258 
00259        eblock = (struct slapi_extension_block *)slapi_ch_calloc( 1, sizeof(*eblock) );
00260 
00261        if ( registered_extensions.extensions[objecttype].count ) {
00262               eblock->extensions = (void **)slapi_ch_calloc( registered_extensions.extensions[objecttype].count, sizeof(void *) );
00263               for ( i = 0; i < registered_extensions.extensions[objecttype].count; i++ ) {
00264                      new_extension( eblock, objecttype, object, parent, i );
00265               }
00266        } else {
00267               eblock->extensions = NULL;
00268        }
00269 
00270        *peblock = eblock;
00271 
00272        return 0;
00273 }
00274 
00275 int slapi_int_free_object_extensions(int objecttype, void *object)
00276 {
00277        int i;
00278        struct slapi_extension_block *eblock;
00279        void **peblock;
00280        void *parent;
00281 
00282        switch ((slapi_extension_t) objecttype) {
00283        case SLAPI_X_EXT_CONNECTION:
00284               peblock = &(((Connection *)object)->c_extensions);
00285               parent = NULL;
00286               break; 
00287        case SLAPI_X_EXT_OPERATION:
00288               peblock = &(((Operation *)object)->o_hdr->oh_extensions);
00289               parent = ((Operation *)object)->o_conn;
00290               break; 
00291        default:
00292               return -1;
00293               break;
00294        }
00295 
00296        eblock = (struct slapi_extension_block *)*peblock;
00297 
00298        if ( eblock->extensions != NULL ) {
00299               for ( i = registered_extensions.extensions[objecttype].count - 1; i >= 0; --i ) {
00300                      free_extension( eblock, objecttype, object, parent, i );
00301               }
00302 
00303               slapi_ch_free( (void **)&eblock->extensions );
00304        }
00305 
00306        slapi_ch_free( peblock );
00307 
00308        return 0;
00309 }
00310 
00311 /* for reusable object types */
00312 int slapi_int_clear_object_extensions(int objecttype, void *object)
00313 {
00314        int i;
00315        struct slapi_extension_block *eblock;
00316        void *parent;
00317 
00318        if ( get_extension_block( objecttype, object, &eblock, &parent ) != 0 ) {
00319               return -1;
00320        }
00321 
00322        if ( eblock->extensions == NULL ) {
00323               /* no extensions */
00324               return 0;
00325        }
00326 
00327        for ( i = registered_extensions.extensions[objecttype].count - 1; i >= 0; --i ) {
00328               free_extension( eblock, objecttype, object, parent, i );
00329        }
00330 
00331        for ( i = 0; i < registered_extensions.extensions[objecttype].count; i++ ) {
00332               new_extension( eblock, objecttype, object, parent, i );
00333        }
00334 
00335        return 0;
00336 }
00337 
00338 int slapi_int_init_object_extensions(void)
00339 {
00340        memset( &registered_extensions, 0, sizeof( registered_extensions ) );
00341 
00342        if ( ldap_pvt_thread_mutex_init( &registered_extensions.mutex ) != 0 ) {
00343               return -1;
00344        }
00345 
00346        return 0;
00347 }
00348 
00349 #endif /* LDAP_SLAPI */