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