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