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