]> git.sur5r.net Git - openldap/blob - servers/slapd/back-meta/dncache.c
ITS#2883 initialize rc before running callbacks
[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-2003 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 = -1;
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                 } 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                 struct metadncache      *cache,
144                 struct berval           *ndn,
145                 int                     target
146 )
147 {
148         struct metadncacheentry *entry, 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 = ( struct metadncacheentry * )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         } else {
178                 entry = ch_calloc( sizeof( struct metadncacheentry ), 1 );
179                 if ( entry == NULL ) {
180                         ldap_pvt_thread_mutex_unlock( &cache->mutex );
181                         return -1;
182                 }
183
184                 ber_dupbv( &entry->dn, ndn );
185                 if ( entry->dn.bv_val == NULL ) {
186                         ldap_pvt_thread_mutex_unlock( &cache->mutex );
187                         return -1;
188                 }
189                 entry->target = target;
190                 entry->lastupdated = curr_time;
191
192                 err = avl_insert( &cache->tree, ( caddr_t )entry,
193                                 meta_dncache_cmp, meta_dncache_dup );
194         }
195         ldap_pvt_thread_mutex_unlock( &cache->mutex );
196
197         return err;
198 }
199
200 /*
201  * meta_dncache_update_entry
202  *
203  * updates target and lastupdated of a struct metadncacheentry if exists,
204  * otherwise it gets created; returns -1 in case of error
205  */
206 int
207 meta_dncache_delete_entry(
208                 struct metadncache      *cache,
209                 struct berval           *ndn
210 )
211 {
212         struct metadncacheentry *entry, tmp_entry;
213
214         assert( cache );
215         assert( ndn );
216
217         tmp_entry.dn = *ndn;
218
219         ldap_pvt_thread_mutex_lock( &cache->mutex );
220         entry = avl_delete( &cache->tree, ( caddr_t )&tmp_entry,
221                         meta_dncache_cmp );
222         ldap_pvt_thread_mutex_unlock( &cache->mutex );
223
224         if ( entry != NULL ) {
225                 meta_dncache_free( ( void * )entry );
226         }
227
228         return 0;
229 }
230
231 /*
232  * meta_dncache_free
233  *
234  * frees an entry
235  * 
236  */
237 void
238 meta_dncache_free(
239                 void *e
240 )
241 {
242         struct metadncacheentry *entry = ( struct metadncacheentry * )e;
243
244         free( entry->dn.bv_val );
245 }
246