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