Home | History | Annotate | Line # | Download | only in back-meta
dncache.c revision 1.1.1.1.2.2
      1 /* $OpenLDAP: pkg/ldap/servers/slapd/back-meta/dncache.c,v 1.16.2.3 2008/02/11 23:26:47 kurt Exp $ */
      2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
      3  *
      4  * Copyright 1999-2008 The OpenLDAP Foundation.
      5  * Portions Copyright 2001-2003 Pierangelo Masarati.
      6  * Portions Copyright 1999-2003 Howard Chu.
      7  * All rights reserved.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted only as authorized by the OpenLDAP
     11  * Public License.
     12  *
     13  * A copy of this license is available in the file LICENSE in the
     14  * top-level directory of the distribution or, alternatively, at
     15  * <http://www.OpenLDAP.org/license.html>.
     16  */
     17 /* ACKNOWLEDGEMENTS:
     18  * This work was initially developed by the Howard Chu for inclusion
     19  * in OpenLDAP Software and subsequently enhanced by Pierangelo
     20  * Masarati.
     21  */
     22 
     23 #include "portable.h"
     24 
     25 #include <stdio.h>
     26 #include <ac/string.h>
     27 
     28 #include "slap.h"
     29 #include "../back-ldap/back-ldap.h"
     30 #include "back-meta.h"
     31 
     32 /*
     33  * The dncache, at present, maps an entry to the target that holds it.
     34  */
     35 
     36 typedef struct metadncacheentry_t {
     37 	struct berval	dn;
     38 	int 		target;
     39 
     40 	time_t 		lastupdated;
     41 } metadncacheentry_t;
     42 
     43 /*
     44  * meta_dncache_cmp
     45  *
     46  * compares two struct metadncacheentry; used by avl stuff
     47  * FIXME: modify avl stuff to delete an entry based on cmp
     48  * (e.g. when ttl expired?)
     49  */
     50 int
     51 meta_dncache_cmp(
     52 	const void	*c1,
     53 	const void	*c2 )
     54 {
     55 	metadncacheentry_t	*cc1 = ( metadncacheentry_t * )c1;
     56 	metadncacheentry_t	*cc2 = ( metadncacheentry_t * )c2;
     57 
     58 	/*
     59 	 * case sensitive, because the dn MUST be normalized
     60 	 */
     61  	return ber_bvcmp( &cc1->dn, &cc2->dn);
     62 }
     63 
     64 /*
     65  * meta_dncache_dup
     66  *
     67  * returns -1 in case a duplicate struct metadncacheentry has been inserted;
     68  * used by avl stuff
     69  */
     70 int
     71 meta_dncache_dup(
     72 	void		*c1,
     73 	void		*c2 )
     74 {
     75 	metadncacheentry_t	*cc1 = ( metadncacheentry_t * )c1;
     76 	metadncacheentry_t	*cc2 = ( metadncacheentry_t * )c2;
     77 
     78 	/*
     79 	 * case sensitive, because the dn MUST be normalized
     80 	 */
     81  	return ( ber_bvcmp( &cc1->dn, &cc2->dn ) == 0 ) ? -1 : 0;
     82 }
     83 
     84 /*
     85  * meta_dncache_get_target
     86  *
     87  * returns the target a dn belongs to, or -1 in case the dn is not
     88  * in the cache
     89  */
     90 int
     91 meta_dncache_get_target(
     92 	metadncache_t	*cache,
     93 	struct berval	*ndn )
     94 {
     95 	metadncacheentry_t	tmp_entry,
     96 				*entry;
     97 	int			target = META_TARGET_NONE;
     98 
     99 	assert( cache != NULL );
    100 	assert( ndn != NULL );
    101 
    102 	tmp_entry.dn = *ndn;
    103 	ldap_pvt_thread_mutex_lock( &cache->mutex );
    104 	entry = ( metadncacheentry_t * )avl_find( cache->tree,
    105 			( caddr_t )&tmp_entry, meta_dncache_cmp );
    106 
    107 	if ( entry != NULL ) {
    108 
    109 		/*
    110 		 * if cache->ttl < 0, cache never expires;
    111 		 * if cache->ttl = 0 no cache is used; shouldn't get here
    112 		 * else, cache is used with ttl
    113 		 */
    114 		if ( cache->ttl < 0 ) {
    115 			target = entry->target;
    116 
    117 		} else {
    118 			if ( entry->lastupdated+cache->ttl > slap_get_time() ) {
    119 				target = entry->target;
    120 			}
    121 		}
    122 	}
    123 	ldap_pvt_thread_mutex_unlock( &cache->mutex );
    124 
    125 	return target;
    126 }
    127 
    128 /*
    129  * meta_dncache_update_entry
    130  *
    131  * updates target and lastupdated of a struct metadncacheentry if exists,
    132  * otherwise it gets created; returns -1 in case of error
    133  */
    134 int
    135 meta_dncache_update_entry(
    136 	metadncache_t	*cache,
    137 	struct berval	*ndn,
    138 	int 		target )
    139 {
    140 	metadncacheentry_t	*entry,
    141 				tmp_entry;
    142 	time_t			curr_time = 0L;
    143 	int			err = 0;
    144 
    145 	assert( cache != NULL );
    146 	assert( ndn != NULL );
    147 
    148 	/*
    149 	 * if cache->ttl < 0, cache never expires;
    150 	 * if cache->ttl = 0 no cache is used; shouldn't get here
    151 	 * else, cache is used with ttl
    152 	 */
    153 	if ( cache->ttl > 0 ) {
    154 		curr_time = slap_get_time();
    155 	}
    156 
    157 	tmp_entry.dn = *ndn;
    158 
    159 	ldap_pvt_thread_mutex_lock( &cache->mutex );
    160 	entry = ( metadncacheentry_t * )avl_find( cache->tree,
    161 			( caddr_t )&tmp_entry, meta_dncache_cmp );
    162 
    163 	if ( entry != NULL ) {
    164 		entry->target = target;
    165 		entry->lastupdated = curr_time;
    166 
    167 	} else {
    168 		entry = ch_malloc( sizeof( metadncacheentry_t ) + ndn->bv_len + 1 );
    169 		if ( entry == NULL ) {
    170 			err = -1;
    171 			goto error_return;
    172 		}
    173 
    174 		entry->dn.bv_len = ndn->bv_len;
    175 		entry->dn.bv_val = (char *)&entry[ 1 ];
    176 		AC_MEMCPY( entry->dn.bv_val, ndn->bv_val, ndn->bv_len );
    177 		entry->dn.bv_val[ ndn->bv_len ] = '\0';
    178 
    179 		entry->target = target;
    180 		entry->lastupdated = curr_time;
    181 
    182 		err = avl_insert( &cache->tree, ( caddr_t )entry,
    183 				meta_dncache_cmp, meta_dncache_dup );
    184 	}
    185 
    186 error_return:;
    187 	ldap_pvt_thread_mutex_unlock( &cache->mutex );
    188 
    189 	return err;
    190 }
    191 
    192 /*
    193  * meta_dncache_update_entry
    194  *
    195  * updates target and lastupdated of a struct metadncacheentry if exists,
    196  * otherwise it gets created; returns -1 in case of error
    197  */
    198 int
    199 meta_dncache_delete_entry(
    200 	metadncache_t	*cache,
    201 	struct berval	*ndn )
    202 {
    203 	metadncacheentry_t	*entry,
    204 				tmp_entry;
    205 
    206 	assert( cache != NULL );
    207 	assert( ndn != NULL );
    208 
    209 	tmp_entry.dn = *ndn;
    210 
    211 	ldap_pvt_thread_mutex_lock( &cache->mutex );
    212 	entry = avl_delete( &cache->tree, ( caddr_t )&tmp_entry,
    213  			meta_dncache_cmp );
    214 	ldap_pvt_thread_mutex_unlock( &cache->mutex );
    215 
    216 	if ( entry != NULL ) {
    217 		meta_dncache_free( ( void * )entry );
    218 	}
    219 
    220 	return 0;
    221 }
    222 
    223 /*
    224  * meta_dncache_free
    225  *
    226  * frees an entry
    227  *
    228  */
    229 void
    230 meta_dncache_free(
    231 	void		*e )
    232 {
    233 	free( e );
    234 }
    235 
    236