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