xref: /netbsd-src/external/bsd/openldap/dist/servers/slapd/back-ndb/tools.cpp (revision e670fd5c413e99c2f6a37901bb21c537fcd322d2)
14e6df137Slukem /* tools.cpp - tools for slap tools */
2d11b170bStron /* $OpenLDAP$ */
34e6df137Slukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
44e6df137Slukem  *
5*e670fd5cSchristos  * Copyright 2008-2021 The OpenLDAP Foundation.
64e6df137Slukem  * All rights reserved.
74e6df137Slukem  *
84e6df137Slukem  * Redistribution and use in source and binary forms, with or without
94e6df137Slukem  * modification, are permitted only as authorized by the OpenLDAP
104e6df137Slukem  * Public License.
114e6df137Slukem  *
124e6df137Slukem  * A copy of this license is available in the file LICENSE in the
134e6df137Slukem  * top-level directory of the distribution or, alternatively, at
144e6df137Slukem  * <http://www.OpenLDAP.org/license.html>.
154e6df137Slukem  */
164e6df137Slukem /* ACKNOWLEDGEMENTS:
174e6df137Slukem  * This work was initially developed by Howard Chu for inclusion
184e6df137Slukem  * in OpenLDAP Software. This work was sponsored by MySQL.
194e6df137Slukem  */
204e6df137Slukem 
214e6df137Slukem #include "portable.h"
224e6df137Slukem 
234e6df137Slukem #include <stdio.h>
244e6df137Slukem #include <ac/string.h>
254e6df137Slukem #include <ac/errno.h>
264e6df137Slukem 
274e6df137Slukem #include "lutil.h"
284e6df137Slukem 
294e6df137Slukem #include "back-ndb.h"
304e6df137Slukem 
314e6df137Slukem typedef struct dn_id {
324e6df137Slukem 	ID id;
334e6df137Slukem 	struct berval dn;
344e6df137Slukem } dn_id;
354e6df137Slukem 
364e6df137Slukem #define	HOLE_SIZE	4096
374e6df137Slukem static dn_id hbuf[HOLE_SIZE], *holes = hbuf;
384e6df137Slukem static unsigned nhmax = HOLE_SIZE;
394e6df137Slukem static unsigned nholes;
404e6df137Slukem static Avlnode *myParents;
414e6df137Slukem 
424e6df137Slukem static Ndb *myNdb;
434e6df137Slukem static NdbTransaction *myScanTxn;
444e6df137Slukem static NdbIndexScanOperation *myScanOp;
454e6df137Slukem 
464e6df137Slukem static NdbRecAttr *myScanID, *myScanOC;
474e6df137Slukem static NdbRecAttr *myScanDN[NDB_MAX_RDNS];
484e6df137Slukem static char myDNbuf[2048];
494e6df137Slukem static char myIdbuf[2*sizeof(ID)];
504e6df137Slukem static char myOcbuf[NDB_OC_BUFLEN];
514e6df137Slukem static NdbRdns myRdns;
524e6df137Slukem 
534e6df137Slukem static NdbTransaction *myPutTxn;
544e6df137Slukem static int myPutCnt;
554e6df137Slukem 
564e6df137Slukem static struct berval *myOcList;
574e6df137Slukem static struct berval myDn;
584e6df137Slukem 
594e6df137Slukem extern "C"
ndb_tool_entry_open(BackendDB * be,int mode)604e6df137Slukem int ndb_tool_entry_open(
614e6df137Slukem 	BackendDB *be, int mode )
624e6df137Slukem {
634e6df137Slukem 	struct ndb_info *ni = (struct ndb_info *) be->be_private;
644e6df137Slukem 
654e6df137Slukem 	myNdb = new Ndb( ni->ni_cluster[0], ni->ni_dbname );
664e6df137Slukem 	return myNdb->init(1024);
674e6df137Slukem }
684e6df137Slukem 
694e6df137Slukem extern "C"
ndb_tool_entry_close(BackendDB * be)704e6df137Slukem int ndb_tool_entry_close(
714e6df137Slukem 	BackendDB *be )
724e6df137Slukem {
734e6df137Slukem 	if ( myPutTxn ) {
744e6df137Slukem 		int rc = myPutTxn->execute(NdbTransaction::Commit);
754e6df137Slukem 		if( rc != 0 ) {
764e6df137Slukem 			char text[1024];
774e6df137Slukem 			snprintf( text, sizeof(text),
784e6df137Slukem 					"txn_commit failed: %s (%d)",
794e6df137Slukem 					myPutTxn->getNdbError().message, myPutTxn->getNdbError().code );
804e6df137Slukem 			Debug( LDAP_DEBUG_ANY,
814e6df137Slukem 				"=> " LDAP_XSTRING(ndb_tool_entry_put) ": %s\n",
824e6df137Slukem 				text, 0, 0 );
834e6df137Slukem 		}
844e6df137Slukem 		myPutTxn->close();
854e6df137Slukem 		myPutTxn = NULL;
864e6df137Slukem 	}
874e6df137Slukem 	myPutCnt = 0;
884e6df137Slukem 
894e6df137Slukem 	if( nholes ) {
904e6df137Slukem 		unsigned i;
914e6df137Slukem 		fprintf( stderr, "Error, entries missing!\n");
924e6df137Slukem 		for (i=0; i<nholes; i++) {
934e6df137Slukem 			fprintf(stderr, "  entry %ld: %s\n",
944e6df137Slukem 				holes[i].id, holes[i].dn.bv_val);
954e6df137Slukem 		}
964e6df137Slukem 		return -1;
974e6df137Slukem 	}
984e6df137Slukem 
994e6df137Slukem 	return 0;
1004e6df137Slukem }
1014e6df137Slukem 
1024e6df137Slukem extern "C"
ndb_tool_entry_next(BackendDB * be)1034e6df137Slukem ID ndb_tool_entry_next(
1044e6df137Slukem 	BackendDB *be )
1054e6df137Slukem {
1064e6df137Slukem 	struct ndb_info *ni = (struct ndb_info *) be->be_private;
1074e6df137Slukem 	char *ptr;
1084e6df137Slukem 	ID id;
1094e6df137Slukem 	int i;
1104e6df137Slukem 
1114e6df137Slukem 	assert( be != NULL );
1124e6df137Slukem 	assert( slapMode & SLAP_TOOL_MODE );
1134e6df137Slukem 
1144e6df137Slukem 	if ( myScanOp->nextResult() ) {
1154e6df137Slukem 		myScanOp->close();
1164e6df137Slukem 		myScanOp = NULL;
1174e6df137Slukem 		myScanTxn->close();
1184e6df137Slukem 		myScanTxn = NULL;
1194e6df137Slukem 		return NOID;
1204e6df137Slukem 	}
1214e6df137Slukem 	id = myScanID->u_64_value();
1224e6df137Slukem 
1234e6df137Slukem 	if ( myOcList ) {
1244e6df137Slukem 		ber_bvarray_free( myOcList );
1254e6df137Slukem 	}
1264e6df137Slukem 	myOcList = ndb_ref2oclist( myOcbuf, NULL );
1274e6df137Slukem 	for ( i=0; i<NDB_MAX_RDNS; i++ ) {
1284e6df137Slukem 		if ( myScanDN[i]->isNULL() || !myRdns.nr_buf[i][0] )
1294e6df137Slukem 			break;
1304e6df137Slukem 	}
1314e6df137Slukem 	myRdns.nr_num = i;
1324e6df137Slukem 	ptr = myDNbuf;
1334e6df137Slukem 	for ( --i; i>=0; i-- ) {
1344e6df137Slukem 		char *buf;
1354e6df137Slukem 		int len;
1364e6df137Slukem 		buf = myRdns.nr_buf[i];
1374e6df137Slukem 		len = *buf++;
1384e6df137Slukem 		ptr = lutil_strncopy( ptr, buf, len );
1394e6df137Slukem 		if ( i )
1404e6df137Slukem 			*ptr++ = ',';
1414e6df137Slukem 	}
1424e6df137Slukem 	*ptr = '\0';
1434e6df137Slukem 	myDn.bv_val = myDNbuf;
1444e6df137Slukem 	myDn.bv_len = ptr - myDNbuf;
1454e6df137Slukem 
1464e6df137Slukem 	return id;
1474e6df137Slukem }
1484e6df137Slukem 
1494e6df137Slukem extern "C"
ndb_tool_entry_first(BackendDB * be)1504e6df137Slukem ID ndb_tool_entry_first(
1514e6df137Slukem 	BackendDB *be )
1524e6df137Slukem {
1534e6df137Slukem 	struct ndb_info *ni = (struct ndb_info *) be->be_private;
1544e6df137Slukem 	int i;
1554e6df137Slukem 
1564e6df137Slukem 	myScanTxn = myNdb->startTransaction();
1574e6df137Slukem 	if ( !myScanTxn )
1584e6df137Slukem 		return NOID;
1594e6df137Slukem 
1604e6df137Slukem 	myScanOp = myScanTxn->getNdbIndexScanOperation( "PRIMARY", DN2ID_TABLE );
1614e6df137Slukem 	if ( !myScanOp )
1624e6df137Slukem 		return NOID;
1634e6df137Slukem 
1644e6df137Slukem 	if ( myScanOp->readTuples( NdbOperation::LM_CommittedRead, NdbScanOperation::SF_KeyInfo ))
1654e6df137Slukem 		return NOID;
1664e6df137Slukem 
1674e6df137Slukem 	myScanID = myScanOp->getValue( EID_COLUMN, myIdbuf );
1684e6df137Slukem 	myScanOC = myScanOp->getValue( OCS_COLUMN, myOcbuf );
1694e6df137Slukem 	for ( i=0; i<NDB_MAX_RDNS; i++ ) {
1704e6df137Slukem 		myScanDN[i] = myScanOp->getValue( i+RDN_COLUMN, myRdns.nr_buf[i] );
1714e6df137Slukem 	}
1724e6df137Slukem 	if ( myScanTxn->execute( NdbTransaction::NoCommit, NdbOperation::AbortOnError, 1 ))
1734e6df137Slukem 		return NOID;
1744e6df137Slukem 
1754e6df137Slukem 	return ndb_tool_entry_next( be );
1764e6df137Slukem }
1774e6df137Slukem 
1784e6df137Slukem extern "C"
ndb_tool_dn2id_get(Backend * be,struct berval * dn)1794e6df137Slukem ID ndb_tool_dn2id_get(
1804e6df137Slukem 	Backend *be,
1814e6df137Slukem 	struct berval *dn
1824e6df137Slukem )
1834e6df137Slukem {
1844e6df137Slukem 	struct ndb_info *ni = (struct ndb_info *) be->be_private;
1854e6df137Slukem 	NdbArgs NA;
1864e6df137Slukem 	NdbRdns rdns;
1874e6df137Slukem 	Entry e;
1884e6df137Slukem 	char text[1024];
1894e6df137Slukem 	Operation op = {0};
1904e6df137Slukem 	Opheader ohdr = {0};
1914e6df137Slukem 	int rc;
1924e6df137Slukem 
1934e6df137Slukem 	if ( BER_BVISEMPTY(dn) )
1944e6df137Slukem 		return 0;
1954e6df137Slukem 
1964e6df137Slukem 	NA.ndb = myNdb;
1974e6df137Slukem 	NA.txn = myNdb->startTransaction();
1984e6df137Slukem 	if ( !NA.txn ) {
1994e6df137Slukem 		snprintf( text, sizeof(text),
2004e6df137Slukem 			"startTransaction failed: %s (%d)",
2014e6df137Slukem 			myNdb->getNdbError().message, myNdb->getNdbError().code );
2024e6df137Slukem 		Debug( LDAP_DEBUG_ANY,
2034e6df137Slukem 			"=> " LDAP_XSTRING(ndb_tool_dn2id_get) ": %s\n",
2044e6df137Slukem 			 text, 0, 0 );
2054e6df137Slukem 		return NOID;
2064e6df137Slukem 	}
2074e6df137Slukem 	if ( myOcList ) {
2084e6df137Slukem 		ber_bvarray_free( myOcList );
2094e6df137Slukem 		myOcList = NULL;
2104e6df137Slukem 	}
2114e6df137Slukem 	op.o_hdr = &ohdr;
2124e6df137Slukem 	op.o_bd = be;
2134e6df137Slukem 	op.o_tmpmemctx = NULL;
2144e6df137Slukem 	op.o_tmpmfuncs = &ch_mfuncs;
2154e6df137Slukem 
2164e6df137Slukem 	NA.e = &e;
2174e6df137Slukem 	e.e_name = *dn;
2184e6df137Slukem 	NA.rdns = &rdns;
2194e6df137Slukem 	NA.ocs = NULL;
2204e6df137Slukem 	rc = ndb_entry_get_info( &op, &NA, 0, NULL );
2214e6df137Slukem 	myOcList = NA.ocs;
2224e6df137Slukem 	NA.txn->close();
2234e6df137Slukem 	if ( rc )
2244e6df137Slukem 		return NOID;
2254e6df137Slukem 
2264e6df137Slukem 	myDn = *dn;
2274e6df137Slukem 
2284e6df137Slukem 	return e.e_id;
2294e6df137Slukem }
2304e6df137Slukem 
2314e6df137Slukem extern "C"
ndb_tool_entry_get(BackendDB * be,ID id)2324e6df137Slukem Entry* ndb_tool_entry_get( BackendDB *be, ID id )
2334e6df137Slukem {
2344e6df137Slukem 	NdbArgs NA;
2354e6df137Slukem 	int rc;
2364e6df137Slukem 	char text[1024];
2374e6df137Slukem 	Operation op = {0};
2384e6df137Slukem 	Opheader ohdr = {0};
2394e6df137Slukem 
2404e6df137Slukem 	assert( be != NULL );
2414e6df137Slukem 	assert( slapMode & SLAP_TOOL_MODE );
2424e6df137Slukem 
2434e6df137Slukem 	NA.txn = myNdb->startTransaction();
2444e6df137Slukem 	if ( !NA.txn ) {
2454e6df137Slukem 		snprintf( text, sizeof(text),
2464e6df137Slukem 			"start_transaction failed: %s (%d)",
2474e6df137Slukem 			myNdb->getNdbError().message, myNdb->getNdbError().code );
2484e6df137Slukem 		Debug( LDAP_DEBUG_ANY,
2494e6df137Slukem 			"=> " LDAP_XSTRING(ndb_tool_entry_get) ": %s\n",
2504e6df137Slukem 			 text, 0, 0 );
2514e6df137Slukem 		return NULL;
2524e6df137Slukem 	}
2534e6df137Slukem 
2544e6df137Slukem 	NA.e = entry_alloc();
2554e6df137Slukem 	NA.e->e_id = id;
2564e6df137Slukem 	ber_dupbv( &NA.e->e_name, &myDn );
2574e6df137Slukem 	dnNormalize( 0, NULL, NULL, &NA.e->e_name, &NA.e->e_nname, NULL );
2584e6df137Slukem 
2594e6df137Slukem 	op.o_hdr = &ohdr;
2604e6df137Slukem 	op.o_bd = be;
2614e6df137Slukem 	op.o_tmpmemctx = NULL;
2624e6df137Slukem 	op.o_tmpmfuncs = &ch_mfuncs;
2634e6df137Slukem 
2644e6df137Slukem 	NA.ndb = myNdb;
2654e6df137Slukem 	NA.ocs = myOcList;
2664e6df137Slukem 	rc = ndb_entry_get_data( &op, &NA, 0 );
2674e6df137Slukem 
2684e6df137Slukem 	if ( rc ) {
2694e6df137Slukem 		entry_free( NA.e );
2704e6df137Slukem 		NA.e = NULL;
2714e6df137Slukem 	}
2724e6df137Slukem 	NA.txn->close();
2734e6df137Slukem 
2744e6df137Slukem 	return NA.e;
2754e6df137Slukem }
2764e6df137Slukem 
2774e6df137Slukem static struct berval glueval[] = {
2784e6df137Slukem 	BER_BVC("glue"),
2794e6df137Slukem 	BER_BVNULL
2804e6df137Slukem };
2814e6df137Slukem 
ndb_dnid_cmp(const void * v1,const void * v2)2824e6df137Slukem static int ndb_dnid_cmp( const void *v1, const void *v2 )
2834e6df137Slukem {
2844e6df137Slukem 	struct dn_id *dn1 = (struct dn_id *)v1,
2854e6df137Slukem 		*dn2 = (struct dn_id *)v2;
2864e6df137Slukem 	return ber_bvcmp( &dn1->dn, &dn2->dn );
2874e6df137Slukem }
2884e6df137Slukem 
ndb_tool_next_id(Operation * op,NdbArgs * NA,struct berval * text,int hole)2894e6df137Slukem static int ndb_tool_next_id(
2904e6df137Slukem 	Operation *op,
2914e6df137Slukem 	NdbArgs *NA,
2924e6df137Slukem 	struct berval *text,
2934e6df137Slukem 	int hole )
2944e6df137Slukem {
2954e6df137Slukem 	struct berval ndn = NA->e->e_nname;
2964e6df137Slukem 	int rc;
2974e6df137Slukem 
2984e6df137Slukem 	if (ndn.bv_len == 0) {
2994e6df137Slukem 		NA->e->e_id = 0;
3004e6df137Slukem 		return 0;
3014e6df137Slukem 	}
3024e6df137Slukem 
3034e6df137Slukem 	rc = ndb_entry_get_info( op, NA, 0, NULL );
3044e6df137Slukem 	if ( rc ) {
3054e6df137Slukem 		Attribute *a, tmp = {0};
3064e6df137Slukem 		if ( !be_issuffix( op->o_bd, &ndn ) ) {
3074e6df137Slukem 			struct dn_id *dptr;
3084e6df137Slukem 			struct berval npdn;
3094e6df137Slukem 			dnParent( &ndn, &npdn );
3104e6df137Slukem 			NA->e->e_nname = npdn;
3114e6df137Slukem 			NA->rdns->nr_num--;
3124e6df137Slukem 			rc = ndb_tool_next_id( op, NA, text, 1 );
3134e6df137Slukem 			NA->e->e_nname = ndn;
3144e6df137Slukem 			NA->rdns->nr_num++;
3154e6df137Slukem 			if ( rc ) {
3164e6df137Slukem 				return rc;
3174e6df137Slukem 			}
3184e6df137Slukem 			/* If parent didn't exist, it was created just now
3194e6df137Slukem 			 * and its ID is now in e->e_id.
3204e6df137Slukem 			 */
3214e6df137Slukem 			dptr = (struct dn_id *)ch_malloc( sizeof( struct dn_id ) + npdn.bv_len + 1);
3224e6df137Slukem 			dptr->id = NA->e->e_id;
3234e6df137Slukem 			dptr->dn.bv_val = (char *)(dptr+1);
3244e6df137Slukem 			strcpy(dptr->dn.bv_val, npdn.bv_val );
3254e6df137Slukem 			dptr->dn.bv_len = npdn.bv_len;
3264e6df137Slukem 			if ( avl_insert( &myParents, dptr, ndb_dnid_cmp, avl_dup_error )) {
3274e6df137Slukem 				ch_free( dptr );
3284e6df137Slukem 			}
3294e6df137Slukem 		}
3304e6df137Slukem 		rc = ndb_next_id( op->o_bd, myNdb, &NA->e->e_id );
3314e6df137Slukem 		if ( rc ) {
3324e6df137Slukem 			snprintf( text->bv_val, text->bv_len,
3334e6df137Slukem 				"next_id failed: %s (%d)",
3344e6df137Slukem 				myNdb->getNdbError().message, myNdb->getNdbError().code );
3354e6df137Slukem 			Debug( LDAP_DEBUG_ANY,
3364e6df137Slukem 				"=> ndb_tool_next_id: %s\n", text->bv_val, 0, 0 );
3374e6df137Slukem 			return rc;
3384e6df137Slukem 		}
3394e6df137Slukem 		if ( hole ) {
3404e6df137Slukem 			a = NA->e->e_attrs;
3414e6df137Slukem 			NA->e->e_attrs = &tmp;
3424e6df137Slukem 			tmp.a_desc = slap_schema.si_ad_objectClass;
3434e6df137Slukem 			tmp.a_vals = glueval;
3444e6df137Slukem 			tmp.a_nvals = tmp.a_vals;
3454e6df137Slukem 			tmp.a_numvals = 1;
3464e6df137Slukem 		}
3474e6df137Slukem 		rc = ndb_entry_put_info( op->o_bd, NA, 0 );
3484e6df137Slukem 		if ( hole ) {
3494e6df137Slukem 			NA->e->e_attrs = a;
3504e6df137Slukem 		}
3514e6df137Slukem 		if ( rc ) {
3524e6df137Slukem 			snprintf( text->bv_val, text->bv_len,
3534e6df137Slukem 				"ndb_entry_put_info failed: %s (%d)",
3544e6df137Slukem 				myNdb->getNdbError().message, myNdb->getNdbError().code );
3554e6df137Slukem 		Debug( LDAP_DEBUG_ANY,
3564e6df137Slukem 			"=> ndb_tool_next_id: %s\n", text->bv_val, 0, 0 );
3574e6df137Slukem 		} else if ( hole ) {
3584e6df137Slukem 			if ( nholes == nhmax - 1 ) {
3594e6df137Slukem 				if ( holes == hbuf ) {
3604e6df137Slukem 					holes = (dn_id *)ch_malloc( nhmax * sizeof(dn_id) * 2 );
3614e6df137Slukem 					AC_MEMCPY( holes, hbuf, sizeof(hbuf) );
3624e6df137Slukem 				} else {
3634e6df137Slukem 					holes = (dn_id *)ch_realloc( holes, nhmax * sizeof(dn_id) * 2 );
3644e6df137Slukem 				}
3654e6df137Slukem 				nhmax *= 2;
3664e6df137Slukem 			}
3674e6df137Slukem 			ber_dupbv( &holes[nholes].dn, &ndn );
3684e6df137Slukem 			holes[nholes++].id = NA->e->e_id;
3694e6df137Slukem 		}
3704e6df137Slukem 	} else if ( !hole ) {
3714e6df137Slukem 		unsigned i;
3724e6df137Slukem 
3734e6df137Slukem 		for ( i=0; i<nholes; i++) {
3744e6df137Slukem 			if ( holes[i].id == NA->e->e_id ) {
3754e6df137Slukem 				int j;
3764e6df137Slukem 				free(holes[i].dn.bv_val);
3774e6df137Slukem 				for (j=i;j<nholes;j++) holes[j] = holes[j+1];
3784e6df137Slukem 				holes[j].id = 0;
3794e6df137Slukem 				nholes--;
3804e6df137Slukem 				rc = ndb_entry_put_info( op->o_bd, NA, 1 );
3814e6df137Slukem 				break;
3824e6df137Slukem 			} else if ( holes[i].id > NA->e->e_id ) {
3834e6df137Slukem 				break;
3844e6df137Slukem 			}
3854e6df137Slukem 		}
3864e6df137Slukem 	}
3874e6df137Slukem 	return rc;
3884e6df137Slukem }
3894e6df137Slukem 
3904e6df137Slukem extern "C"
ndb_tool_entry_put(BackendDB * be,Entry * e,struct berval * text)3914e6df137Slukem ID ndb_tool_entry_put(
3924e6df137Slukem 	BackendDB *be,
3934e6df137Slukem 	Entry *e,
3944e6df137Slukem 	struct berval *text )
3954e6df137Slukem {
3964e6df137Slukem 	struct ndb_info *ni = (struct ndb_info *) be->be_private;
3974e6df137Slukem 	struct dn_id dtmp, *dptr;
3984e6df137Slukem 	NdbArgs NA;
3994e6df137Slukem 	NdbRdns rdns;
4004e6df137Slukem 	int rc, slow = 0;
4014e6df137Slukem 	Operation op = {0};
4024e6df137Slukem 	Opheader ohdr = {0};
4034e6df137Slukem 
4044e6df137Slukem 	assert( be != NULL );
4054e6df137Slukem 	assert( slapMode & SLAP_TOOL_MODE );
4064e6df137Slukem 
4074e6df137Slukem 	assert( text != NULL );
4084e6df137Slukem 	assert( text->bv_val != NULL );
4094e6df137Slukem 	assert( text->bv_val[0] == '\0' );	/* overconservative? */
4104e6df137Slukem 
4114e6df137Slukem 	Debug( LDAP_DEBUG_TRACE, "=> " LDAP_XSTRING(ndb_tool_entry_put)
4124e6df137Slukem 		"( %ld, \"%s\" )\n", (long) e->e_id, e->e_dn, 0 );
4134e6df137Slukem 
4144e6df137Slukem 	if ( !be_issuffix( be, &e->e_nname )) {
4154e6df137Slukem 		dnParent( &e->e_nname, &dtmp.dn );
4164e6df137Slukem 		dptr = (struct dn_id *)avl_find( myParents, &dtmp, ndb_dnid_cmp );
4174e6df137Slukem 		if ( !dptr )
4184e6df137Slukem 			slow = 1;
4194e6df137Slukem 	}
4204e6df137Slukem 
4214e6df137Slukem 	rdns.nr_num = 0;
4224e6df137Slukem 
4234e6df137Slukem 	op.o_hdr = &ohdr;
4244e6df137Slukem 	op.o_bd = be;
4254e6df137Slukem 	op.o_tmpmemctx = NULL;
4264e6df137Slukem 	op.o_tmpmfuncs = &ch_mfuncs;
4274e6df137Slukem 
4284e6df137Slukem 	if ( !slow ) {
4294e6df137Slukem 		rc = ndb_next_id( be, myNdb, &e->e_id );
4304e6df137Slukem 		if ( rc ) {
4314e6df137Slukem 			snprintf( text->bv_val, text->bv_len,
4324e6df137Slukem 				"next_id failed: %s (%d)",
4334e6df137Slukem 				myNdb->getNdbError().message, myNdb->getNdbError().code );
4344e6df137Slukem 			Debug( LDAP_DEBUG_ANY,
4354e6df137Slukem 				"=> ndb_tool_next_id: %s\n", text->bv_val, 0, 0 );
4364e6df137Slukem 			return rc;
4374e6df137Slukem 		}
4384e6df137Slukem 	}
4394e6df137Slukem 
4404e6df137Slukem 	if ( !myPutTxn )
4414e6df137Slukem 		myPutTxn = myNdb->startTransaction();
4424e6df137Slukem 	if ( !myPutTxn ) {
4434e6df137Slukem 		snprintf( text->bv_val, text->bv_len,
4444e6df137Slukem 			"start_transaction failed: %s (%d)",
4454e6df137Slukem 			myNdb->getNdbError().message, myNdb->getNdbError().code );
4464e6df137Slukem 		Debug( LDAP_DEBUG_ANY,
4474e6df137Slukem 			"=> " LDAP_XSTRING(ndb_tool_entry_put) ": %s\n",
4484e6df137Slukem 			 text->bv_val, 0, 0 );
4494e6df137Slukem 		return NOID;
4504e6df137Slukem 	}
4514e6df137Slukem 
4524e6df137Slukem 	/* add dn2id indices */
4534e6df137Slukem 	ndb_dn2rdns( &e->e_name, &rdns );
4544e6df137Slukem 	NA.rdns = &rdns;
4554e6df137Slukem 	NA.e = e;
4564e6df137Slukem 	NA.ndb = myNdb;
4574e6df137Slukem 	NA.txn = myPutTxn;
4584e6df137Slukem 	if ( slow ) {
4594e6df137Slukem 		rc = ndb_tool_next_id( &op, &NA, text, 0 );
4604e6df137Slukem 		if( rc != 0 ) {
4614e6df137Slukem 			goto done;
4624e6df137Slukem 		}
4634e6df137Slukem 	} else {
4644e6df137Slukem 		rc = ndb_entry_put_info( be, &NA, 0 );
4654e6df137Slukem 		if ( rc != 0 ) {
4664e6df137Slukem 			goto done;
4674e6df137Slukem 		}
4684e6df137Slukem 	}
4694e6df137Slukem 
4704e6df137Slukem 	/* id2entry index */
4714e6df137Slukem 	rc = ndb_entry_put_data( be, &NA );
4724e6df137Slukem 	if( rc != 0 ) {
4734e6df137Slukem 		snprintf( text->bv_val, text->bv_len,
4744e6df137Slukem 				"ndb_entry_put_data failed: %s (%d)",
4754e6df137Slukem 				myNdb->getNdbError().message, myNdb->getNdbError().code );
4764e6df137Slukem 		Debug( LDAP_DEBUG_ANY,
4774e6df137Slukem 			"=> " LDAP_XSTRING(ndb_tool_entry_put) ": %s\n",
4784e6df137Slukem 			text->bv_val, 0, 0 );
4794e6df137Slukem 		goto done;
4804e6df137Slukem 	}
4814e6df137Slukem 
4824e6df137Slukem done:
4834e6df137Slukem 	if( rc == 0 ) {
4844e6df137Slukem 		myPutCnt++;
4854e6df137Slukem 		if ( !( myPutCnt & 0x0f )) {
4864e6df137Slukem 			rc = myPutTxn->execute(NdbTransaction::Commit);
4874e6df137Slukem 			if( rc != 0 ) {
4884e6df137Slukem 				snprintf( text->bv_val, text->bv_len,
4894e6df137Slukem 					"txn_commit failed: %s (%d)",
4904e6df137Slukem 					myPutTxn->getNdbError().message, myPutTxn->getNdbError().code );
4914e6df137Slukem 				Debug( LDAP_DEBUG_ANY,
4924e6df137Slukem 					"=> " LDAP_XSTRING(ndb_tool_entry_put) ": %s\n",
4934e6df137Slukem 					text->bv_val, 0, 0 );
4944e6df137Slukem 				e->e_id = NOID;
4954e6df137Slukem 			}
4964e6df137Slukem 			myPutTxn->close();
4974e6df137Slukem 			myPutTxn = NULL;
4984e6df137Slukem 		}
4994e6df137Slukem 	} else {
5004e6df137Slukem 		snprintf( text->bv_val, text->bv_len,
5014e6df137Slukem 			"txn_aborted! %s (%d)",
5024e6df137Slukem 			myPutTxn->getNdbError().message, myPutTxn->getNdbError().code );
5034e6df137Slukem 		Debug( LDAP_DEBUG_ANY,
5044e6df137Slukem 			"=> " LDAP_XSTRING(ndb_tool_entry_put) ": %s\n",
5054e6df137Slukem 			text->bv_val, 0, 0 );
5064e6df137Slukem 		e->e_id = NOID;
5074e6df137Slukem 		myPutTxn->close();
5084e6df137Slukem 	}
5094e6df137Slukem 
5104e6df137Slukem 	return e->e_id;
5114e6df137Slukem }
5124e6df137Slukem 
5134e6df137Slukem extern "C"
ndb_tool_entry_reindex(BackendDB * be,ID id,AttributeDescription ** adv)5144e6df137Slukem int ndb_tool_entry_reindex(
5154e6df137Slukem 	BackendDB *be,
5164e6df137Slukem 	ID id,
5174e6df137Slukem 	AttributeDescription **adv )
5184e6df137Slukem {
5194e6df137Slukem 	struct ndb_info *ni = (struct ndb_info *) be->be_private;
5204e6df137Slukem 
5214e6df137Slukem 	Debug( LDAP_DEBUG_ARGS,
5224e6df137Slukem 		"=> " LDAP_XSTRING(ndb_tool_entry_reindex) "( %ld )\n",
5234e6df137Slukem 		(long) id, 0, 0 );
5244e6df137Slukem 
5254e6df137Slukem 	return 0;
5264e6df137Slukem }
5274e6df137Slukem 
5284e6df137Slukem extern "C"
ndb_tool_entry_modify(BackendDB * be,Entry * e,struct berval * text)5294e6df137Slukem ID ndb_tool_entry_modify(
5304e6df137Slukem 	BackendDB *be,
5314e6df137Slukem 	Entry *e,
5324e6df137Slukem 	struct berval *text )
5334e6df137Slukem {
5344e6df137Slukem 	struct ndb_info *ni = (struct ndb_info *) be->be_private;
5354e6df137Slukem 	int rc;
5364e6df137Slukem 
5374e6df137Slukem 	Debug( LDAP_DEBUG_TRACE,
5384e6df137Slukem 		"=> " LDAP_XSTRING(ndb_tool_entry_modify) "( %ld, \"%s\" )\n",
5394e6df137Slukem 		(long) e->e_id, e->e_dn, 0 );
5404e6df137Slukem 
5414e6df137Slukem done:
5424e6df137Slukem 	return e->e_id;
5434e6df137Slukem }
5444e6df137Slukem 
545