xref: /netbsd-src/external/bsd/openldap/dist/servers/slapd/back-wt/tools.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
1*549b59edSchristos /*	$NetBSD: tools.c,v 1.2 2021/08/14 16:15:02 christos Exp $	*/
2e670fd5cSchristos 
3e670fd5cSchristos /* OpenLDAP WiredTiger backend */
4e670fd5cSchristos /* $OpenLDAP$ */
5e670fd5cSchristos /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6e670fd5cSchristos  *
7e670fd5cSchristos  * Copyright 2002-2021 The OpenLDAP Foundation.
8e670fd5cSchristos  * All rights reserved.
9e670fd5cSchristos  *
10e670fd5cSchristos  * Redistribution and use in source and binary forms, with or without
11e670fd5cSchristos  * modification, are permitted only as authorized by the OpenLDAP
12e670fd5cSchristos  * Public License.
13e670fd5cSchristos  *
14e670fd5cSchristos  * A copy of this license is available in the file LICENSE in the
15e670fd5cSchristos  * top-level directory of the distribution or, alternatively, at
16e670fd5cSchristos  * <http://www.OpenLDAP.org/license.html>.
17e670fd5cSchristos  */
18e670fd5cSchristos /* ACKNOWLEDGEMENTS:
19e670fd5cSchristos  * This work was developed by HAMANO Tsukasa <hamano@osstech.co.jp>
20e670fd5cSchristos  * based on back-bdb for inclusion in OpenLDAP Software.
21e670fd5cSchristos  * WiredTiger is a product of MongoDB Inc.
22e670fd5cSchristos  */
23e670fd5cSchristos 
24e670fd5cSchristos #include <sys/cdefs.h>
25*549b59edSchristos __RCSID("$NetBSD: tools.c,v 1.2 2021/08/14 16:15:02 christos Exp $");
26e670fd5cSchristos 
27e670fd5cSchristos #include "portable.h"
28e670fd5cSchristos 
29e670fd5cSchristos #include <stdio.h>
30e670fd5cSchristos #include <ac/string.h>
31e670fd5cSchristos #include "back-wt.h"
32e670fd5cSchristos #include "slap-config.h"
33e670fd5cSchristos 
34e670fd5cSchristos typedef struct dn_id {
35e670fd5cSchristos     ID id;
36e670fd5cSchristos     struct berval dn;
37e670fd5cSchristos } dn_id;
38e670fd5cSchristos 
39e670fd5cSchristos #define HOLE_SIZE   4096
40e670fd5cSchristos static dn_id hbuf[HOLE_SIZE], *holes = hbuf;
41e670fd5cSchristos static unsigned nhmax = HOLE_SIZE;
42e670fd5cSchristos static unsigned nholes;
43e670fd5cSchristos 
44e670fd5cSchristos static int index_nattrs;
45e670fd5cSchristos 
46e670fd5cSchristos static struct berval    *tool_base;
47e670fd5cSchristos static int      tool_scope;
48e670fd5cSchristos static Filter       *tool_filter;
49e670fd5cSchristos static Entry        *tool_next_entry;
50e670fd5cSchristos 
51e670fd5cSchristos static wt_ctx *wc;
52e670fd5cSchristos static WT_CURSOR *reader;
53e670fd5cSchristos static WT_ITEM item;
54e670fd5cSchristos 
55e670fd5cSchristos int
wt_tool_entry_open(BackendDB * be,int mode)56e670fd5cSchristos wt_tool_entry_open( BackendDB *be, int mode )
57e670fd5cSchristos {
58e670fd5cSchristos     struct wt_info *wi = (struct wt_info *) be->be_private;
59e670fd5cSchristos 	WT_CONNECTION *conn = wi->wi_conn;
60e670fd5cSchristos 	int rc;
61e670fd5cSchristos 
62e670fd5cSchristos 	wc = wt_ctx_init(wi);
63e670fd5cSchristos     if( !wc ){
64e670fd5cSchristos 		Debug( LDAP_DEBUG_ANY,
65e670fd5cSchristos 			   LDAP_XSTRING(wt_tool_entry_open)
66e670fd5cSchristos 			   ": wt_ctx_get failed\n" );
67e670fd5cSchristos 		return -1;
68e670fd5cSchristos     }
69e670fd5cSchristos 
70e670fd5cSchristos 	rc = wc->session->open_cursor(wc->session, WT_TABLE_ID2ENTRY"(entry)"
71e670fd5cSchristos 								  ,NULL, NULL, &reader);
72e670fd5cSchristos 	if ( rc ) {
73e670fd5cSchristos 		Debug( LDAP_DEBUG_ANY,
74e670fd5cSchristos 			   LDAP_XSTRING(wt_tool_entry_open)
75e670fd5cSchristos 			   ": cursor open failed: %s (%d)\n",
76e670fd5cSchristos 			   wiredtiger_strerror(rc), rc );
77e670fd5cSchristos 		return -1;
78e670fd5cSchristos 	}
79e670fd5cSchristos 
80e670fd5cSchristos 	return 0;
81e670fd5cSchristos }
82e670fd5cSchristos 
83e670fd5cSchristos int
wt_tool_entry_close(BackendDB * be)84e670fd5cSchristos wt_tool_entry_close( BackendDB *be )
85e670fd5cSchristos {
86e670fd5cSchristos 	int rc;
87e670fd5cSchristos 
88e670fd5cSchristos 	if( reader ) {
89e670fd5cSchristos 		reader->close(reader);
90e670fd5cSchristos 		reader = NULL;
91e670fd5cSchristos 	}
92e670fd5cSchristos 
93e670fd5cSchristos 	wt_ctx_free(NULL, wc);
94e670fd5cSchristos 
95e670fd5cSchristos     if( nholes ) {
96e670fd5cSchristos         unsigned i;
97e670fd5cSchristos         fprintf( stderr, "Error, entries missing!\n");
98e670fd5cSchristos         for (i=0; i<nholes; i++) {
99e670fd5cSchristos             fprintf(stderr, "  entry %ld: %s\n",
100e670fd5cSchristos 					holes[i].id, holes[i].dn.bv_val);
101e670fd5cSchristos         }
102e670fd5cSchristos         return -1;
103e670fd5cSchristos     }
104e670fd5cSchristos 
105e670fd5cSchristos 	return 0;
106e670fd5cSchristos }
107e670fd5cSchristos 
108e670fd5cSchristos ID
wt_tool_entry_first_x(BackendDB * be,struct berval * base,int scope,Filter * f)109e670fd5cSchristos wt_tool_entry_first_x( BackendDB *be,
110e670fd5cSchristos 					   struct berval *base,
111e670fd5cSchristos 					   int scope,
112e670fd5cSchristos 					   Filter *f )
113e670fd5cSchristos {
114e670fd5cSchristos 	tool_base = base;
115e670fd5cSchristos 	tool_scope = scope;
116e670fd5cSchristos 	tool_filter = f;
117e670fd5cSchristos 
118e670fd5cSchristos 	return wt_tool_entry_next( be );
119e670fd5cSchristos }
120e670fd5cSchristos 
121e670fd5cSchristos ID
wt_tool_entry_next(BackendDB * be)122e670fd5cSchristos wt_tool_entry_next( BackendDB *be )
123e670fd5cSchristos {
124e670fd5cSchristos 	int rc;
125e670fd5cSchristos 	ID id;
126e670fd5cSchristos 
127e670fd5cSchristos 	rc = reader->next(reader);
128e670fd5cSchristos 	switch( rc ){
129e670fd5cSchristos 	case 0:
130e670fd5cSchristos 		break;
131e670fd5cSchristos 	case WT_NOTFOUND:
132e670fd5cSchristos 		return NOID;
133e670fd5cSchristos 	default:
134e670fd5cSchristos 		Debug( LDAP_DEBUG_ANY,
135e670fd5cSchristos 			   LDAP_XSTRING(wt_tool_entry_next)
136e670fd5cSchristos 			   ": next failed: %s (%d)\n",
137e670fd5cSchristos 			   wiredtiger_strerror(rc), rc );
138e670fd5cSchristos 		return NOID;
139e670fd5cSchristos 	}
140e670fd5cSchristos 
141e670fd5cSchristos 	rc = reader->get_key(reader, &id);
142e670fd5cSchristos 	if( rc ){
143e670fd5cSchristos 		Debug( LDAP_DEBUG_ANY,
144e670fd5cSchristos 			   LDAP_XSTRING(wt_tool_entry_next)
145e670fd5cSchristos 			   ": get_key failed: %s (%d)\n",
146e670fd5cSchristos 			   wiredtiger_strerror(rc), rc );
147e670fd5cSchristos 	}
148e670fd5cSchristos 
149e670fd5cSchristos 	rc = reader->get_value(reader, &item);
150e670fd5cSchristos 	if( rc ){
151e670fd5cSchristos 		Debug( LDAP_DEBUG_ANY,
152e670fd5cSchristos 			   LDAP_XSTRING(wt_tool_entry_next)
153e670fd5cSchristos 			   ": get_value failed: %s (%d)\n",
154e670fd5cSchristos 			   wiredtiger_strerror(rc), rc );
155e670fd5cSchristos 	}
156e670fd5cSchristos 	return id;
157e670fd5cSchristos }
158e670fd5cSchristos 
159e670fd5cSchristos static ber_len_t
entry_getlen(unsigned char ** buf)160e670fd5cSchristos entry_getlen(unsigned char **buf)
161e670fd5cSchristos {
162e670fd5cSchristos     ber_len_t len;
163e670fd5cSchristos     int i;
164e670fd5cSchristos 
165e670fd5cSchristos     len = *(*buf)++;
166e670fd5cSchristos     if (len <= 0x7f)
167e670fd5cSchristos         return len;
168e670fd5cSchristos     i = len & 0x7f;
169e670fd5cSchristos     len = 0;
170e670fd5cSchristos     for (;i > 0; i--) {
171e670fd5cSchristos         len <<= 8;
172e670fd5cSchristos         len |= *(*buf)++;
173e670fd5cSchristos     }
174e670fd5cSchristos     return len;
175e670fd5cSchristos }
176e670fd5cSchristos 
wt_entry_header(WT_ITEM * item,EntryHeader * eh)177e670fd5cSchristos int wt_entry_header(WT_ITEM *item, EntryHeader *eh){
178e670fd5cSchristos 	unsigned char *ptr = (unsigned char *)item->data;
179e670fd5cSchristos 
180e670fd5cSchristos     /* Some overlays can create empty entries
181e670fd5cSchristos      * so don't check for zeros here.
182e670fd5cSchristos      */
183e670fd5cSchristos 	eh->nattrs = entry_getlen(&ptr);
184e670fd5cSchristos     eh->nvals = entry_getlen(&ptr);
185e670fd5cSchristos     eh->data = (char *)ptr;
186e670fd5cSchristos 	return LDAP_SUCCESS;
187e670fd5cSchristos }
188e670fd5cSchristos 
189e670fd5cSchristos Entry *
wt_tool_entry_get(BackendDB * be,ID id)190e670fd5cSchristos wt_tool_entry_get( BackendDB *be, ID id )
191e670fd5cSchristos {
192e670fd5cSchristos 	Entry *e = NULL;
193e670fd5cSchristos 	static EntryHeader eh;
194e670fd5cSchristos 	int rc, eoff;
195e670fd5cSchristos 
196e670fd5cSchristos 	assert( be != NULL );
197e670fd5cSchristos 	assert( slapMode & SLAP_TOOL_MODE );
198e670fd5cSchristos 
199e670fd5cSchristos 	rc = wt_entry_header( &item,  &eh );
200e670fd5cSchristos 	assert( rc == 0 );
201e670fd5cSchristos 	eoff = eh.data - (char *)item.data;
202e670fd5cSchristos 
203e670fd5cSchristos 	eh.bv.bv_len = eh.nvals * sizeof( struct berval ) + item.size;
204e670fd5cSchristos 	eh.bv.bv_val = ch_realloc( eh.bv.bv_val, eh.bv.bv_len );
205e670fd5cSchristos     memset(eh.bv.bv_val, 0xff, eh.bv.bv_len);
206e670fd5cSchristos 	eh.data = eh.bv.bv_val + eh.nvals * sizeof( struct berval );
207e670fd5cSchristos     memcpy(eh.data, item.data, item.size);
208e670fd5cSchristos     eh.data += eoff;
209e670fd5cSchristos 
210e670fd5cSchristos 	rc = entry_decode( &eh, &e );
211e670fd5cSchristos 	assert( rc == 0 );
212e670fd5cSchristos 
213e670fd5cSchristos 	if( rc == LDAP_SUCCESS ) {
214e670fd5cSchristos 		e->e_id = id;
215e670fd5cSchristos 	}
216e670fd5cSchristos 
217e670fd5cSchristos 	return e;
218e670fd5cSchristos }
219e670fd5cSchristos 
wt_tool_next_id(Operation * op,Entry * e,struct berval * text,int hole)220e670fd5cSchristos static int wt_tool_next_id(
221e670fd5cSchristos     Operation *op,
222e670fd5cSchristos     Entry *e,
223e670fd5cSchristos     struct berval *text,
224e670fd5cSchristos     int hole )
225e670fd5cSchristos {
226e670fd5cSchristos     struct wt_info *wi = (struct wt_info *) op->o_bd->be_private;
227e670fd5cSchristos 	struct berval dn = e->e_name;
228e670fd5cSchristos 	struct berval ndn = e->e_nname;
229e670fd5cSchristos 	struct berval pdn, npdn;
230e670fd5cSchristos 	int rc;
231e670fd5cSchristos 	ID id = 0;
232e670fd5cSchristos 	ID pid = 0;
233e670fd5cSchristos 
234e670fd5cSchristos     if(ndn.bv_len == 0){
235e670fd5cSchristos         e->e_id = 0;
236e670fd5cSchristos         return 0;
237e670fd5cSchristos     }
238e670fd5cSchristos 
239e670fd5cSchristos 	rc = wt_dn2id(op, wc->session, &ndn, &id);
240e670fd5cSchristos 	if(rc == 0){
241e670fd5cSchristos 		e->e_id = id;
242e670fd5cSchristos 	}else if( rc == WT_NOTFOUND ){
243e670fd5cSchristos 		if ( !be_issuffix( op->o_bd, &ndn ) ) {
244e670fd5cSchristos 			ID eid = e->e_id;
245e670fd5cSchristos 			dnParent( &dn, &pdn );
246e670fd5cSchristos 			dnParent( &ndn, &npdn );
247e670fd5cSchristos 			e->e_name = pdn;
248e670fd5cSchristos 			e->e_nname = npdn;
249e670fd5cSchristos 			rc = wt_tool_next_id( op, e, text, 1 );
250e670fd5cSchristos 			e->e_name = dn;
251e670fd5cSchristos 			e->e_nname = ndn;
252e670fd5cSchristos 			if ( rc ) {
253e670fd5cSchristos 				return rc;
254e670fd5cSchristos 			}
255e670fd5cSchristos 			/* If parent didn't exist, it was created just now
256e670fd5cSchristos 			 * and its ID is now in e->e_id. Make sure the current
257e670fd5cSchristos 			 * entry gets added under the new parent ID.
258e670fd5cSchristos 			 */
259e670fd5cSchristos 			if ( eid != e->e_id ) {
260e670fd5cSchristos 				pid = e->e_id;
261e670fd5cSchristos 			}
262e670fd5cSchristos 		}else{
263e670fd5cSchristos 			pid = id;
264e670fd5cSchristos 		}
265e670fd5cSchristos 		wt_next_id( op->o_bd, &e->e_id );
266e670fd5cSchristos 		rc = wt_dn2id_add(op, wc->session, pid, e);
267e670fd5cSchristos 		if( rc ){
268e670fd5cSchristos 			snprintf( text->bv_val, text->bv_len,
269e670fd5cSchristos 					  "wt_dn2id_add failed: %s (%d)",
270e670fd5cSchristos 					  wiredtiger_strerror(rc), rc );
271e670fd5cSchristos 			Debug( LDAP_DEBUG_ANY,
272e670fd5cSchristos 				   "=> wt_tool_next_id: %s\n", text->bv_val );
273e670fd5cSchristos 		}
274e670fd5cSchristos 
275e670fd5cSchristos 	}else if ( !hole ) {
276e670fd5cSchristos 		unsigned i, j;
277e670fd5cSchristos 		e->e_id = id;
278e670fd5cSchristos 
279e670fd5cSchristos 		for ( i=0; i<nholes; i++) {
280e670fd5cSchristos 			if ( holes[i].id == e->e_id ) {
281e670fd5cSchristos 				free(holes[i].dn.bv_val);
282e670fd5cSchristos 				for (j=i;j<nholes;j++) holes[j] = holes[j+1];
283e670fd5cSchristos 				holes[j].id = 0;
284e670fd5cSchristos 				nholes--;
285e670fd5cSchristos 				break;
286e670fd5cSchristos 			} else if ( holes[i].id > e->e_id ) {
287e670fd5cSchristos 				break;
288e670fd5cSchristos 			}
289e670fd5cSchristos 		}
290e670fd5cSchristos 	}
291e670fd5cSchristos     return rc;
292e670fd5cSchristos }
293e670fd5cSchristos 
294e670fd5cSchristos static int
wt_tool_index_add(Operation * op,wt_ctx * wc,Entry * e)295e670fd5cSchristos wt_tool_index_add(
296e670fd5cSchristos     Operation *op,
297e670fd5cSchristos     wt_ctx *wc,
298e670fd5cSchristos     Entry *e )
299e670fd5cSchristos {
300e670fd5cSchristos 	return wt_index_entry_add( op, wc, e );
301e670fd5cSchristos }
302e670fd5cSchristos 
303e670fd5cSchristos ID
wt_tool_entry_put(BackendDB * be,Entry * e,struct berval * text)304e670fd5cSchristos wt_tool_entry_put( BackendDB *be, Entry *e, struct berval *text )
305e670fd5cSchristos {
306e670fd5cSchristos     struct wt_info *wi = (struct wt_info *) be->be_private;
307e670fd5cSchristos     int rc;
308e670fd5cSchristos 
309e670fd5cSchristos     Operation op = {0};
310e670fd5cSchristos     Opheader ohdr = {0};
311e670fd5cSchristos 
312e670fd5cSchristos 	assert( slapMode & SLAP_TOOL_MODE );
313e670fd5cSchristos 	assert( text != NULL );
314e670fd5cSchristos 	assert( text->bv_val != NULL );
315e670fd5cSchristos 	assert( text->bv_val[0] == '\0' ); /* overconservative? */
316e670fd5cSchristos 
317e670fd5cSchristos     Debug( LDAP_DEBUG_TRACE,
318e670fd5cSchristos 		   "=> " LDAP_XSTRING(wt_tool_entry_put)
319e670fd5cSchristos 		   ": ( \"%s\" )\n", e->e_dn );
320e670fd5cSchristos 
321e670fd5cSchristos     rc = wc->session->begin_transaction(wc->session, NULL);
322e670fd5cSchristos 	if( rc ){
323e670fd5cSchristos 		Debug( LDAP_DEBUG_ANY,
324e670fd5cSchristos 			   LDAP_XSTRING(wt_dn2id_add)
325e670fd5cSchristos 			   ": begin_transaction failed: %s (%d)\n",
326e670fd5cSchristos 			   wiredtiger_strerror(rc), rc );
327e670fd5cSchristos 		return NOID;
328e670fd5cSchristos 	}
329e670fd5cSchristos 
330e670fd5cSchristos 	op.o_hdr = &ohdr;
331e670fd5cSchristos     op.o_bd = be;
332e670fd5cSchristos     op.o_tmpmemctx = NULL;
333e670fd5cSchristos     op.o_tmpmfuncs = &ch_mfuncs;
334e670fd5cSchristos 
335e670fd5cSchristos     rc = wt_tool_next_id( &op, e, text, 0 );
336e670fd5cSchristos 	if( rc != 0 ) {
337e670fd5cSchristos         snprintf( text->bv_val, text->bv_len,
338e670fd5cSchristos 				  "wt_tool_next_id failed: %s (%d)",
339e670fd5cSchristos 				  wiredtiger_strerror(rc), rc );
340e670fd5cSchristos         Debug( LDAP_DEBUG_ANY,
341e670fd5cSchristos 			   "=> " LDAP_XSTRING(wt_tool_entry_put) ": %s\n",
342e670fd5cSchristos 			   text->bv_val );
343e670fd5cSchristos 		goto done;
344e670fd5cSchristos 	}
345e670fd5cSchristos 
346e670fd5cSchristos 	rc = wt_id2entry_add( &op, wc->session, e );
347e670fd5cSchristos 	if( rc != 0 ) {
348e670fd5cSchristos         snprintf( text->bv_val, text->bv_len,
349e670fd5cSchristos 				  "id2entry_add failed: %s (%d)",
350e670fd5cSchristos 				  wiredtiger_strerror(rc), rc );
351e670fd5cSchristos         Debug( LDAP_DEBUG_ANY,
352e670fd5cSchristos 			   "=> " LDAP_XSTRING(wt_tool_entry_put) ": %s\n",
353e670fd5cSchristos 			   text->bv_val );
354e670fd5cSchristos         goto done;
355e670fd5cSchristos     }
356e670fd5cSchristos 
357e670fd5cSchristos 	rc = wt_tool_index_add( &op, wc, e );
358e670fd5cSchristos     if( rc != 0 ) {
359e670fd5cSchristos         snprintf( text->bv_val, text->bv_len,
360e670fd5cSchristos 				  "index_entry_add failed: %s (%d)",
361e670fd5cSchristos 				  rc == LDAP_OTHER ? "Internal error" :
362e670fd5cSchristos 				  wiredtiger_strerror(rc), rc );
363e670fd5cSchristos         Debug( LDAP_DEBUG_ANY,
364e670fd5cSchristos 			   "=> " LDAP_XSTRING(wt_tool_entry_put) ": %s\n",
365e670fd5cSchristos 			   text->bv_val );
366e670fd5cSchristos         goto done;
367e670fd5cSchristos     }
368e670fd5cSchristos 
369e670fd5cSchristos done:
370e670fd5cSchristos 	if ( rc == 0 ){
371e670fd5cSchristos 		rc = wc->session->commit_transaction(wc->session, NULL);
372e670fd5cSchristos 		if( rc != 0 ) {
373e670fd5cSchristos 			snprintf( text->bv_val, text->bv_len,
374e670fd5cSchristos 					  "txn_commit failed: %s (%d)",
375e670fd5cSchristos 					  wiredtiger_strerror(rc), rc );
376e670fd5cSchristos 			Debug( LDAP_DEBUG_ANY,
377e670fd5cSchristos 				   "=> " LDAP_XSTRING(wt_tool_entry_put) ": %s\n",
378e670fd5cSchristos 				   text->bv_val );
379e670fd5cSchristos             e->e_id = NOID;
380e670fd5cSchristos 		}
381e670fd5cSchristos 	}else{
382e670fd5cSchristos 		rc = wc->session->rollback_transaction(wc->session, NULL);
383e670fd5cSchristos 		snprintf( text->bv_val, text->bv_len,
384e670fd5cSchristos 				  "txn_aborted! %s (%d)",
385e670fd5cSchristos 				  rc == LDAP_OTHER ? "Internal error" :
386e670fd5cSchristos 				  wiredtiger_strerror(rc), rc );
387e670fd5cSchristos         Debug( LDAP_DEBUG_ANY,
388e670fd5cSchristos 			   "=> " LDAP_XSTRING(wt_tool_entry_put) ": %s\n",
389e670fd5cSchristos 			   text->bv_val );
390e670fd5cSchristos         e->e_id = NOID;
391e670fd5cSchristos 	}
392e670fd5cSchristos 
393e670fd5cSchristos 	return e->e_id;
394e670fd5cSchristos }
395e670fd5cSchristos 
wt_tool_entry_reindex(BackendDB * be,ID id,AttributeDescription ** adv)396e670fd5cSchristos int wt_tool_entry_reindex(
397e670fd5cSchristos 	BackendDB *be,
398e670fd5cSchristos 	ID id,
399e670fd5cSchristos 	AttributeDescription **adv )
400e670fd5cSchristos {
401e670fd5cSchristos 	struct wt_info *wi = (struct wt_info *) be->be_private;
402e670fd5cSchristos 	int rc;
403e670fd5cSchristos 	Entry *e;
404e670fd5cSchristos 	Operation op = {0};
405e670fd5cSchristos 	Opheader ohdr = {0};
406e670fd5cSchristos 
407e670fd5cSchristos 	Debug( LDAP_DEBUG_ARGS,
408e670fd5cSchristos 		   "=> " LDAP_XSTRING(wt_tool_entry_reindex) "( %ld )\n",
409e670fd5cSchristos 		   (long) id );
410e670fd5cSchristos 	assert( tool_base == NULL );
411e670fd5cSchristos 	assert( tool_filter == NULL );
412e670fd5cSchristos 
413e670fd5cSchristos 	/* No indexes configured, nothing to do. Could return an
414e670fd5cSchristos      * error here to shortcut things.
415e670fd5cSchristos      */
416e670fd5cSchristos 	if (!wi->wi_attrs) {
417e670fd5cSchristos 		return 0;
418e670fd5cSchristos 	}
419e670fd5cSchristos 
420e670fd5cSchristos 	/* Check for explicit list of attrs to index */
421e670fd5cSchristos 	if ( adv ) {
422e670fd5cSchristos 		int i, j, n;
423e670fd5cSchristos 
424e670fd5cSchristos 		if ( wi->wi_attrs[0]->ai_desc != adv[0] ) {
425e670fd5cSchristos 			/* count */
426e670fd5cSchristos 			for ( n = 0; adv[n]; n++ ) ;
427e670fd5cSchristos 
428e670fd5cSchristos 			/* insertion sort */
429e670fd5cSchristos 			for ( i = 0; i < n; i++ ) {
430e670fd5cSchristos 				AttributeDescription *ad = adv[i];
431e670fd5cSchristos 				for ( j = i-1; j>=0; j--) {
432e670fd5cSchristos 					if ( SLAP_PTRCMP( adv[j], ad ) <= 0 ) break;
433e670fd5cSchristos 					adv[j+1] = adv[j];
434e670fd5cSchristos 				}
435e670fd5cSchristos 				adv[j+1] = ad;
436e670fd5cSchristos 			}
437e670fd5cSchristos 		}
438e670fd5cSchristos 
439e670fd5cSchristos 		for ( i = 0; adv[i]; i++ ) {
440e670fd5cSchristos 			if ( wi->wi_attrs[i]->ai_desc != adv[i] ) {
441e670fd5cSchristos 				for ( j = i+1; j < wi->wi_nattrs; j++ ) {
442e670fd5cSchristos 					if ( wi->wi_attrs[j]->ai_desc == adv[i] ) {
443e670fd5cSchristos 						AttrInfo *ai = wi->wi_attrs[i];
444e670fd5cSchristos 						wi->wi_attrs[i] = wi->wi_attrs[j];
445e670fd5cSchristos 						wi->wi_attrs[j] = ai;
446e670fd5cSchristos 						break;
447e670fd5cSchristos 					}
448e670fd5cSchristos 				}
449e670fd5cSchristos 				if ( j == wi->wi_nattrs ) {
450e670fd5cSchristos 					Debug( LDAP_DEBUG_ANY,
451e670fd5cSchristos 						   LDAP_XSTRING(wt_tool_entry_reindex)
452e670fd5cSchristos 						   ": no index configured for %s\n",
453e670fd5cSchristos 						   adv[i]->ad_cname.bv_val );
454e670fd5cSchristos 					return -1;
455e670fd5cSchristos 				}
456e670fd5cSchristos 			}
457e670fd5cSchristos 		}
458e670fd5cSchristos 		wi->wi_nattrs = i;
459e670fd5cSchristos 	}
460e670fd5cSchristos 
461e670fd5cSchristos 	e = wt_tool_entry_get( be, id );
462e670fd5cSchristos 
463e670fd5cSchristos 	if( e == NULL ) {
464e670fd5cSchristos 		Debug( LDAP_DEBUG_ANY,
465e670fd5cSchristos 			   LDAP_XSTRING(wt_tool_entry_reindex)
466e670fd5cSchristos 			   ": could not locate id=%ld\n",
467e670fd5cSchristos 			   (long) id );
468e670fd5cSchristos 		return -1;
469e670fd5cSchristos 	}
470e670fd5cSchristos 
471e670fd5cSchristos 	op.o_hdr = &ohdr;
472e670fd5cSchristos 	op.o_bd = be;
473e670fd5cSchristos 	op.o_tmpmemctx = NULL;
474e670fd5cSchristos 	op.o_tmpmfuncs = &ch_mfuncs;
475e670fd5cSchristos 
476e670fd5cSchristos 	rc = wc->session->begin_transaction(wc->session, NULL);
477e670fd5cSchristos 	if( rc ){
478e670fd5cSchristos 		Debug( LDAP_DEBUG_ANY,
479e670fd5cSchristos 			   LDAP_XSTRING(wt_dn2id_add)
480e670fd5cSchristos 			   ": begin_transaction failed: %s (%d)\n",
481e670fd5cSchristos 			   wiredtiger_strerror(rc), rc );
482e670fd5cSchristos 		goto done;
483e670fd5cSchristos 	}
484e670fd5cSchristos 	Debug( LDAP_DEBUG_TRACE,
485e670fd5cSchristos 		   "=> " LDAP_XSTRING(wt_tool_entry_reindex) "( %ld, \"%s\" )\n",
486e670fd5cSchristos 		   (long) id, e->e_dn );
487e670fd5cSchristos 
488e670fd5cSchristos 	rc = wt_tool_index_add( &op, wc, e );
489e670fd5cSchristos 
490e670fd5cSchristos done:
491e670fd5cSchristos 	if ( rc == 0 ){
492e670fd5cSchristos 		rc = wc->session->commit_transaction(wc->session, NULL);
493e670fd5cSchristos 		if( rc ) {
494e670fd5cSchristos 			Debug( LDAP_DEBUG_ANY,
495e670fd5cSchristos 				   "=> " LDAP_XSTRING(wt_tool_entry_reindex)
496e670fd5cSchristos 				   "commit_transaction failed: %s (%d)\n",
497e670fd5cSchristos 				   wiredtiger_strerror(rc), rc );
498e670fd5cSchristos 		}
499e670fd5cSchristos 	}else{
500e670fd5cSchristos 		rc = wc->session->rollback_transaction(wc->session, NULL);
501e670fd5cSchristos 		Debug( LDAP_DEBUG_ANY,
502e670fd5cSchristos 			   "=> " LDAP_XSTRING(wt_tool_entry_reindex)
503e670fd5cSchristos 			   ": rollback transaction %s (%d)\n",
504e670fd5cSchristos 			   wiredtiger_strerror(rc), rc );
505e670fd5cSchristos 	}
506e670fd5cSchristos 
507e670fd5cSchristos 	wt_entry_release( &op, e, 0 );
508e670fd5cSchristos 
509e670fd5cSchristos 	return rc;
510e670fd5cSchristos }
511e670fd5cSchristos 
512e670fd5cSchristos /*
513e670fd5cSchristos  * Local variables:
514e670fd5cSchristos  * indent-tabs-mode: t
515e670fd5cSchristos  * tab-width: 4
516e670fd5cSchristos  * c-basic-offset: 4
517e670fd5cSchristos  * End:
518e670fd5cSchristos  */
519