1 /* txn.c - TP support functions of the bdb2 backend */
7 bdb2i_txn_head_init( BDB2_TXN_HEAD *head )
10 BDB2_TXN_FILES **fileNodeH;
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++ ) {
17 char fileName[MAXPATHLEN];
19 *fileNodeH = (BDB2_TXN_FILES *) ch_calloc( 1, sizeof( BDB2_TXN_FILES ));
20 if ( *fileNodeH == NULL ) {
22 Debug( LDAP_DEBUG_ANY, "bdb2i_txn_head_init(): out of memory!\n",
28 sprintf( fileName, "%s%s", bdb2i_fixed_filenames[dbFile], BDB2_SUFFIX );
29 (*fileNodeH)->dbc_name = ch_strdup( fileName );
31 fileNodeH = &(*fileNodeH)->next;
40 bdb2i_init_db_file_cache( struct ldbminfo *li, BDB2_TXN_FILES *fileinfo )
45 fileinfo->dbc_refcnt = 1;
47 sprintf( buf, "%s%s%s", li->li_directory, DEFAULT_DIRSEP,
49 if ( stat( buf, &st ) == 0 ) {
50 fileinfo->dbc_blksize = st.st_blksize;
52 fileinfo->dbc_blksize = DEFAULT_BLOCKSIZE;
55 fileinfo->dbc_maxids = ( fileinfo->dbc_blksize / sizeof( ID )) -
57 fileinfo->dbc_maxindirect = ( SLAPD_LDBM_MIN_MAXIDS /
58 fileinfo->dbc_maxids ) + 1;
63 /* create a DB file cache entry for a specified index attribute
64 (if not already done); the function is called during config
65 file read for all index'ed attributes; if "default" index with
66 a non-none selection is given, this is remembered for run-time
67 extension of the list of index files; the function is also
68 called before add or modify operations to check for putative
69 new "default" index files; at that time, files are also opened
72 bdb2i_txn_attr_config(
77 BDB2_TXN_HEAD *head = &li->li_txn_head;
79 /* the "attribute" 'default' is special */
80 if ( strcasecmp( attr, "default" )) {
82 /* create a new index file node, if the index is not known already */
83 BDB2_TXN_FILES **fileNodeH;
84 char fileName[MAXPATHLEN];
86 sprintf( fileName, "%s%s", attr, BDB2_SUFFIX );
88 /* search for the end of the list or a node describing
89 the current attribute */
90 for ( fileNodeH = &head->dbFiles;
91 ( *fileNodeH && strcasecmp( (*fileNodeH)->dbc_name, fileName ));
92 fileNodeH = &(*fileNodeH)->next ) {
96 /* unless we have that attribute already... */
97 if ( *fileNodeH == NULL ) {
100 Debug( LDAP_DEBUG_TRACE,
101 "bdb2i_txn_attr_config(): adding node for \"%s\"\n",
104 /* if we're out of memory, we have to see, how to exit... */
105 if ( ( *fileNodeH = p = (BDB2_TXN_FILES *)
106 ch_calloc( 1, sizeof( BDB2_TXN_FILES )) ) == NULL ) {
108 Debug( LDAP_DEBUG_ANY,
109 "bdb2i_txn_attr_config(): out of memory -- FATAL.\n",
112 /* during configuration (no files are opened)
113 we can just exit, otherwise we kill ourself and
114 hope to shutdown cleanly... */
116 pthread_kill( pthread_self(), LDAP_SIGUSR1 );
122 p->dbc_name = ch_strdup( fileName );
124 /* if requested for, we have to open the DB file */
125 /* BUT NOT "objectclass", 'cause that's a default index ! */
126 if ( open && strcasecmp( fileName, "objectclass" )) {
128 /* re-use filename to get the complete path */
129 sprintf( fileName, "%s%s%s",
130 li->li_directory, DEFAULT_DIRSEP, p->dbc_name );
132 /* since we have an mpool, we should not define a cache size */
133 p->dbc_db = ldbm_open( fileName, LDBM_WRCREAT, li->li_mode, 0 );
135 /* if the files could not be opened, something is wrong;
137 if ( p->dbc_db == NULL ) {
139 Debug( LDAP_DEBUG_ANY,
140 "bdb2i_txn_open_files(): couldn't open file \"%s\" -- FATAL.\n",
142 pthread_kill( pthread_self(), LDAP_SIGUSR1 );
146 bdb2i_init_db_file_cache( li, p );
148 Debug( LDAP_DEBUG_TRACE,
149 "bdb2i_txn_attr_config(): NEW INDEX FILE \"%s\"\n",
155 } else { /* it is "attribute" 'default' */
157 head->withDefIDX = BDB2_WITH_DEF_IDX;
163 /* open the NEXTID file for read/write; if it does not exist,
164 create it (access to the file must be preceeded by a rewind)
167 bdb2i_open_nextid( struct ldbminfo *li )
169 BDB2_TXN_HEAD *head = &li->li_txn_head;
171 char *file = li->li_nextid_file;
173 /* try to open the file for read and write */
174 if ((( fp = fopen( file, "r+" )) == NULL ) &&
175 (( fp = fopen( file, "w+" )) == NULL )) {
177 Debug( LDAP_DEBUG_ANY,
178 "bdb2i_open_nextid: could not open \"%s\"\n",
184 /* the file is open for read/write */
191 /* open all DB during startup of the backend (necessary due to TP)
192 additional files may be opened during slapd life-time due to
193 default indexes (must be configured in slapd.conf;
194 see bdb2i_txn_attr_config)
197 bdb2i_txn_open_files( struct ldbminfo *li )
199 BDB2_TXN_HEAD *head = &li->li_txn_head;
200 BDB2_TXN_FILES *dbFile;
203 for ( dbFile = head->dbFiles; dbFile; dbFile = dbFile->next ) {
204 char fileName[MAXPATHLEN];
206 sprintf( fileName, "%s%s%s",
207 li->li_directory, DEFAULT_DIRSEP, dbFile->dbc_name );
209 /* since we have an mpool, we should not define a cache size */
210 dbFile->dbc_db = ldbm_open( fileName, LDBM_WRCREAT, li->li_mode, 0 );
212 /* if the files could not be opened, something is wrong; complain */
213 if ( dbFile->dbc_db == NULL ) {
215 Debug( LDAP_DEBUG_ANY,
216 "bdb2i_txn_open_files(): couldn't open file \"%s\" -- FATAL.\n",
217 dbFile->dbc_name, 0, 0 );
222 /* initialize the file info */
223 bdb2i_init_db_file_cache( li, dbFile );
225 Debug( LDAP_DEBUG_TRACE, "bdb2i_txn_open_files(): OPEN INDEX \"%s\"\n",
226 dbFile->dbc_name, 0, 0 );
230 rc = bdb2i_open_nextid( li );
236 /* close the NEXTID file */
238 bdb2i_close_nextid( BDB2_TXN_HEAD *head )
240 fclose( head->nextidFP );
241 head->nextidFP = NULL;
245 /* close all DB files during shutdown of the backend */
247 bdb2i_txn_close_files( BackendDB *be )
249 struct ldbminfo *li = (struct ldbminfo *) be->be_private;
250 BDB2_TXN_HEAD *head = &li->li_txn_head;
251 BDB2_TXN_FILES *dbFile;
253 for ( dbFile = head->dbFiles; dbFile; dbFile = dbFile->next ) {
255 ldbm_close( dbFile->dbc_db );
259 bdb2i_close_nextid( head );
264 /* get the db_cache structure associated with a specified
265 DB file (replaces the on-the-fly opening of files in cache_open()
268 bdb2i_get_db_file_cache( struct ldbminfo *li, char *name )
270 BDB2_TXN_HEAD *head = &li->li_txn_head;
271 BDB2_TXN_FILES *dbFile;
274 Debug( LDAP_DEBUG_TRACE, "bdb2i_get_db_file_cache(): looking for file %s\n",
277 for ( dbFile = head->dbFiles; dbFile; dbFile = dbFile->next ) {
280 if ( !strcasecmp( dbFile->dbc_name, name )) return( dbFile );
284 Debug( LDAP_DEBUG_ANY,
285 "bdb2i_get_db_file_cache(): UPS, could't find \"%s\" \n", name, 0, 0 );
287 /* ups, we couldn't find the file */
293 /* check for new attribute indexes, that might have been created
294 during former runs of slapd */
295 /* this is called during startup of the slapd server */
297 bdb2i_check_additional_attr_index( struct ldbminfo *li )
302 if ( ( datadir = opendir( li->li_directory ) ) == NULL ) {
304 Debug( LDAP_DEBUG_ANY,
305 "bdb2i_check_additional_attr_index(): ERROR while opening datadir: %s\n",
306 strerror( errno ), 0, 0 );
311 for ( file = readdir( datadir ); file; file = readdir( datadir )) {
312 char filename[MAXPATHLEN];
315 strcpy( filename, file->d_name );
316 namelen = strlen( filename );
318 if ( namelen > strlen( BDB2_SUFFIX )) {
320 if ( !strcasecmp( filename + namelen - strlen( BDB2_SUFFIX ),
323 *(filename + namelen - strlen( BDB2_SUFFIX )) = '\0';
324 bdb2i_txn_attr_config( li, filename, 0 );
326 Debug( LDAP_DEBUG_TRACE, "INDEX FILE: %s\n", filename, 0, 0 );
340 /* check for the addition of new attribute indexes during add */
341 /* this is called after startup of the slapd server */
342 /* DON'T WORRY ABOUT ACCESS RIGHTS, THAT MIGHT PREVENT US
343 FROM ADDING ATTRIBUTES LATER ON */
345 bdb2i_check_default_attr_index_add( struct ldbminfo *li, Entry *e )
347 BDB2_TXN_HEAD *head = &li->li_txn_head;
349 if ( head->withDefIDX == BDB2_WITH_DEF_IDX ) {
352 for ( ap = e->e_attrs; ap != NULL; ap = ap->a_next ) {
353 if ( strcasecmp( ap->a_type, "objectclass" ))
354 bdb2i_txn_attr_config( li, ap->a_type, 1 );
360 /* check for the addition of new attribute indexes during modify */
361 /* this is called after startup of the slapd server */
362 /* DON'T WORRY ABOUT ACCESS RIGHTS, THAT MIGHT PREVENT US
363 FROM ADDING ATTRIBUTES LATER ON */
365 bdb2i_check_default_attr_index_mod( struct ldbminfo *li, LDAPModList *modlist )
367 BDB2_TXN_HEAD *head = &li->li_txn_head;
369 if ( head->withDefIDX == BDB2_WITH_DEF_IDX ) {
371 char *default_attrs[] = { "modifytimestamp", "modifiersname", NULL };
374 for ( ml = modlist; ml != NULL; ml = ml->ml_next ) {
375 LDAPMod *mod = &ml->ml_mod;
377 if (( mod->mod_op & ~LDAP_MOD_BVALUES ) == LDAP_MOD_ADD )
378 if ( strcasecmp( mod->mod_type, "objectclass" ))
379 bdb2i_txn_attr_config( li, mod->mod_type, 1 );
382 /* these attributes are default when modifying */
383 for ( attr = 0; default_attrs[attr]; attr++ ) {
384 bdb2i_txn_attr_config( li, default_attrs[attr], 1 );