]> git.sur5r.net Git - openldap/blob - servers/slapd/back-bdb/dn2id.c
4b5c46e9b2740c51a3605a7aec2a05ded7b8a1fb
[openldap] / servers / slapd / back-bdb / 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 #include <ac/string.h>
12
13 #include "back-bdb.h"
14
15 int
16 bdb_dn2id_add(
17     Backend     *be,
18         DB_TXN *txn,
19     const char  *dn,
20     ID          id
21 )
22 {
23         int             rc;
24         DBT             key, data;
25         struct bdb_info *bdb = (struct bdb_info *) be->be_private;
26         DB *db = bdb->bi_dn2id->bdi_db;
27
28         Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2id_add( \"%s\", %ld )\n", dn, id, 0 );
29         assert( id != NOID );
30
31         DBTzero( &key );
32         key.size = strlen( dn ) + 2;
33         key.data = ch_malloc( key.size );
34         ((char *)key.data)[0] = DN_BASE_PREFIX;
35         AC_MEMCPY( &((char *)key.data)[1], dn, key.size - 1 );
36
37         DBTzero( &data );
38         data.data = (char *) &id;
39         data.size = sizeof( id );
40
41         /* store it -- don't override */
42         rc = db->put( db, txn, &key, &data, DB_NOOVERWRITE );
43         if( rc != 0 ) {
44                 goto done;
45         }
46
47         {
48                 char *pdn = dn_parent( NULL, dn );
49                 ((char *)(key.data))[0] = DN_ONE_PREFIX;
50
51                 if( pdn != NULL ) {
52                         key.size = strlen( pdn ) + 2;
53                         AC_MEMCPY( &((char*)key.data)[1],
54                                 pdn, key.size - 1 );
55
56                         rc = bdb_idl_insert_key( be, db, txn, &key, id );
57                         free( pdn );
58
59                         if( rc != 0 ) {
60                                 goto done;
61                         }
62                 }
63         }
64
65         {
66                 char **subtree = dn_subtree( NULL, dn );
67
68                 if( subtree != NULL ) {
69                         int i;
70                         ((char *)key.data)[0] = DN_SUBTREE_PREFIX;
71                         for( i=0; subtree[i] != NULL; i++ ) {
72                                 key.size = strlen( subtree[i] ) + 2;
73                                 AC_MEMCPY( &((char *)key.data)[1],
74                                         subtree[i], key.size - 1 );
75
76                                 rc = bdb_idl_insert_key( be, db, txn, &key, id );
77
78                                 if( rc != 0 ) {
79                                         goto done;
80                                 }
81                         }
82
83                         charray_free( subtree );
84                 }
85         }
86
87 done:
88         ch_free( key.data );
89         Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id_add %d\n", rc, 0, 0 );
90         return rc;
91 }
92
93 int
94 bdb_dn2id_delete(
95     Backend     *be,
96         DB_TXN *txn,
97     const char  *dn,
98     ID          id
99 )
100 {
101         int             rc;
102         DBT             key;
103         struct bdb_info *bdb = (struct bdb_info *) be->be_private;
104         DB *db = bdb->bi_dn2id->bdi_db;
105
106         Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2id_delete( \"%s\", %ld )\n", dn, id, 0 );
107         assert( id != NOID );
108
109         DBTzero( &key );
110         key.size = strlen( dn ) + 2;
111         key.data = ch_malloc( key.size );
112         ((char *)key.data)[0] = DN_BASE_PREFIX;
113         AC_MEMCPY( &((char *)key.data)[1], dn, key.size - 1 );
114
115         /* store it -- don't override */
116         rc = db->del( db, txn, &key, 0 );
117         if( rc != 0 ) {
118                 goto done;
119         }
120
121         {
122                 char *pdn = dn_parent( NULL, dn );
123                 ((char *)(key.data))[0] = DN_ONE_PREFIX;
124
125                 if( pdn != NULL ) {
126                         key.size = strlen( pdn ) + 2;
127                         AC_MEMCPY( &((char*)key.data)[1],
128                                 pdn, key.size - 1 );
129
130                         rc = bdb_idl_delete_key( be, db, txn, &key, id );
131                         free( pdn );
132
133                         if( rc != 0 ) {
134                                 goto done;
135                         }
136                 }
137         }
138
139         {
140                 char **subtree = dn_subtree( NULL, dn );
141
142                 if( subtree != NULL ) {
143                         int i;
144                         ((char *)key.data)[0] = DN_SUBTREE_PREFIX;
145                         for( i=0; subtree[i] != NULL; i++ ) {
146                                 key.size = strlen( subtree[i] ) + 2;
147                                 AC_MEMCPY( &((char *)key.data)[1],
148                                         subtree[i], key.size - 1 );
149
150                                 rc = bdb_idl_delete_key( be, db, txn, &key, id );
151
152                                 if( rc != 0 ) {
153                                         goto done;
154                                 }
155                         }
156
157                         charray_free( subtree );
158                 }
159         }
160
161 done:
162         ch_free( key.data );
163         Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id_delete %d\n", rc, 0, 0 );
164         return rc;
165 }
166
167 int
168 bdb_dn2id_children(
169     Backend     *be,
170         DB_TXN *txn,
171     const char *dn
172 )
173 {
174         int             rc;
175         DBT             key, data;
176         struct bdb_info *bdb = (struct bdb_info *) be->be_private;
177         DB *db = bdb->bi_dn2id->bdi_db;
178         ID              id;
179
180         Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2id_children( %s )\n",
181                 dn, 0, 0 );
182
183         DBTzero( &key );
184         key.size = strlen( dn ) + 2;
185         key.data = ch_malloc( key.size );
186         ((char *)key.data)[0] = DN_ONE_PREFIX;
187         AC_MEMCPY( &((char *)key.data)[1], dn, key.size - 1 );
188
189         /* we actually could do a empty get... */
190         DBTzero( &data );
191         data.data = &id;
192         data.ulen = sizeof(id);
193         data.flags = DB_DBT_USERMEM;
194         data.doff = 0;
195         data.dlen = sizeof(id);
196
197         rc = db->get( db, txn, &key, &data, 0 );
198
199         Debug( LDAP_DEBUG_TRACE, "<= bdb_dn2id_children( %s ): %s (%d)\n",
200                 dn,
201                 rc == 0 ? "yes" :       ( rc == DB_NOTFOUND ? "no" :
202                         db_strerror(rc) ), rc );
203
204         return rc;
205 }
206
207 #if 0
208 ID
209 dn2id(
210     Backend     *be,
211     const char  *dn
212 )
213 {
214         struct ldbminfo *li = (struct ldbminfo *) be->be_private;
215         DBCache *db;
216         ID              id;
217         Datum           key, data;
218
219         Debug( LDAP_DEBUG_TRACE, "=> dn2id( \"%s\" )\n", dn, 0, 0 );
220
221         /* first check the cache */
222         if ( (id = cache_find_entry_dn2id( be, &li->li_cache, dn )) != NOID ) {
223                 Debug( LDAP_DEBUG_TRACE, "<= dn2id %ld (in cache)\n", id,
224                         0, 0 );
225                 return( id );
226         }
227
228         if ( (db = ldbm_cache_open( be, "dn2id", LDBM_SUFFIX, LDBM_WRCREAT ))
229                 == NULL ) {
230                 Debug( LDAP_DEBUG_ANY, "<= dn2id could not open dn2id%s\n",
231                         LDBM_SUFFIX, 0, 0 );
232                 return( NOID );
233         }
234
235         ldbm_datum_init( key );
236
237         key.dsize = strlen( dn ) + 2;
238         key.dptr = ch_malloc( key.dsize );
239         sprintf( key.dptr, "%c%s", DN_BASE_PREFIX, dn );
240
241         data = ldbm_cache_fetch( db, key );
242
243         ldbm_cache_close( be, db );
244
245         free( key.dptr );
246
247         if ( data.dptr == NULL ) {
248                 Debug( LDAP_DEBUG_TRACE, "<= dn2id NOID\n", 0, 0, 0 );
249                 return( NOID );
250         }
251
252         AC_MEMCPY( (char *) &id, data.dptr, sizeof(ID) );
253
254         assert( id != NOID );
255
256         ldbm_datum_free( db->dbc_db, data );
257
258         Debug( LDAP_DEBUG_TRACE, "<= dn2id %ld\n", id, 0, 0 );
259         return( id );
260 }
261
262 ID_BLOCK *
263 dn2idl(
264     Backend     *be,
265     const char  *dn,
266         int             prefix
267 )
268 {
269         DBCache *db;
270         Datum           key;
271         ID_BLOCK        *idl;
272
273         Debug( LDAP_DEBUG_TRACE, "=> dn2idl( \"%c%s\" )\n", prefix, dn, 0 );
274
275         if ( (db = ldbm_cache_open( be, "dn2id", LDBM_SUFFIX, LDBM_WRCREAT ))
276                 == NULL ) {
277                 Debug( LDAP_DEBUG_ANY, "<= dn2idl could not open dn2id%s\n",
278                         LDBM_SUFFIX, 0, 0 );
279                 return NULL;
280         }
281
282         ldbm_datum_init( key );
283
284         key.dsize = strlen( dn ) + 2;
285         key.dptr = ch_malloc( key.dsize );
286         sprintf( key.dptr, "%c%s", prefix, dn );
287
288         idl = idl_fetch( be, db, key );
289
290         ldbm_cache_close( be, db );
291
292         free( key.dptr );
293
294         return( idl );
295 }
296
297
298 /*
299  * dn2entry - look up dn in the cache/indexes and return the corresponding
300  * entry.
301  */
302
303 Entry *
304 dn2entry_rw(
305     Backend     *be,
306     const char  *dn,
307     Entry       **matched,
308     int         rw
309 )
310 {
311         ID              id;
312         Entry           *e = NULL;
313         char            *pdn;
314
315         Debug(LDAP_DEBUG_TRACE, "dn2entry_%s: dn: \"%s\"\n",
316                 rw ? "w" : "r", dn, 0);
317
318         if( matched != NULL ) {
319                 /* caller cares about match */
320                 *matched = NULL;
321         }
322
323         if ( (id = dn2id( be, dn )) != NOID &&
324                 (e = id2entry_rw( be, id, rw )) != NULL )
325         {
326                 return( e );
327         }
328
329         if ( id != NOID ) {
330                 Debug(LDAP_DEBUG_ANY,
331                         "dn2entry_%s: no entry for valid id (%ld), dn \"%s\"\n",
332                         rw ? "w" : "r", id, dn);
333                 /* must have been deleted from underneath us */
334                 /* treat as if NOID was found */
335         }
336
337         /* caller doesn't care about match */
338         if( matched == NULL ) return NULL;
339
340         /* entry does not exist - see how much of the dn does exist */
341         /* dn_parent checks returns NULL if dn is suffix */
342         if ( (pdn = dn_parent( be, dn )) != NULL ) {
343                 /* get entry with reader lock */
344                 if ( (e = dn2entry_r( be, pdn, matched )) != NULL ) {
345                         *matched = e;
346                 }
347                 free( pdn );
348         }
349
350         return NULL;
351 }
352 #endif