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