summaryrefslogtreecommitdiffstats
path: root/ldap/c-sdk/libldap/nsprthreadtest.c
diff options
context:
space:
mode:
Diffstat (limited to 'ldap/c-sdk/libldap/nsprthreadtest.c')
-rw-r--r--ldap/c-sdk/libldap/nsprthreadtest.c621
1 files changed, 621 insertions, 0 deletions
diff --git a/ldap/c-sdk/libldap/nsprthreadtest.c b/ldap/c-sdk/libldap/nsprthreadtest.c
new file mode 100644
index 000000000..f9af68b42
--- /dev/null
+++ b/ldap/c-sdk/libldap/nsprthreadtest.c
@@ -0,0 +1,621 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#include <nspr.h>
+#include <stdio.h>
+#include <ldap.h>
+
+#define NAME "cn=Directory Manager"
+#define PASSWORD "secret99"
+#define BASE "dc=example,dc=com"
+
+static int simplebind( LDAP *ld, char *msg, int tries );
+static void search_thread( void * );
+static void modify_thread( void * );
+static void add_thread( void * );
+static void delete_thread( void * );
+static void set_ld_error();
+static int get_ld_error();
+static void set_errno();
+static int get_errno();
+static void tsd_setup();
+static void *my_mutex_alloc( void );
+static void my_mutex_free( void * );
+static int my_mutex_lock( void * );
+static int my_mutex_unlock( void * );
+static LDAPHostEnt *my_gethostbyname( const char *name, LDAPHostEnt *result,
+ char *buffer, int buflen, int *statusp, void *extradata );
+static LDAPHostEnt *my_gethostbyaddr( const char *addr, int length,
+ int type, LDAPHostEnt *result, char *buffer, int buflen,
+ int *statusp, void *extradata );
+static LDAPHostEnt *copyPRHostEnt2LDAPHostEnt( LDAPHostEnt *ldhp,
+ PRHostEnt *prhp );
+
+typedef struct ldapmsgwrapper {
+ LDAPMessage *lmw_messagep;
+ struct ldapmsgwrapper *lmw_next;
+} ldapmsgwrapper;
+
+
+#define CONNECTION_ERROR( lderr ) ( (lderr) == LDAP_SERVER_DOWN || \
+ (lderr) == LDAP_CONNECT_ERROR )
+
+
+LDAP *ld;
+PRUintn tsdindex;
+#ifdef LDAP_MEMCACHE
+LDAPMemCache *memcache = NULL;
+#define MEMCACHE_SIZE (256*1024) /* 256K bytes */
+#define MEMCACHE_TTL (15*60) /* 15 minutes */
+#endif
+
+
+main( int argc, char **argv )
+{
+ PRThread *search_tid, *search_tid2, *search_tid3;
+ PRThread *search_tid4, *modify_tid, *add_tid;
+ PRThread *delete_tid;
+ struct ldap_thread_fns tfns;
+ struct ldap_dns_fns dnsfns;
+ int rc;
+
+ if ( argc != 3 ) {
+ fprintf( stderr, "usage: %s host port\n", argv[0] );
+ exit( 1 );
+ }
+
+ PR_Init( PR_USER_THREAD, PR_PRIORITY_NORMAL, 0 );
+ if ( PR_NewThreadPrivateIndex( &tsdindex, NULL ) != PR_SUCCESS ) {
+ perror( "PR_NewThreadPrivateIndex" );
+ exit( 1 );
+ }
+ tsd_setup(); /* for main thread */
+
+ if ( (ld = ldap_init( argv[1], atoi( argv[2] ) )) == NULL ) {
+ perror( "ldap_open" );
+ exit( 1 );
+ }
+
+ /* set thread function pointers */
+ memset( &tfns, '\0', sizeof(struct ldap_thread_fns) );
+ tfns.ltf_mutex_alloc = my_mutex_alloc;
+ tfns.ltf_mutex_free = my_mutex_free;
+ tfns.ltf_mutex_lock = my_mutex_lock;
+ tfns.ltf_mutex_unlock = my_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;
+ if ( ldap_set_option( ld, LDAP_OPT_THREAD_FN_PTRS, (void *) &tfns )
+ != 0 ) {
+ ldap_perror( ld, "ldap_set_option: thread functions" );
+ exit( 1 );
+ }
+
+ /* set DNS function pointers */
+ memset( &dnsfns, '\0', sizeof(struct ldap_dns_fns) );
+ dnsfns.lddnsfn_bufsize = PR_NETDB_BUF_SIZE;
+ dnsfns.lddnsfn_gethostbyname = my_gethostbyname;
+ dnsfns.lddnsfn_gethostbyaddr = my_gethostbyaddr;
+ if ( ldap_set_option( ld, LDAP_OPT_DNS_FN_PTRS, (void *)&dnsfns )
+ != 0 ) {
+ ldap_perror( ld, "ldap_set_option: DNS functions" );
+ exit( 1 );
+ }
+
+#ifdef LDAP_MEMCACHE
+ /* create the in-memory cache */
+ if (( rc = ldap_memcache_init( MEMCACHE_TTL, MEMCACHE_SIZE, NULL,
+ &tfns, &memcache )) != LDAP_SUCCESS ) {
+ fprintf( stderr, "ldap_memcache_init failed - %s\n",
+ ldap_err2string( rc ));
+ exit( 1 );
+ }
+ if (( rc = ldap_memcache_set( ld, memcache )) != LDAP_SUCCESS ) {
+ fprintf( stderr, "ldap_memcache_set failed - %s\n",
+ ldap_err2string( rc ));
+ exit( 1 );
+ }
+#endif
+
+ /*
+ * set option so that the next call to ldap_simple_bind_s() after
+ * the server connection is lost will attempt to reconnect.
+ */
+ if ( ldap_set_option( ld, LDAP_OPT_RECONNECT, LDAP_OPT_ON ) != 0 ) {
+ ldap_perror( ld, "ldap_set_option: reconnect" );
+ exit( 1 );
+ }
+
+ /* initial bind */
+ if ( simplebind( ld, "ldap_simple_bind_s/main", 1 ) != LDAP_SUCCESS ) {
+ exit( 1 );
+ }
+
+ /* create the operation threads */
+ if ( (search_tid = PR_CreateThread( PR_USER_THREAD, search_thread,
+ "1", PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD,
+ 0 )) == NULL ) {
+ perror( "PR_CreateThread search_thread" );
+ exit( 1 );
+ }
+ if ( (modify_tid = PR_CreateThread( PR_USER_THREAD, modify_thread,
+ "2", PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD,
+ 0 )) == NULL ) {
+ perror( "PR_CreateThread modify_thread" );
+ exit( 1 );
+ }
+ if ( (search_tid2 = PR_CreateThread( PR_USER_THREAD, search_thread,
+ "3", PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD,
+ 0 )) == NULL ) {
+ perror( "PR_CreateThread search_thread 2" );
+ exit( 1 );
+ }
+ if ( (add_tid = PR_CreateThread( PR_USER_THREAD, add_thread,
+ "4", PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD,
+ 0 )) == NULL ) {
+ perror( "PR_CreateThread add_thread" );
+ exit( 1 );
+ }
+ if ( (search_tid3 = PR_CreateThread( PR_USER_THREAD, search_thread,
+ "5", PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD,
+ 0 )) == NULL ) {
+ perror( "PR_CreateThread search_thread 3" );
+ exit( 1 );
+ }
+ if ( (delete_tid = PR_CreateThread( PR_USER_THREAD, delete_thread,
+ "6", PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD,
+ 0 )) == NULL ) {
+ perror( "PR_CreateThread delete_thread" );
+ exit( 1 );
+ }
+ if ( (search_tid4 = PR_CreateThread( PR_USER_THREAD, search_thread,
+ "7", PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD,
+ 0 )) == NULL ) {
+ perror( "PR_CreateThread search_thread 4" );
+ exit( 1 );
+ }
+
+ PR_Cleanup();
+ return( 0 );
+}
+
+
+static int
+simplebind( LDAP *ld, char *msg, int tries )
+{
+ int rc;
+
+ while ( tries-- > 0 ) {
+ rc = ldap_simple_bind_s( ld, NAME, PASSWORD );
+ if ( rc != LDAP_SUCCESS ) {
+ ldap_perror( ld, msg );
+ }
+ if ( tries == 0 || !CONNECTION_ERROR( rc )) {
+ return( rc );
+ }
+ fprintf( stderr,
+ "%s: sleeping for 5 secs - will try %d more time(s)...\n",
+ msg, tries );
+ sleep( 5 );
+ }
+
+ return( rc );
+}
+
+
+static void
+search_thread( void *arg1 )
+{
+ LDAPMessage *res;
+ LDAPMessage *e;
+ char *a;
+ char **v;
+ char *dn;
+ BerElement *ber;
+ int i, rc, msgid;
+ void *tsd;
+ char *id = arg1;
+
+ 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" );
+ rc = ldap_get_lderrno( ld, NULL, NULL );
+ if ( CONNECTION_ERROR( rc ) && simplebind( ld,
+ "bind-search_thread", 5 ) != LDAP_SUCCESS ) {
+ return;
+ }
+ 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 );
+ ldap_memfree( a );
+ }
+ if ( ber != NULL ) {
+ ber_free( ber, 0 );
+ }
+ }
+ 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 );
+ }
+
+ if ( rc == -1 ) {
+ rc = ldap_get_lderrno( ld, NULL, NULL );
+ if ( CONNECTION_ERROR( rc ) && simplebind( ld,
+ "bind-search_thread", 5 ) != LDAP_SUCCESS ) {
+ return;
+ }
+ }
+ }
+}
+
+static void
+modify_thread( void *arg1 )
+{
+ LDAPMessage *res;
+ LDAPMessage *e;
+ int i, modentry, entries, msgid, rc;
+ LDAPMod mod;
+ LDAPMod *mods[2];
+ char *vals[2];
+ char *dn;
+ char *id = arg1;
+ 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 (( rc = ldap_modify_s( ld, dn, mods )) != LDAP_SUCCESS ) {
+ ldap_perror( ld, "ldap_modify_s" );
+ if ( CONNECTION_ERROR( rc ) && simplebind( ld,
+ "bind-modify_thread", 5 ) != LDAP_SUCCESS ) {
+ return;
+ }
+ }
+ free( dn );
+ }
+}
+
+static void
+add_thread( void *arg1 )
+{
+ LDAPMod mod[5];
+ LDAPMod *mods[6];
+ char dn[BUFSIZ], name[40];
+ char *cnvals[2], *snvals[2], *ocvals[2];
+ int i, rc;
+ char *id = arg1;
+
+ 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] = "person";
+ ocvals[1] = 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 (( rc = ldap_add_s( ld, dn, mods )) != LDAP_SUCCESS ) {
+ ldap_perror( ld, "ldap_add_s" );
+ if ( CONNECTION_ERROR( rc ) && simplebind( ld,
+ "bind-add_thread", 5 ) != LDAP_SUCCESS ) {
+ return;
+ }
+ }
+ }
+}
+
+static void
+delete_thread( void *arg1 )
+{
+ LDAPMessage *res;
+ char dn[BUFSIZ], name[40];
+ int entries, msgid, rc;
+ char *id = arg1;
+
+ 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, 1 ) != 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 (( rc = ldap_delete_s( ld, dn )) != LDAP_SUCCESS ) {
+ ldap_perror( ld, "ldap_delete_s" );
+ if ( CONNECTION_ERROR( rc ) && simplebind( ld,
+ "bind-delete_thread", 5 ) != LDAP_SUCCESS ) {
+ return;
+ }
+ }
+ }
+}
+
+struct ldap_error {
+ int le_errno;
+ char *le_matched;
+ char *le_errmsg;
+};
+
+static void
+tsd_setup()
+{
+ void *tsd;
+
+ tsd = (void *) PR_GetThreadPrivate( tsdindex );
+ if ( tsd != NULL ) {
+ fprintf( stderr, "tsd non-null!\n" );
+ exit( 1 );
+ }
+ tsd = (void *) calloc( 1, sizeof(struct ldap_error) );
+ if ( PR_SetThreadPrivate( tsdindex, tsd ) != 0 ) {
+ perror( "PR_SetThreadPrivate" );
+ exit( 1 );
+ }
+}
+
+static void
+set_ld_error( int err, char *matched, char *errmsg, void *dummy )
+{
+ struct ldap_error *le;
+
+ le = (void *) PR_GetThreadPrivate( tsdindex );
+ 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 **matchedp, char **errmsgp, void *dummy )
+{
+ struct ldap_error *le;
+
+ le = PR_GetThreadPrivate( tsdindex );
+ if ( matchedp != NULL ) {
+ *matchedp = le->le_matched;
+ }
+ if ( errmsgp != NULL ) {
+ *errmsgp = le->le_errmsg;
+ }
+ return( le->le_errno );
+}
+
+static void
+set_errno( int oserrno )
+{
+ /* XXXmcs: should this be PR_SetError( oserrno, 0 )? */
+ PR_SetError( PR_UNKNOWN_ERROR, oserrno );
+}
+
+static int
+get_errno( void )
+{
+ /* XXXmcs: should this be PR_GetError()? */
+ return( PR_GetOSError());
+}
+
+static void *
+my_mutex_alloc( void )
+{
+ return( (void *)PR_NewLock());
+}
+
+static void
+my_mutex_free( void *mutex )
+{
+ PR_DestroyLock( (PRLock *)mutex );
+}
+
+static int
+my_mutex_lock( void *mutex )
+{
+ PR_Lock( (PRLock *)mutex );
+ return( 0 );
+}
+
+static int
+my_mutex_unlock( void *mutex )
+{
+ if ( PR_Unlock( (PRLock *)mutex ) == PR_FAILURE ) {
+ return( -1 );
+ }
+
+ return( 0 );
+}
+
+static LDAPHostEnt *
+my_gethostbyname( const char *name, LDAPHostEnt *result,
+ char *buffer, int buflen, int *statusp, void *extradata )
+{
+ PRHostEnt prhent;
+
+ if ( PR_GetHostByName( name, buffer, buflen,
+ &prhent ) != PR_SUCCESS ) {
+ return( NULL );
+ }
+
+ return( copyPRHostEnt2LDAPHostEnt( result, &prhent ));
+}
+
+static LDAPHostEnt *
+my_gethostbyaddr( const char *addr, int length, int type, LDAPHostEnt *result,
+ char *buffer, int buflen, int *statusp, void *extradata )
+{
+ PRHostEnt prhent;
+
+ if ( PR_GetHostByAddr( (PRNetAddr *)addr, buffer, buflen,
+ &prhent ) != PR_SUCCESS ) {
+ return( NULL );
+ }
+
+ return( copyPRHostEnt2LDAPHostEnt( result, &prhent ));
+}
+
+static LDAPHostEnt *
+copyPRHostEnt2LDAPHostEnt( LDAPHostEnt *ldhp, PRHostEnt *prhp )
+{
+ ldhp->ldaphe_name = prhp->h_name;
+ ldhp->ldaphe_aliases = prhp->h_aliases;
+ ldhp->ldaphe_addrtype = prhp->h_addrtype;
+ ldhp->ldaphe_length = prhp->h_length;
+ ldhp->ldaphe_addr_list = prhp->h_addr_list;
+ return( ldhp );
+}