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