Back to index

openldap  2.4.31
cache.c
Go to the documentation of this file.
00001 /* cache.c - routines to maintain an in-core cache of entries */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 2001-2012 The OpenLDAP Foundation.
00006  * Portions Copyright 2001-2003 Pierangelo Masarati.
00007  * All rights reserved.
00008  *
00009  * Redistribution and use in source and binary forms, with or without
00010  * modification, are permitted only as authorized by the OpenLDAP
00011  * Public License.
00012  *
00013  * A copy of this license is available in file LICENSE in the
00014  * top-level directory of the distribution or, alternatively, at
00015  * <http://www.OpenLDAP.org/license.html>.
00016  */
00017 /* ACKNOWLEDGEMENTS:
00018  * This work was initially developed by Pierangelo Masarati for inclusion
00019  * in OpenLDAP Software.
00020  */
00021 
00022 #include "portable.h"
00023 
00024 #include <stdio.h>
00025 #include "ac/string.h"
00026 
00027 #include "slap.h"
00028 
00029 #include "back-monitor.h"
00030 
00031 /*
00032  * The cache maps DNs to Entries.
00033  * Each entry, on turn, holds the list of its children in the e_private field.
00034  * This is used by search operation to perform onelevel and subtree candidate
00035  * selection.
00036  */
00037 typedef struct monitor_cache_t {
00038        struct berval        mc_ndn;
00039        Entry                *mc_e;
00040 } monitor_cache_t;
00041 
00042 /*
00043  * compares entries based on the dn
00044  */
00045 int
00046 monitor_cache_cmp(
00047        const void    *c1,
00048        const void    *c2 )
00049 {
00050        monitor_cache_t      *cc1 = ( monitor_cache_t * )c1;
00051        monitor_cache_t      *cc2 = ( monitor_cache_t * )c2;
00052 
00053        /*
00054         * case sensitive, because the dn MUST be normalized
00055         */
00056        return ber_bvcmp( &cc1->mc_ndn, &cc2->mc_ndn );
00057 }
00058 
00059 /*
00060  * checks for duplicate entries
00061  */
00062 int
00063 monitor_cache_dup(
00064        void          *c1,
00065        void          *c2 )
00066 {
00067        monitor_cache_t *cc1 = ( monitor_cache_t * )c1;
00068        monitor_cache_t *cc2 = ( monitor_cache_t * )c2;
00069 
00070        /*
00071         * case sensitive, because the dn MUST be normalized
00072         */
00073        return ber_bvcmp( &cc1->mc_ndn, &cc2->mc_ndn ) == 0 ? -1 : 0;
00074 }
00075 
00076 /*
00077  * adds an entry to the cache and inits the mutex
00078  */
00079 int
00080 monitor_cache_add(
00081        monitor_info_t       *mi,
00082        Entry         *e )
00083 {
00084        monitor_cache_t      *mc;
00085        monitor_entry_t      *mp;
00086        int           rc;
00087 
00088        assert( mi != NULL );
00089        assert( e != NULL );
00090 
00091        mp = ( monitor_entry_t *)e->e_private;
00092 
00093        mc = ( monitor_cache_t * )ch_malloc( sizeof( monitor_cache_t ) );
00094        mc->mc_ndn = e->e_nname;
00095        mc->mc_e = e;
00096        ldap_pvt_thread_mutex_lock( &mi->mi_cache_mutex );
00097        rc = avl_insert( &mi->mi_cache, ( caddr_t )mc,
00098                      monitor_cache_cmp, monitor_cache_dup );
00099        ldap_pvt_thread_mutex_unlock( &mi->mi_cache_mutex );
00100 
00101        return rc;
00102 }
00103 
00104 /*
00105  * locks the entry (no r/w)
00106  */
00107 int
00108 monitor_cache_lock(
00109        Entry         *e )
00110 {
00111        monitor_entry_t *mp;
00112 
00113        assert( e != NULL );
00114        assert( e->e_private != NULL );
00115 
00116        mp = ( monitor_entry_t * )e->e_private;
00117        ldap_pvt_thread_mutex_lock( &mp->mp_mutex );
00118 
00119        return( 0 );
00120 }
00121 
00122 /*
00123  * tries to lock the entry (no r/w)
00124  */
00125 int
00126 monitor_cache_trylock(
00127        Entry         *e )
00128 {
00129        monitor_entry_t *mp;
00130 
00131        assert( e != NULL );
00132        assert( e->e_private != NULL );
00133 
00134        mp = ( monitor_entry_t * )e->e_private;
00135        return ldap_pvt_thread_mutex_trylock( &mp->mp_mutex );
00136 }
00137 
00138 /*
00139  * gets an entry from the cache based on the normalized dn 
00140  * with mutex locked
00141  */
00142 int
00143 monitor_cache_get(
00144        monitor_info_t       *mi,
00145        struct berval *ndn,
00146        Entry         **ep )
00147 {
00148        monitor_cache_t tmp_mc, *mc;
00149 
00150        assert( mi != NULL );
00151        assert( ndn != NULL );
00152        assert( ep != NULL );
00153 
00154        *ep = NULL;
00155 
00156        tmp_mc.mc_ndn = *ndn;
00157 retry:;
00158        ldap_pvt_thread_mutex_lock( &mi->mi_cache_mutex );
00159        mc = ( monitor_cache_t * )avl_find( mi->mi_cache,
00160                      ( caddr_t )&tmp_mc, monitor_cache_cmp );
00161 
00162        if ( mc != NULL ) {
00163               /* entry is returned with mutex locked */
00164               if ( monitor_cache_trylock( mc->mc_e ) ) {
00165                      ldap_pvt_thread_mutex_unlock( &mi->mi_cache_mutex );
00166                      ldap_pvt_thread_yield();
00167                      goto retry;
00168               }
00169               *ep = mc->mc_e;
00170        }
00171 
00172        ldap_pvt_thread_mutex_unlock( &mi->mi_cache_mutex );
00173 
00174        return ( *ep == NULL ? -1 : 0 );
00175 }
00176 
00177 /*
00178  * gets an entry from the cache based on the normalized dn 
00179  * with mutex locked
00180  */
00181 int
00182 monitor_cache_remove(
00183        monitor_info_t       *mi,
00184        struct berval *ndn,
00185        Entry         **ep )
00186 {
00187        monitor_cache_t tmp_mc, *mc;
00188        struct berval pndn;
00189 
00190        assert( mi != NULL );
00191        assert( ndn != NULL );
00192        assert( ep != NULL );
00193 
00194        *ep = NULL;
00195 
00196        dnParent( ndn, &pndn );
00197 
00198 retry:;
00199        ldap_pvt_thread_mutex_lock( &mi->mi_cache_mutex );
00200 
00201        tmp_mc.mc_ndn = *ndn;
00202        mc = ( monitor_cache_t * )avl_find( mi->mi_cache,
00203                      ( caddr_t )&tmp_mc, monitor_cache_cmp );
00204 
00205        if ( mc != NULL ) {
00206               monitor_cache_t *pmc;
00207 
00208               if ( monitor_cache_trylock( mc->mc_e ) ) {
00209                      ldap_pvt_thread_mutex_unlock( &mi->mi_cache_mutex );
00210                      goto retry;
00211               }
00212 
00213               tmp_mc.mc_ndn = pndn;
00214               pmc = ( monitor_cache_t * )avl_find( mi->mi_cache,
00215                      ( caddr_t )&tmp_mc, monitor_cache_cmp );
00216               if ( pmc != NULL ) {
00217                      monitor_entry_t      *mp = (monitor_entry_t *)mc->mc_e->e_private,
00218                                    *pmp = (monitor_entry_t *)pmc->mc_e->e_private;
00219                      Entry         **entryp;
00220 
00221                      if ( monitor_cache_trylock( pmc->mc_e ) ) {
00222                             monitor_cache_release( mi, mc->mc_e );
00223                             ldap_pvt_thread_mutex_unlock( &mi->mi_cache_mutex );
00224                             goto retry;
00225                      }
00226 
00227                      for ( entryp = &pmp->mp_children; *entryp != NULL;  ) {
00228                             monitor_entry_t      *next = (monitor_entry_t *)(*entryp)->e_private;
00229                             if ( next == mp ) {
00230                                    *entryp = next->mp_next;
00231                                    entryp = NULL;
00232                                    break;
00233                             }
00234 
00235                             entryp = &next->mp_next;
00236                      }
00237 
00238                      if ( entryp != NULL ) {
00239                             Debug( LDAP_DEBUG_ANY,
00240                                    "monitor_cache_remove(\"%s\"): "
00241                                    "not in parent's list\n",
00242                                    ndn->bv_val, 0, 0 );
00243                      }
00244 
00245                      /* either succeeded, and the entry is no longer
00246                       * in its parent's list, or failed, and the
00247                       * entry is neither mucked with nor returned */
00248                      monitor_cache_release( mi, pmc->mc_e );
00249 
00250                      if ( entryp == NULL ) {
00251                             monitor_cache_t *tmpmc;
00252 
00253                             tmp_mc.mc_ndn = *ndn;
00254                             tmpmc = avl_delete( &mi->mi_cache,
00255                                    ( caddr_t )&tmp_mc, monitor_cache_cmp );
00256                             assert( tmpmc == mc );
00257 
00258                             *ep = mc->mc_e;
00259                             ch_free( mc );
00260                             mc = NULL;
00261 
00262                             /* NOTE: we destroy the mutex, but otherwise
00263                              * leave the private data around; specifically,
00264                              * callbacks need be freed by someone else */
00265 
00266                             ldap_pvt_thread_mutex_destroy( &mp->mp_mutex );
00267                             mp->mp_next = NULL;
00268                             mp->mp_children = NULL;
00269                      }
00270 
00271               }
00272 
00273               if ( mc ) {
00274                      monitor_cache_release( mi, mc->mc_e );
00275               }
00276        }
00277 
00278        ldap_pvt_thread_mutex_unlock( &mi->mi_cache_mutex );
00279 
00280        return ( *ep == NULL ? -1 : 0 );
00281 }
00282 
00283 /*
00284  * If the entry exists in cache, it is returned in locked status;
00285  * otherwise, if the parent exists, if it may generate volatile 
00286  * descendants an attempt to generate the required entry is
00287  * performed and, if successful, the entry is returned
00288  */
00289 int
00290 monitor_cache_dn2entry(
00291        Operation            *op,
00292        SlapReply            *rs,
00293        struct berval        *ndn,
00294        Entry                **ep,
00295        Entry                **matched )
00296 {
00297        monitor_info_t *mi = (monitor_info_t *)op->o_bd->be_private;
00298        int                  rc;
00299        struct berval        p_ndn = BER_BVNULL;
00300        Entry                *e_parent;
00301        monitor_entry_t      *mp;
00302               
00303        assert( mi != NULL );
00304        assert( ndn != NULL );
00305        assert( ep != NULL );
00306        assert( matched != NULL );
00307 
00308        *matched = NULL;
00309 
00310        if ( !dnIsSuffix( ndn, &op->o_bd->be_nsuffix[ 0 ] ) ) {
00311               return( -1 );
00312        }
00313 
00314        rc = monitor_cache_get( mi, ndn, ep );
00315               if ( !rc && *ep != NULL ) {
00316               return( 0 );
00317        }
00318 
00319        /* try with parent/ancestors */
00320        if ( BER_BVISNULL( ndn ) ) {
00321               BER_BVSTR( &p_ndn, "" );
00322 
00323        } else {
00324               dnParent( ndn, &p_ndn );
00325        }
00326 
00327        rc = monitor_cache_dn2entry( op, rs, &p_ndn, &e_parent, matched );
00328        if ( rc || e_parent == NULL ) {
00329               return( -1 );
00330        }
00331 
00332        mp = ( monitor_entry_t * )e_parent->e_private;
00333        rc = -1;
00334        if ( mp->mp_flags & MONITOR_F_VOLATILE_CH ) {
00335               /* parent entry generates volatile children */
00336               rc = monitor_entry_create( op, rs, ndn, e_parent, ep );
00337        }
00338 
00339        if ( !rc ) {
00340               monitor_cache_lock( *ep );
00341               monitor_cache_release( mi, e_parent );
00342 
00343        } else {
00344               *matched = e_parent;
00345        }
00346        
00347        return( rc );
00348 }
00349 
00350 /*
00351  * releases the lock of the entry; if it is marked as volatile, it is
00352  * destroyed.
00353  */
00354 int
00355 monitor_cache_release(
00356        monitor_info_t       *mi,
00357        Entry         *e )
00358 {
00359        monitor_entry_t *mp;
00360 
00361        assert( mi != NULL );
00362        assert( e != NULL );
00363        assert( e->e_private != NULL );
00364        
00365        mp = ( monitor_entry_t * )e->e_private;
00366 
00367        if ( mp->mp_flags & MONITOR_F_VOLATILE ) {
00368               monitor_cache_t      *mc, tmp_mc;
00369 
00370               /* volatile entries do not return to cache */
00371               ldap_pvt_thread_mutex_lock( &mi->mi_cache_mutex );
00372               tmp_mc.mc_ndn = e->e_nname;
00373               mc = avl_delete( &mi->mi_cache,
00374                             ( caddr_t )&tmp_mc, monitor_cache_cmp );
00375               ldap_pvt_thread_mutex_unlock( &mi->mi_cache_mutex );
00376               if ( mc != NULL ) {
00377                      ch_free( mc );
00378               }
00379               
00380               ldap_pvt_thread_mutex_unlock( &mp->mp_mutex );
00381               ldap_pvt_thread_mutex_destroy( &mp->mp_mutex );
00382               ch_free( mp );
00383               e->e_private = NULL;
00384               entry_free( e );
00385 
00386               return( 0 );
00387        }
00388        
00389        ldap_pvt_thread_mutex_unlock( &mp->mp_mutex );
00390 
00391        return( 0 );
00392 }
00393 
00394 static void
00395 monitor_entry_destroy( void *v_mc )
00396 {
00397        monitor_cache_t             *mc = (monitor_cache_t *)v_mc;
00398 
00399        if ( mc->mc_e != NULL ) {
00400               monitor_entry_t *mp;
00401 
00402               assert( mc->mc_e->e_private != NULL );
00403        
00404               mp = ( monitor_entry_t * )mc->mc_e->e_private;
00405 
00406               if ( mp->mp_cb ) {
00407                      monitor_callback_t   *cb;
00408 
00409                      for ( cb = mp->mp_cb; cb != NULL; ) {
00410                             monitor_callback_t   *next = cb->mc_next;
00411 
00412                             if ( cb->mc_free ) {
00413                                    (void)cb->mc_free( mc->mc_e, &cb->mc_private );
00414                             }
00415                             ch_free( mp->mp_cb );
00416 
00417                             cb = next;
00418                      }
00419               }
00420 
00421               ldap_pvt_thread_mutex_destroy( &mp->mp_mutex );
00422 
00423               ch_free( mp );
00424               mc->mc_e->e_private = NULL;
00425               entry_free( mc->mc_e );
00426        }
00427 
00428        ch_free( mc );
00429 }
00430 
00431 int
00432 monitor_cache_destroy(
00433        monitor_info_t       *mi )
00434 {
00435        if ( mi->mi_cache ) {
00436               avl_free( mi->mi_cache, monitor_entry_destroy );
00437        }
00438 
00439        return 0;
00440 }
00441 
00442 int monitor_back_release(
00443        Operation *op,
00444        Entry *e,
00445        int rw )
00446 {
00447        monitor_info_t       *mi = ( monitor_info_t * )op->o_bd->be_private;
00448        return monitor_cache_release( mi, e );
00449 }