/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include <stdio.h>
#include <malloc.h>
#include <errno.h>
#include <pthread.h>
#include <ldap.h>
#define NAME "cn=Directory Manager"
#define PASSWORD "secret99"
#define BASE "o=Airius.com"
static void *search_thread();
static void *modify_thread();
static void *add_thread();
static void *delete_thread();
static void *my_mutex_alloc();
static void my_mutex_free();
static void set_ld_error();
static int get_ld_error();
static void set_errno();
static int get_errno();
static void tsd_setup();
typedef struct ldapmsgwrapper {
LDAPMessage *lmw_messagep;
struct ldapmsgwrapper *lmw_next;
} ldapmsgwrapper;
LDAP *ld;
pthread_key_t key;
main( int argc, char **argv )
{
pthread_attr_t attr;
pthread_t search_tid, search_tid2, search_tid3, search_tid4;
pthread_t modify_tid, add_tid, delete_tid;
void *status;
struct ldap_thread_fns tfns;
if ( argc != 3 ) {
fprintf( stderr, "usage: %s host port\n", argv[0] );
exit( 1 );
}
if ( pthread_key_create( &key, free ) != 0 ) {
perror( "pthread_key_create" );
}
tsd_setup();
if ( (ld = ldap_init( argv[1], atoi( argv[2] ) )) == NULL ) {
perror( "ldap_open" );
exit( 1 );
}
/* set mutex pointers */
memset( &tfns, '\0', sizeof(struct ldap_thread_fns) );
tfns.ltf_mutex_alloc = (void *(*)(void)) my_mutex_alloc;
tfns.ltf_mutex_free = (void (*)(void *)) my_mutex_free;
tfns.ltf_mutex_lock = (int (*)(void *)) pthread_mutex_lock;
tfns.ltf_mutex_unlock = (int (*)(void *)) pthread_mutex_unlock;
tfns.ltf_get_errno = get_errno;
tfns.ltf_set_errno = set_errno;
tfns.ltf_get_lderrno = get_ld_error;
tfns.ltf_set_lderrno = set_ld_error;
tfns.ltf_lderrno_arg = NULL;
/* set ld_errno pointers */
if ( ldap_set_option( ld, LDAP_OPT_THREAD_FN_PTRS, (void *) &tfns )
!= 0 ) {
ldap_perror( ld, "ldap_set_option: thread pointers" );
}
if ( ldap_simple_bind_s( ld, NAME, PASSWORD ) != LDAP_SUCCESS ) {
ldap_perror( ld, "ldap_simple_bind_s" );
exit( 1 );
}
if ( pthread_attr_init( &attr ) != 0 ) {
perror( "pthread_attr_init" );
exit( 1 );
}
pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE );
if ( pthread_create( &search_tid, &attr, search_thread, "1" ) != 0 ) {
perror( "pthread_create search_thread" );
exit( 1 );
}
if ( pthread_create( &modify_tid, &attr, modify_thread, "2" ) != 0 ) {
perror( "pthread_create modify_thread" );
exit( 1 );
}
if ( pthread_create( &search_tid2, &attr, search_thread, "3" ) != 0 ) {
perror( "pthread_create search_thread2" );
exit( 1 );
}
if ( pthread_create( &add_tid, &attr, add_thread, "4" ) != 0 ) {
perror( "pthread_create add_thread" );
exit( 1 );
}
if ( pthread_create( &search_tid3, &attr, search_thread, "5" ) != 0 ) {
perror( "pthread_create search_thread3" );
exit( 1 );
}
if ( pthread_create( &delete_tid, &attr, delete_thread, "6" ) != 0 ) {
perror( "pthread_create delete_thread" );
exit( 1 );
}
if ( pthread_create( &search_tid4, &attr, search_thread, "7" ) != 0 ) {
perror( "pthread_create search_thread4" );
exit( 1 );
}
pthread_join( search_tid2, &status );
pthread_join( search_tid3, &status );
pthread_join( search_tid4, &status );
pthread_join( modify_tid, &status );
pthread_join( add_tid, &status );
pthread_join( delete_tid, &status );
pthread_join( search_tid, &status );
}
static void *
search_thread( char *id )
{
LDAPMessage *res;
LDAPMessage *e;
char *a;
char **v;
char *dn;
BerElement *ber;
int i, rc, msgid;
void *tsd;
printf( "search_thread\n" );
tsd_setup();
for ( ;; ) {
printf( "%sSearching...\n", id );
if ( (msgid = ldap_search( ld, BASE, LDAP_SCOPE_SUBTREE,
"(objectclass=*)", NULL, 0 )) == -1 ) {
ldap_perror( ld, "ldap_search_s" );
continue;
}
while ( (rc = ldap_result( ld, msgid, 0, NULL, &res ))
== LDAP_RES_SEARCH_ENTRY ) {
for ( e = ldap_first_entry( ld, res ); e != NULL;
e = ldap_next_entry( ld, e ) ) {
dn = ldap_get_dn( ld, e );
/* printf( "%sdn: %s\n", id, dn ); */
free( dn );
for ( a = ldap_first_attribute( ld, e, &ber );
a != NULL; a = ldap_next_attribute( ld, e,
ber ) ) {
v = ldap_get_values( ld, e, a );
for ( i = 0; v && v[i] != 0; i++ ) {
/*
printf( "%s%s: %s\n", id, a,
v[i] );
*/
}
ldap_value_free( v );
free( a );
}
}
ldap_msgfree( res );
/* printf( "%s\n", id ); */
}
if ( rc == -1 || ldap_result2error( ld, res, 0 ) !=
LDAP_SUCCESS ) {
ldap_perror( ld, "ldap_search" );
} else {
printf( "%sDone with one round\n", id );
}
}
}
static void *
modify_thread( char *id )
{
LDAPMessage *res;
LDAPMessage *e;
int i, modentry, entries, msgid, rc;
LDAPMod mod;
LDAPMod *mods[2];
char *vals[2];
char *dn;
ldapmsgwrapper *list, *lmwp, *lastlmwp;
printf( "modify_thread\n" );
tsd_setup();
if ( (msgid = ldap_search( ld, BASE, LDAP_SCOPE_SUBTREE,
"(objectclass=*)", NULL, 0 )) == -1 ) {
ldap_perror( ld, "ldap_search_s" );
exit( 1 );
}
entries = 0;
list = lastlmwp = NULL;
while ( (rc = ldap_result( ld, msgid, 0, NULL, &res ))
== LDAP_RES_SEARCH_ENTRY ) {
entries++;
if (( lmwp = (ldapmsgwrapper *)
malloc( sizeof( ldapmsgwrapper ))) == NULL ) {
perror( "modify_thread: malloc" );
exit( 1 );
}
lmwp->lmw_messagep = res;
lmwp->lmw_next = NULL;
if ( lastlmwp == NULL ) {
list = lastlmwp = lmwp;
} else {
lastlmwp->lmw_next = lmwp;
}
lastlmwp = lmwp;
}
if ( rc == -1 || ldap_result2error( ld, res, 0 ) != LDAP_SUCCESS ) {
ldap_perror( ld, "modify_thread: ldap_search" );
exit( 1 );
} else {
entries++;
printf( "%sModify got %d entries\n", id, entries );
}
mods[0] = &mod;
mods[1] = NULL;
vals[0] = "bar";
vals[1] = NULL;
for ( ;; ) {
modentry = rand() % entries;
for ( i = 0, lmwp = list; lmwp != NULL && i < modentry;
i++, lmwp = lmwp->lmw_next ) {
/* NULL */
}
if ( lmwp == NULL ) {
fprintf( stderr,
"%sModify could not find entry %d of %d\n",
id, modentry, entries );
continue;
}
e = lmwp->lmw_messagep;
printf( "%sPicked entry %d of %d\n", id, i, entries );
dn = ldap_get_dn( ld, e );
mod.mod_op = LDAP_MOD_REPLACE;
mod.mod_type = "description";
mod.mod_values = vals;
printf( "%sModifying (%s)\n", id, dn );
if ( ldap_modify_s( ld, dn, mods ) != LDAP_SUCCESS ) {
ldap_perror( ld, "ldap_modify_s" );
}
free( dn );
}
}
static void *
add_thread( char *id )
{
LDAPMod mod[5];
LDAPMod *mods[6];
char dn[BUFSIZ], name[40];
char *cnvals[2], *snvals[2], *ocvals[3];
int i;
printf( "add_thread\n" );
tsd_setup();
for ( i = 0; i < 5; i++ ) {
mods[i] = &mod[i];
}
mods[5] = NULL;
mod[0].mod_op = 0;
mod[0].mod_type = "cn";
mod[0].mod_values = cnvals;
cnvals[1] = NULL;
mod[1].mod_op = 0;
mod[1].mod_type = "sn";
mod[1].mod_values = snvals;
snvals[1] = NULL;
mod[2].mod_op = 0;
mod[2].mod_type = "objectclass";
mod[2].mod_values = ocvals;
ocvals[0] = "top";
ocvals[1] = "person";
ocvals[2] = NULL;
mods[3] = NULL;
for ( ;; ) {
sprintf( name, "%d", rand() );
sprintf( dn, "cn=%s, " BASE, name );
cnvals[0] = name;
snvals[0] = name;
printf( "%sAdding entry (%s)\n", id, dn );
if ( ldap_add_s( ld, dn, mods ) != LDAP_SUCCESS ) {
ldap_perror( ld, "ldap_add_s" );
}
}
}
static void *
delete_thread( char *id )
{
LDAPMessage *res;
char dn[BUFSIZ], name[40];
int entries, msgid, rc;
printf( "delete_thread\n" );
tsd_setup();
if ( (msgid = ldap_search( ld, BASE, LDAP_SCOPE_SUBTREE,
"(objectclass=*)", NULL, 0 )) == -1 ) {
ldap_perror( ld, "delete_thread: ldap_search_s" );
exit( 1 );
}
entries = 0;
while ( (rc = ldap_result( ld, msgid, 0, NULL, &res ))
== LDAP_RES_SEARCH_ENTRY ) {
entries++;
ldap_msgfree( res );
}
entries++;
if ( rc == -1 || ldap_result2error( ld, res, 0 ) != LDAP_SUCCESS ) {
ldap_perror( ld, "delete_thread: ldap_search" );
} else {
printf( "%sDelete got %d entries\n", id, entries );
}
for ( ;; ) {
sprintf( name, "%d", rand() );
sprintf( dn, "cn=%s, " BASE, name );
printf( "%sDeleting entry (%s)\n", id, dn );
if ( ldap_delete_s( ld, dn ) != LDAP_SUCCESS ) {
ldap_perror( ld, "ldap_delete_s" );
}
}
}
static void *
my_mutex_alloc( void )
{
pthread_mutex_t *mutexp;
if ( (mutexp = malloc( sizeof(pthread_mutex_t) )) != NULL ) {
pthread_mutex_init( mutexp, NULL );
}
return( mutexp );
}
static void
my_mutex_free( void *mutexp )
{
pthread_mutex_destroy( (pthread_mutex_t *) mutexp );
}
struct ldap_error {
int le_errno;
char *le_matched;
char *le_errmsg;
};
static void
tsd_setup()
{
void *tsd;
tsd = pthread_getspecific( key );
if ( tsd != NULL ) {
fprintf( stderr, "tsd non-null!\n" );
pthread_exit( NULL );
}
tsd = (void *) calloc( 1, sizeof(struct ldap_error) );
pthread_setspecific( key, tsd );
}
static void
set_ld_error( int err, char *matched, char *errmsg, void *dummy )
{
struct ldap_error *le;
le = pthread_getspecific( key );
le->le_errno = err;
if ( le->le_matched != NULL ) {
ldap_memfree( le->le_matched );
}
le->le_matched = matched;
if ( le->le_errmsg != NULL ) {
ldap_memfree( le->le_errmsg );
}
le->le_errmsg = errmsg;
}
static int
get_ld_error( char **matched, char **errmsg, void *dummy )
{
struct ldap_error *le;
le = pthread_getspecific( key );
if ( matched != NULL ) {
*matched = le->le_matched;
}
if ( errmsg != NULL ) {
*errmsg = le->le_errmsg;
}
return( le->le_errno );
}
static void
set_errno( int err )
{
errno = err;
}
static int
get_errno( void )
{
return( errno );
}
syntax highlighted by Code2HTML, v. 0.9.1