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