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