dncache.c revision 1.1.1.3 1 /* $NetBSD: dncache.c,v 1.1.1.3 2010/12/12 15:23:10 adam Exp $ */
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
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