]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldbm/tools.c
ITS#4310 seems to affect also back-ldbm
[openldap] / servers / slapd / back-ldbm / tools.c
1 /* tools.c - tools for slap tools */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 1998-2006 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
27 static LDBMCursor *cursorp = NULL;
28 static DBCache *id2entry = NULL;
29
30 int ldbm_tool_entry_open(
31         BackendDB *be, int mode )
32 {
33         struct ldbminfo *li = (struct ldbminfo *) be->be_private;
34         int flags;
35
36         assert( slapMode & SLAP_TOOL_MODE );
37         assert( id2entry == NULL );
38
39         switch( mode ) {
40         case 1:
41                 flags = LDBM_WRCREAT;
42                 break;
43         case 2:
44 #ifdef TRUNCATE_MODE
45                 flags = LDBM_NEWDB;
46 #else
47                 flags = LDBM_WRCREAT;
48 #endif
49                 break;
50         default:
51                 flags = LDBM_READER;
52         }
53
54         li->li_dbwritesync = 0;
55
56         if ( (id2entry = ldbm_cache_open( be, "id2entry", LDBM_SUFFIX, flags ))
57             == NULL ) {
58                 Debug( LDAP_DEBUG_ANY, "Could not open/create id2entry" LDBM_SUFFIX "\n",
59                     0, 0, 0 );
60
61                 return( -1 );
62         }
63
64         return 0;
65 }
66
67 int ldbm_tool_entry_close(
68         BackendDB *be )
69 {
70         struct ldbminfo *li = (struct ldbminfo *) be->be_private;
71
72         assert( slapMode & SLAP_TOOL_MODE );
73         assert( id2entry != NULL );
74
75         ldbm_cache_close( be, id2entry );
76         li->li_dbwritesync = 1;
77         id2entry = NULL;
78
79         return 0;
80 }
81
82 ID ldbm_tool_entry_first(
83         BackendDB *be )
84 {
85         Datum key;
86         ID id;
87
88         assert( slapMode & SLAP_TOOL_MODE );
89         assert( id2entry != NULL );
90
91         key = ldbm_firstkey( id2entry->dbc_db, &cursorp );
92
93         if( key.dptr == NULL ) {
94                 return NOID;
95         }
96
97         AC_MEMCPY( &id, key.dptr, key.dsize );
98 #ifndef WORDS_BIGENDIAN
99         id = ntohl( id );
100 #endif
101
102         ldbm_datum_free( id2entry->dbc_db, key );
103
104         return id;
105 }
106
107 ID ldbm_tool_entry_next(
108         BackendDB *be )
109 {
110         Datum key;
111         ID id;
112
113         assert( slapMode & SLAP_TOOL_MODE );
114         assert( id2entry != NULL );
115
116         /* allow for NEXTID */
117         ldbm_datum_init( key );
118
119         key = ldbm_nextkey( id2entry->dbc_db, key, cursorp );
120
121         if( key.dptr == NULL ) {
122                 return NOID;
123         }
124
125         AC_MEMCPY( &id, key.dptr, key.dsize );
126 #ifndef WORDS_BIGENDIAN
127         id = ntohl( id );
128 #endif
129
130         ldbm_datum_free( id2entry->dbc_db, key );
131
132         return id;
133 }
134
135 Entry* ldbm_tool_entry_get( BackendDB *be, ID id )
136 {
137         Entry *e;
138         Datum key, data;
139 #ifndef WORDS_BIGENDIAN
140         ID id2;
141 #endif
142         assert( slapMode & SLAP_TOOL_MODE );
143         assert( id2entry != NULL );
144
145         ldbm_datum_init( key );
146
147 #ifndef WORDS_BIGENDIAN
148         id2 = htonl( id );
149         key.dptr = (char *) &id2;
150 #else
151         key.dptr = (char *) &id;
152 #endif
153         key.dsize = sizeof(ID);
154
155         data = ldbm_cache_fetch( id2entry, key );
156
157         if ( data.dptr == NULL ) {
158                 return NULL;
159         }
160
161         e = str2entry2( data.dptr, 0 );
162         ldbm_datum_free( id2entry->dbc_db, data );
163
164         if( e != NULL ) {
165                 e->e_id = id;
166         }
167
168         return e;
169 }
170
171 ID ldbm_tool_entry_put(
172         BackendDB *be,
173         Entry *e,
174         struct berval *text )
175 {
176         struct ldbminfo *li = (struct ldbminfo *) be->be_private;
177         Datum key, data;
178         int rc, len;
179         ID id;
180         Operation op = {0};
181         Opheader ohdr = {0};
182
183         assert( slapMode & SLAP_TOOL_MODE );
184         assert( id2entry != NULL );
185
186         assert( text != NULL );
187         assert( text->bv_val != NULL );
188         assert( text->bv_val[0] == '\0' );      /* overconservative? */
189
190         if ( next_id_get( be, &id ) || id == NOID ) {
191                 strncpy( text->bv_val, "unable to get nextid", text->bv_len );
192                 return NOID;
193         }
194
195         e->e_id = li->li_nextid++;
196
197         Debug( LDAP_DEBUG_TRACE, "=> ldbm_tool_entry_put( %ld, \"%s\" )\n",
198                 e->e_id, e->e_dn, 0 );
199
200         if ( dn2id( be, &e->e_nname, &id ) ) {
201                 /* something bad happened to ldbm cache */
202                 strncpy( text->bv_val, "ldbm cache corrupted", text->bv_len );
203                 return NOID;
204         }
205
206         if( id != NOID ) {
207                 Debug( LDAP_DEBUG_TRACE,
208                         "<= ldbm_tool_entry_put: \"%s\" already exists (id=%ld)\n",
209                         e->e_ndn, id, 0 );
210                 strncpy( text->bv_val, "already exists", text->bv_len );
211                 return NOID;
212         }
213
214         op.o_hdr = &ohdr;
215         op.o_bd = be;
216         op.o_tmpmemctx = NULL;
217         op.o_tmpmfuncs = &ch_mfuncs;
218
219         rc = index_entry_add( &op, e );
220         if( rc != 0 ) {
221                 strncpy( text->bv_val, "index add failed", text->bv_len );
222                 return NOID;
223         }
224
225         rc = dn2id_add( be, &e->e_nname, e->e_id );
226         if( rc != 0 ) {
227                 strncpy( text->bv_val, "dn2id add failed", text->bv_len );
228                 return NOID;
229         }
230
231         ldbm_datum_init( key );
232         ldbm_datum_init( data );
233
234 #ifndef WORDS_BIGENDIAN
235         id = htonl( e->e_id );
236         key.dptr = (char *) &id;
237 #else
238         key.dptr = (char *) &e->e_id;
239 #endif
240         key.dsize = sizeof(ID);
241
242         data.dptr = entry2str( e, &len );
243         data.dsize = len + 1;
244
245         /* store it */
246         rc = ldbm_cache_store( id2entry, key, data, LDBM_REPLACE );
247
248         if( rc != 0 ) {
249                 (void) dn2id_delete( be, &e->e_nname, e->e_id );
250                 strncpy( text->bv_val, "cache store failed", text->bv_len );
251                 return NOID;
252         }
253
254         return e->e_id;
255 }
256
257 int ldbm_tool_entry_reindex(
258         BackendDB *be,
259         ID id )
260 {
261         int rc;
262         Entry *e;
263         Operation op = {0};
264         Opheader ohdr = {0};
265
266         Debug( LDAP_DEBUG_ARGS, "=> ldbm_tool_entry_reindex( %ld )\n",
267                 (long) id, 0, 0 );
268
269
270         e = ldbm_tool_entry_get( be, id );
271
272         if( e == NULL ) {
273                 Debug( LDAP_DEBUG_ANY,
274                         "ldbm_tool_entry_reindex:: could not locate id=%ld\n",
275                         (long) id, 0, 0 );
276
277                 return -1;
278         }
279
280         /*
281          * just (re)add them for now
282          * assume that some other routine (not yet implemented)
283          * will zap index databases
284          *
285          */
286
287         Debug( LDAP_DEBUG_TRACE, "=> ldbm_tool_entry_reindex( %ld, \"%s\" )\n",
288                 id, e->e_dn, 0 );
289
290         dn2id_add( be, &e->e_nname, e->e_id );
291
292         op.o_hdr = &ohdr;
293         op.o_bd = be;
294         op.o_tmpmemctx = NULL;
295         op.o_tmpmfuncs = &ch_mfuncs;
296         rc = index_entry_add( &op, e );
297
298         entry_free( e );
299
300         return rc;
301 }
302
303 int ldbm_tool_sync( BackendDB *be )
304 {
305         struct ldbminfo *li = (struct ldbminfo *) be->be_private;
306
307         assert( slapMode & SLAP_TOOL_MODE );
308
309         if ( li->li_nextid != NOID ) {
310                 if ( next_id_write( be, li->li_nextid ) ) {
311                         return( -1 );
312                 }
313         }
314
315         return 0;
316 }