]> git.sur5r.net Git - openldap/blob - servers/slapd/back-monitor/cache.c
Fixup bdb_entry_release now that entry_decode uses two memory blocks
[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         /*
58          * case sensitive, because the dn MUST be normalized
59          */
60         return strcmp( cc1->mc_ndn, cc2->mc_ndn );
61 }
62
63 /*
64  * checks for duplicate entries
65  */
66 int
67 monitor_cache_dup(
68                 void *c1,
69                 void *c2
70 )
71 {
72         struct monitorcache *cc1 = ( struct monitorcache * )c1;
73         struct monitorcache *cc2 = ( struct monitorcache * )c2;
74         
75         /*
76          * case sensitive, because the dn MUST be normalized
77          */
78         return ( strcmp( cc1->mc_ndn, cc2->mc_ndn ) == 0 ) ? -1 : 0;
79 }
80
81 /*
82  * adds an entry to the cache and inits the mutex
83  */
84 int
85 monitor_cache_add(
86                 struct monitorinfo      *mi,
87                 Entry                   *e
88 )
89 {
90         struct monitorcache     *mc;
91         struct monitorentrypriv *mp;
92         int                     rc;
93
94         assert( mi != NULL );
95         assert( e != NULL );
96
97         mp = ( struct monitorentrypriv *)e->e_private;
98         ldap_pvt_thread_mutex_init( &mp->mp_mutex );
99
100         mc = ( struct monitorcache * )ch_malloc( sizeof( struct monitorcache ) );
101         mc->mc_ndn = e->e_ndn;
102         mc->mc_e = e;
103         ldap_pvt_thread_mutex_lock( &mi->mi_cache_mutex );
104         rc = avl_insert( &mi->mi_cache, ( caddr_t )mc,
105                         monitor_cache_cmp, monitor_cache_dup );
106         ldap_pvt_thread_mutex_unlock( &mi->mi_cache_mutex );
107
108         return rc;
109 }
110
111 /*
112  * locks the entry (no r/w)
113  */
114 int
115 monitor_cache_lock(
116                 Entry                   *e
117 )
118 {
119                 struct monitorentrypriv *mp;
120
121                 assert( e != NULL );
122                 assert( e->e_private != NULL );
123
124                 mp = ( struct monitorentrypriv * )e->e_private;
125                 ldap_pvt_thread_mutex_lock( &mp->mp_mutex );
126
127                 return( 0 );
128 }
129
130 /*
131  * gets an entry from the cache based on the normalized dn 
132  * with mutex locked
133  */
134 int
135 monitor_cache_get(
136                 struct monitorinfo      *mi,
137                 const char              *ndn,
138                 Entry                   **ep
139 )
140 {
141         struct monitorcache tmp_mc, *mc;
142
143         assert( mi != NULL );
144         assert( ndn != NULL );
145         assert( ep != NULL );
146
147         tmp_mc.mc_ndn = ( char * )ndn;
148         ldap_pvt_thread_mutex_lock( &mi->mi_cache_mutex );
149         mc = ( struct monitorcache * )avl_find( mi->mi_cache,
150                         ( caddr_t )&tmp_mc, monitor_cache_cmp );
151
152         if ( mc != NULL ) {
153                 /* entry is returned with mutex locked */
154                 monitor_cache_lock( mc->mc_e );
155                 ldap_pvt_thread_mutex_unlock( &mi->mi_cache_mutex );
156                 *ep = mc->mc_e;
157
158                 return( 0 );
159         }
160         
161         ldap_pvt_thread_mutex_unlock( &mi->mi_cache_mutex );
162         *ep = NULL;
163
164         return( -1 );
165 }
166
167 /*
168  * If the entry exists in cache, it is returned in locked status;
169  * otherwise, if the parent exists, if it may generate volatile 
170  * descendants an attempt to generate the required entry is
171  * performed and, if successful, the entry is returned
172  */
173 int
174 monitor_cache_dn2entry(
175                 struct monitorinfo      *mi,
176                 const char              *ndn,
177                 Entry                   **ep
178 )
179 {
180         int rc;
181
182         char *p_ndn;
183         Entry *e_parent;
184         struct monitorentrypriv *mp;
185                 
186         assert( mi != NULL );
187         assert( ndn != NULL );
188         assert( ep != NULL );
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         p_ndn = dn_parent( NULL, ndn );
197         rc = monitor_cache_dn2entry( mi, p_ndn, &e_parent );
198         free( p_ndn );
199         if ( rc || e_parent == NULL) {
200                 return( -1 );
201         }
202
203         mp = ( struct monitorentrypriv * )e_parent->e_private;
204         rc = -1;
205         if ( mp->mp_flags & MONITOR_F_VOLATILE_CH ) {
206                 /* parent entry generates volatile children */
207                 rc = monitor_entry_create( mi, ndn, e_parent, ep );
208         }
209         monitor_cache_release( mi, e_parent );
210         
211         return( rc );
212 }
213
214 /*
215  * releases the lock of the entry; if it is marked as volatile, it is
216  * destroyed.
217  */
218 int
219 monitor_cache_release(
220         struct monitorinfo      *mi,
221         Entry                   *e
222 )
223 {
224         struct monitorentrypriv *mp;
225
226         assert( mi != NULL );
227         assert( e != NULL );
228         assert( e->e_private != NULL );
229         
230         mp = ( struct monitorentrypriv * )e->e_private;
231
232         if ( mp->mp_flags & MONITOR_F_VOLATILE ) {
233                 /* volatile entries do not return to cache */
234                 ldap_pvt_thread_mutex_destroy( &mp->mp_mutex );
235                 ch_free( mp );
236                 e->e_private = NULL;
237                 entry_free( e );
238                 return( 0 );
239         }
240         
241         ldap_pvt_thread_mutex_unlock( &mp->mp_mutex );
242         return( 0 );
243 }
244