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