xref: /netbsd-src/external/bsd/openldap/dist/servers/slapd/back-meta/dncache.c (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
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