]> git.sur5r.net Git - openldap/blob - servers/slapd/back-monitor/cache.c
fix NOOP return code (ITS#4563; I'll check and confirm it later; NOOP support might...
[openldap] / servers / slapd / back-monitor / cache.c
1 /* cache.c - routines to maintain an in-core cache of entries */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 2001-2006 The OpenLDAP Foundation.
6  * Portions Copyright 2001-2003 Pierangelo Masarati.
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 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 Pierangelo Masarati for inclusion
19  * in OpenLDAP Software.
20  */
21
22 #include "portable.h"
23
24 #include <stdio.h>
25 #include "ac/string.h"
26
27 #include "slap.h"
28
29 #include "back-monitor.h"
30
31 /*
32  * The cache maps DNs to Entries.
33  * Each entry, on turn, holds the list of its children in the e_private field.
34  * This is used by search operation to perform onelevel and subtree candidate
35  * selection.
36  */
37 typedef struct monitor_cache_t {
38         struct berval           mc_ndn;
39         Entry                   *mc_e;
40 } monitor_cache_t;
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         monitor_cache_t         *cc1 = ( monitor_cache_t * )c1;
51         monitor_cache_t         *cc2 = ( monitor_cache_t * )c2;
52
53         /*
54          * case sensitive, because the dn MUST be normalized
55          */
56         return ber_bvcmp( &cc1->mc_ndn, &cc2->mc_ndn );
57 }
58
59 /*
60  * checks for duplicate entries
61  */
62 int
63 monitor_cache_dup(
64         void            *c1,
65         void            *c2 )
66 {
67         monitor_cache_t *cc1 = ( monitor_cache_t * )c1;
68         monitor_cache_t *cc2 = ( monitor_cache_t * )c2;
69
70         /*
71          * case sensitive, because the dn MUST be normalized
72          */
73         return ber_bvcmp( &cc1->mc_ndn, &cc2->mc_ndn ) == 0 ? -1 : 0;
74 }
75
76 /*
77  * adds an entry to the cache and inits the mutex
78  */
79 int
80 monitor_cache_add(
81         monitor_info_t  *mi,
82         Entry           *e )
83 {
84         monitor_cache_t *mc;
85         monitor_entry_t *mp;
86         int             rc;
87
88         assert( mi != NULL );
89         assert( e != NULL );
90
91         mp = ( monitor_entry_t *)e->e_private;
92
93         mc = ( monitor_cache_t * )ch_malloc( sizeof( monitor_cache_t ) );
94         mc->mc_ndn = e->e_nname;
95         mc->mc_e = e;
96         ldap_pvt_thread_mutex_lock( &mi->mi_cache_mutex );
97         rc = avl_insert( &mi->mi_cache, ( caddr_t )mc,
98                         monitor_cache_cmp, monitor_cache_dup );
99         ldap_pvt_thread_mutex_unlock( &mi->mi_cache_mutex );
100
101         return rc;
102 }
103
104 /*
105  * locks the entry (no r/w)
106  */
107 int
108 monitor_cache_lock(
109         Entry           *e )
110 {
111         monitor_entry_t *mp;
112
113         assert( e != NULL );
114         assert( e->e_private != NULL );
115
116         mp = ( monitor_entry_t * )e->e_private;
117         ldap_pvt_thread_mutex_lock( &mp->mp_mutex );
118
119         return( 0 );
120 }
121
122 /*
123  * gets an entry from the cache based on the normalized dn 
124  * with mutex locked
125  */
126 int
127 monitor_cache_get(
128         monitor_info_t  *mi,
129         struct berval   *ndn,
130         Entry           **ep )
131 {
132         monitor_cache_t tmp_mc, *mc;
133
134         assert( mi != NULL );
135         assert( ndn != NULL );
136         assert( ep != NULL );
137
138         *ep = NULL;
139
140         tmp_mc.mc_ndn = *ndn;
141         ldap_pvt_thread_mutex_lock( &mi->mi_cache_mutex );
142         mc = ( monitor_cache_t * )avl_find( mi->mi_cache,
143                         ( caddr_t )&tmp_mc, monitor_cache_cmp );
144
145         if ( mc != NULL ) {
146                 /* entry is returned with mutex locked */
147                 monitor_cache_lock( mc->mc_e );
148                 *ep = mc->mc_e;
149         }
150
151         ldap_pvt_thread_mutex_unlock( &mi->mi_cache_mutex );
152
153         return ( *ep == NULL ? -1 : 0 );
154 }
155
156 /*
157  * If the entry exists in cache, it is returned in locked status;
158  * otherwise, if the parent exists, if it may generate volatile 
159  * descendants an attempt to generate the required entry is
160  * performed and, if successful, the entry is returned
161  */
162 int
163 monitor_cache_dn2entry(
164         Operation               *op,
165         SlapReply               *rs,
166         struct berval           *ndn,
167         Entry                   **ep,
168         Entry                   **matched )
169 {
170         monitor_info_t *mi = (monitor_info_t *)op->o_bd->be_private;
171         int                     rc;
172         struct berval           p_ndn = BER_BVNULL;
173         Entry                   *e_parent;
174         monitor_entry_t         *mp;
175                 
176         assert( mi != NULL );
177         assert( ndn != NULL );
178         assert( ep != NULL );
179         assert( matched != NULL );
180
181         *matched = NULL;
182
183         if ( !dnIsSuffix( ndn, &op->o_bd->be_nsuffix[ 0 ] ) ) {
184                 return( -1 );
185         }
186
187         rc = monitor_cache_get( mi, ndn, ep );
188         if ( !rc && *ep != NULL ) {
189                 return( 0 );
190         }
191
192         /* try with parent/ancestors */
193         if ( BER_BVISNULL( ndn ) ) {
194                 BER_BVSTR( &p_ndn, "" );
195
196         } else {
197                 dnParent( ndn, &p_ndn );
198         }
199
200         rc = monitor_cache_dn2entry( op, rs, &p_ndn, &e_parent, matched );
201         if ( rc || e_parent == NULL ) {
202                 return( -1 );
203         }
204
205         mp = ( monitor_entry_t * )e_parent->e_private;
206         rc = -1;
207         if ( mp->mp_flags & MONITOR_F_VOLATILE_CH ) {
208                 /* parent entry generates volatile children */
209                 rc = monitor_entry_create( op, rs, ndn, e_parent, ep );
210         }
211
212         if ( !rc ) {
213                 monitor_cache_lock( *ep );
214                 monitor_cache_release( mi, e_parent );
215
216         } else {
217                 *matched = e_parent;
218         }
219         
220         return( rc );
221 }
222
223 /*
224  * releases the lock of the entry; if it is marked as volatile, it is
225  * destroyed.
226  */
227 int
228 monitor_cache_release(
229         monitor_info_t  *mi,
230         Entry           *e )
231 {
232         monitor_entry_t *mp;
233
234         assert( mi != NULL );
235         assert( e != NULL );
236         assert( e->e_private != NULL );
237         
238         mp = ( monitor_entry_t * )e->e_private;
239
240         if ( mp->mp_flags & MONITOR_F_VOLATILE ) {
241                 monitor_cache_t *mc, tmp_mc;
242
243                 /* volatile entries do not return to cache */
244                 ldap_pvt_thread_mutex_lock( &mi->mi_cache_mutex );
245                 tmp_mc.mc_ndn = e->e_nname;
246                 mc = avl_delete( &mi->mi_cache,
247                                 ( caddr_t )&tmp_mc, monitor_cache_cmp );
248                 ldap_pvt_thread_mutex_unlock( &mi->mi_cache_mutex );
249                 if ( mc != NULL ) {
250                         ch_free( mc );
251                 }
252                 
253                 ldap_pvt_thread_mutex_unlock( &mp->mp_mutex );
254                 ldap_pvt_thread_mutex_destroy( &mp->mp_mutex );
255                 ch_free( mp );
256                 e->e_private = NULL;
257                 entry_free( e );
258
259                 return( 0 );
260         }
261         
262         ldap_pvt_thread_mutex_unlock( &mp->mp_mutex );
263
264         return( 0 );
265 }
266
267 static void
268 monitor_entry_destroy( void *v_mc )
269 {
270         monitor_cache_t         *mc = (monitor_cache_t *)v_mc;
271
272         if ( mc->mc_e != NULL ) {
273                 monitor_entry_t *mp;
274
275                 assert( mc->mc_e->e_private != NULL );
276         
277                 mp = ( monitor_entry_t * )mc->mc_e->e_private;
278
279                 if ( mp->mp_cb ) {
280                         if ( mp->mp_cb->mc_free ) {
281                                 mp->mp_cb->mc_free( mc->mc_e,
282                                         mp->mp_cb->mc_private );
283                         }
284                         ch_free( mp->mp_cb );
285                 }
286
287                 ldap_pvt_thread_mutex_destroy( &mp->mp_mutex );
288
289                 ch_free( mp );
290                 mc->mc_e->e_private = NULL;
291                 entry_free( mc->mc_e );
292         }
293
294         ch_free( mc );
295 }
296
297 int
298 monitor_cache_destroy(
299         monitor_info_t  *mi )
300 {
301         if ( mi->mi_cache ) {
302                 avl_free( mi->mi_cache, monitor_entry_destroy );
303         }
304
305         return 0;
306 }
307