]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldbm/dn2id.c
Serialize access to idl insert/delete key routines (ITS 1359)
[openldap] / servers / slapd / back-ldbm / dn2id.c
1 /* dn2id.c - routines to deal with the dn2id index */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 #include "portable.h"
9
10 #include <stdio.h>
11
12 #include <ac/string.h>
13 #include <ac/socket.h>
14
15 #include "slap.h"
16 #include "back-ldbm.h"
17 #include "proto-back-ldbm.h"
18
19 int
20 dn2id_add(
21     Backend     *be,
22     const char  *dn,
23     ID          id
24 )
25 {
26         int             rc, flags;
27         DBCache *db;
28         Datum           key, data;
29         struct ldbminfo *li = (struct ldbminfo *) be->be_private;
30
31 #ifdef NEW_LOGGING
32         LDAP_LOG(( "backend", LDAP_LEVEL_ENTRY,
33                    "dn2id_add: (%s):%ld\n", dn, id ));
34 #else
35         Debug( LDAP_DEBUG_TRACE, "=> dn2id_add( \"%s\", %ld )\n", dn, id, 0 );
36 #endif
37
38         assert( id != NOID );
39
40         if ( (db = ldbm_cache_open( be, "dn2id", LDBM_SUFFIX, LDBM_WRCREAT ))
41             == NULL ) {
42 #ifdef NEW_LOGGING
43                 LDAP_LOG(( "backend", LDAP_LEVEL_ERR,
44                            "dn2id_add: couldn't open/create dn2id%s\n", LDBM_SUFFIX ));
45 #else
46                 Debug( LDAP_DEBUG_ANY, "Could not open/create dn2id%s\n",
47                     LDBM_SUFFIX, 0, 0 );
48 #endif
49
50                 return( -1 );
51         }
52
53         ldbm_datum_init( key );
54         key.dsize = strlen( dn ) + 2;
55         key.dptr = ch_malloc( key.dsize );
56         sprintf( key.dptr, "%c%s", DN_BASE_PREFIX, dn );
57
58         ldbm_datum_init( data );
59         data.dptr = (char *) &id;
60         data.dsize = sizeof(ID);
61
62         flags = LDBM_INSERT;
63         rc = ldbm_cache_store( db, key, data, flags );
64
65         free( key.dptr );
66
67         if ( rc != -1 ) {
68                 char *pdn = dn_parent( NULL, dn );
69
70                 if( pdn != NULL ) {
71                         ldbm_datum_init( key );
72                         key.dsize = strlen( pdn ) + 2;
73                         key.dptr = ch_malloc( key.dsize );
74                         sprintf( key.dptr, "%c%s", DN_ONE_PREFIX, pdn );
75                         ldap_pvt_thread_mutex_lock( &db->dbc_write_mutex );
76                         rc = idl_insert_key( be, db, key, id );
77                         ldap_pvt_thread_mutex_unlock( &db->dbc_write_mutex );
78                         free( key.dptr );
79                         free( pdn );
80                 }
81         }
82
83         if ( rc != -1 ) {
84                 char **subtree = dn_subtree( NULL, dn );
85
86                 if( subtree != NULL ) {
87                         int i;
88                         for( i=0; subtree[i] != NULL; i++ ) {
89                                 ldbm_datum_init( key );
90                                 key.dsize = strlen( subtree[i] ) + 2;
91                                 key.dptr = ch_malloc( key.dsize );
92                                 sprintf( key.dptr, "%c%s",
93                                         DN_SUBTREE_PREFIX, subtree[i] );
94                                 ldap_pvt_thread_mutex_lock( &db->dbc_write_mutex );
95                                 rc = idl_insert_key( be, db, key, id );
96                                 ldap_pvt_thread_mutex_unlock( &db->dbc_write_mutex );
97                                 free( key.dptr );
98
99                                 if(rc == -1) break;
100                         }
101
102                         charray_free( subtree );
103                 }
104         }
105
106         ldbm_cache_close( be, db );
107
108 #ifdef NEW_LOGGING
109         LDAP_LOG(( "backend", LDAP_LEVEL_ENTRY,
110                    "dn2id_add: return %d\n", rc ));
111 #else
112         Debug( LDAP_DEBUG_TRACE, "<= dn2id_add %d\n", rc, 0, 0 );
113 #endif
114
115         return( rc );
116 }
117
118 int
119 dn2id(
120     Backend     *be,
121     const char  *dn,
122     ID          *idp
123 )
124 {
125         struct ldbminfo *li = (struct ldbminfo *) be->be_private;
126         DBCache *db;
127         Datum           key, data;
128
129 #ifdef NEW_LOGGING
130         LDAP_LOG(( "backend", LDAP_LEVEL_ENTRY,
131                    "dn2id: (%s)\n", dn ));
132 #else
133         Debug( LDAP_DEBUG_TRACE, "=> dn2id( \"%s\" )\n", dn, 0, 0 );
134 #endif
135
136         assert( idp );
137
138         /* first check the cache */
139         if ( (*idp = cache_find_entry_ndn2id( be, &li->li_cache, dn )) != NOID ) {
140 #ifdef NEW_LOGGING
141                 LDAP_LOG(( "backend", LDAP_LEVEL_DETAIL1,
142                            "dn2id: (%s)%ld in cache.\n", dn, *idp ));
143 #else
144                 Debug( LDAP_DEBUG_TRACE, "<= dn2id %ld (in cache)\n", *idp,
145                         0, 0 );
146 #endif
147
148                 return( 0 );
149         }
150
151         if ( (db = ldbm_cache_open( be, "dn2id", LDBM_SUFFIX, LDBM_WRCREAT ))
152                 == NULL ) {
153 #ifdef NEW_LOGGING
154                 LDAP_LOG(( "backend", LDAP_LEVEL_ERR,
155                            "dn2id: couldn't open dn2id%s\n", LDBM_SUFFIX ));
156 #else
157                 Debug( LDAP_DEBUG_ANY, "<= dn2id could not open dn2id%s\n",
158                         LDBM_SUFFIX, 0, 0 );
159 #endif
160                 /*
161                  * return code !0 if ldbm cache open failed;
162                  * callers should handle this
163                  */
164                 *idp = NOID;
165                 return( -1 );
166         }
167
168         ldbm_datum_init( key );
169
170         key.dsize = strlen( dn ) + 2;
171         key.dptr = ch_malloc( key.dsize );
172         sprintf( key.dptr, "%c%s", DN_BASE_PREFIX, dn );
173
174         data = ldbm_cache_fetch( db, key );
175
176         ldbm_cache_close( be, db );
177
178         free( key.dptr );
179
180         if ( data.dptr == NULL ) {
181 #ifdef NEW_LOGGING
182                 LDAP_LOG(( "backend", LDAP_LEVEL_INFO,
183                            "dn2id: (%s) NOID\n", dn ));
184 #else
185                 Debug( LDAP_DEBUG_TRACE, "<= dn2id NOID\n", 0, 0, 0 );
186 #endif
187
188                 *idp = NOID;
189                 return( 0 );
190         }
191
192         AC_MEMCPY( (char *) idp, data.dptr, sizeof(ID) );
193
194         assert( *idp != NOID );
195
196         ldbm_datum_free( db->dbc_db, data );
197
198 #ifdef NEW_LOGGING
199         LDAP_LOG(( "backend", LDAP_LEVEL_ENTRY,
200                    "dn2id: %ld\n", *idp ));
201 #else
202         Debug( LDAP_DEBUG_TRACE, "<= dn2id %ld\n", *idp, 0, 0 );
203 #endif
204
205         return( 0 );
206 }
207
208 int
209 dn2idl(
210     Backend     *be,
211     const char  *dn,
212     int         prefix,
213     ID_BLOCK    **idlp
214 )
215 {
216         DBCache *db;
217         Datum           key;
218
219 #ifdef NEW_LOGGING
220         LDAP_LOG(( "backend", LDAP_LEVEL_ENTRY,
221                    "dn2idl: \"%c%s\"\n", prefix, dn ));
222 #else
223         Debug( LDAP_DEBUG_TRACE, "=> dn2idl( \"%c%s\" )\n", prefix, dn, 0 );
224 #endif
225
226         assert( idlp != NULL );
227         *idlp = NULL;
228
229         if ( (db = ldbm_cache_open( be, "dn2id", LDBM_SUFFIX, LDBM_WRCREAT ))
230                 == NULL ) {
231 #ifdef NEW_LOGGING
232                 LDAP_LOG(( "backend", LDAP_LEVEL_ERR,
233                            "dn2idl: could not open dn2id%s\n", LDBM_SUFFIX ));
234 #else
235                 Debug( LDAP_DEBUG_ANY, "<= dn2idl could not open dn2id%s\n",
236                         LDBM_SUFFIX, 0, 0 );
237 #endif
238
239                 return -1;
240         }
241
242         ldbm_datum_init( key );
243
244         key.dsize = strlen( dn ) + 2;
245         key.dptr = ch_malloc( key.dsize );
246         sprintf( key.dptr, "%c%s", prefix, dn );
247
248         *idlp = idl_fetch( be, db, key );
249
250         ldbm_cache_close( be, db );
251
252         free( key.dptr );
253
254         return( 0 );
255 }
256
257
258 int
259 dn2id_delete(
260     Backend     *be,
261     const char  *dn,
262         ID id
263 )
264 {
265         DBCache *db;
266         Datum           key;
267         int             rc;
268
269 #ifdef NEW_LOGGING
270         LDAP_LOG(( "backend", LDAP_LEVEL_ENTRY,
271                    "dn2id_delete: (%s)%ld\n", dn, id ));
272 #else
273         Debug( LDAP_DEBUG_TRACE, "=> dn2id_delete( \"%s\", %ld )\n", dn, id, 0 );
274 #endif
275
276
277         assert( id != NOID );
278
279         if ( (db = ldbm_cache_open( be, "dn2id", LDBM_SUFFIX, LDBM_WRCREAT ))
280             == NULL ) {
281 #ifdef NEW_LOGGING
282                 LDAP_LOG(( "backend", LDAP_LEVEL_ERR,
283                            "dn2id_delete: couldn't open db2id%s\n", LDBM_SUFFIX ));
284 #else
285                 Debug( LDAP_DEBUG_ANY,
286                     "<= dn2id_delete could not open dn2id%s\n", LDBM_SUFFIX,
287                     0, 0 );
288 #endif
289
290                 return( -1 );
291         }
292
293
294         {
295                 char *pdn = dn_parent( NULL, dn );
296
297                 if( pdn != NULL ) {
298                         ldbm_datum_init( key );
299                         key.dsize = strlen( pdn ) + 2;
300                         key.dptr = ch_malloc( key.dsize );
301                         sprintf( key.dptr, "%c%s", DN_ONE_PREFIX, pdn );
302
303                         ldap_pvt_thread_mutex_lock( &db->dbc_write_mutex );
304                         (void) idl_delete_key( be, db, key, id );
305                         ldap_pvt_thread_mutex_unlock( &db->dbc_write_mutex );
306
307                         free( key.dptr );
308                         free( pdn );
309                 }
310         }
311
312         {
313                 char **subtree = dn_subtree( NULL, dn );
314
315                 if( subtree != NULL ) {
316                         int i;
317                         for( i=0; subtree[i] != NULL; i++ ) {
318                                 ldbm_datum_init( key );
319                                 key.dsize = strlen( subtree[i] ) + 2;
320                                 key.dptr = ch_malloc( key.dsize );
321                                 sprintf( key.dptr, "%c%s",
322                                         DN_SUBTREE_PREFIX, subtree[i] );
323
324                                 ldap_pvt_thread_mutex_lock( &db->dbc_write_mutex );
325                                 (void) idl_delete_key( be, db, key, id );
326                                 ldap_pvt_thread_mutex_unlock( &db->dbc_write_mutex );
327
328                                 free( key.dptr );
329                         }
330
331                         charray_free( subtree );
332                 }
333         }
334
335         ldbm_datum_init( key );
336
337         key.dsize = strlen( dn ) + 2;
338         key.dptr = ch_malloc( key.dsize );
339         sprintf( key.dptr, "%c%s", DN_BASE_PREFIX, dn );
340
341         rc = ldbm_cache_delete( db, key );
342
343         free( key.dptr );
344
345         ldbm_cache_close( be, db );
346
347 #ifdef NEW_LOGGING
348         LDAP_LOG(( "backend", LDAP_LEVEL_ENTRY,
349                    "dn2id_delete: return %d\n", rc ));
350 #else
351         Debug( LDAP_DEBUG_TRACE, "<= dn2id_delete %d\n", rc, 0, 0 );
352 #endif
353
354         return( rc );
355 }
356
357 /*
358  * dn2entry - look up dn in the cache/indexes and return the corresponding
359  * entry.
360  */
361
362 Entry *
363 dn2entry_rw(
364     Backend     *be,
365     const char  *dn,
366     Entry       **matched,
367     int         rw
368 )
369 {
370         ID              id;
371         Entry           *e = NULL;
372         char            *pdn;
373
374 #ifdef NEW_LOGGING
375         LDAP_LOG(( "backend", LDAP_LEVEL_ENTRY,
376                    "dn2entry_rw: %s entry %s\n", rw ? "w" : "r",
377                    dn ));
378 #else
379         Debug(LDAP_DEBUG_TRACE, "dn2entry_%s: dn: \"%s\"\n",
380                 rw ? "w" : "r", dn, 0);
381 #endif
382
383
384         if( matched != NULL ) {
385                 /* caller cares about match */
386                 *matched = NULL;
387         }
388
389         if ( dn2id( be, dn, &id ) ) {
390                 /* something bad happened to ldbm cache */
391                 return( NULL );
392
393         } else if ( id != NOID ) {
394                 /* try to return the entry */
395                 if ((e = id2entry_rw( be, id, rw )) != NULL ) {
396                         return( e );
397                 }
398
399 #ifdef NEW_LOGGING
400                 LDAP_LOG(( "backend", LDAP_LEVEL_ERR,
401                            "dn2entry_rw: no entry for valid id (%ld), dn (%s)\n",
402                            id, dn ));
403 #else
404                 Debug(LDAP_DEBUG_ANY,
405                         "dn2entry_%s: no entry for valid id (%ld), dn \"%s\"\n",
406                         rw ? "w" : "r", id, dn);
407 #endif
408
409                 /* must have been deleted from underneath us */
410                 /* treat as if NOID was found */
411         }
412
413         /* caller doesn't care about match */
414         if( matched == NULL ) return NULL;
415
416         /* entry does not exist - see how much of the dn does exist */
417         /* dn_parent checks returns NULL if dn is suffix */
418         if ( (pdn = dn_parent( be, dn )) != NULL ) {
419                 /* get entry with reader lock */
420                 if ( (e = dn2entry_r( be, pdn, matched )) != NULL ) {
421                         *matched = e;
422                 }
423                 free( pdn );
424         }
425
426         return NULL;
427 }
428