From 5ea77a75dd2d2158401331879f3c8f47940a732c Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 18:35:32 +0200 Subject: Adding upstream version 2.5.13+dfsg. Signed-off-by: Daniel Baumann --- servers/slapd/back-asyncmeta/dncache.c | 228 +++++++++++++++++++++++++++++++++ 1 file changed, 228 insertions(+) create mode 100644 servers/slapd/back-asyncmeta/dncache.c (limited to 'servers/slapd/back-asyncmeta/dncache.c') diff --git a/servers/slapd/back-asyncmeta/dncache.c b/servers/slapd/back-asyncmeta/dncache.c new file mode 100644 index 0000000..a588290 --- /dev/null +++ b/servers/slapd/back-asyncmeta/dncache.c @@ -0,0 +1,228 @@ +/* dncache.c - dn caching for back-asyncmeta */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software . + * + * Copyright 2016-2022 The OpenLDAP Foundation. + * Portions Copyright 2016 Symas Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ + +/* ACKNOWLEDGEMENTS: + * This work was developed by Symas Corporation + * based on back-meta module for inclusion in OpenLDAP Software. + * This work was sponsored by Ericsson. */ + +#include "portable.h" + +#include +#include + +#include "slap.h" +#include "../back-ldap/back-ldap.h" +#include "back-asyncmeta.h" + +/* + * The dncache, at present, maps an entry to the target that holds it. + */ + +typedef struct metadncacheentry_t { + struct berval dn; + int target; + + time_t lastupdated; +} metadncacheentry_t; + +/* + * asyncmeta_dncache_cmp + * + * compares two struct metadncacheentry; used by avl stuff + * FIXME: modify avl stuff to delete an entry based on cmp + * (e.g. when ttl expired?) + */ +int +asyncmeta_dncache_cmp( + const void *c1, + const void *c2 ) +{ + metadncacheentry_t *cc1 = ( metadncacheentry_t * )c1; + metadncacheentry_t *cc2 = ( metadncacheentry_t * )c2; + + /* + * case sensitive, because the dn MUST be normalized + */ + return ber_bvcmp( &cc1->dn, &cc2->dn); +} + +/* + * asyncmeta_dncache_dup + * + * returns -1 in case a duplicate struct metadncacheentry has been inserted; + * used by avl stuff + */ +int +asyncmeta_dncache_dup( + void *c1, + void *c2 ) +{ + metadncacheentry_t *cc1 = ( metadncacheentry_t * )c1; + metadncacheentry_t *cc2 = ( metadncacheentry_t * )c2; + + /* + * case sensitive, because the dn MUST be normalized + */ + return ( ber_bvcmp( &cc1->dn, &cc2->dn ) == 0 ) ? -1 : 0; +} + +/* + * asyncmeta_dncache_get_target + * + * returns the target a dn belongs to, or -1 in case the dn is not + * in the cache + */ +int +asyncmeta_dncache_get_target( + a_metadncache_t *cache, + struct berval *ndn ) +{ + metadncacheentry_t tmp_entry, + *entry; + int target = META_TARGET_NONE; + + assert( cache != NULL ); + assert( ndn != NULL ); + + tmp_entry.dn = *ndn; + ldap_pvt_thread_mutex_lock( &cache->mutex ); + entry = ( metadncacheentry_t * )ldap_avl_find( cache->tree, + ( caddr_t )&tmp_entry, asyncmeta_dncache_cmp ); + + if ( entry != NULL ) { + + /* + * if cache->ttl < 0, cache never expires; + * if cache->ttl = 0 no cache is used; shouldn't get here + * else, cache is used with ttl + */ + if ( cache->ttl < 0 ) { + target = entry->target; + + } else { + if ( entry->lastupdated+cache->ttl > slap_get_time() ) { + target = entry->target; + } + } + } + ldap_pvt_thread_mutex_unlock( &cache->mutex ); + + return target; +} + +/* + * asyncmeta_dncache_update_entry + * + * updates target and lastupdated of a struct metadncacheentry if exists, + * otherwise it gets created; returns -1 in case of error + */ +int +asyncmeta_dncache_update_entry( + a_metadncache_t *cache, + struct berval *ndn, + int target ) +{ + metadncacheentry_t *entry, + tmp_entry; + time_t curr_time = 0L; + int err = 0; + + assert( cache != NULL ); + assert( ndn != NULL ); + + /* + * if cache->ttl < 0, cache never expires; + * if cache->ttl = 0 no cache is used; shouldn't get here + * else, cache is used with ttl + */ + if ( cache->ttl > 0 ) { + curr_time = slap_get_time(); + } + + tmp_entry.dn = *ndn; + + ldap_pvt_thread_mutex_lock( &cache->mutex ); + entry = ( metadncacheentry_t * )ldap_avl_find( cache->tree, + ( caddr_t )&tmp_entry, asyncmeta_dncache_cmp ); + + if ( entry != NULL ) { + entry->target = target; + entry->lastupdated = curr_time; + + } else { + entry = ch_malloc( sizeof( metadncacheentry_t ) + ndn->bv_len + 1 ); + if ( entry == NULL ) { + err = -1; + goto error_return; + } + + entry->dn.bv_len = ndn->bv_len; + entry->dn.bv_val = (char *)&entry[ 1 ]; + AC_MEMCPY( entry->dn.bv_val, ndn->bv_val, ndn->bv_len ); + entry->dn.bv_val[ ndn->bv_len ] = '\0'; + + entry->target = target; + entry->lastupdated = curr_time; + + err = ldap_avl_insert( &cache->tree, ( caddr_t )entry, + asyncmeta_dncache_cmp, asyncmeta_dncache_dup ); + } + +error_return:; + ldap_pvt_thread_mutex_unlock( &cache->mutex ); + + return err; +} + +int +asyncmeta_dncache_delete_entry( + a_metadncache_t *cache, + struct berval *ndn ) +{ + metadncacheentry_t *entry, + tmp_entry; + + assert( cache != NULL ); + assert( ndn != NULL ); + + tmp_entry.dn = *ndn; + + ldap_pvt_thread_mutex_lock( &cache->mutex ); + entry = ldap_avl_delete( &cache->tree, ( caddr_t )&tmp_entry, + asyncmeta_dncache_cmp ); + ldap_pvt_thread_mutex_unlock( &cache->mutex ); + + if ( entry != NULL ) { + asyncmeta_dncache_free( ( void * )entry ); + } + + return 0; +} + +/* + * meta_dncache_free + * + * frees an entry + * + */ +void +asyncmeta_dncache_free( + void *e ) +{ + free( e ); +} -- cgit v1.2.3