Addition of a new Concurrency Test fro testing slapd performance and

correctness of locking schemas in backends.
In back-bdb2 open NEXTID during startup and close at shutdown.
This commit is contained in:
Kurt Spanier 1999-02-15 10:49:20 +00:00
parent a71f328831
commit 39f0066db4
18 changed files with 1103 additions and 57 deletions

View File

@ -32,7 +32,7 @@ Modify -lldap to be session-level multithreaded
Port slapd (incl back-ldbm & tools) to NT
MajorLDAP - Design and implement an LDAP-enabled mailing list manager
Slapd-DB2 - Design and implement a backend to take full advantage
of the latest DB2 features.
of the latest DB2 features <ksp@openldap.org>.
Medium projects

View File

@ -90,7 +90,6 @@ struct dbcache {
int dbc_refcnt;
int dbc_maxids;
int dbc_maxindirect;
time_t dbc_lastref;
long dbc_blksize;
char *dbc_name;
LDBM dbc_db;
@ -146,6 +145,11 @@ typedef struct _bdb2_txn_head {
#define BDB2_DB_ID2CHILDREN_FILE 3
#define BDB2_DB_OC_IDX_FILE 4
/* a file pointer for the NEXTID file
(must be opened appropriately at backend
entry and closed on leave */
FILE *nextidFP;
/* is the default attribute index set to non-none */
int withDefIDX;
#define BDB2_WITH_DEF_IDX 1
@ -187,9 +191,6 @@ struct ldbminfo {
Avlnode *li_attrs;
int li_dbcachesize;
int li_dbcachewsync;
struct dbcache li_dbcache[MAXDBCACHE];
ldap_pvt_thread_mutex_t li_dbcache_mutex;
ldap_pvt_thread_cond_t li_dbcache_cv;
/* a list of all files of the database */
BDB2_TXN_HEAD li_txn_head;

View File

@ -128,26 +128,26 @@ bdb2i_index_read(
realval = val;
tmpval = NULL;
if ( prefix != UNKNOWN_PREFIX ) {
unsigned int len = strlen( val );
unsigned int len = strlen( val );
if ( (len + 2) < sizeof(buf) ) {
if ( (len + 2) < sizeof(buf) ) {
realval = buf;
} else {
/* value + prefix + null */
tmpval = (char *) ch_malloc( len + 2 );
realval = tmpval;
}
realval[0] = prefix;
strcpy( &realval[1], val );
realval[0] = prefix;
strcpy( &realval[1], val );
}
key.dptr = realval;
key.dsize = strlen( realval ) + 1;
idl = bdb2i_idl_fetch( be, db, key );
if ( tmpval != NULL ) {
free( tmpval );
}
if ( tmpval != NULL ) {
free( tmpval );
}
bdb2i_cache_close( be, db );
@ -168,7 +168,6 @@ add_value(
{
int rc;
Datum key;
ID_BLOCK *idl = NULL;
char *tmpval = NULL;
char *realval = val;
char buf[BUFSIZ];
@ -180,17 +179,17 @@ add_value(
Debug( LDAP_DEBUG_TRACE, "=> add_value( \"%c%s\" )\n", prefix, val, 0 );
if ( prefix != UNKNOWN_PREFIX ) {
unsigned int len = strlen( val );
unsigned int len = strlen( val );
if ( (len + 2) < sizeof(buf) ) {
if ( (len + 2) < sizeof(buf) ) {
realval = buf;
} else {
/* value + prefix + null */
tmpval = (char *) ch_malloc( len + 2 );
realval = tmpval;
}
realval[0] = prefix;
strcpy( &realval[1], val );
realval[0] = prefix;
strcpy( &realval[1], val );
}
key.dptr = realval;
@ -202,10 +201,6 @@ add_value(
free( tmpval );
}
if( idl != NULL ) {
bdb2i_idl_free( idl );
}
ldap_pvt_thread_yield();
/* Debug( LDAP_DEBUG_TRACE, "<= add_value %d\n", rc, 0, 0 ); */

View File

@ -177,8 +177,6 @@ bdb2i_back_db_init_internal(
ldap_pvt_thread_mutex_init( &li->li_add_mutex );
ldap_pvt_thread_mutex_init( &li->li_cache.c_mutex );
ldap_pvt_thread_mutex_init( &li->li_nextid_mutex );
ldap_pvt_thread_mutex_init( &li->li_dbcache_mutex );
ldap_pvt_thread_cond_init( &li->li_dbcache_cv );
/* initialize the TP file head */
if ( bdb2i_txn_head_init( &li->li_txn_head ) != 0 )

View File

@ -13,32 +13,29 @@
#include "slap.h"
#include "back-bdb2.h"
/* XXX the separate handling of the NEXTID file is in contrast to TP */
/* the NEXTID file is beeing opened during database start-up */
static ID
next_id_read( BackendDB *be )
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
BDB2_TXN_HEAD *head = &li->li_txn_head;
FILE* fp = head->nextidFP;
ID id;
char buf[20];
char* file = li->li_nextid_file;
FILE* fp;
if ( (fp = fopen( file, "r" )) == NULL ) {
Debug( LDAP_DEBUG_ANY,
"next_id_read: could not open \"%s\"\n",
file, 0, 0 );
return NOID;
}
/* set the file pointer to the beginnig of the file */
rewind( fp );
/* read the nextid */
if ( fgets( buf, sizeof(buf), fp ) == NULL ) {
Debug( LDAP_DEBUG_ANY,
"next_id_read: could not fgets nextid from \"%s\"\n",
file, 0, 0 );
fclose( fp );
li->li_nextid_file, 0, 0 );
return NOID;
}
id = atol( buf );
fclose( fp );
if(id < 1) {
Debug( LDAP_DEBUG_ANY,
@ -50,31 +47,30 @@ next_id_read( BackendDB *be )
return id;
}
/* XXX the separate handling of the NEXTID file is in contrast to TP */
/* the NEXTID file is beeing opened during database start-up */
static int
next_id_write( BackendDB *be, ID id )
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
BDB2_TXN_HEAD *head = &li->li_txn_head;
FILE* fp = head->nextidFP;
char buf[20];
char* file = li->li_nextid_file;
FILE* fp;
int rc;
int rc = 0;
if ( (fp = fopen( file, "w" )) == NULL ) {
Debug( LDAP_DEBUG_ANY, "next_id_write(%ld): could not open \"%s\"\n",
id, file, 0 );
return -1;
}
rc = 0;
/* set the file pointer to the beginnig of the file */
rewind( fp );
/* write the nextid */
if ( fprintf( fp, "%ld\n", id ) == EOF ) {
Debug( LDAP_DEBUG_ANY, "next_id_write(%ld): cannot fprintf\n",
id, 0, 0 );
rc = -1;
}
if( fclose( fp ) != 0 ) {
Debug( LDAP_DEBUG_ANY, "next_id_write %ld: cannot fclose\n",
/* if forced flushing of files is in effect, do so */
if( li->li_dbcachewsync && ( fflush( fp ) != 0 )) {
Debug( LDAP_DEBUG_ANY, "next_id_write %ld: cannot fflush\n",
id, 0, 0 );
rc = -1;
}

View File

@ -19,7 +19,7 @@ static void remove_old_locks( char *home );
static void
bdb2i_db_errcall( char *prefix, char *message )
{
Debug( LDAP_DEBUG_ANY, "dbd2_db_errcall(): %s %s", prefix, message, 0 );
Debug( LDAP_DEBUG_ANY, "bdb2_db_errcall(): %s %s", prefix, message, 0 );
}

View File

@ -39,16 +39,10 @@ bdb2i_txn_head_init( BDB2_TXN_HEAD *head )
static void
bdb2i_init_db_file_cache( struct ldbminfo *li, BDB2_TXN_FILES *fileinfo )
{
time_t curtime;
struct stat st;
char buf[MAXPATHLEN];
ldap_pvt_thread_mutex_lock( &currenttime_mutex );
curtime = currenttime;
ldap_pvt_thread_mutex_unlock( &currenttime_mutex );
fileinfo->dbc_refcnt = 1;
fileinfo->dbc_lastref = curtime;
sprintf( buf, "%s%s%s", li->li_directory, DEFAULT_DIRSEP,
fileinfo->dbc_name );
@ -66,6 +60,14 @@ bdb2i_init_db_file_cache( struct ldbminfo *li, BDB2_TXN_FILES *fileinfo )
}
/* create a DB file cache entry for a specified index attribute
(if not already done); the function is called during config
file read for all index'ed attributes; if "default" index with
a non-none selection is given, this is remembered for run-time
extension of the list of index files; the function is also
called before add or modify operations to check for putative
new "default" index files; at that time, files are also opened
*/
void
bdb2i_txn_attr_config(
struct ldbminfo *li,
@ -158,11 +160,45 @@ bdb2i_txn_attr_config(
}
/* open the NEXTID file for read/write; if it does not exist,
create it (access to the file must be preceeded by a rewind)
*/
static int
bdb2i_open_nextid( struct ldbminfo *li )
{
BDB2_TXN_HEAD *head = &li->li_txn_head;
FILE *fp = NULL;
char *file = li->li_nextid_file;
/* try to open the file for read and write */
if ((( fp = fopen( file, "r+" )) == NULL ) &&
(( fp = fopen( file, "w+" )) == NULL )) {
Debug( LDAP_DEBUG_ANY,
"bdb2i_open_nextid: could not open \"%s\"\n",
file, 0, 0 );
return( -1 );
}
/* the file is open for read/write */
head->nextidFP = fp;
return( 0 );
}
/* open all DB during startup of the backend (necessary due to TP)
additional files may be opened during slapd life-time due to
default indexes (must be configured in slapd.conf;
see bdb2i_txn_attr_config)
*/
int
bdb2i_txn_open_files( struct ldbminfo *li )
{
BDB2_TXN_HEAD *head = &li->li_txn_head;
BDB2_TXN_FILES *dbFile;
int rc;
for ( dbFile = head->dbFiles; dbFile; dbFile = dbFile->next ) {
char fileName[MAXPATHLEN];
@ -179,7 +215,7 @@ bdb2i_txn_open_files( struct ldbminfo *li )
Debug( LDAP_DEBUG_ANY,
"bdb2i_txn_open_files(): couldn't open file \"%s\" -- FATAL.\n",
dbFile->dbc_name, 0, 0 );
return( 1 );
return( -1 );
}
@ -191,10 +227,22 @@ bdb2i_txn_open_files( struct ldbminfo *li )
}
return 0;
rc = bdb2i_open_nextid( li );
return rc;
}
/* close the NEXTID file */
static void
bdb2i_close_nextid( BDB2_TXN_HEAD *head )
{
fclose( head->nextidFP );
head->nextidFP = NULL;
}
/* close all DB files during shutdown of the backend */
void
bdb2i_txn_close_files( BackendDB *be )
{
@ -207,9 +255,15 @@ bdb2i_txn_close_files( BackendDB *be )
ldbm_close( dbFile->dbc_db );
}
bdb2i_close_nextid( head );
}
/* get the db_cache structure associated with a specified
DB file (replaces the on-the-fly opening of files in cache_open()
*/
BDB2_TXN_FILES *
bdb2i_get_db_file_cache( struct ldbminfo *li, char *name )
{

View File

@ -4,7 +4,32 @@
## tests Makefile.in for OpenLDAP
BUILD_BDB2 = @BUILD_BDB2@
bdb2-local: FORCE
SRC = slapd-tester.c slapd-search.c
PROGRAMS = slapd-tester slapd-search slapd-read slapd-addel
LDAP_INCDIR= ../include
LDAP_LIBDIR= ../libraries
XLIBS = -lldap_r -llber -llutil
build-tools: FORCE
$(MAKE) $(MFLAGS) load-tools
load-tools: $(PROGRAMS)
slapd-tester: slapd-tester.o
$(LTLINK) -o $@ slapd-tester.o
slapd-search: slapd-search.o $(LDAP_LIBLBER_DEPEND) $(LDAP_LIBLDAP_DEPEND)
$(LTLINK) -o $@ slapd-search.o $(LDAP_LIBPATH) $(XLIBS)
slapd-read: slapd-read.o $(LDAP_LIBLBER_DEPEND) $(LDAP_LIBLDAP_DEPEND)
$(LTLINK) -o $@ slapd-read.o $(LDAP_LIBPATH) $(XLIBS)
slapd-addel: slapd-addel.o $(LDAP_LIBLBER_DEPEND) $(LDAP_LIBLDAP_DEPEND)
$(LTLINK) -o $@ slapd-addel.o $(LDAP_LIBPATH) $(XLIBS)
bdb2-local: build-tools FORCE
@if test "$(BUILD_BDB2)" = "yes" ; then \
$(LN_S) $(srcdir)/data . ; \
echo "Initiating LDAP tests..." ; \
@ -14,7 +39,7 @@ bdb2-local: FORCE
echo "run configure with --enable-bdb2" ; \
fi
all-local: FORCE
all-local: build-tools FORCE
@-$(LN_S) $(srcdir)/data .
@echo "Initiating LDAP tests..."; \
$(MKDIR) test-db test-repl ; \
@ -22,8 +47,12 @@ all-local: FORCE
clean-local: FORCE
$(RM) test-db/[!C]* test-repl/[!C]* *core
$(RM) $(PROGRAMS)
$(RM) *.o
veryclean-local: FORCE
@-$(RM) data
$(RM) -r test-db test-repl
$(RM) $(PROGRAMS)
$(RM) *.o

26
tests/data/do_add.1 Normal file
View File

@ -0,0 +1,26 @@
cn=James A Jones 2, ou=Alumni Association, ou=People, o=University of Michigan, c=US
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: newPilotPerson
objectclass: umichPerson
cn: James A Jones 2
cn: James Jones
cn: Jim Jones
sn: Jones
postaladdress: Alumni Association $ 111 Maple St $ Ann Arbor, MI 48109
seealso: cn=All Staff, ou=Groups, o=University of Michigan, c=US
uid: jaj
krbname: jaj@umich.edu
userpassword: jaj
nobatchupdates: TRUE
onvacation: FALSE
homepostaladdress: 3882 Beverly Rd. $ Ann Arbor, MI 48105
homephone: +1 313 555 4772
multilinedescription: Outstanding
title: Mad Cow Researcher, UM Alumni Association
pager: +1 313 555 3923
mail: jaj@mail.alumni.umich.edu
facsimiletelephonenumber: +1 313 555 4332
telephonenumber: +1 313 555 0895

5
tests/data/do_read.0 Normal file
View File

@ -0,0 +1,5 @@
cn=Barbara Jensen, ou=Information Technology Division, ou=People, o=University of Michigan, c=US
cn=ITD Staff,ou=Groups,o=University of Michigan,c=US
ou=Groups, o=University of Michigan, c=US
ou=Alumni Association, ou=People, o=University of Michigan, c=US
cn=James A Jones 1, ou=Alumni Association, ou=People, o=University of Michigan, c=US

5
tests/data/do_search.0 Normal file
View File

@ -0,0 +1,5 @@
cn=Barbara Jensen
cn=Bjorn Jensen
cn=James A Jones 1
cn=Bjorn Jensen
cn=Alumni Assoc Staff

View File

@ -13,6 +13,7 @@ argsfile ./test-db/slapd.args
backend bdb2
home ./test-db
mpoolsize 2100000
database bdb2
cachesize 4

View File

@ -31,6 +31,7 @@ SLURPD=../servers/slurpd/slurpd
LDAPSEARCH=../clients/tools/ldapsearch
LDAPMODIFY=../clients/tools/ldapmodify
LDAPADD=../clients/tools/ldapadd
SLAPDTESTER=slapd-tester
LVL=5
PORT=9009
SLAVEPORT=9010

View File

@ -0,0 +1,68 @@
#!/bin/sh
if [ $# -eq 0 ]; then
SRCDIR="."
else
SRCDIR=$1; shift
fi
if [ $# -eq 1 ]; then
BDB2=$1; shift
fi
echo "running defines.sh $SRCDIR $BDB2"
. $SRCDIR/scripts/defines.sh $SRCDIR $BDB2
echo "Datadir is $DATADIR"
echo "Cleaning up in $DBDIR..."
rm -f $DBDIR/[!C]*
echo "Running ldif2ldbm to build slapd database..."
$LDIF2LDBM -f $CONF -i $LDIF -e ../servers/slapd/tools
RC=$?
if [ $RC != 0 ]; then
echo "ldif2ldbm failed!"
exit $RC
fi
echo "Starting slapd on TCP/IP port $PORT..."
$SLAPD -f $CONF -p $PORT -d $LVL $TIMING > $MASTERLOG 2>&1 &
PID=$!
echo "Waiting 5 seconds for slapd to start..."
sleep 5
echo "Using tester for concurrent server access..."
$SLAPDTESTER -b "$BASEDN" -d "$DATADIR" -h localhost -p $PORT -D "$MANAGERDN" -w $PASSWD -l 100
RC=$?
if [ $RC != 0 ]; then
echo "slapd-tester failed!"
exit $RC
fi
echo "Using ldapsearch to retrieve all the entries..."
$LDAPSEARCH -L -S "" -b "$BASEDN" -h localhost -p $PORT \
'objectClass=*' > $SEARCHOUT 2>&1
RC=$?
kill -HUP $PID
if [ $RC != 0 ]; then
echo "ldapsearch failed!"
exit $RC
fi
echo "Comparing retrieved entries to LDIF file used to create database"
cmp $SEARCHOUT $LDIF
if [ $? != 0 ]; then
echo "comparison failed - database was not created correctly"
exit 1
fi
echo ">>>>> Test succeeded"
exit 0

276
tests/slapd-addel.c Normal file
View File

@ -0,0 +1,276 @@
#include "portable.h"
#include <stdio.h>
#include <ac/string.h>
#include <ac/ctype.h>
#include <ac/socket.h>
#include <ac/unistd.h>
#include <ac/wait.h>
#include <sys/param.h>
#include "lber.h"
#include "ldap.h"
#define LOOPS 100
static char *
get_add_entry( char *filename, LDAPMod ***mods );
static void
do_addel( char *host, int port, char *manager, char *passwd,
char *dn, LDAPMod **attrs, int maxloop );
static void
usage( char *name )
{
fprintf( stderr, "usage: %s [-h <host>] -p port -D <managerDN> -w <passwd> -f <addfile> [-l <loops>]\n",
name );
exit( 1 );
}
int
main( int argc, char **argv )
{
int i, j;
char *host = "localhost";
int port = -1;
char *manager = NULL;
char *passwd = NULL;
char *filename = NULL;
char *entry = NULL;
int loops = LOOPS;
LDAPMod **attrs = NULL;
while ( (i = getopt( argc, argv, "h:p:D:w:f:l:" )) != EOF ) {
switch( i ) {
case 'h': /* the servers host */
host = strdup( optarg );
break;
case 'p': /* the servers port */
port = atoi( optarg );
break;
case 'D': /* the servers manager */
manager = strdup( optarg );
break;
case 'w': /* the server managers password */
passwd = strdup( optarg );
break;
case 'f': /* file with entry search request */
filename = strdup( optarg );
break;
case 'l': /* the number of loops */
loops = atoi( optarg );
break;
default:
usage( argv[0] );
break;
}
}
if (( filename == NULL ) || ( port == -1 ) ||
( manager == NULL ) || ( passwd == NULL ))
usage( argv[0] );
entry = get_add_entry( filename, &attrs );
if (( entry == NULL ) || ( *entry == '\0' )) {
fprintf( stderr, "%s: invalid entry DN in file \"%s\".\n",
argv[0], filename );
exit( 1 );
}
if (( attrs == NULL ) || ( *attrs == '\0' )) {
fprintf( stderr, "%s: invalid attrs in file \"%s\".\n",
argv[0], filename );
exit( 1 );
}
do_addel( host, port, manager, passwd, entry, attrs, loops );
exit( 0 );
}
#define safe_realloc( ptr, size ) ( ptr == NULL ? malloc( size ) : \
realloc( ptr, size ))
static void
addmodifyop( LDAPMod ***pmodsp, int modop, char *attr, char *value, int vlen )
{
LDAPMod **pmods;
int i, j;
struct berval *bvp;
pmods = *pmodsp;
modop |= LDAP_MOD_BVALUES;
i = 0;
if ( pmods != NULL ) {
for ( ; pmods[ i ] != NULL; ++i ) {
if ( strcasecmp( pmods[ i ]->mod_type, attr ) == 0 &&
pmods[ i ]->mod_op == modop ) {
break;
}
}
}
if ( pmods == NULL || pmods[ i ] == NULL ) {
if (( pmods = (LDAPMod **)safe_realloc( pmods, (i + 2) *
sizeof( LDAPMod * ))) == NULL ) {
perror( "safe_realloc" );
exit( 1 );
}
*pmodsp = pmods;
pmods[ i + 1 ] = NULL;
if (( pmods[ i ] = (LDAPMod *)calloc( 1, sizeof( LDAPMod )))
== NULL ) {
perror( "calloc" );
exit( 1 );
}
pmods[ i ]->mod_op = modop;
if (( pmods[ i ]->mod_type = strdup( attr )) == NULL ) {
perror( "strdup" );
exit( 1 );
}
}
if ( value != NULL ) {
j = 0;
if ( pmods[ i ]->mod_bvalues != NULL ) {
for ( ; pmods[ i ]->mod_bvalues[ j ] != NULL; ++j ) {
;
}
}
if (( pmods[ i ]->mod_bvalues =
(struct berval **)safe_realloc( pmods[ i ]->mod_bvalues,
(j + 2) * sizeof( struct berval * ))) == NULL ) {
perror( "safe_realloc" );
exit( 1 );
}
pmods[ i ]->mod_bvalues[ j + 1 ] = NULL;
if (( bvp = (struct berval *)malloc( sizeof( struct berval )))
== NULL ) {
perror( "malloc" );
exit( 1 );
}
pmods[ i ]->mod_bvalues[ j ] = bvp;
bvp->bv_len = vlen;
if (( bvp->bv_val = (char *)malloc( vlen + 1 )) == NULL ) {
perror( "malloc" );
exit( 1 );
}
SAFEMEMCPY( bvp->bv_val, value, vlen );
bvp->bv_val[ vlen ] = '\0';
}
}
static char *
get_add_entry( char *filename, LDAPMod ***mods )
{
FILE *fp;
char *entry = NULL;
if ( fp = fopen( filename, "r" )) {
char line[BUFSIZ];
if ( fgets( line, BUFSIZ, fp )) {
char *nl;
if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
*nl = '\0';
entry = strdup( line );
}
while ( fgets( line, BUFSIZ, fp )) {
char *nl;
char *value;
if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
*nl = '\0';
if ( *line == '\0' ) break;
if ( !( value = strchr( line, ':' ))) break;
*value++ = '\0';
while ( *value && isblank( *value )) value++;
addmodifyop( mods, LDAP_MOD_ADD, line, value, strlen( value ));
}
fclose( fp );
}
return( entry );
}
static void
do_addel(
char *host,
int port,
char *manager,
char *passwd,
char *entry,
LDAPMod **attrs,
int maxloop
)
{
LDAP *ld;
int i;
if (( ld = ldap_init( host, port )) == NULL ) {
perror( "ldap_init" );
exit( 1 );
}
if ( ldap_bind_s( ld, manager, passwd, LDAP_AUTH_SIMPLE )
!= LDAP_SUCCESS ) {
ldap_perror( ld, "ldap_bind" );
exit( 1 );
}
fprintf( stderr, "Add/Delete(%d): entry=\"%s\".\n", maxloop, entry );
for ( i = 0; i < maxloop; i++ ) {
/* add the entry */
if ( ldap_add_s( ld, entry, attrs ) != LDAP_SUCCESS ) {
ldap_perror( ld, "ldap_add" );
break;
}
/* wait a second for the add to really complete */
sleep( 1 );
/* now delete the entry again */
if ( ldap_delete_s( ld, entry ) != LDAP_SUCCESS ) {
ldap_perror( ld, "ldap_delete" );
break;
}
}
ldap_unbind( ld );
}

117
tests/slapd-read.c Normal file
View File

@ -0,0 +1,117 @@
#include "portable.h"
#include <stdio.h>
#include <ac/string.h>
#include <ac/ctype.h>
#include <ac/socket.h>
#include <ac/unistd.h>
#include <ac/wait.h>
#include <sys/param.h>
#include "lber.h"
#include "ldap.h"
#define LOOPS 100
static void
do_read( char *host, int port, char *entry, int maxloop );
static void
usage( char *name )
{
fprintf( stderr, "usage: %s [-h <host>] -p port -e <entry> [-l <loops>]\n",
name );
exit( 1 );
}
int
main( int argc, char **argv )
{
int i, j;
char *host = "localhost";
int port = -1;
char *entry = NULL;
int loops = LOOPS;
while ( (i = getopt( argc, argv, "h:p:e:l:" )) != EOF ) {
switch( i ) {
case 'h': /* the servers host */
host = strdup( optarg );
break;
case 'p': /* the servers port */
port = atoi( optarg );
break;
case 'e': /* file with entry search request */
entry = strdup( optarg );
break;
case 'l': /* the number of loops */
loops = atoi( optarg );
break;
default:
usage( argv[0] );
break;
}
}
if (( entry == NULL ) || ( port == -1 ))
usage( argv[0] );
if ( *entry == '\0' ) {
fprintf( stderr, "%s: invalid EMPTY entry DN.\n",
argv[0] );
exit( 1 );
}
do_read( host, port, entry, loops );
exit( 0 );
}
static void
do_read( char *host, int port, char *entry, int maxloop )
{
LDAP *ld;
int i;
char *attrs[] = { "cn", "sn", NULL };
char *filter = "(objectclass=*)";
if (( ld = ldap_init( host, port )) == NULL ) {
perror( "ldap_init" );
exit( 1 );
}
if ( ldap_bind_s( ld, NULL, NULL, LDAP_AUTH_SIMPLE ) != LDAP_SUCCESS ) {
ldap_perror( ld, "ldap_bind" );
exit( 1 );
}
fprintf( stderr, "Read(%d): entry=\"%s\".\n", maxloop, entry );
for ( i = 0; i < maxloop; i++ ) {
LDAPMessage *res;
if ( ldap_search_s( ld, entry, LDAP_SCOPE_BASE,
filter, attrs, 0, &res ) != LDAP_SUCCESS ) {
ldap_perror( ld, "ldap_read" );
break;
}
ldap_msgfree( res );
}
ldap_unbind( ld );
}

122
tests/slapd-search.c Normal file
View File

@ -0,0 +1,122 @@
#include "portable.h"
#include <stdio.h>
#include <ac/string.h>
#include <ac/ctype.h>
#include <ac/socket.h>
#include <ac/unistd.h>
#include <ac/wait.h>
#include <sys/param.h>
#include "lber.h"
#include "ldap.h"
#define LOOPS 100
static void
do_search( char *host, int port, char *sbase, char *filter, int maxloop );
static void
usage( char *name )
{
fprintf( stderr, "usage: %s [-h <host>] -p port -b <searchbase> -f <searchfiter> [-l <loops>]\n",
name );
exit( 1 );
}
int
main( int argc, char **argv )
{
int i, j;
char *host = "localhost";
int port = -1;
char *sbase = NULL;
char *filter = NULL;
int loops = LOOPS;
while ( (i = getopt( argc, argv, "h:p:b:f:l:" )) != EOF ) {
switch( i ) {
case 'h': /* the servers host */
host = strdup( optarg );
break;
case 'p': /* the servers port */
port = atoi( optarg );
break;
case 'b': /* file with search base */
sbase = strdup( optarg );
break;
case 'f': /* the search request */
filter = strdup( optarg );
break;
case 'l': /* number of loops */
loops = atoi( optarg );
break;
default:
usage( argv[0] );
break;
}
}
if (( sbase == NULL ) || ( filter == NULL ) || ( port == -1 ))
usage( argv[0] );
if ( *filter == '\0' ) {
fprintf( stderr, "%s: invalid EMPTY search filter.\n",
argv[0] );
exit( 1 );
}
do_search( host, port, sbase, filter, loops );
exit( 0 );
}
static void
do_search( char *host, int port, char *sbase, char *filter, int maxloop )
{
LDAP *ld;
int i;
char *attrs[] = { "cn", "sn", NULL };
if (( ld = ldap_init( host, port )) == NULL ) {
perror( "ldap_init" );
exit( 1 );
}
if ( ldap_bind_s( ld, NULL, NULL, LDAP_AUTH_SIMPLE ) != LDAP_SUCCESS ) {
ldap_perror( ld, "ldap_bind" );
exit( 1 );
}
fprintf( stderr, "Search(%d): base=\"%s\", filter=\"%s\".\n",
maxloop, sbase, filter );
for ( i = 0; i < maxloop; i++ ) {
LDAPMessage *res;
if ( ldap_search_s( ld, sbase, LDAP_SCOPE_SUBTREE,
filter, attrs, 0, &res ) != LDAP_SUCCESS ) {
ldap_perror( ld, "ldap_search" );
break;
}
ldap_msgfree( res );
}
ldap_unbind( ld );
}

352
tests/slapd-tester.c Normal file
View File

@ -0,0 +1,352 @@
#include "portable.h"
#include <stdio.h>
#include <ac/string.h>
#include <ac/ctype.h>
#include <ac/socket.h>
#include <ac/unistd.h>
#include <ac/wait.h>
#include <dirent.h>
#include <sys/param.h>
#include "ldapconfig.h"
#define SEARCHCMD "slapd-search"
#define READCMD "slapd-read"
#define ADDCMD "slapd-addel"
#define MAXARGS 100
#define MAXREQS 20
#define LOOPS "100"
#define TSEARCHFILE "do_search.0"
#define TREADFILE "do_read.0"
#define TADDFILE "do_add."
static char *get_file_name( char *dirname, char *filename );
static int get_search_filters( char *filename, char *filters[] );
static int get_read_entries( char *filename, char *entries[] );
static void fork_child( char *prog, char *args[] );
static void wait4kids( int nkidval );
static int maxkids = 20;
static int nkids;
static void
usage( char *name )
{
fprintf( stderr, "usage: %s [-h <host>] -p <port> -D <manager> -w <passwd> -d <datadir> -b <baseDN> [-j <maxchild>] [-l <loops>]\n", name );
exit( 1 );
}
int
main( int argc, char **argv )
{
int i, j;
char *host = "localhost";
char *port = NULL;
char *manager = NULL;
char *passwd = NULL;
char *dirname = NULL;
char *sbase = NULL;
char *loops = LOOPS;
DIR *datadir;
struct dirent *file;
char *sfile = NULL;
char *sreqs[MAXREQS];
int snum = 0;
char *rfile = NULL;
char *rreqs[MAXREQS];
int rnum = 0;
char *afiles[MAXREQS];
int anum = 0;
char *sargs[MAXARGS];
int sanum;
char scmd[MAXPATHLEN];
char *rargs[MAXARGS];
int ranum;
char rcmd[MAXPATHLEN];
char *aargs[MAXARGS];
int aanum;
char acmd[MAXPATHLEN];
while ( (i = getopt( argc, argv, "h:p:D:w:b:d:j:l:" )) != EOF ) {
switch( i ) {
case 'h': /* slapd host */
host = strdup( optarg );
break;
case 'p': /* the servers port number */
port = strdup( optarg );
break;
case 'D': /* slapd manager */
manager = strdup( optarg );
break;
case 'w': /* the managers passwd */
passwd = strdup( optarg );
break;
case 'b': /* the base DN */
sbase = strdup( optarg );
break;
case 'd': /* data directory */
dirname = strdup( optarg );
break;
case 'j': /* the number of parallel clients */
maxkids = atoi( optarg );
break;
case 'l': /* the number of loops per client */
loops = strdup( optarg );
break;
default:
usage( argv[0] );
break;
}
}
if (( dirname == NULL ) || ( sbase == NULL ) || ( port == NULL ) ||
( manager == NULL ) || ( passwd == NULL ))
usage( argv[0] );
/* get the file list */
if ( ( datadir = opendir( dirname )) == NULL ) {
fprintf( stderr, "%s: couldn't open data directory \"%s\".\n",
argv[0], dirname );
exit( 1 );
}
/* look for search, read, and add/delete files */
for ( file = readdir( datadir ); file; file = readdir( datadir )) {
if ( !strcasecmp( file->d_name, TSEARCHFILE )) {
sfile = get_file_name( dirname, file->d_name );
continue;
} else if ( !strcasecmp( file->d_name, TREADFILE )) {
rfile = get_file_name( dirname, file->d_name );
continue;
} else if ( !strncasecmp( file->d_name, TADDFILE, strlen( TADDFILE ))
&& ( anum < MAXREQS )) {
afiles[anum++] = get_file_name( dirname, file->d_name );
continue;
}
}
/* look for search requests */
if ( sfile ) {
snum = get_search_filters( sfile, sreqs );
}
/* look for read requests */
if ( rfile ) {
rnum = get_read_entries( rfile, rreqs );
}
/*
* generate the search clients
*/
sanum = 0;
sprintf( scmd, "%s", SEARCHCMD );
sargs[sanum++] = scmd;
sargs[sanum++] = "-h";
sargs[sanum++] = host;
sargs[sanum++] = "-p";
sargs[sanum++] = port;
sargs[sanum++] = "-b";
sargs[sanum++] = sbase;
sargs[sanum++] = "-l";
sargs[sanum++] = loops;
sargs[sanum++] = "-f";
sargs[sanum++] = NULL; /* will hold the search request */
sargs[sanum++] = NULL;
/*
* generate the read clients
*/
ranum = 0;
sprintf( rcmd, "%s", READCMD );
rargs[ranum++] = rcmd;
rargs[ranum++] = "-h";
rargs[ranum++] = host;
rargs[ranum++] = "-p";
rargs[ranum++] = port;
rargs[ranum++] = "-l";
rargs[ranum++] = loops;
rargs[ranum++] = "-e";
rargs[ranum++] = NULL; /* will hold the read entry */
rargs[ranum++] = NULL;
/*
* generate the add/delete clients
*/
aanum = 0;
sprintf( acmd, "%s", ADDCMD );
aargs[aanum++] = acmd;
aargs[aanum++] = "-h";
aargs[aanum++] = host;
aargs[aanum++] = "-p";
aargs[aanum++] = port;
aargs[aanum++] = "-D";
aargs[aanum++] = manager;
aargs[aanum++] = "-w";
aargs[aanum++] = passwd;
aargs[aanum++] = "-l";
aargs[aanum++] = loops;
aargs[aanum++] = "-f";
aargs[aanum++] = NULL; /* will hold the add data file */
aargs[aanum++] = NULL;
for ( j = 0; j < MAXREQS; j++ ) {
if ( j < snum ) {
sargs[sanum - 2] = sreqs[j];
fork_child( scmd, sargs );
}
if ( j < rnum ) {
rargs[ranum - 2] = rreqs[j];
fork_child( rcmd, rargs );
}
if ( j < anum ) {
aargs[aanum - 2] = afiles[j];
fork_child( acmd, aargs );
}
}
wait4kids( -1 );
exit( 0 );
}
static char *
get_file_name( char *dirname, char *filename )
{
char buf[MAXPATHLEN];
sprintf( buf, "%s%s%s", dirname, DEFAULT_DIRSEP, filename );
return( strdup( buf ));
}
static int
get_search_filters( char *filename, char *filters[] )
{
FILE *fp;
int filter = 0;
if ( fp = fopen( filename, "r" )) {
char line[BUFSIZ];
while (( filter < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
char *nl;
if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
*nl = '\0';
filters[filter++] = strdup( line );
}
fclose( fp );
}
return( filter );
}
static int
get_read_entries( char *filename, char *entries[] )
{
FILE *fp;
int entry = 0;
if ( fp = fopen( filename, "r" )) {
char line[BUFSIZ];
while (( entry < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) {
char *nl;
if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' )))
*nl = '\0';
entries[entry++] = strdup( line );
}
fclose( fp );
}
return( entry );
}
static void
fork_child( char *prog, char *args[] )
{
int status, pid;
wait4kids( maxkids );
switch ( pid = fork() ) {
case 0: /* child */
execvp( prog, args );
fprintf( stderr, "%s: ", prog );
perror( "execv" );
exit( -1 );
break;
case -1: /* trouble */
fprintf( stderr, "Could not fork to run %s\n", prog );
perror( "fork" );
break;
default: /* parent */
nkids++;
break;
}
}
static void
wait4kids( int nkidval )
{
int status;
unsigned char *p;
while ( nkids >= nkidval ) {
wait( &status );
p = (unsigned char *) &status;
if ( p[sizeof(int) - 1] == 0177 ) {
fprintf( stderr,
"stopping: child stopped with signal %d\n",
p[sizeof(int) - 2] );
} else if ( p[sizeof(int) - 1] != 0 ) {
fprintf( stderr,
"stopping: child terminated with signal %d\n",
p[sizeof(int) - 1] );
exit( p[sizeof(int) - 1] );
} else if ( p[sizeof(int) - 2] != 0 ) {
fprintf( stderr,
"stopping: child exited with status %d\n",
p[sizeof(int) - 2] );
exit( p[sizeof(int) - 2] );
} else {
nkids--;
}
}
}