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