]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldbm/tools.c
Notices
[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-2003 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 #ifdef NEW_LOGGING
59                 LDAP_LOG( BACK_LDBM, CRIT,
60                            "Could not open/create id2entry%s\n", LDBM_SUFFIX, 0, 0 );
61 #else
62                 Debug( LDAP_DEBUG_ANY, "Could not open/create id2entry" LDBM_SUFFIX "\n",
63                     0, 0, 0 );
64 #endif
65
66                 return( -1 );
67         }
68
69         return 0;
70 }
71
72 int ldbm_tool_entry_close(
73         BackendDB *be )
74 {
75         struct ldbminfo *li = (struct ldbminfo *) be->be_private;
76
77         assert( slapMode & SLAP_TOOL_MODE );
78         assert( id2entry != NULL );
79
80         ldbm_cache_close( be, id2entry );
81         li->li_dbwritesync = 1;
82         id2entry = NULL;
83
84         return 0;
85 }
86
87 ID ldbm_tool_entry_first(
88         BackendDB *be )
89 {
90         Datum key;
91         ID id;
92
93         assert( slapMode & SLAP_TOOL_MODE );
94         assert( id2entry != NULL );
95
96         key = ldbm_firstkey( id2entry->dbc_db, &cursorp );
97
98         if( key.dptr == NULL ) {
99                 return NOID;
100         }
101
102         AC_MEMCPY( &id, key.dptr, key.dsize );
103 #ifndef WORDS_BIGENDIAN
104         id = ntohl( id );
105 #endif
106
107         ldbm_datum_free( id2entry->dbc_db, key );
108
109         return id;
110 }
111
112 ID ldbm_tool_entry_next(
113         BackendDB *be )
114 {
115         Datum key;
116         ID id;
117
118         assert( slapMode & SLAP_TOOL_MODE );
119         assert( id2entry != NULL );
120
121         /* allow for NEXTID */
122         ldbm_datum_init( key );
123
124         key = ldbm_nextkey( id2entry->dbc_db, key, cursorp );
125
126         if( key.dptr == NULL ) {
127                 return NOID;
128         }
129
130         AC_MEMCPY( &id, key.dptr, key.dsize );
131 #ifndef WORDS_BIGENDIAN
132         id = ntohl( id );
133 #endif
134
135         ldbm_datum_free( id2entry->dbc_db, key );
136
137         return id;
138 }
139
140 Entry* ldbm_tool_entry_get( BackendDB *be, ID id )
141 {
142         Entry *e;
143         Datum key, data;
144 #ifndef WORDS_BIGENDIAN
145         ID id2;
146 #endif
147         assert( slapMode & SLAP_TOOL_MODE );
148         assert( id2entry != NULL );
149
150         ldbm_datum_init( key );
151
152 #ifndef WORDS_BIGENDIAN
153         id2 = htonl( id );
154         key.dptr = (char *) &id2;
155 #else
156         key.dptr = (char *) &id;
157 #endif
158         key.dsize = sizeof(ID);
159
160         data = ldbm_cache_fetch( id2entry, key );
161
162         if ( data.dptr == NULL ) {
163                 return NULL;
164         }
165
166         e = str2entry( data.dptr );
167         ldbm_datum_free( id2entry->dbc_db, data );
168
169         if( e != NULL ) {
170                 e->e_id = id;
171         }
172
173         return e;
174 }
175
176 ID ldbm_tool_entry_put(
177         BackendDB *be,
178         Entry *e,
179         struct berval *text )
180 {
181         struct ldbminfo *li = (struct ldbminfo *) be->be_private;
182         Datum key, data;
183         int rc, len;
184         ID id;
185         Operation op = {0};
186
187         assert( slapMode & SLAP_TOOL_MODE );
188         assert( id2entry != NULL );
189
190         assert( text );
191         assert( text->bv_val );
192         assert( text->bv_val[0] == '\0' );      /* overconservative? */
193
194         if ( next_id_get( be, &id ) || id == NOID ) {
195                 strncpy( text->bv_val, "unable to get nextid", text->bv_len );
196                 return NOID;
197         }
198
199         e->e_id = li->li_nextid++;
200
201 #ifdef NEW_LOGGING
202         LDAP_LOG( BACK_LDBM, ENTRY,
203                 "ldbm_tool_entry_put: (%s)%ld\n", e->e_dn, e->e_id ,0 );
204 #else
205         Debug( LDAP_DEBUG_TRACE, "=> ldbm_tool_entry_put( %ld, \"%s\" )\n",
206                 e->e_id, e->e_dn, 0 );
207 #endif
208
209         if ( dn2id( be, &e->e_nname, &id ) ) {
210                 /* something bad happened to ldbm cache */
211                 strncpy( text->bv_val, "ldbm cache corrupted", text->bv_len );
212                 return NOID;
213         }
214
215         if( id != NOID ) {
216 #ifdef NEW_LOGGING
217                 LDAP_LOG( BACK_LDBM, ENTRY,
218                         "ldbm_tool_entry_put: \"%s\" already exists (id=%ld)\n",
219                         e->e_dn, id, 0 );
220 #else
221                 Debug( LDAP_DEBUG_TRACE,
222                         "<= ldbm_tool_entry_put: \"%s\" already exists (id=%ld)\n",
223                         e->e_ndn, id, 0 );
224 #endif
225                 strncpy( text->bv_val, "already exists", text->bv_len );
226                 return NOID;
227         }
228
229         op.o_bd = be;
230         op.o_tmpmemctx = NULL;
231         op.o_tmpmfuncs = &ch_mfuncs;
232
233         rc = index_entry_add( &op, e );
234         if( rc != 0 ) {
235                 strncpy( text->bv_val, "index add failed", text->bv_len );
236                 return NOID;
237         }
238
239         rc = dn2id_add( be, &e->e_nname, e->e_id );
240         if( rc != 0 ) {
241                 strncpy( text->bv_val, "dn2id add failed", text->bv_len );
242                 return NOID;
243         }
244
245         ldbm_datum_init( key );
246         ldbm_datum_init( data );
247
248 #ifndef WORDS_BIGENDIAN
249         id = htonl( e->e_id );
250         key.dptr = (char *) &id;
251 #else
252         key.dptr = (char *) &e->e_id;
253 #endif
254         key.dsize = sizeof(ID);
255
256         data.dptr = entry2str( e, &len );
257         data.dsize = len + 1;
258
259         /* store it */
260         rc = ldbm_cache_store( id2entry, key, data, LDBM_REPLACE );
261
262         if( rc != 0 ) {
263                 (void) dn2id_delete( be, &e->e_nname, e->e_id );
264                 strncpy( text->bv_val, "cache store failed", text->bv_len );
265                 return NOID;
266         }
267
268         return e->e_id;
269 }
270
271 int ldbm_tool_entry_reindex(
272         BackendDB *be,
273         ID id )
274 {
275         int rc;
276         Entry *e;
277         Operation op = {0};
278
279 #ifdef NEW_LOGGING
280         LDAP_LOG( BACK_LDBM, ENTRY, "ldbm_tool_entry_reindex: ID=%ld\n", 
281                 (long)id, 0, 0 );
282 #else
283         Debug( LDAP_DEBUG_ARGS, "=> ldbm_tool_entry_reindex( %ld )\n",
284                 (long) id, 0, 0 );
285 #endif
286
287
288         e = ldbm_tool_entry_get( be, id );
289
290         if( e == NULL ) {
291 #ifdef NEW_LOGGING
292                 LDAP_LOG( BACK_LDBM, INFO,
293                    "ldbm_tool_entry_reindex: could not locate id %ld\n", 
294                    (long)id, 0, 0  );
295 #else
296                 Debug( LDAP_DEBUG_ANY,
297                         "ldbm_tool_entry_reindex:: could not locate id=%ld\n",
298                         (long) id, 0, 0 );
299 #endif
300
301                 return -1;
302         }
303
304         /*
305          * just (re)add them for now
306          * assume that some other routine (not yet implemented)
307          * will zap index databases
308          *
309          */
310
311 #ifdef NEW_LOGGING
312         LDAP_LOG( BACK_LDBM, ENTRY,
313                    "ldbm_tool_entry_reindex: (%s) %ld\n", e->e_dn, id, 0 );
314 #else
315         Debug( LDAP_DEBUG_TRACE, "=> ldbm_tool_entry_reindex( %ld, \"%s\" )\n",
316                 id, e->e_dn, 0 );
317 #endif
318
319         dn2id_add( be, &e->e_nname, e->e_id );
320
321         op.o_bd = be;
322         op.o_tmpmemctx = NULL;
323         op.o_tmpmfuncs = &ch_mfuncs;
324         rc = index_entry_add( &op, e );
325
326         entry_free( e );
327
328         return rc;
329 }
330
331 int ldbm_tool_sync( BackendDB *be )
332 {
333         struct ldbminfo *li = (struct ldbminfo *) be->be_private;
334
335         assert( slapMode & SLAP_TOOL_MODE );
336
337         if ( li->li_nextid != NOID ) {
338                 if ( next_id_write( be, li->li_nextid ) ) {
339                         return( -1 );
340                 }
341         }
342
343         return 0;
344 }