]> git.sur5r.net Git - openldap/blob - servers/slapd/back-monitor/cache.c
fix generated connection entries
[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                 SlapReply               *rs,
174                 struct berval           *ndn,
175                 Entry                   **ep,
176                 Entry                   **matched
177 )
178 {
179         monitor_info_t *mi = (monitor_info_t *)op->o_bd->be_private;
180         int                     rc;
181         struct berval           p_ndn = BER_BVNULL;
182         Entry                   *e_parent;
183         monitor_entry_t         *mp;
184                 
185         assert( mi != NULL );
186         assert( ndn != NULL );
187         assert( ep != NULL );
188         assert( matched != NULL );
189
190         *matched = NULL;
191
192         if ( !dnIsSuffix( ndn, &op->o_bd->be_nsuffix[ 0 ] ) ) {
193                 return( -1 );
194         }
195
196         rc = monitor_cache_get( mi, ndn, ep );
197         if ( !rc && *ep != NULL ) {
198                 return( 0 );
199         }
200
201         /* try with parent/ancestors */
202         if ( BER_BVISNULL( ndn ) ) {
203                 BER_BVSTR( &p_ndn, "" );
204
205         } else {
206                 dnParent( ndn, &p_ndn );
207         }
208
209         rc = monitor_cache_dn2entry( op, rs, &p_ndn, &e_parent, matched );
210         if ( rc || e_parent == NULL ) {
211                 return( -1 );
212         }
213
214         mp = ( monitor_entry_t * )e_parent->e_private;
215         rc = -1;
216         if ( mp->mp_flags & MONITOR_F_VOLATILE_CH ) {
217                 /* parent entry generates volatile children */
218                 rc = monitor_entry_create( op, rs, ndn, e_parent, ep );
219         }
220
221         if ( !rc ) {
222                 monitor_cache_release( mi, e_parent );
223         } else {
224                 *matched = e_parent;
225         }
226         
227         return( rc );
228 }
229
230 /*
231  * releases the lock of the entry; if it is marked as volatile, it is
232  * destroyed.
233  */
234 int
235 monitor_cache_release(
236         monitor_info_t  *mi,
237         Entry           *e
238 )
239 {
240         monitor_entry_t *mp;
241
242         assert( mi != NULL );
243         assert( e != NULL );
244         assert( e->e_private != NULL );
245         
246         mp = ( monitor_entry_t * )e->e_private;
247
248         if ( mp->mp_flags & MONITOR_F_VOLATILE ) {
249                 monitor_cache_t *mc, tmp_mc;
250
251                 /* volatile entries do not return to cache */
252                 ldap_pvt_thread_mutex_lock( &mi->mi_cache_mutex );
253                 tmp_mc.mc_ndn = e->e_nname;
254                 mc = avl_delete( &mi->mi_cache,
255                                 ( caddr_t )&tmp_mc, monitor_cache_cmp );
256                 ldap_pvt_thread_mutex_unlock( &mi->mi_cache_mutex );
257                 ch_free( mc );
258                 
259                 ldap_pvt_thread_mutex_unlock( &mp->mp_mutex );
260                 ldap_pvt_thread_mutex_destroy( &mp->mp_mutex );
261                 ch_free( mp );
262                 e->e_private = NULL;
263                 entry_free( e );
264
265                 return( 0 );
266         }
267         
268         ldap_pvt_thread_mutex_unlock( &mp->mp_mutex );
269
270         return( 0 );
271 }
272