Back to index

openldap  2.4.31
dncache.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 1999-2012 The OpenLDAP Foundation.
00005  * Portions Copyright 2001-2003 Pierangelo Masarati.
00006  * Portions Copyright 1999-2003 Howard Chu.
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 the 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 the Howard Chu for inclusion
00019  * in OpenLDAP Software and subsequently enhanced by Pierangelo
00020  * Masarati.
00021  */
00022 
00023 #include "portable.h"
00024 
00025 #include <stdio.h>
00026 #include <ac/string.h>
00027 
00028 #include "slap.h"
00029 #include "../back-ldap/back-ldap.h"
00030 #include "back-meta.h"
00031 
00032 /*
00033  * The dncache, at present, maps an entry to the target that holds it.
00034  */
00035 
00036 typedef struct metadncacheentry_t {
00037        struct berval dn;
00038        int           target;
00039 
00040        time_t               lastupdated;
00041 } metadncacheentry_t;
00042 
00043 /*
00044  * meta_dncache_cmp
00045  *
00046  * compares two struct metadncacheentry; used by avl stuff
00047  * FIXME: modify avl stuff to delete an entry based on cmp
00048  * (e.g. when ttl expired?)
00049  */
00050 int
00051 meta_dncache_cmp(
00052        const void    *c1,
00053        const void    *c2 )
00054 {
00055        metadncacheentry_t   *cc1 = ( metadncacheentry_t * )c1;
00056        metadncacheentry_t   *cc2 = ( metadncacheentry_t * )c2;
00057 
00058        /*
00059         * case sensitive, because the dn MUST be normalized
00060         */
00061        return ber_bvcmp( &cc1->dn, &cc2->dn);
00062 }
00063 
00064 /*
00065  * meta_dncache_dup
00066  *
00067  * returns -1 in case a duplicate struct metadncacheentry has been inserted;
00068  * used by avl stuff
00069  */
00070 int
00071 meta_dncache_dup(
00072        void          *c1,
00073        void          *c2 )
00074 {
00075        metadncacheentry_t   *cc1 = ( metadncacheentry_t * )c1;
00076        metadncacheentry_t   *cc2 = ( metadncacheentry_t * )c2;
00077        
00078        /*
00079         * case sensitive, because the dn MUST be normalized
00080         */
00081        return ( ber_bvcmp( &cc1->dn, &cc2->dn ) == 0 ) ? -1 : 0;
00082 }
00083 
00084 /*
00085  * meta_dncache_get_target
00086  *
00087  * returns the target a dn belongs to, or -1 in case the dn is not
00088  * in the cache
00089  */
00090 int
00091 meta_dncache_get_target(
00092        metadncache_t *cache,
00093        struct berval *ndn )
00094 {
00095        metadncacheentry_t   tmp_entry,
00096                             *entry;
00097        int                  target = META_TARGET_NONE;
00098 
00099        assert( cache != NULL );
00100        assert( ndn != NULL );
00101 
00102        tmp_entry.dn = *ndn;
00103        ldap_pvt_thread_mutex_lock( &cache->mutex );
00104        entry = ( metadncacheentry_t * )avl_find( cache->tree,
00105                      ( caddr_t )&tmp_entry, meta_dncache_cmp );
00106 
00107        if ( entry != NULL ) {
00108               
00109               /*
00110                * if cache->ttl < 0, cache never expires;
00111                * if cache->ttl = 0 no cache is used; shouldn't get here
00112                * else, cache is used with ttl
00113                */
00114               if ( cache->ttl < 0 ) { 
00115                      target = entry->target;
00116 
00117               } else {
00118                      if ( entry->lastupdated+cache->ttl > slap_get_time() ) {
00119                             target = entry->target;
00120                      }
00121               }
00122        }
00123        ldap_pvt_thread_mutex_unlock( &cache->mutex );
00124 
00125        return target;
00126 }
00127 
00128 /*
00129  * meta_dncache_update_entry
00130  *
00131  * updates target and lastupdated of a struct metadncacheentry if exists,
00132  * otherwise it gets created; returns -1 in case of error
00133  */
00134 int
00135 meta_dncache_update_entry(
00136        metadncache_t *cache,
00137        struct berval *ndn,
00138        int           target )
00139 {
00140        metadncacheentry_t   *entry,
00141                             tmp_entry;
00142        time_t               curr_time = 0L;
00143        int                  err = 0;
00144 
00145        assert( cache != NULL );
00146        assert( ndn != NULL );
00147 
00148        /*
00149         * if cache->ttl < 0, cache never expires;
00150         * if cache->ttl = 0 no cache is used; shouldn't get here
00151         * else, cache is used with ttl
00152         */
00153        if ( cache->ttl > 0 ) {
00154               curr_time = slap_get_time();
00155        }
00156 
00157        tmp_entry.dn = *ndn;
00158 
00159        ldap_pvt_thread_mutex_lock( &cache->mutex );
00160        entry = ( metadncacheentry_t * )avl_find( cache->tree,
00161                      ( caddr_t )&tmp_entry, meta_dncache_cmp );
00162 
00163        if ( entry != NULL ) {
00164               entry->target = target;
00165               entry->lastupdated = curr_time;
00166 
00167        } else {
00168               entry = ch_malloc( sizeof( metadncacheentry_t ) + ndn->bv_len + 1 );
00169               if ( entry == NULL ) {
00170                      err = -1;
00171                      goto error_return;
00172               }
00173 
00174               entry->dn.bv_len = ndn->bv_len;
00175               entry->dn.bv_val = (char *)&entry[ 1 ];
00176               AC_MEMCPY( entry->dn.bv_val, ndn->bv_val, ndn->bv_len );
00177               entry->dn.bv_val[ ndn->bv_len ] = '\0';
00178 
00179               entry->target = target;
00180               entry->lastupdated = curr_time;
00181 
00182               err = avl_insert( &cache->tree, ( caddr_t )entry,
00183                             meta_dncache_cmp, meta_dncache_dup );
00184        }
00185 
00186 error_return:;
00187        ldap_pvt_thread_mutex_unlock( &cache->mutex );
00188 
00189        return err;
00190 }
00191 
00192 /*
00193  * meta_dncache_update_entry
00194  *
00195  * updates target and lastupdated of a struct metadncacheentry if exists,
00196  * otherwise it gets created; returns -1 in case of error
00197  */
00198 int
00199 meta_dncache_delete_entry(
00200        metadncache_t *cache,
00201        struct berval *ndn )
00202 {
00203        metadncacheentry_t   *entry,
00204                             tmp_entry;
00205 
00206        assert( cache != NULL );
00207        assert( ndn != NULL );
00208 
00209        tmp_entry.dn = *ndn;
00210 
00211        ldap_pvt_thread_mutex_lock( &cache->mutex );
00212        entry = avl_delete( &cache->tree, ( caddr_t )&tmp_entry,
00213                      meta_dncache_cmp );
00214        ldap_pvt_thread_mutex_unlock( &cache->mutex );
00215 
00216        if ( entry != NULL ) {
00217               meta_dncache_free( ( void * )entry );
00218        }
00219 
00220        return 0;
00221 }
00222 
00223 /*
00224  * meta_dncache_free
00225  *
00226  * frees an entry
00227  * 
00228  */
00229 void
00230 meta_dncache_free(
00231        void          *e )
00232 {
00233        free( e );
00234 }
00235