]> git.sur5r.net Git - openldap/blob - servers/slapd/back-monitor/cache.c
Memory cleanup
[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-2005 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         ldap_pvt_thread_mutex_init( &mp->mp_mutex );
93
94         mc = ( monitor_cache_t * )ch_malloc( sizeof( monitor_cache_t ) );
95         mc->mc_ndn = e->e_nname;
96         mc->mc_e = e;
97         ldap_pvt_thread_mutex_lock( &mi->mi_cache_mutex );
98         rc = avl_insert( &mi->mi_cache, ( caddr_t )mc,
99                         monitor_cache_cmp, monitor_cache_dup );
100         ldap_pvt_thread_mutex_unlock( &mi->mi_cache_mutex );
101
102         return rc;
103 }
104
105 /*
106  * locks the entry (no r/w)
107  */
108 int
109 monitor_cache_lock(
110         Entry           *e )
111 {
112         monitor_entry_t *mp;
113
114         assert( e != NULL );
115         assert( e->e_private != NULL );
116
117         mp = ( monitor_entry_t * )e->e_private;
118         ldap_pvt_thread_mutex_lock( &mp->mp_mutex );
119
120         return( 0 );
121 }
122
123 /*
124  * gets an entry from the cache based on the normalized dn 
125  * with mutex locked
126  */
127 int
128 monitor_cache_get(
129         monitor_info_t  *mi,
130         struct berval   *ndn,
131         Entry           **ep )
132 {
133         monitor_cache_t tmp_mc, *mc;
134
135         assert( mi != NULL );
136         assert( ndn != NULL );
137         assert( ep != NULL );
138
139         tmp_mc.mc_ndn = *ndn;
140         ldap_pvt_thread_mutex_lock( &mi->mi_cache_mutex );
141         mc = ( monitor_cache_t * )avl_find( mi->mi_cache,
142                         ( caddr_t )&tmp_mc, monitor_cache_cmp );
143
144         if ( mc != NULL ) {
145                 /* entry is returned with mutex locked */
146                 monitor_cache_lock( mc->mc_e );
147                 ldap_pvt_thread_mutex_unlock( &mi->mi_cache_mutex );
148                 *ep = mc->mc_e;
149
150                 return( 0 );
151         }
152         
153         ldap_pvt_thread_mutex_unlock( &mi->mi_cache_mutex );
154         *ep = NULL;
155
156         return( -1 );
157 }
158
159 /*
160  * If the entry exists in cache, it is returned in locked status;
161  * otherwise, if the parent exists, if it may generate volatile 
162  * descendants an attempt to generate the required entry is
163  * performed and, if successful, the entry is returned
164  */
165 int
166 monitor_cache_dn2entry(
167         Operation               *op,
168         SlapReply               *rs,
169         struct berval           *ndn,
170         Entry                   **ep,
171         Entry                   **matched )
172 {
173         monitor_info_t *mi = (monitor_info_t *)op->o_bd->be_private;
174         int                     rc;
175         struct berval           p_ndn = BER_BVNULL;
176         Entry                   *e_parent;
177         monitor_entry_t         *mp;
178                 
179         assert( mi != NULL );
180         assert( ndn != NULL );
181         assert( ep != NULL );
182         assert( matched != NULL );
183
184         *matched = NULL;
185
186         if ( !dnIsSuffix( ndn, &op->o_bd->be_nsuffix[ 0 ] ) ) {
187                 return( -1 );
188         }
189
190         rc = monitor_cache_get( mi, ndn, ep );
191         if ( !rc && *ep != NULL ) {
192                 return( 0 );
193         }
194
195         /* try with parent/ancestors */
196         if ( BER_BVISNULL( ndn ) ) {
197                 BER_BVSTR( &p_ndn, "" );
198
199         } else {
200                 dnParent( ndn, &p_ndn );
201         }
202
203         rc = monitor_cache_dn2entry( op, rs, &p_ndn, &e_parent, matched );
204         if ( rc || e_parent == NULL ) {
205                 return( -1 );
206         }
207
208         mp = ( monitor_entry_t * )e_parent->e_private;
209         rc = -1;
210         if ( mp->mp_flags & MONITOR_F_VOLATILE_CH ) {
211                 /* parent entry generates volatile children */
212                 rc = monitor_entry_create( op, rs, ndn, e_parent, ep );
213         }
214
215         if ( !rc ) {
216                 monitor_cache_lock( *ep );
217                 monitor_cache_release( mi, e_parent );
218
219         } else {
220                 *matched = e_parent;
221         }
222         
223         return( rc );
224 }
225
226 /*
227  * releases the lock of the entry; if it is marked as volatile, it is
228  * destroyed.
229  */
230 int
231 monitor_cache_release(
232         monitor_info_t  *mi,
233         Entry           *e )
234 {
235         monitor_entry_t *mp;
236
237         assert( mi != NULL );
238         assert( e != NULL );
239         assert( e->e_private != NULL );
240         
241         mp = ( monitor_entry_t * )e->e_private;
242
243         if ( mp->mp_flags & MONITOR_F_VOLATILE ) {
244                 monitor_cache_t *mc, tmp_mc;
245
246                 /* volatile entries do not return to cache */
247                 ldap_pvt_thread_mutex_lock( &mi->mi_cache_mutex );
248                 tmp_mc.mc_ndn = e->e_nname;
249                 mc = avl_delete( &mi->mi_cache,
250                                 ( caddr_t )&tmp_mc, monitor_cache_cmp );
251                 ldap_pvt_thread_mutex_unlock( &mi->mi_cache_mutex );
252                 if ( mc != NULL ) {
253                         ch_free( mc );
254                 }
255                 
256                 ldap_pvt_thread_mutex_unlock( &mp->mp_mutex );
257                 ldap_pvt_thread_mutex_destroy( &mp->mp_mutex );
258                 ch_free( mp );
259                 e->e_private = NULL;
260                 entry_free( e );
261
262                 return( 0 );
263         }
264         
265         ldap_pvt_thread_mutex_unlock( &mp->mp_mutex );
266
267         return( 0 );
268 }
269