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