]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldbm/dn2id.c
ae9489a519c67a4e4745a0067a5df825a86108c6
[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-2005 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         Debug( LDAP_DEBUG_TRACE, "=> dn2id_add( \"%s\", %ld )\n", dn->bv_val, id, 0 );
42
43         assert( id != NOID );
44
45         db = ldbm_cache_open( be, "dn2id", LDBM_SUFFIX, LDBM_WRCREAT );
46         if ( db == NULL ) {
47                 Debug( LDAP_DEBUG_ANY, "Could not open/create dn2id%s\n",
48                     LDBM_SUFFIX, 0, 0 );
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         Debug( LDAP_DEBUG_TRACE, "<= dn2id_add %d\n", rc, 0, 0 );
107
108         return( rc );
109 }
110
111 int
112 dn2id(
113     Backend     *be,
114     struct berval *dn,
115     ID          *idp
116 )
117 {
118         struct ldbminfo *li = (struct ldbminfo *) be->be_private;
119         DBCache *db;
120         Datum           key, data;
121         unsigned char   *tmp;
122
123         Debug( LDAP_DEBUG_TRACE, "=> dn2id( \"%s\" )\n", dn->bv_val, 0, 0 );
124
125         assert( idp );
126
127         /* first check the cache */
128         *idp = cache_find_entry_ndn2id( be, &li->li_cache, dn );
129         if ( *idp != NOID ) {
130                 Debug( LDAP_DEBUG_TRACE, "<= dn2id %ld (in cache)\n", *idp,
131                         0, 0 );
132
133                 return( 0 );
134         }
135
136         db = ldbm_cache_open( be, "dn2id", LDBM_SUFFIX, LDBM_WRCREAT );
137         if ( db == NULL ) {
138                 Debug( LDAP_DEBUG_ANY, "<= dn2id could not open dn2id%s\n",
139                         LDBM_SUFFIX, 0, 0 );
140                 /*
141                  * return code !0 if ldbm cache open failed;
142                  * callers should handle this
143                  */
144                 *idp = NOID;
145                 return( -1 );
146         }
147
148         ldbm_datum_init( key );
149
150         key.dsize = dn->bv_len + 2;
151         key.dptr = ch_malloc( key.dsize );
152         tmp = (unsigned char *)key.dptr;
153         tmp[0] = DN_BASE_PREFIX;
154         tmp++;
155         AC_MEMCPY( tmp, dn->bv_val, dn->bv_len );
156         tmp[dn->bv_len] = '\0';
157
158         data = ldbm_cache_fetch( db, key );
159
160         ldbm_cache_close( be, db );
161
162         free( key.dptr );
163
164         if ( data.dptr == NULL ) {
165                 Debug( LDAP_DEBUG_TRACE, "<= dn2id NOID\n", 0, 0, 0 );
166
167                 *idp = NOID;
168                 return( 0 );
169         }
170
171         AC_MEMCPY( (char *) idp, data.dptr, sizeof(ID) );
172
173         assert( *idp != NOID );
174
175         ldbm_datum_free( db->dbc_db, data );
176
177         Debug( LDAP_DEBUG_TRACE, "<= dn2id %ld\n", *idp, 0, 0 );
178
179         return( 0 );
180 }
181
182 int
183 dn2idl(
184     Backend     *be,
185     struct berval       *dn,
186     int         prefix,
187     ID_BLOCK    **idlp
188 )
189 {
190         DBCache *db;
191         Datum           key;
192         unsigned char   *tmp;
193
194         Debug( LDAP_DEBUG_TRACE, "=> dn2idl( \"%c%s\" )\n", prefix, dn->bv_val, 0 );
195
196         assert( idlp != NULL );
197         *idlp = NULL;
198
199         if ( prefix == DN_SUBTREE_PREFIX && be_issuffix(be, dn) ) {
200                 *idlp = idl_allids( be );
201                 return 0;
202         }
203
204         db = ldbm_cache_open( be, "dn2id", LDBM_SUFFIX, LDBM_WRCREAT );
205         if ( db == NULL ) {
206                 Debug( LDAP_DEBUG_ANY, "<= dn2idl could not open dn2id%s\n",
207                         LDBM_SUFFIX, 0, 0 );
208
209                 return -1;
210         }
211
212         ldbm_datum_init( key );
213
214         key.dsize = dn->bv_len + 2;
215         key.dptr = ch_malloc( key.dsize );
216         tmp = (unsigned char *)key.dptr;
217         tmp[0] = prefix;
218         tmp++;
219         AC_MEMCPY( tmp, dn->bv_val, dn->bv_len );
220         tmp[dn->bv_len] = '\0';
221
222         *idlp = idl_fetch( be, db, key );
223
224         ldbm_cache_close( be, db );
225
226         free( key.dptr );
227
228         return( 0 );
229 }
230
231
232 int
233 dn2id_delete(
234     Backend     *be,
235     struct berval *dn,
236         ID id
237 )
238 {
239         DBCache *db;
240         Datum           key;
241         int             rc;
242         char            *buf;
243         struct berval   ptr, pdn;
244
245         Debug( LDAP_DEBUG_TRACE, "=> dn2id_delete( \"%s\", %ld )\n", dn->bv_val, id, 0 );
246
247
248         assert( id != NOID );
249
250         db = ldbm_cache_open( be, "dn2id", LDBM_SUFFIX, LDBM_WRCREAT );
251         if ( db == NULL ) {
252                 Debug( LDAP_DEBUG_ANY,
253                     "<= dn2id_delete could not open dn2id%s\n", LDBM_SUFFIX,
254                     0, 0 );
255
256                 return( -1 );
257         }
258
259         ldbm_datum_init( key );
260         key.dsize = dn->bv_len + 2;
261         buf = ch_malloc( key.dsize );
262         key.dptr = buf;
263         buf[0] = DN_BASE_PREFIX;
264         ptr.bv_val = buf + 1;
265         ptr.bv_len = dn->bv_len;
266         AC_MEMCPY( ptr.bv_val, dn->bv_val, dn->bv_len );
267         ptr.bv_val[dn->bv_len] = '\0';
268
269         rc = ldbm_cache_delete( db, key );
270         
271         if( !be_issuffix( be, &ptr )) {
272                 buf[0] = DN_SUBTREE_PREFIX;
273                 ldap_pvt_thread_mutex_lock( &db->dbc_write_mutex );
274                 (void) idl_delete_key( be, db, key, id );
275                 ldap_pvt_thread_mutex_unlock( &db->dbc_write_mutex );
276
277                 dnParent( &ptr, &pdn );
278
279                 pdn.bv_val[-1] = DN_ONE_PREFIX;
280                 key.dsize = pdn.bv_len + 2;
281                 key.dptr = pdn.bv_val - 1;
282                 ptr = pdn;
283
284                 ldap_pvt_thread_mutex_lock( &db->dbc_write_mutex );
285                 (void) idl_delete_key( be, db, key, id );
286                 ldap_pvt_thread_mutex_unlock( &db->dbc_write_mutex );
287         }
288
289         while ( rc != -1 && !be_issuffix( be, &ptr )) {
290                 ptr.bv_val[-1] = DN_SUBTREE_PREFIX;
291
292                 ldap_pvt_thread_mutex_lock( &db->dbc_write_mutex );
293                 (void) idl_delete_key( be, db, key, id );
294                 ldap_pvt_thread_mutex_unlock( &db->dbc_write_mutex );
295
296                 dnParent( &ptr, &pdn );
297                 key.dsize = pdn.bv_len + 2;
298                 key.dptr = pdn.bv_val - 1;
299                 ptr = pdn;
300         }
301
302         free( buf );
303
304         ldbm_cache_close( be, db );
305
306         Debug( LDAP_DEBUG_TRACE, "<= dn2id_delete %d\n", rc, 0, 0 );
307
308         return( rc );
309 }
310
311 /*
312  * dn2entry - look up dn in the cache/indexes and return the corresponding
313  * entry.
314  */
315
316 Entry *
317 dn2entry_rw(
318     Backend     *be,
319     struct berval *dn,
320     Entry       **matched,
321     int         rw
322 )
323 {
324         ID              id;
325         Entry           *e = NULL;
326         struct berval   pdn;
327
328         Debug(LDAP_DEBUG_TRACE, "dn2entry_%s: dn: \"%s\"\n",
329                 rw ? "w" : "r", dn->bv_val, 0);
330
331
332         if( matched != NULL ) {
333                 /* caller cares about match */
334                 *matched = NULL;
335         }
336
337         if ( dn2id( be, dn, &id ) ) {
338                 /* something bad happened to ldbm cache */
339                 return( NULL );
340
341         }
342         
343         if ( id != NOID ) {
344                 /* try to return the entry */
345                 if ((e = id2entry_rw( be, id, rw )) != NULL ) {
346                         return( e );
347                 }
348
349                 Debug(LDAP_DEBUG_ANY,
350                         "dn2entry_%s: no entry for valid id (%ld), dn \"%s\"\n",
351                         rw ? "w" : "r", id, dn->bv_val);
352
353                 /* must have been deleted from underneath us */
354                 /* treat as if NOID was found */
355         }
356
357         /* caller doesn't care about match */
358         if( matched == NULL ) return NULL;
359
360         /* entry does not exist - see how much of the dn does exist */
361         if ( !be_issuffix( be, dn ) && (dnParent( dn, &pdn ), pdn.bv_len) ) {
362                 /* get entry with reader lock */
363                 if ((e = dn2entry_r( be, &pdn, matched )) != NULL )
364                 {
365                         *matched = e;
366                 }
367         }
368
369         return NULL;
370 }
371