From a637926bf27d346a07eb80692393e99cf19b49f5 Mon Sep 17 00:00:00 2001
From: Pierangelo Masarati <ando@openldap.org>
Date: Sat, 11 Sep 2004 16:15:53 +0000
Subject: [PATCH] use GMP for multiple precision in counters

---
 build/top.mk                           |   2 +-
 configure.in                           |  14 +++
 servers/slapd/back-monitor/operation.c | 143 +++++++++++++++++--------
 servers/slapd/back-monitor/sent.c      |  55 ++++++++--
 servers/slapd/connection.c             |  92 ++++++++++------
 servers/slapd/init.c                   | 138 ++++++++++++++++--------
 servers/slapd/proto-slap.h             |  19 ++--
 servers/slapd/result.c                 |  45 +++++---
 servers/slapd/slap.h                   |  47 ++++++++
 9 files changed, 396 insertions(+), 159 deletions(-)

diff --git a/build/top.mk b/build/top.mk
index a003feb19b..3806dcf42d 100644
--- a/build/top.mk
+++ b/build/top.mk
@@ -193,7 +193,7 @@ SLAPD_SQL_LDFLAGS = @SLAPD_SQL_LDFLAGS@
 SLAPD_SQL_INCLUDES = @SLAPD_SQL_INCLUDES@
 SLAPD_SQL_LIBS = @SLAPD_SQL_LIBS@
 
-SLAPD_LIBS = @SLAPD_LIBS@ @SLAPD_PERL_LDFLAGS@ @SLAPD_SQL_LDFLAGS@ @SLAPD_SQL_LIBS@ @SLAPD_SLP_LIBS@
+SLAPD_LIBS = @SLAPD_LIBS@ @SLAPD_PERL_LDFLAGS@ @SLAPD_SQL_LDFLAGS@ @SLAPD_SQL_LIBS@ @SLAPD_SLP_LIBS@ @SLAPD_GMP_LIBS@
 SLURPD_LIBS = @SLURPD_LIBS@
 
 # Our Defaults
diff --git a/configure.in b/configure.in
index 084f2221e9..db0cbaf7f4 100644
--- a/configure.in
+++ b/configure.in
@@ -553,6 +553,7 @@ LIBSLAPITOOLS=
 AUTH_LIBS=
 
 SLAPD_SLP_LIBS=
+SLAPD_GMP_LIBS=
 
 dnl ================================================================
 dnl Checks for programs
@@ -2228,6 +2229,18 @@ if test $ol_enable_slp != no ; then
 	fi
 fi
 
+dnl ----------------------------------------------------------------
+dnl Check for GMP API Library
+AC_CHECK_HEADERS( gmp.h )
+
+if test $ac_cv_header_gmp_h = yes ; then
+	AC_CHECK_LIB(gmp, __gmpz_add_ui, [have_gmp=yes], [have_gmp=no])
+	if test $have_gmp = yes ; then
+		AC_DEFINE(HAVE_GMP, 1, [define if you have -lgmp])
+		SLAPD_GMP_LIBS=-lgmp
+	fi
+fi
+
 dnl ----------------------------------------------------------------
 dnl Checks for typedefs, structures, and compiler characteristics.
 
@@ -2843,6 +2856,7 @@ AC_SUBST(LIBSLAPITOOLS)
 AC_SUBST(AUTH_LIBS)
 
 AC_SUBST(SLAPD_SLP_LIBS)
+AC_SUBST(SLAPD_GMP_LIBS)
 
 AC_SUBST(SLAPD_SQL_LDFLAGS)
 AC_SUBST(SLAPD_SQL_LIBS)
diff --git a/servers/slapd/back-monitor/operation.c b/servers/slapd/back-monitor/operation.c
index 1427104520..eb7be9baa8 100644
--- a/servers/slapd/back-monitor/operation.c
+++ b/servers/slapd/back-monitor/operation.c
@@ -28,20 +28,22 @@
 #include "back-monitor.h"
 #include "lber_pvt.h"
 
-static struct berval 
-	bv_op[] = {
-		BER_BVC( "Bind" ),
-		BER_BVC( "Unbind" ),
-		BER_BVC( "Add" ),
-		BER_BVC( "Delete" ),
-		BER_BVC( "Modrdn" ),
-		BER_BVC( "Modify" ),
-		BER_BVC( "Compare" ),
-		BER_BVC( "Search" ),
-		BER_BVC( "Abandon" ),
-		BER_BVC( "Extended" ),
-		BER_BVNULL
-	};
+struct monitor_ops_t {
+	struct berval	rdn;
+	struct berval	nrdn;
+} monitor_op[] = {
+	{ BER_BVC( "cn=Bind" ),		BER_BVC( "cn=bind" )		},
+	{ BER_BVC( "cn=Unbind" ),	BER_BVC( "cn=unbind" )		},
+	{ BER_BVC( "cn=Add" ),		BER_BVC( "cn=add" )		},
+	{ BER_BVC( "cn=Delete" ),	BER_BVC( "cn=delete" )		},
+	{ BER_BVC( "cn=Modrdn" ),	BER_BVC( "cn=modrdn" )		},
+	{ BER_BVC( "cn=Modify" ),	BER_BVC( "cn=modify" )		},
+	{ BER_BVC( "cn=Compare" ),	BER_BVC( "cn=compare" )		},
+	{ BER_BVC( "cn=Search" ),	BER_BVC( "cn=search" )		},
+	{ BER_BVC( "cn=Abandon" ),	BER_BVC( "cn=abandon" )		},
+	{ BER_BVC( "cn=Extended" ),	BER_BVC( "cn=extended" )	},
+	{ BER_BVNULL,			BER_BVNULL			}
+};
 
 int
 monitor_subsys_ops_init(
@@ -64,9 +66,9 @@ monitor_subsys_ops_init(
 			&monitor_subsys[SLAPD_MONITOR_OPS].mss_ndn, &e_op ) ) {
 		Debug( LDAP_DEBUG_ANY,
 			"monitor_subsys_ops_init: "
-			"unable to get entry '%s'\n%s%s",
+			"unable to get entry \"%s\"\n",
 			monitor_subsys[SLAPD_MONITOR_OPS].mss_ndn.bv_val, 
-			"", "" );
+			0, 0 );
 		return( -1 );
 	}
 
@@ -81,7 +83,7 @@ monitor_subsys_ops_init(
 		 * Initiated ops
 		 */
 		snprintf( buf, sizeof( buf ),
-				"dn: cn=%s,%s\n"
+				"dn: %s,%s\n"
 				"objectClass: %s\n"
 				"structuralObjectClass: %s\n"
 				"cn: %s\n"
@@ -91,11 +93,11 @@ monitor_subsys_ops_init(
 				"modifiersName: %s\n"
 				"createTimestamp: %s\n"
 				"modifyTimestamp: %s\n",
-				bv_op[ i ].bv_val,
+				monitor_op[ i ].rdn.bv_val,
 				monitor_subsys[SLAPD_MONITOR_OPS].mss_dn.bv_val,
 				mi->mi_oc_monitorOperation->soc_cname.bv_val,
 				mi->mi_oc_monitorOperation->soc_cname.bv_val,
-				bv_op[ i ].bv_val,
+				&monitor_op[ i ].rdn.bv_val[STRLENOF( "cn=" )],
 				mi->mi_ad_monitorOpInitiated->ad_cname.bv_val,
 				mi->mi_ad_monitorOpCompleted->ad_cname.bv_val,
 				mi->mi_creatorsName.bv_val,
@@ -107,8 +109,8 @@ monitor_subsys_ops_init(
 		if ( e == NULL ) {
 			Debug( LDAP_DEBUG_ANY,
 				"monitor_subsys_ops_init: "
-				"unable to create entry 'cn=%s,%s'\n",
-				bv_op[ i ].bv_val,
+				"unable to create entry \"%s,%s\"\n",
+				monitor_op[ i ].rdn.bv_val,
 				monitor_subsys[SLAPD_MONITOR_OPS].mss_ndn.bv_val, 0 );
 			return( -1 );
 		}
@@ -124,8 +126,8 @@ monitor_subsys_ops_init(
 		if ( monitor_cache_add( mi, e ) ) {
 			Debug( LDAP_DEBUG_ANY,
 				"monitor_subsys_ops_init: "
-				"unable to add entry 'cn=%s,%s'\n",
-				bv_op[ i ].bv_val,
+				"unable to add entry \"%s,%s\"\n",
+				monitor_op[ i ].rdn.bv_val,
 				monitor_subsys[SLAPD_MONITOR_OPS].mss_ndn.bv_val, 0 );
 			return( -1 );
 		}
@@ -147,33 +149,58 @@ monitor_subsys_ops_update(
 	Entry                   *e
 )
 {
-	struct monitorinfo *mi = (struct monitorinfo *)op->o_bd->be_private;
-	long 		nInitiated = 0, nCompleted = 0;
-	char 		*rdnvalue;
-	int 		i;
-	Attribute	*a;
-	char		buf[] = "+9223372036854775807L";
+	struct monitorinfo	*mi = 
+		(struct monitorinfo *)op->o_bd->be_private;
+
+#ifdef HAVE_GMP
+	mpz_t			nInitiated,
+				nCompleted;
+#else /* ! HAVE_GMP */
+	unsigned long		nInitiated = 0,
+				nCompleted = 0;
+	char			buf[] = "+9223372036854775807L";
+#endif /* ! HAVE_GMP */
+	struct berval		rdn;
+	int 			i;
+	Attribute		*a;
+	static struct berval	bv_ops = BER_BVC( "cn=operations" );
 
 	assert( mi );
 	assert( e );
 
-	rdnvalue = e->e_dn + ( sizeof( "cn=" ) - 1 );
+	dnRdn( &e->e_nname, &rdn );
 
-	if ( strncmp( rdnvalue, SLAPD_MONITOR_OPS_NAME,
-				sizeof( SLAPD_MONITOR_OPS_NAME ) - 1 ) == 0 )
-	{
+	if ( dn_match( &rdn, &bv_ops ) ) {
+#ifdef HAVE_GMP
+		mpz_init( nInitiated );
+		mpz_init( nCompleted );
+#endif /* ! HAVE_GMP */
+
+		ldap_pvt_thread_mutex_lock( &slap_counters.sc_ops_mutex );
 		for ( i = 0; i < SLAP_OP_LAST; i++ ) {
-			nInitiated += num_ops_initiated_[ i ];
-			nCompleted += num_ops_completed_[ i ];
+#ifdef HAVE_GMP
+			mpz_add( nInitiated, nInitiated, slap_counters.sc_ops_initiated_[ i ] );
+			mpz_add( nCompleted, nCompleted, slap_counters.sc_ops_completed_[ i ] );
+#else /* ! HAVE_GMP */
+			nInitiated += slap_counter.sc_ops_initiated_[ i ];
+			nCompleted += slap_counter.sc_ops_completed_[ i ];
+#endif /* ! HAVE_GMP */
 		}
+		ldap_pvt_thread_mutex_unlock( &slap_counters.sc_ops_mutex );
 		
 	} else {
 		for ( i = 0; i < SLAP_OP_LAST; i++ ) {
-			if ( strncmp( rdnvalue, bv_op[ i ].bv_val, 
-						bv_op[ i ].bv_len ) == 0 )
+			if ( dn_match( &rdn, &monitor_op[ i ].nrdn ) )
 			{
-				nInitiated = num_ops_initiated_[ i ];
-				nCompleted = num_ops_completed_[ i ];
+				ldap_pvt_thread_mutex_lock( &slap_counters.sc_ops_mutex );
+#ifdef HAVE_GMP
+				mpz_init_set( nInitiated, slap_counters.sc_ops_initiated_[ i ] );
+				mpz_init_set( nCompleted, slap_counters.sc_ops_completed_[ i ] );
+#else /* ! HAVE_GMP */
+				nInitiated = slap_counter.sc_ops_initiated_[ i ];
+				nCompleted = slap_counter.sc_ops_completed_[ i ];
+#endif /* ! HAVE_GMP */
+				ldap_pvt_thread_mutex_unlock( &slap_counters.sc_ops_mutex );
 				break;
 			}
 		}
@@ -186,16 +213,46 @@ monitor_subsys_ops_update(
 
 	a = attr_find( e->e_attrs, mi->mi_ad_monitorOpInitiated );
 	assert ( a != NULL );
-	snprintf( buf, sizeof( buf ), "%ld", nInitiated );
 	free( a->a_vals[ 0 ].bv_val );
+#ifdef HAVE_GMP
+	/* NOTE: there should be no minus sign allowed in the counters... */
+	a->a_vals[ 0 ].bv_len = mpz_sizeinbase( nInitiated, 10 );
+	a->a_vals[ 0 ].bv_val = ber_memalloc( a->a_vals[ 0 ].bv_len + 1 );
+	(void)mpz_get_str( a->a_vals[ 0 ].bv_val, 10, nInitiated );
+	mpz_clear( nInitiated );
+	/* NOTE: according to the documentation, the result 
+	 * of mpz_sizeinbase() can exceed the length of the
+	 * string representation of the number by 1
+	 */
+	if ( a->a_vals[ 0 ].bv_val[ a->a_vals[ 0 ].bv_len - 1 ] == '\0' ) {
+		a->a_vals[ 0 ].bv_len--;
+	}
+#else /* ! HAVE_GMP */
+	snprintf( buf, sizeof( buf ), "%ld", nInitiated );
 	ber_str2bv( buf, 0, 1, &a->a_vals[ 0 ] );
-
+#endif /* ! HAVE_GMP */
+	
 	a = attr_find( e->e_attrs, mi->mi_ad_monitorOpCompleted );
 	assert ( a != NULL );
-	snprintf( buf, sizeof( buf ), "%ld", nCompleted );
 	free( a->a_vals[ 0 ].bv_val );
+#ifdef HAVE_GMP
+	/* NOTE: there should be no minus sign allowed in the counters... */
+	a->a_vals[ 0 ].bv_len = mpz_sizeinbase( nCompleted, 10 );
+	a->a_vals[ 0 ].bv_val = ber_memalloc( a->a_vals[ 0 ].bv_len + 1 );
+	(void)mpz_get_str( a->a_vals[ 0 ].bv_val, 10, nCompleted );
+	mpz_clear( nCompleted );
+	/* NOTE: according to the documentation, the result 
+	 * of mpz_sizeinbase() can exceed the length of the
+	 * string representation of the number by 1
+	 */
+	if ( a->a_vals[ 0 ].bv_val[ a->a_vals[ 0 ].bv_len - 1 ] == '\0' ) {
+		a->a_vals[ 0 ].bv_len--;
+	}
+#else /* ! HAVE_GMP */
+	snprintf( buf, sizeof( buf ), "%ld", nCompleted );
 	ber_str2bv( buf, 0, 1, &a->a_vals[ 0 ] );
-
+#endif /* ! HAVE_GMP */
+	
 	return( 0 );
 }
 
diff --git a/servers/slapd/back-monitor/sent.c b/servers/slapd/back-monitor/sent.c
index 161a0a403b..de041f0b0d 100644
--- a/servers/slapd/back-monitor/sent.c
+++ b/servers/slapd/back-monitor/sent.c
@@ -40,10 +40,10 @@ struct monitor_sent_t {
 	struct berval	rdn;
 	struct berval	nrdn;
 } monitor_sent[] = {
+	{ BER_BVC("cn=Bytes"),		BER_BVC("cn=bytes")		},
+	{ BER_BVC("cn=PDU"),		BER_BVC("cn=pdu")		},
 	{ BER_BVC("cn=Entries"),	BER_BVC("cn=entries")		},
 	{ BER_BVC("cn=Referrals"),	BER_BVC("cn=referrals")		},
-	{ BER_BVC("cn=PDU"),		BER_BVC("cn=pdu")		},
-	{ BER_BVC("cn=Bytes"),		BER_BVC("cn=bytes")		},
 	{ BER_BVNULL,			BER_BVNULL			}
 };
 
@@ -150,9 +150,15 @@ monitor_subsys_sent_update(
 		(struct monitorinfo *)op->o_bd->be_private;
 	
 	struct berval		rdn;
+#ifdef HAVE_GMP
+	mpz_t			n;
+#else /* ! HAVE_GMP */
 	unsigned long 		n;
+#endif /* ! HAVE_GMP */
 	Attribute		*a;
+#ifndef HAVE_GMP
 	char			buf[] = "+9223372036854775807L";
+#endif /* ! HAVE_GMP */
 	int			i;
 
 	assert( mi );
@@ -170,37 +176,68 @@ monitor_subsys_sent_update(
 		return 0;
 	}
 
-	ldap_pvt_thread_mutex_lock(&num_sent_mutex);
+	ldap_pvt_thread_mutex_lock(&slap_counters.sc_sent_mutex);
 	switch ( i ) {
 	case MONITOR_SENT_ENTRIES:
-		n = num_entries_sent;
+#ifdef HAVE_GMP
+		mpz_init_set( n, slap_counters.sc_entries );
+#else /* ! HAVE_GMP */
+		n = slap_counters.sc_entries;
+#endif /* ! HAVE_GMP */
 		break;
 
 	case MONITOR_SENT_REFERRALS:
-		n = num_refs_sent;
+#ifdef HAVE_GMP
+		mpz_init_set( n, slap_counters.sc_refs );
+#else /* ! HAVE_GMP */
+		n = slap_counters.sc_refs;
+#endif /* ! HAVE_GMP */
 		break;
 
 	case MONITOR_SENT_PDU:
-		n = num_pdu_sent;
+#ifdef HAVE_GMP
+		mpz_init_set( n, slap_counters.sc_pdu );
+#else /* ! HAVE_GMP */
+		n = slap_counters.sc_pdu;
+#endif /* ! HAVE_GMP */
 		break;
 
 	case MONITOR_SENT_BYTES:
-		n = num_bytes_sent;
+#ifdef HAVE_GMP
+		mpz_init_set( n, slap_counters.sc_bytes );
+#else /* ! HAVE_GMP */
+		n = slap_counters.sc_bytes;
+#endif /* ! HAVE_GMP */
 		break;
 
 	default:
 		assert(0);
 	}
-	ldap_pvt_thread_mutex_unlock(&num_sent_mutex);
+	ldap_pvt_thread_mutex_unlock(&slap_counters.sc_sent_mutex);
 	
 	a = attr_find( e->e_attrs, mi->mi_ad_monitorCounter );
 	if ( a == NULL ) {
 		return -1;
 	}
 
-	snprintf( buf, sizeof( buf ), "%lu", n );
 	free( a->a_vals[ 0 ].bv_val );
+#ifdef HAVE_GMP
+	/* NOTE: there should be no minus sign allowed in the counters... */
+	a->a_vals[ 0 ].bv_len = mpz_sizeinbase( n, 10 );
+	a->a_vals[ 0 ].bv_val = ber_memalloc( a->a_vals[ 0 ].bv_len + 1 );
+	(void)mpz_get_str( a->a_vals[ 0 ].bv_val, 10, n );
+	mpz_clear( n );
+	/* NOTE: according to the documentation, the result 
+	 * of mpz_sizeinbase() can exceed the length of the
+	 * string representation of the number by 1
+	 */
+	if ( a->a_vals[ 0 ].bv_val[ a->a_vals[ 0 ].bv_len - 1 ] == '\0' ) {
+		a->a_vals[ 0 ].bv_len--;
+	}
+#else /* ! HAVE_GMP */
+	snprintf( buf, sizeof( buf ), "%lu", n );
 	ber_str2bv( buf, 0, 1, &a->a_vals[ 0 ] );
+#endif /* ! HAVE_GMP */
 
 	return 0;
 }
diff --git a/servers/slapd/connection.c b/servers/slapd/connection.c
index 8d353bdb2b..8ea63ce71f 100644
--- a/servers/slapd/connection.c
+++ b/servers/slapd/connection.c
@@ -865,14 +865,41 @@ void connection_done( Connection *c )
  */
 
 #ifdef SLAPD_MONITOR
-#define INCR_OP(var,index) \
+#ifdef HAVE_GMP
+#define INCR_OP_INITIATED(index) \
 	do { \
-		ldap_pvt_thread_mutex_lock( &num_ops_mutex ); \
-		(var)[(index)]++; \
-		ldap_pvt_thread_mutex_unlock( &num_ops_mutex ); \
+		ldap_pvt_thread_mutex_lock( &slap_counters.sc_ops_mutex ); \
+		mpz_add_ui(slap_counters.sc_ops_initiated_[(index)], \
+				slap_counters.sc_ops_initiated_[(index)], 1); \
+		ldap_pvt_thread_mutex_unlock( &slap_counters.sc_ops_mutex ); \
 	} while (0)
+#define INCR_OP_COMPLETED(index) \
+	do { \
+		ldap_pvt_thread_mutex_lock( &slap_counters.sc_ops_mutex ); \
+		mpz_add_ui(slap_counters.sc_ops_completed, \
+				slap_counters.sc_ops_completed, 1); \
+		mpz_add_ui(slap_counters.sc_ops_completed_[(index)], \
+				slap_counters.sc_ops_completed_[(index)], 1); \
+		ldap_pvt_thread_mutex_unlock( &slap_counters.sc_ops_mutex ); \
+	} while (0)
+#else /* ! HAVE_GMP */
+#define INCR_OP_INITIATED(index) \
+	do { \
+		ldap_pvt_thread_mutex_lock( &slap_counters.sc_ops_mutex ); \
+		slap_counters.sc_ops_initiated_[(index)]++; \
+		ldap_pvt_thread_mutex_unlock( &slap_counters.sc_ops_mutex ); \
+	} while (0)
+#define INCR_OP_COMPLETED(index) \
+	do { \
+		ldap_pvt_thread_mutex_lock( &slap_counters.sc_ops_mutex ); \
+		slap_counters.sc_ops_completed++; \
+		slap_counters.sc_ops_completed_[(index)]++; \
+		ldap_pvt_thread_mutex_unlock( &slap_counters.sc_ops_mutex ); \
+	} while (0)
+#endif /* ! HAVE_GMP */
 #else /* !SLAPD_MONITOR */
-#define INCR_OP(var,index) 
+#define INCR_OP_INITIATED(index) 
+#define INCR_OP_COMPLETED(index) 
 #endif /* !SLAPD_MONITOR */
 
 static void *
@@ -890,9 +917,13 @@ connection_operation( void *ctx, void *arg_v )
 	void *memctx_null = NULL;
 	ber_len_t memsiz;
 
-	ldap_pvt_thread_mutex_lock( &num_ops_mutex );
-	num_ops_initiated++;
-	ldap_pvt_thread_mutex_unlock( &num_ops_mutex );
+	ldap_pvt_thread_mutex_lock( &slap_counters.sc_ops_mutex );
+#ifdef HAVE_GMP
+	mpz_add_ui(slap_counters.sc_ops_initiated, slap_counters.sc_ops_initiated, 1);
+#else /* ! HAVE_GMP */
+	slap_counters.sc_ops_initiated++;
+#endif /* ! HAVE_GMP */
+	ldap_pvt_thread_mutex_unlock( &slap_counters.sc_ops_mutex );
 
 	op->o_threadctx = ctx;
 
@@ -952,52 +983,52 @@ connection_operation( void *ctx, void *arg_v )
 
 	switch ( tag ) {
 	case LDAP_REQ_BIND:
-		INCR_OP(num_ops_initiated_, SLAP_OP_BIND);
+		INCR_OP_INITIATED(SLAP_OP_BIND);
 		rc = do_bind( op, &rs );
 		break;
 
 	case LDAP_REQ_UNBIND:
-		INCR_OP(num_ops_initiated_, SLAP_OP_UNBIND);
+		INCR_OP_INITIATED(SLAP_OP_UNBIND);
 		rc = do_unbind( op, &rs );
 		break;
 
 	case LDAP_REQ_ADD:
-		INCR_OP(num_ops_initiated_, SLAP_OP_ADD);
+		INCR_OP_INITIATED(SLAP_OP_ADD);
 		rc = do_add( op, &rs );
 		break;
 
 	case LDAP_REQ_DELETE:
-		INCR_OP(num_ops_initiated_, SLAP_OP_DELETE);
+		INCR_OP_INITIATED(SLAP_OP_DELETE);
 		rc = do_delete( op, &rs );
 		break;
 
 	case LDAP_REQ_MODRDN:
-		INCR_OP(num_ops_initiated_, SLAP_OP_MODRDN);
+		INCR_OP_INITIATED(SLAP_OP_MODRDN);
 		rc = do_modrdn( op, &rs );
 		break;
 
 	case LDAP_REQ_MODIFY:
-		INCR_OP(num_ops_initiated_, SLAP_OP_MODIFY);
+		INCR_OP_INITIATED(SLAP_OP_MODIFY);
 		rc = do_modify( op, &rs );
 		break;
 
 	case LDAP_REQ_COMPARE:
-		INCR_OP(num_ops_initiated_, SLAP_OP_COMPARE);
+		INCR_OP_INITIATED(SLAP_OP_COMPARE);
 		rc = do_compare( op, &rs );
 		break;
 
 	case LDAP_REQ_SEARCH:
-		INCR_OP(num_ops_initiated_, SLAP_OP_SEARCH);
+		INCR_OP_INITIATED(SLAP_OP_SEARCH);
 		rc = do_search( op, &rs );
 		break;
 
 	case LDAP_REQ_ABANDON:
-		INCR_OP(num_ops_initiated_, SLAP_OP_ABANDON);
+		INCR_OP_INITIATED(SLAP_OP_ABANDON);
 		rc = do_abandon( op, &rs );
 		break;
 
 	case LDAP_REQ_EXTENDED:
-		INCR_OP(num_ops_initiated_, SLAP_OP_EXTENDED);
+		INCR_OP_INITIATED(SLAP_OP_EXTENDED);
 		rc = do_extended( op, &rs );
 		break;
 
@@ -1009,47 +1040,44 @@ connection_operation( void *ctx, void *arg_v )
 operations_error:
 	if( rc == SLAPD_DISCONNECT ) tag = LBER_ERROR;
 
-	ldap_pvt_thread_mutex_lock( &num_ops_mutex );
-
-	num_ops_completed++;
 #ifdef SLAPD_MONITOR
 	switch (oldtag) {
 	case LDAP_REQ_BIND:
-		num_ops_completed_[SLAP_OP_BIND]++;
+		INCR_OP_COMPLETED(SLAP_OP_BIND);
 		break;
 	case LDAP_REQ_UNBIND:
-		num_ops_completed_[SLAP_OP_UNBIND]++;
+		INCR_OP_COMPLETED(SLAP_OP_UNBIND);
 		break;
 	case LDAP_REQ_ADD:
-		num_ops_completed_[SLAP_OP_ADD]++;
+		INCR_OP_COMPLETED(SLAP_OP_ADD);
 		break;
 	case LDAP_REQ_DELETE:
-		num_ops_completed_[SLAP_OP_DELETE]++;
+		INCR_OP_COMPLETED(SLAP_OP_DELETE);
 		break;
 	case LDAP_REQ_MODRDN:
-		num_ops_completed_[SLAP_OP_MODRDN]++;
+		INCR_OP_COMPLETED(SLAP_OP_MODRDN);
 		break;
 	case LDAP_REQ_MODIFY:
-		num_ops_completed_[SLAP_OP_MODIFY]++;
+		INCR_OP_COMPLETED(SLAP_OP_MODIFY);
 		break;
 	case LDAP_REQ_COMPARE:
-		num_ops_completed_[SLAP_OP_COMPARE]++;
+		INCR_OP_COMPLETED(SLAP_OP_COMPARE);
 		break;
 	case LDAP_REQ_SEARCH:
-		num_ops_completed_[SLAP_OP_SEARCH]++;
+		INCR_OP_COMPLETED(SLAP_OP_SEARCH);
 		break;
 	case LDAP_REQ_ABANDON:
-		num_ops_completed_[SLAP_OP_ABANDON]++;
+		INCR_OP_COMPLETED(SLAP_OP_ABANDON);
 		break;
 	case LDAP_REQ_EXTENDED:
-		num_ops_completed_[SLAP_OP_EXTENDED]++;
+		INCR_OP_COMPLETED(SLAP_OP_EXTENDED);
 		break;
 	default:
 		/* not reachable */
 		assert( 0 );
 	}
 #endif /* SLAPD_MONITOR */
-	ldap_pvt_thread_mutex_unlock( &num_ops_mutex );
+	ldap_pvt_thread_mutex_unlock( &slap_counters.sc_ops_mutex );
 
 	if ( op->o_cancel == SLAP_CANCEL_REQ ) {
 		op->o_cancel = LDAP_TOO_LATE;
diff --git a/servers/slapd/init.c b/servers/slapd/init.c
index 40def39a95..6dce7e7d08 100644
--- a/servers/slapd/init.c
+++ b/servers/slapd/init.c
@@ -72,19 +72,8 @@ ldap_pvt_thread_mutex_t	gmtime_mutex;
 ldap_pvt_thread_mutex_t	passwd_mutex;
 #endif
 
-unsigned long			num_ops_initiated = 0;
-unsigned long			num_ops_completed = 0;
-#ifdef SLAPD_MONITOR
-unsigned long			num_ops_initiated_[SLAP_OP_LAST];
-unsigned long			num_ops_completed_[SLAP_OP_LAST];
-#endif /* SLAPD_MONITOR */
-ldap_pvt_thread_mutex_t	num_ops_mutex;
+slap_counters_t			slap_counters;
 
-unsigned long			num_entries_sent;
-unsigned long			num_refs_sent;
-unsigned long			num_bytes_sent;
-unsigned long			num_pdu_sent;
-ldap_pvt_thread_mutex_t	num_sent_mutex;
 /*
  * these mutexes must be used when calling the entry2str()
  * routine since it returns a pointer to static data.
@@ -99,10 +88,11 @@ int
 slap_init( int mode, const char *name )
 {
 	int rc;
+	int i;
 
 	assert( mode );
 
-	if( slapMode != SLAP_UNDEFINED_MODE ) {
+	if ( slapMode != SLAP_UNDEFINED_MODE ) {
 		Debug( LDAP_DEBUG_ANY,
 		 "%s init: init called twice (old=%d, new=%d)\n",
 		 name, slapMode, mode );
@@ -113,57 +103,78 @@ slap_init( int mode, const char *name )
 	slapMode = mode;
 
 	switch ( slapMode & SLAP_MODE ) {
-		case SLAP_SERVER_MODE:
-		case SLAP_TOOL_MODE:
-			Debug( LDAP_DEBUG_TRACE,
-				"%s init: initiated %s.\n",	name,
-				(mode & SLAP_MODE) == SLAP_TOOL_MODE ? "tool" : "server",
-				0 );
+	case SLAP_SERVER_MODE:
+	case SLAP_TOOL_MODE:
+		Debug( LDAP_DEBUG_TRACE,
+			"%s init: initiated %s.\n",	name,
+			(mode & SLAP_MODE) == SLAP_TOOL_MODE ? "tool" : "server",
+			0 );
+
 
+		slap_name = name;
 
-			slap_name = name;
-	
-			(void) ldap_pvt_thread_initialize();
+		(void) ldap_pvt_thread_initialize();
 
-			ldap_pvt_thread_pool_init( &connection_pool,
+		ldap_pvt_thread_pool_init( &connection_pool,
 				connection_pool_max, 0);
 
-			ldap_pvt_thread_mutex_init( &entry2str_mutex );
-			ldap_pvt_thread_mutex_init( &replog_mutex );
-			ldap_pvt_thread_mutex_init( &num_ops_mutex );
-			ldap_pvt_thread_mutex_init( &num_sent_mutex );
+		ldap_pvt_thread_mutex_init( &entry2str_mutex );
+		ldap_pvt_thread_mutex_init( &replog_mutex );
+
+		ldap_pvt_thread_mutex_init( &slap_counters.sc_sent_mutex );
+		ldap_pvt_thread_mutex_init( &slap_counters.sc_ops_mutex );
+#ifdef HAVE_GMP
+		mpz_init( slap_counters.sc_bytes );
+		mpz_init( slap_counters.sc_pdu );
+		mpz_init( slap_counters.sc_entries );
+		mpz_init( slap_counters.sc_refs );
+
+		mpz_init( slap_counters.sc_ops_completed );
+		mpz_init( slap_counters.sc_ops_initiated );
 
 #ifdef SLAPD_MONITOR
-			{
-				int i;
-				for ( i = 0; i < SLAP_OP_LAST; i++ ) {
-					num_ops_initiated_[ i ] = 0;
-					num_ops_completed_[ i ] = 0;
-				}
-			}
-#endif
+		for ( i = 0; i < SLAP_OP_LAST; i++ ) {
+			mpz_init( slap_counters.sc_ops_initiated_[ i ] );
+			mpz_init( slap_counters.sc_ops_completed_[ i ] );
+		}
+#endif /* SLAPD_MONITOR */
+#else /* ! HAVE_GMP */
+		slap_counters.sc_bytes = 0;
+		slap_counters.sc_pdu = 0;
+		slap_counters.sc_entries = 0;
+		slap_counters.sc_refs = 0;
+
+		slap_counters.sc_ops_completed = 0;
+		slap_counters.sc_ops_initiated = 0;
+#ifdef SLAPD_MONITOR
+		for ( i = 0; i < SLAP_OP_LAST; i++ ) {
+			slap_counters.sc_ops_initiated_[ i ] = 0;
+			slap_counters.sc_ops_completed_[ i ] = 0;
+		}
+#endif /* SLAPD_MONITOR */
+#endif /* ! HAVE_GMP */
 
 #ifndef HAVE_GMTIME_R
-			ldap_pvt_thread_mutex_init( &gmtime_mutex );
+		ldap_pvt_thread_mutex_init( &gmtime_mutex );
 #endif
 #if defined( SLAPD_CRYPT ) || defined( SLAPD_SPASSWD )
-			ldap_pvt_thread_mutex_init( &passwd_mutex );
+		ldap_pvt_thread_mutex_init( &passwd_mutex );
 #endif
 
-			rc = slap_sasl_init();
+		rc = slap_sasl_init();
 
-			if( rc == 0 ) {
-				rc = backend_init( );
-			}
+		if( rc == 0 ) {
+			rc = backend_init( );
+		}
 
-			break;
+		break;
 
-		default:
-			Debug( LDAP_DEBUG_ANY,
-				"%s init: undefined mode (%d).\n", name, mode, 0 );
+	default:
+		Debug( LDAP_DEBUG_ANY,
+			"%s init: undefined mode (%d).\n", name, mode, 0 );
 
-			rc = 1;
-			break;
+		rc = 1;
+		break;
 	}
 
 	return rc;
@@ -220,6 +231,7 @@ int slap_shutdown( Backend *be )
 int slap_destroy(void)
 {
 	int rc;
+	int i;
 
 	Debug( LDAP_DEBUG_TRACE,
 		"%s destroy: freeing system resources.\n",
@@ -232,6 +244,38 @@ int slap_destroy(void)
 
 	entry_destroy();
 
+	switch ( slapMode & SLAP_MODE ) {
+	case SLAP_SERVER_MODE:
+	case SLAP_TOOL_MODE:
+
+		ldap_pvt_thread_mutex_destroy( &slap_counters.sc_sent_mutex );
+		ldap_pvt_thread_mutex_destroy( &slap_counters.sc_ops_mutex );
+#ifdef HAVE_GMP
+		mpz_clear( slap_counters.sc_bytes );
+		mpz_clear( slap_counters.sc_pdu );
+		mpz_clear( slap_counters.sc_entries );
+		mpz_clear( slap_counters.sc_refs );
+		mpz_clear( slap_counters.sc_ops_completed );
+		mpz_clear( slap_counters.sc_ops_initiated );
+
+#ifdef SLAPD_MONITOR
+		for ( i = 0; i < SLAP_OP_LAST; i++ ) {
+			mpz_clear( slap_counters.sc_ops_initiated_[ i ] );
+			mpz_clear( slap_counters.sc_ops_completed_[ i ] );
+		}
+#endif /* SLAPD_MONITOR */
+#endif /* HAVE_GMP */
+		break;
+
+	default:
+		Debug( LDAP_DEBUG_ANY,
+			"slap_destroy(): undefined mode (%d).\n", slapMode, 0, 0 );
+
+		rc = 1;
+		break;
+
+	}
+
 	ldap_pvt_thread_destroy();
 
 	/* should destory the above mutex */
diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h
index 5482f0a07c..ddb45d4977 100644
--- a/servers/slapd/proto-slap.h
+++ b/servers/slapd/proto-slap.h
@@ -640,6 +640,11 @@ LDAP_SLAPD_F (int) filter_escape_value LDAP_P(( struct berval *in,
 
 LDAP_SLAPD_F (int) test_filter LDAP_P(( Operation *op, Entry *e, Filter *f ));
 
+/*
+ * frontend.c
+ */
+LDAP_SLAPD_F (int) frontend_init LDAP_P(( void ));
+
 /*
  * globals.c
  */
@@ -1317,19 +1322,7 @@ LDAP_SLAPD_V (int)		ldap_syslog;
 LDAP_SLAPD_V (struct berval)	default_search_base;
 LDAP_SLAPD_V (struct berval)	default_search_nbase;
 
-LDAP_SLAPD_V (ldap_pvt_thread_mutex_t)	num_sent_mutex;
-LDAP_SLAPD_V (unsigned long)		num_bytes_sent;
-LDAP_SLAPD_V (unsigned long)		num_pdu_sent;
-LDAP_SLAPD_V (unsigned long)		num_entries_sent;
-LDAP_SLAPD_V (unsigned long)		num_refs_sent;
-
-LDAP_SLAPD_V (ldap_pvt_thread_mutex_t)	num_ops_mutex;
-LDAP_SLAPD_V (unsigned long)		num_ops_completed;
-LDAP_SLAPD_V (unsigned long)		num_ops_initiated;
-#ifdef SLAPD_MONITOR
-LDAP_SLAPD_V (unsigned long)		num_ops_completed_[SLAP_OP_LAST];
-LDAP_SLAPD_V (unsigned long)		num_ops_initiated_[SLAP_OP_LAST];
-#endif /* SLAPD_MONITOR */
+LDAP_SLAPD_V (slap_counters_t)	slap_counters;
 
 LDAP_SLAPD_V (char *)		slapd_pid_file;
 LDAP_SLAPD_V (char *)		slapd_args_file;
diff --git a/servers/slapd/result.c b/servers/slapd/result.c
index b80743871e..1f87393182 100644
--- a/servers/slapd/result.c
+++ b/servers/slapd/result.c
@@ -447,10 +447,15 @@ send_ldap_response(
 	}
 #endif /* LDAP_SLAPI */
 
-	ldap_pvt_thread_mutex_lock( &num_sent_mutex );
-	num_bytes_sent += bytes;
-	num_pdu_sent++;
-	ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
+	ldap_pvt_thread_mutex_lock( &slap_counters.sc_sent_mutex );
+#ifdef HAVE_GMP
+	mpz_add_ui( slap_counters.sc_pdu, slap_counters.sc_pdu, 1 );
+	mpz_add_ui( slap_counters.sc_bytes, slap_counters.sc_bytes, bytes );
+#else /* ! HAVE_GMP */
+	slap_counters.sc_bytes += bytes;
+	slap_counters.sc_pdu++;
+#endif /* ! HAVE_GMP */
+	ldap_pvt_thread_mutex_unlock( &slap_counters.sc_sent_mutex );
 
 cleanup:;
 	/* Tell caller that we did this for real, as opposed to being
@@ -1175,11 +1180,17 @@ slap_send_search_entry( Operation *op, SlapReply *rs )
 		}
 		rs->sr_nentries++;
 
-		ldap_pvt_thread_mutex_lock( &num_sent_mutex );
-		num_bytes_sent += bytes;
-		num_entries_sent++;
-		num_pdu_sent++;
-		ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
+		ldap_pvt_thread_mutex_lock( &slap_counters.sc_sent_mutex );
+#ifdef HAVE_GMP
+		mpz_add_ui( slap_counters.sc_bytes, slap_counters.sc_bytes, bytes );
+		mpz_add_ui( slap_counters.sc_entries, slap_counters.sc_entries, 1 );
+		mpz_add_ui( slap_counters.sc_pdu, slap_counters.sc_pdu, 1 );
+#else /* ! HAVE_GMP */
+		slap_counters.sc_bytes += bytes;
+		slap_counters.sc_entries++;
+		slap_counters.sc_pdu++;
+#endif /* ! HAVE_GMP */
+		ldap_pvt_thread_mutex_unlock( &slap_counters.sc_sent_mutex );
 	}
 
 	Statslog( LDAP_DEBUG_STATS2, "conn=%lu op=%lu ENTRY dn=\"%s\"\n",
@@ -1364,11 +1375,17 @@ slap_send_search_reference( Operation *op, SlapReply *rs )
 	bytes = send_ldap_ber( op->o_conn, ber );
 	ber_free_buf( ber );
 
-	ldap_pvt_thread_mutex_lock( &num_sent_mutex );
-	num_bytes_sent += bytes;
-	num_refs_sent++;
-	num_pdu_sent++;
-	ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
+	ldap_pvt_thread_mutex_lock( &slap_counters.sc_sent_mutex );
+#ifdef HAVE_GMP
+	mpz_add_ui( slap_counters.sc_bytes, slap_counters.sc_bytes, bytes );
+	mpz_add_ui( slap_counters.sc_refs, slap_counters.sc_refs, 1 );
+	mpz_add_ui( slap_counters.sc_pdu, slap_counters.sc_pdu, 1 );
+#else /* ! HAVE_GMP */
+	slap_counters.sc_bytes += bytes;
+	slap_counters.sc_refs++;
+	slap_counters.sc_pdu++;
+#endif /* ! HAVE_GMP */
+	ldap_pvt_thread_mutex_unlock( &slap_counters.sc_sent_mutex );
 #ifdef LDAP_CONNECTIONLESS
 	}
 #endif
diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h
index 9fa5fc22e6..0b7b5dba64 100644
--- a/servers/slapd/slap.h
+++ b/servers/slapd/slap.h
@@ -29,6 +29,10 @@
 
 #include "ldap_defaults.h"
 
+#ifdef HAVE_GMP
+#include <gmp.h>
+#endif /* HAVE_GMP */
+
 #include <stdio.h>
 #include <ac/stdlib.h>
 
@@ -2424,6 +2428,49 @@ enum {
 };
 #endif /* SLAPD_MONITOR */
 
+typedef struct slap_counters_t {
+	ldap_pvt_thread_mutex_t	sc_sent_mutex;
+#ifdef HAVE_GMP
+	mpz_t			sc_bytes;
+	mpz_t			sc_pdu;
+	mpz_t			sc_entries;
+	mpz_t			sc_refs;
+#else /* ! HAVE_GMP */
+	unsigned long		sc_bytes;
+	unsigned long		sc_pdu;
+	unsigned long		sc_entries;
+	unsigned long		sc_refs;
+#endif /* ! HAVE_GMP */
+
+	ldap_pvt_thread_mutex_t	sc_ops_mutex;
+#ifdef HAVE_GMP
+	mpz_t			sc_ops_completed;
+	mpz_t			sc_ops_initiated;
+#ifdef SLAPD_MONITOR
+	mpz_t			sc_ops_completed_[SLAP_OP_LAST];
+	mpz_t			sc_ops_initiated_[SLAP_OP_LAST];
+#endif /* SLAPD_MONITOR */
+#else /* ! HAVE_GMP */
+	unsigned long		sc_ops_completed;
+	unsigned long		sc_ops_initiated;
+#ifdef SLAPD_MONITOR
+	unsigned long		sc_ops_completed_[SLAP_OP_LAST];
+	unsigned long		sc_ops_initiated_[SLAP_OP_LAST];
+#endif /* SLAPD_MONITOR */
+#endif /* ! HAVE_GMP */
+} slap_counters_t;
+
+#define	num_sent_mutex		slap_counters.sc_sent_mutex
+#define	num_bytes_sent		slap_counters.sc_bytes
+#define	num_pdu_sent		slap_counters.sc_pdu
+#define	num_entries_sent	slap_counters.sc_entries
+#define	num_refs_sent		slap_counters.sc_refs
+#define	num_ops_mutex		slap_counters.sc_ops_mutex
+#define num_ops_completed	slap_counters.sc_ops_completed
+#define num_ops_initiated	slap_counters.sc_ops_initiated
+#define num_ops_completed_	slap_counters.sc_ops_completed_
+#define num_ops_initiated_	slap_counters.sc_ops_initiated_
+
 /*
  * Better know these all around slapd
  */
-- 
GitLab