]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldbm/id2entry.c
Fix ITS#1991 - referrals with sarch base == target (wasn't sure at first,
[openldap] / servers / slapd / back-ldbm / id2entry.c
1 /* id2entry.c - routines to deal with the id2entry index */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2002 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/socket.h>
13
14 #include "slap.h"
15 #include "back-ldbm.h"
16
17 /*
18  * This routine adds (or updates) an entry on disk.
19  * The cache should already be updated. 
20  */
21
22 int
23 id2entry_add( Backend *be, Entry *e )
24 {
25         DBCache *db;
26         Datum           key, data;
27         int             len, rc, flags;
28 #ifndef WORDS_BIGENDIAN
29         ID              id;
30 #endif
31
32         ldbm_datum_init( key );
33         ldbm_datum_init( data );
34
35 #ifdef NEW_LOGGING
36         LDAP_LOG( INDEX, ENTRY, "id2entry_add: (%s)%ld\n", e->e_dn, e->e_id, 0 );
37 #else
38         Debug( LDAP_DEBUG_TRACE, "=> id2entry_add( %ld, \"%s\" )\n", e->e_id,
39             e->e_dn, 0 );
40 #endif
41
42
43         if ( (db = ldbm_cache_open( be, "id2entry", LDBM_SUFFIX, LDBM_WRCREAT ))
44             == NULL ) {
45 #ifdef NEW_LOGGING
46                 LDAP_LOG( INDEX, ERR, 
47                    "id2entry_add: could not open/create id2entry%s\n", 
48                    LDBM_SUFFIX, 0,0 );
49 #else
50                 Debug( LDAP_DEBUG_ANY, "Could not open/create id2entry%s\n",
51                     LDBM_SUFFIX, 0, 0 );
52 #endif
53
54                 return( -1 );
55         }
56
57 #ifdef WORDS_BIGENDIAN
58         key.dptr = (char *) &e->e_id;
59 #else
60         id = htonl(e->e_id);
61         key.dptr = (char *) &id;
62 #endif
63         key.dsize = sizeof(ID);
64
65         ldap_pvt_thread_mutex_lock( &entry2str_mutex );
66         data.dptr = entry2str( e, &len );
67         data.dsize = len + 1;
68
69         /* store it */
70         flags = LDBM_REPLACE;
71         rc = ldbm_cache_store( db, key, data, flags );
72
73         ldap_pvt_thread_mutex_unlock( &entry2str_mutex );
74
75         ldbm_cache_close( be, db );
76
77 #ifdef NEW_LOGGING
78         LDAP_LOG( INDEX, ENTRY, "id2entry_add: return %d\n", rc, 0, 0 );
79 #else
80         Debug( LDAP_DEBUG_TRACE, "<= id2entry_add %d\n", rc, 0, 0 );
81 #endif
82
83
84         return( rc );
85 }
86
87 int
88 id2entry_delete( Backend *be, Entry *e )
89 {
90         struct ldbminfo *li = (struct ldbminfo *) be->be_private;
91         DBCache *db;
92         Datum           key;
93         int             rc;
94 #ifndef WORDS_BIGENDIAN
95         ID              id;
96 #endif
97
98 #ifdef NEW_LOGGING
99         LDAP_LOG( INDEX, ENTRY, "id2entry_delete: (%s)%ld\n", e->e_dn, e->e_id, 0 );
100 #else
101         Debug(LDAP_DEBUG_TRACE, "=> id2entry_delete( %ld, \"%s\" )\n", e->e_id,
102             e->e_dn, 0 );
103 #endif
104
105
106 #ifdef notdef
107 #ifdef LDAP_RDWR_DEBUG
108         /* check for writer lock */
109         assert(ldap_pvt_thread_rdwr_writers(&e->e_rdwr) == 1);
110 #endif
111 #endif
112
113         ldbm_datum_init( key );
114
115         if ( (db = ldbm_cache_open( be, "id2entry", LDBM_SUFFIX, LDBM_WRCREAT ))
116                 == NULL ) {
117 #ifdef NEW_LOGGING
118                 LDAP_LOG( INDEX, ERR, 
119                            "id2entry_delete: could not open/create id2entry%s\n",
120                            LDBM_SUFFIX, 0, 0 );
121 #else
122                 Debug( LDAP_DEBUG_ANY, "Could not open/create id2entry%s\n",
123                     LDBM_SUFFIX, 0, 0 );
124 #endif
125
126                 return( -1 );
127         }
128
129         if ( cache_delete_entry( &li->li_cache, e ) != 0 ) {
130 #ifdef NEW_LOGGING
131                 LDAP_LOG( INDEX, ERR, 
132                            "id2entry_delete: Could not delete (%s)%ld from cache\n",
133                            e->e_dn, e->e_id, 0 );
134 #else
135                 Debug(LDAP_DEBUG_ANY, "could not delete %ld (%s) from cache\n",
136                     e->e_id, e->e_dn, 0 );
137 #endif
138
139         }
140
141 #ifdef WORDS_BIGENDIAN
142         key.dptr = (char *) &e->e_id;
143 #else
144         id = htonl(e->e_id);
145         key.dptr = (char *) &id;
146 #endif
147         key.dsize = sizeof(ID);
148
149         rc = ldbm_cache_delete( db, key );
150
151         ldbm_cache_close( be, db );
152
153 #ifdef NEW_LOGGING
154         LDAP_LOG( INDEX, ENTRY, "id2entry_delete: return %d\n", rc, 0, 0 );
155 #else
156         Debug( LDAP_DEBUG_TRACE, "<= id2entry_delete %d\n", rc, 0, 0 );
157 #endif
158
159         return( rc );
160 }
161
162 /* returns entry with reader/writer lock */
163 Entry *
164 id2entry_rw( Backend *be, ID id, int rw )
165 {
166         struct ldbminfo *li = (struct ldbminfo *) be->be_private;
167         DBCache *db;
168         Datum           key, data;
169         Entry           *e;
170 #ifndef WORDS_BIGENDIAN
171         ID              id2;
172 #endif
173
174         ldbm_datum_init( key );
175         ldbm_datum_init( data );
176
177 #ifdef NEW_LOGGING
178         LDAP_LOG( INDEX, ENTRY, 
179                    "id2entry_rw: %s (%ld)\n", rw ? "write" : "read", id, 0 );
180 #else
181         Debug( LDAP_DEBUG_TRACE, "=> id2entry_%s( %ld )\n",
182                 rw ? "w" : "r", id, 0 );
183 #endif
184
185
186         if ( (e = cache_find_entry_id( &li->li_cache, id, rw )) != NULL ) {
187 #ifdef NEW_LOGGING
188                 LDAP_LOG( INDEX, DETAIL1, 
189                            "id2entry_rw: %s (%ld) 0x%lx (cache).\n",
190                            rw ? "write" : "read", id, (unsigned long)e  );
191 #else
192                 Debug( LDAP_DEBUG_TRACE, "<= id2entry_%s( %ld ) 0x%lx (cache)\n",
193                         rw ? "w" : "r", id, (unsigned long) e );
194 #endif
195
196                 return( e );
197         }
198
199         if ( (db = ldbm_cache_open( be, "id2entry", LDBM_SUFFIX, LDBM_WRCREAT ))
200                 == NULL ) {
201 #ifdef NEW_LOGGING
202                 LDAP_LOG( INDEX, ERR, 
203                            "id2entry_rw: could not open id2entry%s\n", LDBM_SUFFIX, 0, 0 );
204 #else
205                 Debug( LDAP_DEBUG_ANY, "Could not open id2entry%s\n",
206                     LDBM_SUFFIX, 0, 0 );
207 #endif
208
209                 return( NULL );
210         }
211
212 #ifdef WORDS_BIGENDIAN
213         key.dptr = (char *) &id;
214 #else
215         id2 = htonl(id);
216         key.dptr = (char *) &id2;
217 #endif
218         key.dsize = sizeof(ID);
219
220         data = ldbm_cache_fetch( db, key );
221
222         if ( data.dptr == NULL ) {
223 #ifdef NEW_LOGGING
224                 LDAP_LOG( INDEX, ERR, 
225                            "id2entry_rw: (%ld) not found\n", id, 0, 0 );
226 #else
227                 Debug( LDAP_DEBUG_TRACE, "<= id2entry_%s( %ld ) not found\n",
228                         rw ? "w" : "r", id, 0 );
229 #endif
230
231                 ldbm_cache_close( be, db );
232                 return( NULL );
233         }
234
235         e = str2entry( data.dptr );
236         ldbm_datum_free( db->dbc_db, data );
237         ldbm_cache_close( be, db );
238
239         if ( e == NULL ) {
240 #ifdef NEW_LOGGING
241                 LDAP_LOG( INDEX, ERR, 
242                            "id2entry_rw: %s of %ld failed\n", rw ? "write" : "read", id, 0);
243 #else
244                 Debug( LDAP_DEBUG_TRACE, "<= id2entry_%s( %ld ) (failed)\n",
245                         rw ? "w" : "r", id, 0 );
246 #endif
247
248                 return( NULL );
249         }
250
251         e->e_id = id;
252
253         if( cache_add_entry_rw( &li->li_cache, e, rw ) != 0 ) {
254                 entry_free( e );
255
256                 /* XXX this is a kludge.
257                  * maybe the entry got added underneath us
258                  * There are many underlying race condtions in the cache/disk code.
259                  */
260                 if ( (e = cache_find_entry_id( &li->li_cache, id, rw )) != NULL ) {
261 #ifdef NEW_LOGGING
262                         LDAP_LOG( INDEX, DETAIL1, 
263                                    "id2entry_rw: %s of %ld 0x%lx (cache)\n",
264                                    rw ? "write" : "read", id, (unsigned long)e  );
265 #else
266                         Debug( LDAP_DEBUG_TRACE, "<= id2entry_%s( %ld ) 0x%lx (cache)\n",
267                                 rw ? "w" : "r", id, (unsigned long) e );
268 #endif
269
270                         return( e );
271                 }
272
273 #ifdef NEW_LOGGING
274                 LDAP_LOG( INDEX, ERR, 
275                            "id2entry_rw: %s of %ld (cache add failed)\n",
276                            rw ? "write" : "read", id, 0 );
277 #else
278                 Debug( LDAP_DEBUG_TRACE, "<= id2entry_%s( %ld ) (cache add failed)\n",
279                         rw ? "w" : "r", id, 0 );
280 #endif
281
282                 return NULL;
283         }
284
285 #ifdef NEW_LOGGING
286         LDAP_LOG( INDEX, ENTRY, 
287                    "id2entry_rw: %s of %ld 0x%lx (disk)\n",
288                    rw ? "write" : "read", id, (unsigned long)e  );
289 #else
290         Debug( LDAP_DEBUG_TRACE, "<= id2entry_%s( %ld ) 0x%lx (disk)\n",
291                 rw ? "w" : "r", id, (unsigned long) e );
292 #endif
293
294         /* marks the entry as committed, so it will get added to the cache
295          * when the lock is released */
296         cache_entry_commit( e );
297
298         return( e );
299 }