]> git.sur5r.net Git - openldap/blob - servers/slapd/back-monitor/cache.c
0281564db01a63f63c0f25a9fd0b0cb3aeb2a998
[openldap] / servers / slapd / back-monitor / cache.c
1 /* cache.c - routines to maintain an in-core cache of entries */
2 /*
3  * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6 /*
7  * Copyright 2001 The OpenLDAP Foundation, All Rights Reserved.
8  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
9  * 
10  * Copyright 2001, Pierangelo Masarati, All rights reserved. <ando@sys-net.it>
11  * 
12  * This work has beed deveolped for the OpenLDAP Foundation 
13  * in the hope that it may be useful to the Open Source community, 
14  * but WITHOUT ANY WARRANTY.
15  * 
16  * Permission is granted to anyone to use this software for any purpose
17  * on any computer system, and to alter it and redistribute it, subject
18  * to the following restrictions:
19  * 
20  * 1. The author and SysNet s.n.c. are not responsible for the consequences
21  *    of use of this software, no matter how awful, even if they arise from
22  *    flaws in it.
23  * 
24  * 2. The origin of this software must not be misrepresented, either by
25  *    explicit claim or by omission.  Since few users ever read sources,
26  *    credits should appear in the documentation.
27  * 
28  * 3. Altered versions must be plainly marked as such, and must not be
29  *    misrepresented as being the original software.  Since few users
30  *    ever read sources, credits should appear in the documentation.
31  *    SysNet s.n.c. cannot be responsible for the consequences of the
32  *    alterations.
33  * 
34  * 4. This notice may not be removed or altered.
35  */
36
37 #include "portable.h"
38
39 #include <stdio.h>
40
41 #include "slap.h"
42
43 #include "back-monitor.h"
44
45 /*
46  * compares entries based on the dn
47  */
48 int
49 monitor_cache_cmp(
50                 const void *c1,
51                 const void *c2
52 )
53 {
54         struct monitorcache     *cc1 = ( struct monitorcache * )c1;
55         struct monitorcache     *cc2 = ( struct monitorcache * )c2;
56
57         int                     d = cc1->mc_ndn->bv_len - cc2->mc_ndn->bv_len;
58         
59         /*
60          * case sensitive, because the dn MUST be normalized
61          */
62         return d != 0 ? d : strcmp( cc1->mc_ndn->bv_val, cc2->mc_ndn->bv_val );
63 }
64
65 /*
66  * checks for duplicate entries
67  */
68 int
69 monitor_cache_dup(
70                 void *c1,
71                 void *c2
72 )
73 {
74         struct monitorcache *cc1 = ( struct monitorcache * )c1;
75         struct monitorcache *cc2 = ( struct monitorcache * )c2;
76
77         
78         /*
79          * case sensitive, because the dn MUST be normalized
80          */
81 #if 0
82         int                     cmp = monitor_cache_cmp( c1, c2 );
83 #else
84         int                     d = cc1->mc_ndn->bv_len - cc2->mc_ndn->bv_len;
85         int                     cmp = 
86                 d != 0 ? d : strcmp( cc1->mc_ndn->bv_val, cc2->mc_ndn->bv_val );
87 #endif
88
89         return cmp == 0 ? -1 : 0;
90 }
91
92 /*
93  * adds an entry to the cache and inits the mutex
94  */
95 int
96 monitor_cache_add(
97                 struct monitorinfo      *mi,
98                 Entry                   *e
99 )
100 {
101         struct monitorcache     *mc;
102         struct monitorentrypriv *mp;
103         int                     rc;
104
105         assert( mi != NULL );
106         assert( e != NULL );
107
108         mp = ( struct monitorentrypriv *)e->e_private;
109         ldap_pvt_thread_mutex_init( &mp->mp_mutex );
110
111         mc = ( struct monitorcache * )ch_malloc( sizeof( struct monitorcache ) );
112         mc->mc_ndn = &e->e_nname;
113         mc->mc_e = e;
114         ldap_pvt_thread_mutex_lock( &mi->mi_cache_mutex );
115         rc = avl_insert( &mi->mi_cache, ( caddr_t )mc,
116                         monitor_cache_cmp, monitor_cache_dup );
117         ldap_pvt_thread_mutex_unlock( &mi->mi_cache_mutex );
118
119         return rc;
120 }
121
122 /*
123  * locks the entry (no r/w)
124  */
125 int
126 monitor_cache_lock(
127                 Entry                   *e
128 )
129 {
130                 struct monitorentrypriv *mp;
131
132                 assert( e != NULL );
133                 assert( e->e_private != NULL );
134
135                 mp = ( struct monitorentrypriv * )e->e_private;
136                 ldap_pvt_thread_mutex_lock( &mp->mp_mutex );
137
138                 return( 0 );
139 }
140
141 /*
142  * gets an entry from the cache based on the normalized dn 
143  * with mutex locked
144  */
145 int
146 monitor_cache_get(
147                 struct monitorinfo      *mi,
148                 struct berval           *ndn,
149                 Entry                   **ep
150 )
151 {
152         struct monitorcache tmp_mc, *mc;
153
154         assert( mi != NULL );
155         assert( ndn != NULL );
156         assert( ep != NULL );
157
158         tmp_mc.mc_ndn = ndn;
159         ldap_pvt_thread_mutex_lock( &mi->mi_cache_mutex );
160         mc = ( struct monitorcache * )avl_find( mi->mi_cache,
161                         ( caddr_t )&tmp_mc, monitor_cache_cmp );
162
163         if ( mc != NULL ) {
164                 /* entry is returned with mutex locked */
165                 monitor_cache_lock( mc->mc_e );
166                 ldap_pvt_thread_mutex_unlock( &mi->mi_cache_mutex );
167                 *ep = mc->mc_e;
168
169                 return( 0 );
170         }
171         
172         ldap_pvt_thread_mutex_unlock( &mi->mi_cache_mutex );
173         *ep = NULL;
174
175         return( -1 );
176 }
177
178 /*
179  * If the entry exists in cache, it is returned in locked status;
180  * otherwise, if the parent exists, if it may generate volatile 
181  * descendants an attempt to generate the required entry is
182  * performed and, if successful, the entry is returned
183  */
184 int
185 monitor_cache_dn2entry(
186                 struct monitorinfo      *mi,
187                 struct berval           *ndn,
188                 Entry                   **ep,
189                 Entry                   **matched
190 )
191 {
192         int             rc;
193
194         struct berval           p_ndn = { 0L, NULL };
195         Entry                   *e_parent;
196         struct monitorentrypriv *mp;
197                 
198         assert( mi != NULL );
199         assert( ndn != NULL );
200         assert( ep != NULL );
201         assert( matched != NULL );
202
203         *matched = NULL;
204
205         rc = monitor_cache_get( mi, ndn, ep );
206         if ( !rc && *ep != NULL ) {
207                 return( 0 );
208         }
209
210         /* try with parent/ancestors */
211         if ( ndn->bv_len ) {
212                 p_ndn.bv_val = dn_parent( NULL, ndn->bv_val );
213         }
214
215         if ( p_ndn.bv_val == NULL ) {
216                 p_ndn.bv_val = "";
217                 p_ndn.bv_len = 0;
218                 
219         } else {
220                 p_ndn.bv_len = ndn->bv_len 
221                         - ( ber_len_t ) ( p_ndn.bv_val - ndn->bv_val );
222         }
223
224         rc = monitor_cache_dn2entry( mi, &p_ndn, &e_parent, matched );
225         if ( rc || e_parent == NULL) {
226                 return( -1 );
227         }
228
229         mp = ( struct monitorentrypriv * )e_parent->e_private;
230         rc = -1;
231         if ( mp->mp_flags & MONITOR_F_VOLATILE_CH ) {
232                 /* parent entry generates volatile children */
233                 rc = monitor_entry_create( mi, ndn, e_parent, ep );
234         }
235
236         if ( !rc ) {
237                 monitor_cache_release( mi, e_parent );
238         } else {
239                 *matched = e_parent;
240         }
241         
242         return( rc );
243 }
244
245 /*
246  * releases the lock of the entry; if it is marked as volatile, it is
247  * destroyed.
248  */
249 int
250 monitor_cache_release(
251         struct monitorinfo      *mi,
252         Entry                   *e
253 )
254 {
255         struct monitorentrypriv *mp;
256
257         assert( mi != NULL );
258         assert( e != NULL );
259         assert( e->e_private != NULL );
260         
261         mp = ( struct monitorentrypriv * )e->e_private;
262
263         if ( mp->mp_flags & MONITOR_F_VOLATILE ) {
264                 struct monitorcache     *mc, tmp_mc;
265
266                 /* volatile entries do not return to cache */
267                 ldap_pvt_thread_mutex_lock( &mi->mi_cache_mutex );
268                 tmp_mc.mc_ndn = &e->e_nname;
269                 mc = avl_delete( &mi->mi_cache,
270                                 ( caddr_t )&tmp_mc, monitor_cache_cmp );
271                 ldap_pvt_thread_mutex_unlock( &mi->mi_cache_mutex );
272                 ch_free( mc );
273                 
274                 ldap_pvt_thread_mutex_destroy( &mp->mp_mutex );
275                 ch_free( mp );
276                 e->e_private = NULL;
277                 entry_free( e );
278
279                 return( 0 );
280         }
281         
282         ldap_pvt_thread_mutex_unlock( &mp->mp_mutex );
283
284         return( 0 );
285 }
286