]> git.sur5r.net Git - openldap/blob - servers/slapd/back-meta/dncache.c
ITS#3796 fix IDL cache lock setup/teardown
[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 #include <ac/string.h>
27
28 #include "slap.h"
29 #include "../back-ldap/back-ldap.h"
30 #include "back-meta.h"
31
32 /*
33  * The dncache, at present, maps an entry to the target that holds it.
34  */
35
36 typedef struct metadncacheentry_t {
37         struct berval   dn;
38         int             target;
39
40         time_t          lastupdated;
41 } metadncacheentry_t;
42
43 /*
44  * meta_dncache_cmp
45  *
46  * compares two struct metadncacheentry; used by avl stuff
47  * FIXME: modify avl stuff to delete an entry based on cmp
48  * (e.g. when ttl expired?)
49  */
50 int
51 meta_dncache_cmp(
52         const void      *c1,
53         const void      *c2 )
54 {
55         metadncacheentry_t      *cc1 = ( metadncacheentry_t * )c1;
56         metadncacheentry_t      *cc2 = ( metadncacheentry_t * )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         metadncacheentry_t      *cc1 = ( metadncacheentry_t * )c1;
76         metadncacheentry_t      *cc2 = ( metadncacheentry_t * )c2;
77         
78         /*
79          * case sensitive, because the dn MUST be normalized
80          */
81         return ( ber_bvcmp( &cc1->dn, &cc2->dn ) == 0 ) ? -1 : 0;
82 }
83
84 /*
85  * meta_dncache_get_target
86  *
87  * returns the target a dn belongs to, or -1 in case the dn is not
88  * in the cache
89  */
90 int
91 meta_dncache_get_target(
92         metadncache_t   *cache,
93         struct berval   *ndn )
94 {
95         metadncacheentry_t      tmp_entry,
96                                 *entry;
97         time_t                  curr_time;
98         int                     target = META_TARGET_NONE;
99
100         assert( cache );
101         assert( ndn );
102
103         tmp_entry.dn = *ndn;
104         ldap_pvt_thread_mutex_lock( &cache->mutex );
105         entry = ( metadncacheentry_t * )avl_find( cache->tree,
106                         ( caddr_t )&tmp_entry, meta_dncache_cmp );
107
108         if ( entry != NULL ) {
109                 
110                 /*
111                  * if cache->ttl < 0, cache never expires;
112                  * if cache->ttl = 0 no cache is used; shouldn't get here
113                  * else, cache is used with ttl
114                  */
115                 if ( cache->ttl < 0 ) { 
116                         target = entry->target;
117
118                 } else {
119
120                         /*
121                          * Need mutex?
122                          */     
123                         curr_time = time( NULL );
124
125                         if ( entry->lastupdated+cache->ttl > curr_time ) {
126                                 target = entry->target;
127                         }
128                 }
129         }
130         ldap_pvt_thread_mutex_unlock( &cache->mutex );
131
132         return target;
133 }
134
135 /*
136  * meta_dncache_update_entry
137  *
138  * updates target and lastupdated of a struct metadncacheentry if exists,
139  * otherwise it gets created; returns -1 in case of error
140  */
141 int
142 meta_dncache_update_entry(
143         metadncache_t   *cache,
144         struct berval   *ndn,
145         int             target )
146 {
147         metadncacheentry_t      *entry,
148                                 tmp_entry;
149         time_t                  curr_time = 0L;
150         int                     err = 0;
151
152         assert( cache );
153         assert( ndn );
154
155         /*
156          * if cache->ttl < 0, cache never expires;
157          * if cache->ttl = 0 no cache is used; shouldn't get here
158          * else, cache is used with ttl
159          */
160         if ( cache->ttl > 0 ) {
161
162                 /*
163                  * Need mutex?
164                  */
165                 curr_time = time( NULL );
166         }
167
168         tmp_entry.dn = *ndn;
169
170         ldap_pvt_thread_mutex_lock( &cache->mutex );
171         entry = ( metadncacheentry_t * )avl_find( cache->tree,
172                         ( caddr_t )&tmp_entry, meta_dncache_cmp );
173
174         if ( entry != NULL ) {
175                 entry->target = target;
176                 entry->lastupdated = curr_time;
177
178         } else {
179                 entry = ch_malloc( sizeof( metadncacheentry_t ) + ndn->bv_len + 1 );
180                 if ( entry == NULL ) {
181                         ldap_pvt_thread_mutex_unlock( &cache->mutex );
182                         return -1;
183                 }
184
185                 entry->dn.bv_val = (char *)&entry[ 1 ];
186                 AC_MEMCPY( entry->dn.bv_val, ndn->bv_val, ndn->bv_len + 1 );
187                 entry->target = target;
188                 entry->lastupdated = curr_time;
189
190                 err = avl_insert( &cache->tree, ( caddr_t )entry,
191                                 meta_dncache_cmp, meta_dncache_dup );
192         }
193         ldap_pvt_thread_mutex_unlock( &cache->mutex );
194
195         return err;
196 }
197
198 /*
199  * meta_dncache_update_entry
200  *
201  * updates target and lastupdated of a struct metadncacheentry if exists,
202  * otherwise it gets created; returns -1 in case of error
203  */
204 int
205 meta_dncache_delete_entry(
206         metadncache_t   *cache,
207         struct berval   *ndn )
208 {
209         metadncacheentry_t      *entry,
210                                 tmp_entry;
211
212         assert( cache );
213         assert( ndn );
214
215         tmp_entry.dn = *ndn;
216
217         ldap_pvt_thread_mutex_lock( &cache->mutex );
218         entry = avl_delete( &cache->tree, ( caddr_t )&tmp_entry,
219                         meta_dncache_cmp );
220         ldap_pvt_thread_mutex_unlock( &cache->mutex );
221
222         if ( entry != NULL ) {
223                 meta_dncache_free( ( void * )entry );
224         }
225
226         return 0;
227 }
228
229 /*
230  * meta_dncache_free
231  *
232  * frees an entry
233  * 
234  */
235 void
236 meta_dncache_free(
237         void            *e )
238 {
239         free( e );
240 }
241