]> git.sur5r.net Git - openldap/blob - servers/slapd/back-bdb2/txn.c
Introduction of a new Berkeley DB version 2 (!) specific backend.
[openldap] / servers / slapd / back-bdb2 / txn.c
1 /* txn.c - TP support functions of the bdb2 backend */
2
3 #include "txn.h"
4
5
6 void
7 bdb2i_txn_head_init( BDB2_TXN_HEAD *head )
8 {
9         int             dbFile;
10         BDB2_TXN_FILES  **fileNodeH;
11
12         /*  for each fixed DB file allocate a file descriptor node and
13         initialize the file's name  */
14         fileNodeH = &head->dbFiles;
15         for ( dbFile = BDB2_DB_DN_FILE; dbFile <= BDB2_DB_OC_IDX_FILE; dbFile++ ) {
16
17                 char fileName[MAXPATHLEN];
18
19                 *fileNodeH = head->dbFileHandle[dbFile] =
20                         (BDB2_TXN_FILES *) ch_calloc( 1, sizeof( BDB2_TXN_FILES ));
21                 if ( *fileNodeH == NULL ) {
22
23                         Debug( LDAP_DEBUG_ANY, "bdb2i_txn_head_init(): out of memory!\n",
24                                         0, 0, 0 );
25                         exit( 1 );
26
27                 }
28
29                 sprintf( fileName, "%s%s", bdb2i_fixed_filenames[dbFile], LDBM_SUFFIX );
30                 (*fileNodeH)->dbc_name = strdup( fileName );
31
32                 fileNodeH = &(*fileNodeH)->next;
33
34         }
35
36 }
37
38
39 static void
40 bdb2i_init_db_file_cache( struct ldbminfo *li, BDB2_TXN_FILES *fileinfo )
41 {
42         time_t      curtime;
43         struct stat st;
44         char        buf[MAXPATHLEN];
45
46         pthread_mutex_lock( &currenttime_mutex );
47         curtime = currenttime;
48         pthread_mutex_unlock( &currenttime_mutex );
49
50         fileinfo->dbc_refcnt = 1;
51         fileinfo->dbc_lastref = curtime;
52
53         sprintf( buf, "%s%s%s", li->li_directory, DEFAULT_DIRSEP,
54                                         fileinfo->dbc_name );
55         if ( stat( buf, &st ) == 0 ) {
56                 fileinfo->dbc_blksize = st.st_blksize;
57         } else {
58                 fileinfo->dbc_blksize = DEFAULT_BLOCKSIZE;
59         }
60
61         fileinfo->dbc_maxids = ( fileinfo->dbc_blksize / sizeof( ID )) - 2;
62         fileinfo->dbc_maxindirect = ( SLAPD_LDBM_MIN_MAXIDS /
63                 fileinfo->dbc_maxids ) + 1;
64
65 }
66
67
68 void
69 bdb2i_txn_attr_config(
70         struct ldbminfo  *li,
71         char             *attr,
72         int              open )
73 {
74         BDB2_TXN_HEAD  *head = &li->li_txn_head;
75
76         /*  the "attribute" 'default' is special  */
77         if ( strcasecmp( attr, "default" )) {
78
79                 /*  create a new index file node, if the index is not known  already  */
80                 BDB2_TXN_FILES  **fileNodeH;
81                 char            fileName[MAXPATHLEN];
82
83                 sprintf( fileName, "%s%s", attr,  LDBM_SUFFIX );
84
85                 /*  search for the end of the list or a node describing
86                         the current attribute  */
87                 for ( fileNodeH = &head->dbFiles;
88                                 ( *fileNodeH && strcasecmp( (*fileNodeH)->dbc_name, fileName ));
89                                 fileNodeH = &(*fileNodeH)->next ) {
90
91                 }
92
93                 /*  unless we have that attribute already...  */
94                 if ( *fileNodeH == NULL ) {
95                         BDB2_TXN_FILES *p;
96
97                         Debug( LDAP_DEBUG_TRACE,
98                                         "bdb2i_txn_attr_config(): adding node for \"%s\"\n",
99                                         fileName, 0, 0 );
100
101                         /*  if we're out of memory, we have to see, how to exit...  */
102                         if ( ( *fileNodeH = p = (BDB2_TXN_FILES *)
103                                         ch_calloc( 1, sizeof( BDB2_TXN_FILES )) ) == NULL ) {
104
105                                 Debug( LDAP_DEBUG_ANY,
106                                                 "bdb2i_txn_attr_config(): out of memory -- FATAL.\n",
107                                                 0, 0, 0 );
108
109                                 /*  during configuration (no files are opened)
110                                         we can just exit, otherwise we kill ourself and
111                                         hope to shutdown cleanly...  */
112                                 if ( open ) {
113                                         pthread_kill( pthread_self(), LDAP_SIGUSR1 );
114                                 } else {
115                                         exit( 1 );
116                                 }
117                         }
118
119                         p->dbc_name = strdup( fileName );
120
121                         /*  if requested for, we have to open the DB file  */
122                         /*  BUT NOT "objectclass", 'cause that's a default index !  */
123                         if ( open && strcasecmp( fileName, "objectclass" )) {
124
125                                 /*  since we have an mpool, we should not define a cache size */
126                                 p->dbc_db = ldbm_open_env( p->dbc_name, LDBM_WRCREAT,
127                                                         li->li_mode, 0, &li->li_db_env );
128
129                                 /*  if the files could not be opened, something is wrong;
130                                         complain  */
131                                 if ( p->dbc_db == NULL ) {
132
133                                         Debug( LDAP_DEBUG_ANY,
134                                 "bdb2i_txn_open_files(): couldn't open file \"%s\" -- FATAL.\n",
135                                                 p->dbc_name, 0, 0 );
136                                         pthread_kill( pthread_self(), LDAP_SIGUSR1 );
137
138                                 }
139
140                                 bdb2i_init_db_file_cache( li, p );
141
142                                 Debug( LDAP_DEBUG_TRACE,
143                                         "bdb2i_txn_attr_config(): NEW INDEX FILE \"%s\"\n",
144                                         p->dbc_name, 0, 0 );
145
146                         }
147                 }
148
149         } else {  /*  it is "attribute" 'default'  */
150
151                 head->withDefIDX = BDB2_WITH_DEF_IDX;
152
153         }
154 }
155
156
157 void
158 bdb2i_txn_open_files( struct ldbminfo *li )
159 {
160         BDB2_TXN_HEAD   *head = &li->li_txn_head;
161         BDB2_TXN_FILES  *dbFile;
162
163         for ( dbFile = head->dbFiles; dbFile; dbFile = dbFile->next ) {
164
165                 /*  since we have an mpool, we should not define a cache size */
166                 dbFile->dbc_db = ldbm_open_env( dbFile->dbc_name, LDBM_WRCREAT,
167                                                         li->li_mode, 0, &li->li_db_env );
168
169                 /*  if the files could not be opened, something is wrong; complain  */
170                 if ( dbFile->dbc_db == NULL ) {
171
172                         Debug( LDAP_DEBUG_ANY,
173                                 "bdb2i_txn_open_files(): couldn't open file \"%s\" -- FATAL.\n",
174                                 dbFile->dbc_name, 0, 0 );
175                         exit( 1 );
176
177                 }
178
179                 /*  initialize the file info  */
180                 bdb2i_init_db_file_cache( li, dbFile );
181
182                 Debug( LDAP_DEBUG_TRACE, "bdb2i_txn_open_files(): OPEN INDEX \"%s\"\n",
183                                 dbFile->dbc_name, 0, 0 );
184
185         }
186
187 }
188
189
190 void
191 bdb2i_txn_close_files( BDB2_TXN_HEAD *head)
192 {
193         BDB2_TXN_FILES  *dbFile;
194
195         for ( dbFile = head->dbFiles; dbFile; dbFile = dbFile->next ) {
196
197                 ldbm_close( dbFile->dbc_db );
198
199         }
200 }
201
202
203 BDB2_TXN_FILES *
204 bdb2i_get_db_file_cache( struct ldbminfo *li, char *name )
205 {
206         BDB2_TXN_HEAD  *head = &li->li_txn_head;
207         BDB2_TXN_FILES *dbFile;
208         int            dbFileNum;
209
210         for ( dbFile = head->dbFiles; dbFile; dbFile = dbFile->next ) {
211
212                 if ( !strcasecmp( dbFile->dbc_name, name )) return( dbFile );
213
214         }
215
216         Debug( LDAP_DEBUG_ANY,
217                 "bdb2i_get_db_file_cache(): UPS, could't find \"%s\" \n", name, 0, 0 );
218
219         /*  ups, we couldn't find the file  */
220         return( NULL );
221
222 }
223
224
225 /*  check for new attribute indexes, that might have been created
226     during former runs of slapd  */
227 /*  this is called during startup of the slapd server  */
228 void
229 bdb2i_check_additional_attr_index( struct ldbminfo *li )
230 {
231         DIR            *datadir;
232         struct dirent  *file;
233
234         if ( ( datadir = opendir( li->li_directory ) ) == NULL ) {
235         /* if ( ( datadir = opendir( "/tmp" ) ) == NULL ) { */
236
237                 Debug( LDAP_DEBUG_ANY,
238         "bdb2i_check_additional_attr_index(): ERROR while opening datadir: %s\n",
239                                 strerror( errno ), 0, 0 );
240                 exit( 1 );
241
242         }
243
244         for ( file = readdir( datadir ); file; file = readdir( datadir )) {
245                 char  filename[MAXPATHLEN];
246                 int   namelen;
247
248                 strcpy( filename, file->d_name );
249                 namelen = strlen( filename );
250
251                 if ( namelen > strlen( LDBM_SUFFIX )) {
252
253                         if ( !strcasecmp( filename + namelen - strlen( LDBM_SUFFIX ),
254                                                         LDBM_SUFFIX )) {
255
256                                 *(filename + namelen - strlen( LDBM_SUFFIX )) = '\0';
257                                 bdb2i_txn_attr_config( li, filename, 0 );
258
259                                 Debug( LDAP_DEBUG_TRACE, "INDEX FILE: %s\n", filename, 0, 0 );
260
261                         }
262
263                 }
264
265         }
266
267         closedir( datadir );
268
269 }
270
271
272 /*  check for the addition of new attribute indexes during add  */
273 /*  this is called after startup of the slapd server  */
274 /*  DON'T WORRY ABOUT ACCESS RIGHTS, THAT MIGHT PREVENT US
275         FROM ADDING ATTRIBUTES LATER ON  */
276 void
277 bdb2i_check_default_attr_index_add( struct ldbminfo *li, Entry *e )
278 {
279         BDB2_TXN_HEAD  *head = &li->li_txn_head;
280
281         if ( head->withDefIDX == BDB2_WITH_DEF_IDX ) {
282                 Attribute   *ap;
283
284                 for ( ap = e->e_attrs; ap != NULL; ap = ap->a_next ) {
285                         if ( strcasecmp( ap->a_type, "objectclass" ))
286                                 bdb2i_txn_attr_config( li, ap->a_type, 1 );
287                 }
288         }
289 }
290
291
292 /*  check for the addition of new attribute indexes during modify  */
293 /*  this is called after startup of the slapd server  */
294 /*  DON'T WORRY ABOUT ACCESS RIGHTS, THAT MIGHT PREVENT US
295         FROM ADDING ATTRIBUTES LATER ON  */
296 void
297 bdb2i_check_default_attr_index_mod( struct ldbminfo *li, LDAPModList *modlist )
298 {
299         BDB2_TXN_HEAD  *head = &li->li_txn_head;
300
301         if ( head->withDefIDX == BDB2_WITH_DEF_IDX ) {
302                 LDAPModList *ml;
303                 char  *default_attrs[] = { "modifytimestamp", "modifiersname", NULL };
304                 int   attr;
305
306                 for ( ml = modlist; ml != NULL; ml = ml->ml_next ) {
307                         LDAPMod *mod = &ml->ml_mod;
308
309                         if (( mod->mod_op & ~LDAP_MOD_BVALUES ) == LDAP_MOD_ADD )
310                                 if ( strcasecmp( mod->mod_type, "objectclass" ))
311                                         bdb2i_txn_attr_config( li, mod->mod_type, 1 );
312                 }
313
314                 /*  these attributes are default when modifying  */
315                 for ( attr = 0; default_attrs[attr]; attr++ ) {
316                         bdb2i_txn_attr_config( li, default_attrs[attr], 1 );
317                 }
318         }
319 }
320
321