1/* $NetBSD$ */ 2 3/* OpenLDAP: pkg/ldap/servers/slapd/back-meta/dncache.c,v 1.16.2.5 2010/04/13 20:23:31 kurt Exp */ 4/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 5 * 6 * Copyright 1999-2010 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 38typedef 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 */ 52int 53meta_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 */ 72int 73meta_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 */ 92int 93meta_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 */ 136int 137meta_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 188error_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 */ 200int 201meta_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 */ 231void 232meta_dncache_free( 233 void *e ) 234{ 235 free( e ); 236} 237 238