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