]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldbm/dbcache.c
New dn2id format with base/one/subtree indices (ldbm/bdb2)
[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         Debug( LDAP_DEBUG_ARGS,
125             "ldbm_cache_open (blksize %ld) (maxids %d) (maxindirect %d)\n",
126             li->li_dbcache[i].dbc_blksize, li->li_dbcache[i].dbc_maxids,
127             li->li_dbcache[i].dbc_maxindirect );
128         Debug( LDAP_DEBUG_TRACE, "<= ldbm_cache_open (opened %d)\n", i, 0, 0 );
129         ldap_pvt_thread_mutex_unlock( &li->li_dbcache_mutex );
130         return( &li->li_dbcache[i] );
131 }
132
133 void
134 ldbm_cache_close( Backend *be, DBCache *db )
135 {
136         struct ldbminfo *li = (struct ldbminfo *) be->be_private;
137
138         ldap_pvt_thread_mutex_lock( &li->li_dbcache_mutex );
139         if ( --db->dbc_refcnt == 0 ) {
140                 ldap_pvt_thread_cond_signal( &li->li_dbcache_cv );
141         }
142         ldap_pvt_thread_mutex_unlock( &li->li_dbcache_mutex );
143 }
144
145 void
146 ldbm_cache_really_close( Backend *be, DBCache *db )
147 {
148         struct ldbminfo *li = (struct ldbminfo *) be->be_private;
149
150         ldap_pvt_thread_mutex_lock( &li->li_dbcache_mutex );
151         if ( --db->dbc_refcnt == 0 ) {
152                 ldap_pvt_thread_cond_signal( &li->li_dbcache_cv );
153                 ldbm_close( db->dbc_db );
154                 free( db->dbc_name );
155                 db->dbc_name = NULL;
156         }
157         ldap_pvt_thread_mutex_unlock( &li->li_dbcache_mutex );
158 }
159
160 void
161 ldbm_cache_flush_all( Backend *be )
162 {
163         struct ldbminfo *li = (struct ldbminfo *) be->be_private;
164         int             i;
165
166         ldap_pvt_thread_mutex_lock( &li->li_dbcache_mutex );
167         for ( i = 0; i < MAXDBCACHE; i++ ) {
168                 if ( li->li_dbcache[i].dbc_name != NULL ) {
169                         Debug( LDAP_DEBUG_TRACE, "ldbm flushing db (%s)\n",
170                             li->li_dbcache[i].dbc_name, 0, 0 );
171                         ldbm_sync( li->li_dbcache[i].dbc_db );
172 #ifdef SLAP_CLEANUP
173                         if ( li->li_dbcache[i].dbc_refcnt != 0 ) {
174                                 Debug( LDAP_DEBUG_TRACE,
175                                        "refcnt = %d, couldn't close db (%s)\n",
176                                        li->li_dbcache[i].dbc_refcnt,
177                                        li->li_dbcache[i].dbc_name, 0 );
178                         } else {
179                                 Debug( LDAP_DEBUG_TRACE,
180                                        "ldbm closing db (%s)\n",
181                                        li->li_dbcache[i].dbc_name, 0, 0 );
182                                 ldap_pvt_thread_cond_signal( &li->li_dbcache_cv );
183                                 ldbm_close( li->li_dbcache[i].dbc_db );
184                                 free( li->li_dbcache[i].dbc_name );
185                                 li->li_dbcache[i].dbc_name = NULL;
186                         }
187 #endif /* SLAP_CLEANUP */
188                 }
189         }
190         ldap_pvt_thread_mutex_unlock( &li->li_dbcache_mutex );
191 }
192
193 Datum
194 ldbm_cache_fetch(
195     DBCache     *db,
196     Datum               key
197 )
198 {
199         Datum   data;
200
201         return ldbm_fetch( db->dbc_db, key );
202
203         return( data );
204 }
205
206 int
207 ldbm_cache_store(
208     DBCache     *db,
209     Datum               key,
210     Datum               data,
211     int                 flags
212 )
213 {
214         int     rc;
215
216 #ifdef LDBM_DEBUG
217         Statslog( LDAP_DEBUG_STATS,
218                 "=> ldbm_cache_store(): key.dptr=%s, key.dsize=%d\n",
219                 key.dptr, key.dsize, 0, 0, 0 );
220
221         Statslog( LDAP_DEBUG_STATS,
222                 "=> ldbm_cache_store(): key.dptr=0x%08x, data.dptr=0x%0 8x\n",
223                 key.dptr, data.dptr, 0, 0, 0 );
224
225         Statslog( LDAP_DEBUG_STATS,
226                 "=> ldbm_cache_store(): data.dptr=%s, data.dsize=%d\n",
227                 data.dptr, data.dsize, 0, 0, 0 );
228
229         Statslog( LDAP_DEBUG_STATS,
230                 "=> ldbm_cache_store(): flags=0x%08x\n",
231                 flags, 0, 0, 0, 0 );
232 #endif /* LDBM_DEBUG */
233
234         rc = ldbm_store( db->dbc_db, key, data, flags );
235
236         return( rc );
237 }
238
239 int
240 ldbm_cache_delete(
241     DBCache     *db,
242     Datum               key
243 )
244 {
245         int     rc;
246
247         rc = ldbm_delete( db->dbc_db, key );
248
249         return( rc );
250 }