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