]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldbm/dbcache.c
Implement DN_PARENT_PREFIX and framework for DN_SUBTREE_PREFIX.
[openldap] / servers / slapd / back-ldbm / dbcache.c
1 /* ldbmcache.c - maintain a cache of open ldbm files */
2 /*
3  * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6
7 #include "portable.h"
8
9 #include <stdio.h>
10
11 #include <ac/errno.h>
12 #include <ac/socket.h>
13 #include <ac/string.h>
14 #include <ac/time.h>
15
16 #include <sys/stat.h>
17
18 #ifdef HAVE_SYS_PARAM_H
19 #include <sys/param.h>
20 #endif
21
22 #include "ldap_defaults.h"
23 #include "slap.h"
24 #include "back-ldbm.h"
25
26 DBCache *
27 ldbm_cache_open(
28     Backend     *be,
29     char        *name,
30     char        *suffix,
31     int         flags
32 )
33 {
34         struct ldbminfo *li = (struct ldbminfo *) be->be_private;
35         int             i, lru;
36         time_t          oldtime, curtime;
37         char            buf[MAXPATHLEN];
38 #ifdef HAVE_ST_BLKSIZE
39         struct stat     st;
40 #endif
41
42         sprintf( buf, "%s" LDAP_DIRSEP "%s%s",
43                 li->li_directory, name, suffix );
44
45         Debug( LDAP_DEBUG_TRACE, "=> ldbm_cache_open( \"%s\", %d, %o )\n", buf,
46             flags, li->li_mode );
47
48         lru = 0;
49         curtime = slap_get_time();
50         oldtime = curtime;
51
52         ldap_pvt_thread_mutex_lock( &li->li_dbcache_mutex );
53         for ( i = 0; i < MAXDBCACHE && li->li_dbcache[i].dbc_name != NULL;
54             i++ ) {
55                 /* already open - return it */
56                 if ( strcmp( li->li_dbcache[i].dbc_name, buf ) == 0 ) {
57                         li->li_dbcache[i].dbc_refcnt++;
58                         Debug( LDAP_DEBUG_TRACE,
59                             "<= ldbm_cache_open (cache %d)\n", i, 0, 0 );
60                         ldap_pvt_thread_mutex_unlock( &li->li_dbcache_mutex );
61                         return( &li->li_dbcache[i] );
62                 }
63
64                 /* keep track of lru db */
65                 if ( li->li_dbcache[i].dbc_lastref < oldtime &&
66                     li->li_dbcache[i].dbc_refcnt == 0 ) {
67                         lru = i;
68                         oldtime = li->li_dbcache[i].dbc_lastref;
69                 }
70         }
71
72         /* no empty slots, not already open - close lru and use that slot */
73         if ( i == MAXDBCACHE ) {
74                 i = lru;
75                 if ( li->li_dbcache[i].dbc_refcnt != 0 ) {
76                         Debug( LDAP_DEBUG_ANY,
77                             "ldbm_cache_open no unused db to close - waiting\n",
78                             0, 0, 0 );
79                         lru = -1;
80                         while ( lru == -1 ) {
81                                 ldap_pvt_thread_cond_wait( &li->li_dbcache_cv,
82                                     &li->li_dbcache_mutex );
83                                 for ( i = 0; i < MAXDBCACHE; i++ ) {
84                                         if ( li->li_dbcache[i].dbc_refcnt
85                                             == 0 ) {
86                                                 lru = i;
87                                                 break;
88                                         }
89                                 }
90                         }
91                         i = lru;
92                 }
93                 ldbm_close( li->li_dbcache[i].dbc_db );
94                 free( li->li_dbcache[i].dbc_name );
95                 li->li_dbcache[i].dbc_name = NULL;
96         }
97
98         if ( (li->li_dbcache[i].dbc_db = ldbm_open( buf, flags, li->li_mode,
99             li->li_dbcachesize )) == NULL ) {
100                 int err = errno;
101                 Debug( LDAP_DEBUG_TRACE,
102                     "<= ldbm_cache_open NULL \"%s\" errno %d reason \"%s\")\n",
103                     buf, err, err > -1 && err < sys_nerr ?
104                     sys_errlist[err] : "unknown" );
105                 ldap_pvt_thread_mutex_unlock( &li->li_dbcache_mutex );
106                 return( NULL );
107         }
108         li->li_dbcache[i].dbc_name = ch_strdup( buf );
109         li->li_dbcache[i].dbc_refcnt = 1;
110         li->li_dbcache[i].dbc_lastref = curtime;
111 #ifdef HAVE_ST_BLKSIZE
112         if ( stat( buf, &st ) == 0 ) {
113                 li->li_dbcache[i].dbc_blksize = st.st_blksize;
114         } else
115 #endif
116         {
117                 li->li_dbcache[i].dbc_blksize = DEFAULT_BLOCKSIZE;
118         }
119         li->li_dbcache[i].dbc_maxids = (li->li_dbcache[i].dbc_blksize /
120             sizeof(ID)) - ID_BLOCK_IDS_OFFSET;
121         li->li_dbcache[i].dbc_maxindirect = (SLAPD_LDBM_MIN_MAXIDS /
122             li->li_dbcache[i].dbc_maxids) + 1;
123
124 #ifndef CONT_POSTFIX
125         /* don't let maxindirect exceed 9 */
126         li->li_dbcache[i].dbc_maxindirect %= 10;
127 #endif
128
129         Debug( LDAP_DEBUG_ARGS,
130             "ldbm_cache_open (blksize %ld) (maxids %d) (maxindirect %d)\n",
131             li->li_dbcache[i].dbc_blksize, li->li_dbcache[i].dbc_maxids,
132             li->li_dbcache[i].dbc_maxindirect );
133         Debug( LDAP_DEBUG_TRACE, "<= ldbm_cache_open (opened %d)\n", i, 0, 0 );
134         ldap_pvt_thread_mutex_unlock( &li->li_dbcache_mutex );
135         return( &li->li_dbcache[i] );
136 }
137
138 void
139 ldbm_cache_close( Backend *be, DBCache *db )
140 {
141         struct ldbminfo *li = (struct ldbminfo *) be->be_private;
142
143         ldap_pvt_thread_mutex_lock( &li->li_dbcache_mutex );
144         if ( --db->dbc_refcnt == 0 ) {
145                 ldap_pvt_thread_cond_signal( &li->li_dbcache_cv );
146         }
147         ldap_pvt_thread_mutex_unlock( &li->li_dbcache_mutex );
148 }
149
150 void
151 ldbm_cache_really_close( Backend *be, DBCache *db )
152 {
153         struct ldbminfo *li = (struct ldbminfo *) be->be_private;
154
155         ldap_pvt_thread_mutex_lock( &li->li_dbcache_mutex );
156         if ( --db->dbc_refcnt == 0 ) {
157                 ldap_pvt_thread_cond_signal( &li->li_dbcache_cv );
158                 ldbm_close( db->dbc_db );
159                 free( db->dbc_name );
160                 db->dbc_name = NULL;
161         }
162         ldap_pvt_thread_mutex_unlock( &li->li_dbcache_mutex );
163 }
164
165 void
166 ldbm_cache_flush_all( Backend *be )
167 {
168         struct ldbminfo *li = (struct ldbminfo *) be->be_private;
169         int             i;
170
171         ldap_pvt_thread_mutex_lock( &li->li_dbcache_mutex );
172         for ( i = 0; i < MAXDBCACHE; i++ ) {
173                 if ( li->li_dbcache[i].dbc_name != NULL ) {
174                         Debug( LDAP_DEBUG_TRACE, "ldbm flushing db (%s)\n",
175                             li->li_dbcache[i].dbc_name, 0, 0 );
176                         ldbm_sync( li->li_dbcache[i].dbc_db );
177 #ifdef SLAP_CLEANUP
178                         if ( li->li_dbcache[i].dbc_refcnt != 0 ) {
179                                 Debug( LDAP_DEBUG_TRACE,
180                                        "refcnt = %d, couldn't close db (%s)\n",
181                                        li->li_dbcache[i].dbc_refcnt,
182                                        li->li_dbcache[i].dbc_name, 0 );
183                         } else {
184                                 Debug( LDAP_DEBUG_TRACE,
185                                        "ldbm closing db (%s)\n",
186                                        li->li_dbcache[i].dbc_name, 0, 0 );
187                                 ldap_pvt_thread_cond_signal( &li->li_dbcache_cv );
188                                 ldbm_close( li->li_dbcache[i].dbc_db );
189                                 free( li->li_dbcache[i].dbc_name );
190                                 li->li_dbcache[i].dbc_name = NULL;
191                         }
192 #endif /* SLAP_CLEANUP */
193                 }
194         }
195         ldap_pvt_thread_mutex_unlock( &li->li_dbcache_mutex );
196 }
197
198 Datum
199 ldbm_cache_fetch(
200     DBCache     *db,
201     Datum               key
202 )
203 {
204         Datum   data;
205
206         ldbm_datum_init( data );
207
208         data = ldbm_fetch( db->dbc_db, key );
209
210         return( data );
211 }
212
213 int
214 ldbm_cache_store(
215     DBCache     *db,
216     Datum               key,
217     Datum               data,
218     int                 flags
219 )
220 {
221         int     rc;
222
223 #ifdef LDBM_DEBUG
224         Statslog( LDAP_DEBUG_STATS,
225                 "=> ldbm_cache_store(): key.dptr=%s, key.dsize=%d\n",
226                 key.dptr, key.dsize, 0, 0, 0 );
227
228         Statslog( LDAP_DEBUG_STATS,
229                 "=> ldbm_cache_store(): key.dptr=0x%08x, data.dptr=0x%0 8x\n",
230                 key.dptr, data.dptr, 0, 0, 0 );
231
232         Statslog( LDAP_DEBUG_STATS,
233                 "=> ldbm_cache_store(): data.dptr=%s, data.dsize=%d\n",
234                 data.dptr, data.dsize, 0, 0, 0 );
235
236         Statslog( LDAP_DEBUG_STATS,
237                 "=> ldbm_cache_store(): flags=0x%08x\n",
238                 flags, 0, 0, 0, 0 );
239 #endif /* LDBM_DEBUG */
240
241         rc = ldbm_store( db->dbc_db, key, data, flags );
242
243         return( rc );
244 }
245
246 int
247 ldbm_cache_delete(
248     DBCache     *db,
249     Datum               key
250 )
251 {
252         int     rc;
253
254         rc = ldbm_delete( db->dbc_db, key );
255
256         return( rc );
257 }