]> git.sur5r.net Git - openldap/blob - servers/slapd/back-meta/dncache.c
de9ed89fea4a369f0af46d3f82e4fe9f3a499cb3
[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-2017 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         int                     target = META_TARGET_NONE;
98
99         assert( cache != NULL );
100         assert( ndn != NULL );
101
102         tmp_entry.dn = *ndn;
103         ldap_pvt_thread_mutex_lock( &cache->mutex );
104         entry = ( metadncacheentry_t * )avl_find( cache->tree,
105                         ( caddr_t )&tmp_entry, meta_dncache_cmp );
106
107         if ( entry != NULL ) {
108                 
109                 /*
110                  * if cache->ttl < 0, cache never expires;
111                  * if cache->ttl = 0 no cache is used; shouldn't get here
112                  * else, cache is used with ttl
113                  */
114                 if ( cache->ttl < 0 ) { 
115                         target = entry->target;
116
117                 } else {
118                         if ( entry->lastupdated+cache->ttl > slap_get_time() ) {
119                                 target = entry->target;
120                         }
121                 }
122         }
123         ldap_pvt_thread_mutex_unlock( &cache->mutex );
124
125         return target;
126 }
127
128 /*
129  * meta_dncache_update_entry
130  *
131  * updates target and lastupdated of a struct metadncacheentry if exists,
132  * otherwise it gets created; returns -1 in case of error
133  */
134 int
135 meta_dncache_update_entry(
136         metadncache_t   *cache,
137         struct berval   *ndn,
138         int             target )
139 {
140         metadncacheentry_t      *entry,
141                                 tmp_entry;
142         time_t                  curr_time = 0L;
143         int                     err = 0;
144
145         assert( cache != NULL );
146         assert( ndn != NULL );
147
148         /*
149          * if cache->ttl < 0, cache never expires;
150          * if cache->ttl = 0 no cache is used; shouldn't get here
151          * else, cache is used with ttl
152          */
153         if ( cache->ttl > 0 ) {
154                 curr_time = slap_get_time();
155         }
156
157         tmp_entry.dn = *ndn;
158
159         ldap_pvt_thread_mutex_lock( &cache->mutex );
160         entry = ( metadncacheentry_t * )avl_find( cache->tree,
161                         ( caddr_t )&tmp_entry, meta_dncache_cmp );
162
163         if ( entry != NULL ) {
164                 entry->target = target;
165                 entry->lastupdated = curr_time;
166
167         } else {
168                 entry = ch_malloc( sizeof( metadncacheentry_t ) + ndn->bv_len + 1 );
169                 if ( entry == NULL ) {
170                         err = -1;
171                         goto error_return;
172                 }
173
174                 entry->dn.bv_len = ndn->bv_len;
175                 entry->dn.bv_val = (char *)&entry[ 1 ];
176                 AC_MEMCPY( entry->dn.bv_val, ndn->bv_val, ndn->bv_len );
177                 entry->dn.bv_val[ ndn->bv_len ] = '\0';
178
179                 entry->target = target;
180                 entry->lastupdated = curr_time;
181
182                 err = avl_insert( &cache->tree, ( caddr_t )entry,
183                                 meta_dncache_cmp, meta_dncache_dup );
184         }
185
186 error_return:;
187         ldap_pvt_thread_mutex_unlock( &cache->mutex );
188
189         return err;
190 }
191
192 /*
193  * meta_dncache_update_entry
194  *
195  * updates target and lastupdated of a struct metadncacheentry if exists,
196  * otherwise it gets created; returns -1 in case of error
197  */
198 int
199 meta_dncache_delete_entry(
200         metadncache_t   *cache,
201         struct berval   *ndn )
202 {
203         metadncacheentry_t      *entry,
204                                 tmp_entry;
205
206         assert( cache != NULL );
207         assert( ndn != NULL );
208
209         tmp_entry.dn = *ndn;
210
211         ldap_pvt_thread_mutex_lock( &cache->mutex );
212         entry = avl_delete( &cache->tree, ( caddr_t )&tmp_entry,
213                         meta_dncache_cmp );
214         ldap_pvt_thread_mutex_unlock( &cache->mutex );
215
216         if ( entry != NULL ) {
217                 meta_dncache_free( ( void * )entry );
218         }
219
220         return 0;
221 }
222
223 /*
224  * meta_dncache_free
225  *
226  * frees an entry
227  * 
228  */
229 void
230 meta_dncache_free(
231         void            *e )
232 {
233         free( e );
234 }
235