[Fedora-directory-commits] ldapserver/ldap/servers/slapd add.c, 1.14, 1.15 agtmmap.c, 1.11, 1.12 agtmmap.h, 1.11, 1.12 bind.c, 1.16, 1.17 compare.c, 1.8, 1.9 connection.c, 1.21, 1.22 defbackend.c, 1.6, 1.7 delete.c, 1.9, 1.10 fe.h, 1.9, 1.10 globals.c, 1.8, 1.9 init.c, 1.7, 1.8 libglobs.c, 1.27, 1.28 libslapd.def, 1.18, 1.19 main.c, 1.26, 1.27 modify.c, 1.17, 1.18 modrdn.c, 1.10, 1.11 monitor.c, 1.7, 1.8 proto-slap.h, 1.39, 1.40 result.c, 1.14, 1.15 search.c, 1.10, 1.11 slap.h, 1.37, 1.38 slapi-private.h, 1.27, 1.28 snmp_collator.c, 1.15, 1.16

Nathan Kinder nkinder at fedoraproject.org
Fri Oct 24 22:37:01 UTC 2008


Author: nkinder

Update of /cvs/dirsec/ldapserver/ldap/servers/slapd
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv9308/ldap/servers/slapd

Modified Files:
	add.c agtmmap.c agtmmap.h bind.c compare.c connection.c 
	defbackend.c delete.c fe.h globals.c init.c libglobs.c 
	libslapd.def main.c modify.c modrdn.c monitor.c proto-slap.h 
	result.c search.c slap.h slapi-private.h snmp_collator.c 
Log Message:
Resolves: 207457
Summary: Convert counters to 64-bit capable Slapi_Counter type.



Index: add.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/add.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -r1.14 -r1.15
--- add.c	17 Oct 2008 22:12:47 -0000	1.14
+++ add.c	24 Oct 2008 22:36:58 -0000	1.15
@@ -93,7 +93,7 @@
     ber = operation->o_ber;
 
 	/* count the add request */
-	snmp_increment_counter(g_get_global_snmp_vars()->ops_tbl.dsAddEntryOps);
+	slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsAddEntryOps);
 
 	/*
 	 * Parse the add request.  It looks like this:


Index: agtmmap.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/agtmmap.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- agtmmap.c	8 Oct 2008 17:29:03 -0000	1.11
+++ agtmmap.c	24 Oct 2008 22:36:58 -0000	1.12
@@ -87,8 +87,8 @@
  *	mode      ->  Must be one of O_RDONLY / O_RDWR.
  *		      O_RDWR creates the file if it does not exist.
  * Outputs:
- *	hdl	  ->  Opaque handle to the mapped file. Should be passed
- *		      Passed to a subsequent agt_mupdate_stats() or 
+ *	hdl	  ->  Opaque handle to the mapped file. Should be
+ *		      passed to a subsequent agt_mupdate_stats() or 
  *		      agt_mread_stats() or agt_mclose_stats() call.
  * Return Values:
  *		      Returns 0 on successfully doing the memmap or error codes 


Index: agtmmap.h
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/agtmmap.h,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- agtmmap.h	18 Oct 2007 01:22:29 -0000	1.11
+++ agtmmap.h	24 Oct 2008 22:36:58 -0000	1.12
@@ -123,32 +123,32 @@
     /*
      *      Ops Table attributes
      */
-    PRUint32 dsAnonymousBinds;
-    PRUint32 dsUnAuthBinds;
-    PRUint32 dsSimpleAuthBinds;
-    PRUint32 dsStrongAuthBinds;
-    PRUint32 dsBindSecurityErrors;
-    PRUint32 dsInOps;
-    PRUint32 dsReadOps;
-    PRUint32 dsCompareOps;
-    PRUint32 dsAddEntryOps;
-    PRUint32 dsRemoveEntryOps;
-    PRUint32 dsModifyEntryOps;
-    PRUint32 dsModifyRDNOps;
-    PRUint32 dsListOps;
-    PRUint32 dsSearchOps;
-    PRUint32 dsOneLevelSearchOps;
-    PRUint32 dsWholeSubtreeSearchOps;
-    PRUint32 dsReferrals;
-    PRUint32 dsChainings;
-    PRUint32 dsSecurityErrors;
-    PRUint32 dsErrors;
-    PRUint32 dsConnections;	 /* Number of currently connected clients */
-    PRUint32 dsConnectionSeq; /* Monotonically increasing number bumped on each new conn est */
-    PRUint32 dsBytesRecv;	/* Count of bytes read from clients */
-    PRUint32 dsBytesSent;	/* Count of bytes sent to clients */
-    PRUint32 dsEntriesReturned; /* Number of entries returned by the server */
-    PRUint32 dsReferralsReturned; /* Number of entries returned by the server */
+    PRUint64 dsAnonymousBinds;
+    PRUint64 dsUnAuthBinds;
+    PRUint64 dsSimpleAuthBinds;
+    PRUint64 dsStrongAuthBinds;
+    PRUint64 dsBindSecurityErrors;
+    PRUint64 dsInOps;
+    PRUint64 dsReadOps;
+    PRUint64 dsCompareOps;
+    PRUint64 dsAddEntryOps;
+    PRUint64 dsRemoveEntryOps;
+    PRUint64 dsModifyEntryOps;
+    PRUint64 dsModifyRDNOps;
+    PRUint64 dsListOps;
+    PRUint64 dsSearchOps;
+    PRUint64 dsOneLevelSearchOps;
+    PRUint64 dsWholeSubtreeSearchOps;
+    PRUint64 dsReferrals;
+    PRUint64 dsChainings;
+    PRUint64 dsSecurityErrors;
+    PRUint64 dsErrors;
+    PRUint64 dsConnections;	 /* Number of currently connected clients */
+    PRUint64 dsConnectionSeq; /* Monotonically increasing number bumped on each new conn est */
+    PRUint64 dsBytesRecv;	/* Count of bytes read from clients */
+    PRUint64 dsBytesSent;	/* Count of bytes sent to clients */
+    PRUint64 dsEntriesReturned; /* Number of entries returned by the server */
+    PRUint64 dsReferralsReturned; /* Number of entries returned by the server */
 };
 
 struct entries_stats_t
@@ -156,11 +156,11 @@
     /*
      *  Entries Table Attributes
      */
-    PRUint32 dsMasterEntries;
-    PRUint32 dsCopyEntries;
-    PRUint32 dsCacheEntries;
-    PRUint32 dsCacheHits;
-    PRUint32 dsSlaveHits;
+    PRUint64 dsMasterEntries;
+    PRUint64 dsCopyEntries;
+    PRUint64 dsCacheEntries;
+    PRUint64 dsCacheHits;
+    PRUint64 dsSlaveHits;
 };
 
 struct int_stats_t


Index: bind.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/bind.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -r1.16 -r1.17
--- bind.c	17 Oct 2008 22:12:47 -0000	1.16
+++ bind.c	24 Oct 2008 22:36:58 -0000	1.17
@@ -345,7 +345,7 @@
          * All SASL auth methods are categorized as strong binds,
          * although they are not necessarily stronger than simple.
          */
-        snmp_increment_counter(g_get_global_snmp_vars()->ops_tbl.dsStrongAuthBinds);
+        slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsStrongAuthBinds);
         if ( saslmech == NULL || *saslmech == '\0' ) {
             send_ldap_result( pb, LDAP_AUTH_METHOD_NOT_SUPPORTED, NULL,
                               "SASL mechanism absent", 0, NULL );
@@ -423,13 +423,13 @@
         }
         break;
     case LDAP_AUTH_SIMPLE:
-        snmp_increment_counter(g_get_global_snmp_vars()->ops_tbl.dsSimpleAuthBinds);
+        slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsSimpleAuthBinds);
         /* accept null binds */
         if (dn == NULL || *dn == '\0') {
-            snmp_increment_counter(g_get_global_snmp_vars()->ops_tbl.dsAnonymousBinds);
+            slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsAnonymousBinds);
             /* by definition its anonymous is also UnAuthenticated so increment 
                that counter */
-            snmp_increment_counter(g_get_global_snmp_vars()->ops_tbl.dsUnAuthBinds);
+            slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsUnAuthBinds);
 
             /* call preop plugins */
             if (plugin_call_plugins( pb, SLAPI_PLUGIN_PRE_BIND_FN ) == 0){
@@ -455,7 +455,7 @@
     if ( isroot && method == LDAP_AUTH_SIMPLE ) {
         if ( cred.bv_len == 0 ) {
             /* unauthenticated bind */
-            snmp_increment_counter(g_get_global_snmp_vars()->ops_tbl.dsUnAuthBinds);
+            slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsUnAuthBinds);
 
         } else {
             /* a passwd was supplied -- check it */
@@ -473,7 +473,7 @@
                 send_ldap_result( pb, LDAP_INVALID_CREDENTIALS, NULL,
                                   NULL, 0, NULL );
 				/* increment BindSecurityErrorcount */
-                snmp_increment_counter(g_get_global_snmp_vars()->ops_tbl.dsBindSecurityErrors);
+                slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsBindSecurityErrors);
                 value_done(&cv);
                 goto free_and_return;
             }
@@ -617,11 +617,11 @@
                 
                 if(cred.bv_len == 0) {
                     /* its an UnAuthenticated Bind, DN specified but no pw */
-                    snmp_increment_counter(g_get_global_snmp_vars()->ops_tbl.dsUnAuthBinds);
+                    slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsUnAuthBinds);
                 }else{
                     /* password must have been invalid */
                     /* increment BindSecurityError count */
-                    snmp_increment_counter(g_get_global_snmp_vars()->ops_tbl.dsBindSecurityErrors);
+                    slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsBindSecurityErrors);
                 }
 			
             }


Index: compare.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/compare.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- compare.c	17 Oct 2008 22:12:47 -0000	1.8
+++ compare.c	24 Oct 2008 22:36:58 -0000	1.9
@@ -77,7 +77,7 @@
 	LDAPDebug( LDAP_DEBUG_TRACE, "do_compare\n", 0, 0, 0 );
 
 	/* count the compare request */
-	snmp_increment_counter(g_get_global_snmp_vars()->ops_tbl.dsCompareOps);
+	slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsCompareOps);
 
     /* have to init this here so we can "done" it below if we short circuit */
     slapi_sdn_init(&sdn);


Index: connection.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/connection.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -r1.21 -r1.22
--- connection.c	17 Oct 2008 22:12:47 -0000	1.21
+++ connection.c	24 Oct 2008 22:36:58 -0000	1.22
@@ -220,8 +220,8 @@
     conn->c_connid = slapi_counter_increment(num_conns);
 
     if (! in_referral_mode) {
-	snmp_increment_counter(g_get_global_snmp_vars()->ops_tbl.dsConnectionSeq);
-	snmp_increment_counter(g_get_global_snmp_vars()->ops_tbl.dsConnections);
+	slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsConnectionSeq);
+	slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsConnections);
     }
 
     /* 
@@ -650,7 +650,7 @@
 static void inc_op_count(Connection* conn)
 {
 	PR_AtomicIncrement(&conn->c_opscompleted);
-	PR_AtomicIncrement(&ops_completed);
+	slapi_counter_increment(ops_completed);
 }
 
 static int connection_increment_reference(Connection *conn)
@@ -828,8 +828,8 @@
     slapi_pblock_set (pb, SLAPI_DESTROY_CONTENT, &destroy_content);
 
 	if (! config_check_referral_mode()) {
-		PR_AtomicIncrement(&ops_initiated);
-		snmp_increment_counter(g_get_global_snmp_vars()->ops_tbl.dsInOps); 
+		slapi_counter_increment(ops_initiated);
+		slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsInOps); 
 	}
 
 	if ( (tag = ber_get_int( op->o_ber, &msgid ))
@@ -2064,8 +2064,8 @@
 			connection_make_new_pb(&pb,conn);
 			PR_Unlock(conn->c_mutex);
 			if (! config_check_referral_mode()) {
-	    		  PR_AtomicIncrement(&ops_initiated);
-	    		  snmp_increment_counter(g_get_global_snmp_vars()->ops_tbl.dsInOps); 
+			  slapi_counter_increment(ops_initiated);
+	    		  slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsInOps); 
 			}
 		}
 		/* Once we're here we have a pb */ 
@@ -2171,7 +2171,7 @@
 		/* number of ops on this connection */
 		PR_AtomicIncrement(&conn->c_opscompleted);
 		/* total number of ops for the server */
-		PR_AtomicIncrement(&ops_completed);
+		slapi_counter_increment(ops_completed);
 		/* If this op isn't a persistent search, remove it */
 		if ( !( pb->pb_op->o_flags & OP_FLAG_PS )) {
 		    /* delete from connection operation queue & decr refcnt */
@@ -2247,8 +2247,8 @@
     PR_Unlock( op_thread_lock );
 	
 	if (! config_check_referral_mode()) {
-	    PR_AtomicIncrement(&ops_initiated);
-	    snmp_increment_counter(g_get_global_snmp_vars()->ops_tbl.dsInOps); 
+	    slapi_counter_increment(ops_initiated);
+	    slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsInOps); 
 	}
 	return 0;
 }
@@ -2567,7 +2567,7 @@
 	}
 
 	if (! config_check_referral_mode()) {
-	    snmp_increment_counter(g_get_global_snmp_vars()->ops_tbl.dsConnections);
+	    slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsConnections);
 	}
 
 	conn->c_gettingber = 0;


Index: defbackend.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/defbackend.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- defbackend.c	18 Oct 2007 00:08:34 -0000	1.6
+++ defbackend.c	24 Oct 2008 22:36:58 -0000	1.7
@@ -216,7 +216,7 @@
     slapi_pblock_get( pb, SLAPI_BIND_METHOD, &method );
     slapi_pblock_get( pb, SLAPI_BIND_CREDENTIALS, &cred );
     if ( method == LDAP_AUTH_SIMPLE && cred->bv_len == 0 ) {
-	snmp_increment_counter(g_get_global_snmp_vars()->ops_tbl.dsAnonymousBinds);
+	slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsAnonymousBinds);
 	rc = SLAPI_BIND_ANONYMOUS;
     } else {
 	send_nobackend_ldap_result( pb );


Index: delete.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/delete.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- delete.c	17 Oct 2008 22:12:47 -0000	1.9
+++ delete.c	24 Oct 2008 22:36:58 -0000	1.10
@@ -80,7 +80,7 @@
 	ber = operation->o_ber;
 
 	/* count the delete request */
-	snmp_increment_counter(g_get_global_snmp_vars()->ops_tbl.dsRemoveEntryOps);
+	slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsRemoveEntryOps);
 
 	/*
 	 * Parse the delete request.  It looks like this:


Index: fe.h
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/fe.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- fe.h	17 Oct 2008 22:12:47 -0000	1.9
+++ fe.h	24 Oct 2008 22:36:58 -0000	1.10
@@ -56,9 +56,8 @@
 #endif /* DONT_DECLARE_SLAPD_LDAP_DEBUG */
 #endif
 #endif
-extern PRInt32 ops_initiated;
-extern PRInt32 ops_completed;
-extern PRLock *ops_mutex;
+extern Slapi_Counter *ops_initiated;
+extern Slapi_Counter *ops_completed;
 extern PRThread *listener_tid;
 extern PRThread *listener_tid;
 extern Slapi_Counter *num_conns;


Index: globals.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/globals.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- globals.c	17 Oct 2008 22:12:47 -0000	1.8
+++ globals.c	24 Oct 2008 22:36:58 -0000	1.9
@@ -88,9 +88,8 @@
 /*
  * global variables that need mutex protection
  */
-PRInt32		ops_initiated;
-PRInt32		ops_completed;
-PRLock		*ops_mutex;
+Slapi_Counter	*ops_initiated;
+Slapi_Counter	*ops_completed;
 Slapi_Counter	*num_conns;
 
 
@@ -171,4 +170,17 @@
     sep->sep_slapd_ssl_init2 = (caddr_t)slapd_ssl_init2;
     set_dll_entry_points( sep );
    
+	/* To apply the nsslapd-counters config value properly,
+	   these values are initialized here after config file is read */
+	if (config_get_slapi_counters()) {
+		ops_initiated = slapi_counter_new();
+		ops_completed = slapi_counter_new();
+		g_set_num_entries_sent( slapi_counter_new() );
+		g_set_num_bytes_sent( slapi_counter_new() );
+	} else {
+		ops_initiated = NULL;
+		ops_completed = NULL;
+		g_set_num_entries_sent( NULL );
+		g_set_num_bytes_sent( NULL );
+	}
 }


Index: init.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/init.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- init.c	17 Oct 2008 22:12:47 -0000	1.7
+++ init.c	24 Oct 2008 22:36:58 -0000	1.8
@@ -73,16 +73,12 @@
 	/* We don't worry about free'ing this stuff
          * since the only time we want to do that is when
          * the process is exiting. */
-	ops_mutex = PR_NewLock();
 	num_conns = slapi_counter_new();
-	g_set_num_sent_mutex( PR_NewLock() );
 	g_set_current_conn_count_mutex( PR_NewLock() );
 
 	slapd_re_init();
 
-	if ( ops_mutex == NULL ||
-	    g_get_num_sent_mutex() == NULL ||
-	    g_get_current_conn_count_mutex() == NULL )
+	if ( g_get_current_conn_count_mutex() == NULL )
 	{
 		LDAPDebug( LDAP_DEBUG_ANY,
 		    "init: PR_NewLock failed\n", 0, 0, 0 );


Index: libglobs.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/libglobs.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -r1.27 -r1.28
--- libglobs.c	23 Oct 2008 22:42:55 -0000	1.27
+++ libglobs.c	24 Oct 2008 22:36:58 -0000	1.28
@@ -488,6 +488,10 @@
                 NULL, 0,
 		(void**)&global_slapdFrontendConfig.ldapi_auto_dn_suffix, CONFIG_STRING, NULL},
 #endif
+	{CONFIG_SLAPI_COUNTER_ATTRIBUTE, config_set_slapi_counters,
+		NULL, 0,
+		(void**)&global_slapdFrontendConfig.slapi_counters, CONFIG_ON_OFF, 
+		config_get_slapi_counters},
 	{CONFIG_ACCESSLOG_MINFREEDISKSPACE_ATTRIBUTE, NULL,
 		log_set_mindiskspace, SLAPD_ACCESS_LOG,
 		(void**)&global_slapdFrontendConfig.accesslog_minfreespace, CONFIG_INT, NULL},
@@ -836,6 +840,7 @@
 #if defined(ENABLE_AUTO_DN_SUFFIX)
   cfg->ldapi_auto_dn_suffix = slapi_ch_strdup("cn=peercred,cn=external,cn=auth");
 #endif
+  cfg->slapi_counters = LDAP_ON;
   cfg->threadnumber = SLAPD_DEFAULT_MAX_THREADS;
   cfg->maxthreadsperconn = SLAPD_DEFAULT_MAX_THREADS_PER_CONN;
   cfg->reservedescriptors = SLAPD_DEFAULT_RESERVE_FDS;
@@ -1398,6 +1403,22 @@
 }
 #endif
 
+/*
+ * Set nsslapd-counters: on | off to the internal config variable slapi_counters.
+ * If set to off, slapi_counters is not initialized and the counters are not
+ * incremented.  Note: counters which are necessary for the server's running
+ * are not disabled.
+ */
+int config_set_slapi_counters( const char *attrname, char *value, char *errorbuf, int apply )
+{
+	int retVal = LDAP_SUCCESS;
+	slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+
+	retVal = config_set_onoff(attrname, value,
+				&(slapdFrontendConfig->slapi_counters), errorbuf, apply);
+
+	return retVal;
+}
 
 int
 config_set_securelistenhost( const char *attrname, char *value, char *errorbuf, int apply ) {
@@ -3438,6 +3459,17 @@
 }
 #endif
 
+int config_get_slapi_counters()
+{   
+  int retVal;
+  slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig(); 
+  CFG_LOCK_READ(slapdFrontendConfig);
+  retVal = slapdFrontendConfig->slapi_counters;
+  CFG_UNLOCK_READ(slapdFrontendConfig);
+
+  return retVal;
+}
+
 char *
 config_get_workingdir() {
   slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();


Index: libslapd.def
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/libslapd.def,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -r1.18 -r1.19
--- libslapd.def	4 Oct 2007 16:27:47 -0000	1.18
+++ libslapd.def	24 Oct 2008 22:36:58 -0000	1.19
@@ -211,8 +211,6 @@
 	g_set_num_bytes_sent	@173
 	g_get_num_entries_sent	@174
 	g_set_num_entries_sent	@175
-	g_get_num_sent_mutex	@176
-	g_set_num_sent_mutex	@177
 	g_get_default_referral	@178
 	g_set_default_referral	@179
 	slapi_ch_bvdup		@180


Index: main.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/main.c,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -r1.26 -r1.27
--- main.c	15 Oct 2008 06:30:05 -0000	1.26
+++ main.c	24 Oct 2008 22:36:58 -0000	1.27
@@ -1039,7 +1039,12 @@
 				slapdFrontendConfig->configdir);
 
 		eq_init();					/* must be done before plugins started */
-		snmp_collator_start();
+
+		/* Start the SNMP collator if counters are enabled. */
+		if (config_get_slapi_counters()) {
+			snmp_collator_start();
+		}
+
 		ps_init_psearch_system();   /* must come before plugin_startall() */
 
 		/* Initailize the mapping tree */


Index: modify.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/modify.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -r1.17 -r1.18
--- modify.c	17 Oct 2008 22:12:47 -0000	1.17
+++ modify.c	24 Oct 2008 22:36:58 -0000	1.18
@@ -138,7 +138,7 @@
 	ber = operation->o_ber;
 
 	/* count the modify request */
-	snmp_increment_counter(g_get_global_snmp_vars()->ops_tbl.dsModifyEntryOps);
+	slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsModifyEntryOps);
 
 	/*
 	 * Parse the modify request.  It looks like this:


Index: modrdn.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/modrdn.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- modrdn.c	17 Oct 2008 22:12:47 -0000	1.10
+++ modrdn.c	24 Oct 2008 22:36:58 -0000	1.11
@@ -79,7 +79,7 @@
 	LDAPDebug( LDAP_DEBUG_TRACE, "do_modrdn\n", 0, 0, 0 );
 
 	/* count the modrdn request */
-	snmp_increment_counter(g_get_global_snmp_vars()->ops_tbl.dsModifyRDNOps);
+	slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsModifyRDNOps);
 
 	slapi_pblock_get( pb, SLAPI_OPERATION, &operation);
 	ber = operation->o_ber;


Index: monitor.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/monitor.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- monitor.c	20 Sep 2007 16:54:38 -0000	1.7
+++ monitor.c	24 Oct 2008 22:36:58 -0000	1.8
@@ -93,30 +93,22 @@
 
 	connection_table_as_entry(the_connection_table, e);
 
-	PR_Lock( ops_mutex );
-	sprintf( buf, "%ld", (long) ops_initiated );
-	PR_Unlock( ops_mutex );
+	sprintf( buf, "%" PRIu64, slapi_counter_get_value(ops_initiated) );
 	val.bv_val = buf;
 	val.bv_len = strlen( buf );
 	attrlist_replace( &e->e_attrs, "opsinitiated", vals );
 
-	PR_Lock( ops_mutex );
-	sprintf( buf, "%ld", (long) ops_completed );
-	PR_Unlock( ops_mutex );
+	sprintf( buf, "%" PRIu64, slapi_counter_get_value(ops_completed) );
 	val.bv_val = buf;
 	val.bv_len = strlen( buf );
 	attrlist_replace( &e->e_attrs, "opscompleted", vals );
 
-	PR_Lock( g_get_num_sent_mutex() );
-	len = PR_snprintf ( buf, BUFSIZ, "%llu", g_get_num_entries_sent() );
-	PR_Unlock( g_get_num_sent_mutex() );
+	len = PR_snprintf ( buf, BUFSIZ, "%" PRIu64, g_get_num_entries_sent() );
 	val.bv_val = buf;
 	val.bv_len = ( unsigned long ) len;
 	attrlist_replace( &e->e_attrs, "entriessent", vals );
 
-	PR_Lock( g_get_num_sent_mutex() );
-	len = PR_snprintf ( buf, BUFSIZ, "%llu", g_get_num_bytes_sent() );
-	PR_Unlock( g_get_num_sent_mutex() );
+	len = PR_snprintf ( buf, BUFSIZ, "%" PRIu64, g_get_num_bytes_sent() );
 	val.bv_val = buf;
 	val.bv_len = ( unsigned long ) len;
 	attrlist_replace( &e->e_attrs, "bytessent", vals );


Index: proto-slap.h
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/proto-slap.h,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -r1.39 -r1.40
--- proto-slap.h	24 Oct 2008 00:21:18 -0000	1.39
+++ proto-slap.h	24 Oct 2008 22:36:58 -0000	1.40
@@ -255,6 +255,7 @@
 #if defined(ENABLE_AUTO_DN_SUFFIX)
 int config_set_ldapi_auto_dn_suffix( const char *attrname, char *value, char *errorbuf, int apply );   
 #endif
+int config_set_slapi_counters( const char *attrname, char *value, char *errorbuf, int apply );   
 int config_set_srvtab( const char *attrname, char *value, char *errorbuf, int apply );
 int config_set_sizelimit( const char *attrname, char *value, char *errorbuf, int apply );
 int config_set_lastmod( const char *attrname, char *value, char *errorbuf, int apply );
@@ -370,6 +371,7 @@
 #if defined(ENABLE_AUTO_DN_SUFFIX)
 char *config_get_ldapi_auto_dn_suffix(); 
 #endif
+int config_get_slapi_counters(); 
 char *config_get_srvtab();
 int config_get_sizelimit();
 char *config_get_pw_storagescheme();
@@ -821,14 +823,12 @@
 /*
  * result.c
  */
-void g_set_num_entries_sent( PRUint64 val );
+void g_set_num_entries_sent( Slapi_Counter *counter );
 PRUint64 g_get_num_entries_sent();
-void g_set_num_bytes_sent( PRUint64 val );
+void g_set_num_bytes_sent( Slapi_Counter *counter );
 PRUint64 g_get_num_bytes_sent();
-void g_set_num_sent_mutex( PRLock *plock );
 void g_set_default_referral( struct berval **ldap_url );
 struct berval	**g_get_default_referral();
-PRLock *g_get_num_sent_mutex();
 void disconnect_server( Connection *conn, PRUint64 opconnid, int opid, PRErrorCode reason, PRInt32 error );
 int send_ldap_search_entry( Slapi_PBlock *pb, Slapi_Entry *e, LDAPControl **ectrls,
 	char **attrs, int attrsonly );


Index: result.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/result.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -r1.14 -r1.15
--- result.c	17 Oct 2008 22:12:47 -0000	1.14
+++ result.c	24 Oct 2008 22:36:58 -0000	1.15
@@ -60,9 +60,8 @@
 
 #include <ssl.h>
 
-PRUint64 num_entries_sent;
-PRUint64 num_bytes_sent;
-PRLock	*num_sent_mutex;
+Slapi_Counter *num_entries_sent;
+Slapi_Counter *num_bytes_sent;
 
 static long	current_conn_count;
 static PRLock	*current_conn_count_mutex;
@@ -82,34 +81,24 @@
 #define SLAPI_SEND_VATTR_FLAG_REALONLY          0x01
 #define SLAPI_SEND_VATTR_FLAG_VIRTUALONLY       0x02
 
-void g_set_num_entries_sent( PRUint64 val )
+void g_set_num_entries_sent( Slapi_Counter *counter )
 {
-	num_entries_sent = val;
+	num_entries_sent = counter;
 }
 
 PRUint64 g_get_num_entries_sent()
 {
-	return( num_entries_sent );
+	return( slapi_counter_get_value(num_entries_sent) );
 }
 
-void g_set_num_bytes_sent( PRUint64 val )
+void g_set_num_bytes_sent( Slapi_Counter *counter )
 {
-	num_bytes_sent = val;
+	num_bytes_sent = counter;
 }
 
 PRUint64 g_get_num_bytes_sent()
 {
-	return( num_bytes_sent );
-}
-
-void g_set_num_sent_mutex( PRLock *plock )
-{
-	num_sent_mutex = plock;
-}
-
-PRLock *g_get_num_sent_mutex()
-{
-	return( num_sent_mutex );
+	return( slapi_counter_get_value(num_bytes_sent) );
 }
 
 static void
@@ -327,8 +316,7 @@
                    || err == LDAP_INSUFFICIENT_ACCESS
                    || err == LDAP_AUTH_UNKNOWN )
 		{
-			if(g_get_global_snmp_vars()->ops_tbl.dsSecurityErrors!=NULL)
-				snmp_increment_counter(g_get_global_snmp_vars()->ops_tbl.dsSecurityErrors);	
+			slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsSecurityErrors);	
 		}else if(   err != LDAP_REFERRAL 
 			 && err != LDAP_OPT_REFERRALS
 			 && err != LDAP_PARTIAL_RESULTS)
@@ -338,8 +326,7 @@
 			    --referrals 
 			    -- partially seviced operations will not be conted as an error
                       */
-			if(g_get_global_snmp_vars()->ops_tbl.dsErrors!=NULL)
-				snmp_increment_counter(g_get_global_snmp_vars()->ops_tbl.dsErrors);	
+			slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsErrors);	
 		}
 
 	}
@@ -413,7 +400,7 @@
 			int	len;
 
 		        /* count the referral */
-  		        snmp_increment_counter(g_get_global_snmp_vars()->ops_tbl.dsReferrals);
+  		        slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsReferrals);
 
 			/*
 			 * figure out how much space we need
@@ -486,7 +473,7 @@
 		 */
 	        /* count the referral */
 		if (! config_check_referral_mode())
-		    snmp_increment_counter(g_get_global_snmp_vars()->ops_tbl.dsReferrals);
+		    slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsReferrals);
 		rc = ber_printf( ber, "{it{esst{s", operation->o_msgid, tag, err,
 		    matched ? matched : "", text ? text : "", LDAP_TAG_REFERRAL,
 		    urls[0]->bv_val );
@@ -677,7 +664,7 @@
 	char	*attrs[2] = { NULL, NULL };
 
 	/* count the referral */
-	snmp_increment_counter(g_get_global_snmp_vars()->ops_tbl.dsReferrals);
+	slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsReferrals);
 
 	attrs[0] = refAttr;
 	if ( e != NULL && 
@@ -1526,14 +1513,13 @@
 				"flush_ber() wrote %u bytes to socket %d\n",
 				bytes, conn->c_sd, 0 );
 			LL_I2L ( b, bytes ) ;
-			LL_ADD ( num_bytes_sent, num_bytes_sent, b);
+			slapi_counter_add(num_bytes_sent, b);
 			
 			if ( type == _LDAP_SEND_ENTRY ) {
-				LL_I2L ( b, 1 );
-				LL_ADD ( num_entries_sent, num_entries_sent, b );
+				slapi_counter_increment(num_entries_sent);
 			}
 			if (! config_check_referral_mode())
-				(*(g_get_global_snmp_vars()->ops_tbl.dsBytesSent))+= bytes;
+				slapi_counter_add(g_get_global_snmp_vars()->ops_tbl.dsBytesSent, bytes);
 		}
 	}
 	
@@ -1542,11 +1528,11 @@
 		plugin_call_plugins( pb, SLAPI_PLUGIN_POST_RESULT_FN );
 		break;
 	case _LDAP_SEND_REFERRAL:
-		snmp_increment_counter(g_get_global_snmp_vars()->ops_tbl.dsReferralsReturned);
+		slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsReferralsReturned);
 		plugin_call_plugins( pb, SLAPI_PLUGIN_POST_REFERRAL_FN );
 		break;
 	case _LDAP_SEND_ENTRY:
-		snmp_increment_counter(g_get_global_snmp_vars()->ops_tbl.dsEntriesReturned);
+		slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsEntriesReturned);
 		plugin_call_plugins( pb, SLAPI_PLUGIN_POST_ENTRY_FN );
 		break;
 	}


Index: search.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/search.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- search.c	17 Oct 2008 22:12:47 -0000	1.10
+++ search.c	24 Oct 2008 22:36:58 -0000	1.11
@@ -87,7 +87,7 @@
 	ber = operation->o_ber;
 
 	/* count the search request */
-	snmp_increment_counter(g_get_global_snmp_vars()->ops_tbl.dsSearchOps);
+	slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsSearchOps);
 
 	/*
 	 * Parse the search request.  It looks like this:
@@ -141,11 +141,11 @@
 	/* check and record the scope for snmp */
 	if ( scope == LDAP_SCOPE_ONELEVEL) {
 		/* count the one level search request */
-		snmp_increment_counter(g_get_global_snmp_vars()->ops_tbl.dsOneLevelSearchOps);
+		slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsOneLevelSearchOps);
 
 	} else if (scope == LDAP_SCOPE_SUBTREE) {
 		/* count the subtree search request */
-		snmp_increment_counter(g_get_global_snmp_vars()->ops_tbl.dsWholeSubtreeSearchOps);
+		slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsWholeSubtreeSearchOps);
 	}
 
 	/* filter - returns a "normalized" version */


Index: slap.h
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/slap.h,v
retrieving revision 1.37
retrieving revision 1.38
diff -u -r1.37 -r1.38
--- slap.h	17 Oct 2008 22:12:47 -0000	1.37
+++ slap.h	24 Oct 2008 22:36:58 -0000	1.38
@@ -152,6 +152,7 @@
 
 #define	SLAPD_LOGGING	1
 #define NUM_SNMP_INT_TBL_ROWS 5
+#define SNMP_FIELD_LENGTH 100
 
 /* include NSPR header files */
 #include "nspr.h"
@@ -1529,57 +1530,56 @@
 #include "proto-slap.h"
 LDAPMod** entry2mods(Slapi_Entry *, LDAPMod **, int *, int);
 
-/* SNMP Variables */
+/* SNMP Counter Variables */
 struct snmp_ops_tbl_t{
-    PRUint32 *dsAnonymousBinds;
-    PRUint32 *dsUnAuthBinds;
-    PRUint32 *dsSimpleAuthBinds;
-    PRUint32 *dsStrongAuthBinds;
-    PRUint32 *dsBindSecurityErrors;
-    PRUint32 *dsInOps;
-    PRUint32 *dsReadOps;
-    PRUint32 *dsCompareOps;
-    PRUint32 *dsAddEntryOps;
-    PRUint32 *dsRemoveEntryOps;
-    PRUint32 *dsModifyEntryOps;
-    PRUint32 *dsModifyRDNOps;
-    PRUint32 *dsListOps;
-    PRUint32 *dsSearchOps;
-    PRUint32 *dsOneLevelSearchOps;
-    PRUint32 *dsWholeSubtreeSearchOps;
-    PRUint32 *dsReferrals;
-    PRUint32 *dsChainings;
-    PRUint32 *dsSecurityErrors;
-    PRUint32 *dsErrors;
-    PRUint32 *dsConnections;	 /* Number of currently connected clients */
-    PRUint32 *dsConnectionSeq; /* Monotonically increasing number bumped on each new conn est */
-    PRUint32 *dsBytesRecv;	/* Count of bytes read from clients */
-    PRUint32 *dsBytesSent;	/* Count of bytes sent to clients */
-    PRUint32 *dsEntriesReturned;
-    PRUint32 *dsReferralsReturned;
+    Slapi_Counter *dsAnonymousBinds;
+    Slapi_Counter *dsUnAuthBinds;
+    Slapi_Counter *dsSimpleAuthBinds;
+    Slapi_Counter *dsStrongAuthBinds;
+    Slapi_Counter *dsBindSecurityErrors;
+    Slapi_Counter *dsInOps;
+    Slapi_Counter *dsReadOps;
+    Slapi_Counter *dsCompareOps;
+    Slapi_Counter *dsAddEntryOps;
+    Slapi_Counter *dsRemoveEntryOps;
+    Slapi_Counter *dsModifyEntryOps;
+    Slapi_Counter *dsModifyRDNOps;
+    Slapi_Counter *dsListOps;
+    Slapi_Counter *dsSearchOps;
+    Slapi_Counter *dsOneLevelSearchOps;
+    Slapi_Counter *dsWholeSubtreeSearchOps;
+    Slapi_Counter *dsReferrals;
+    Slapi_Counter *dsChainings;
+    Slapi_Counter *dsSecurityErrors;
+    Slapi_Counter *dsErrors;
+    Slapi_Counter *dsConnections;	 /* Number of currently connected clients */
+    Slapi_Counter *dsConnectionSeq; /* Monotonically increasing number bumped on each new conn est */
+    Slapi_Counter *dsBytesRecv;	/* Count of bytes read from clients */
+    Slapi_Counter *dsBytesSent;	/* Count of bytes sent to clients */
+    Slapi_Counter *dsEntriesReturned;
+    Slapi_Counter *dsReferralsReturned;
 };
 
 struct snmp_entries_tbl_t{
-   /* entries table */
-   PRUint32 *dsMasterEntries;
-   PRUint32 *dsCopyEntries;
-   PRUint32 *dsCacheEntries;
-   PRUint32 *dsCacheHits;
-   PRUint32 *dsSlaveHits;
+    /* entries table */
+    Slapi_Counter *dsMasterEntries;
+    Slapi_Counter *dsCopyEntries;
+    Slapi_Counter *dsCacheEntries;
+    Slapi_Counter *dsCacheHits;
+    Slapi_Counter *dsSlaveHits;
 };
 
 struct snmp_int_tbl_t{
-
    /* interaction table */
-   PRUint32 *dsIntIndex;
-   char *dsName;
-   time_t *dsTimeOfCreation;          
-   time_t *dsTimeOfLastAttempt;      
-   time_t *dsTimeOfLastSuccess;      
-   PRUint32 *dsFailuresSinceLastSuccess;
-   PRUint32 *dsFailures;
-   PRUint32 *dsSuccesses;
-   char *dsURL;
+   PRUint32 dsIntIndex;
+   char dsName[SNMP_FIELD_LENGTH];
+   time_t dsTimeOfCreation;          
+   time_t dsTimeOfLastAttempt;      
+   time_t dsTimeOfLastSuccess;      
+   PRUint32 dsFailuresSinceLastSuccess;
+   PRUint32 dsFailures;
+   PRUint32 dsSuccesses;
+   char dsURL[SNMP_FIELD_LENGTH];
 };
 
 /* operation statistics */
@@ -1709,6 +1709,7 @@
 #define CONFIG_LDAPI_GIDNUMBER_TYPE_ATTRIBUTE "nsslapd-ldapigidnumbertype"
 #define CONFIG_LDAPI_SEARCH_BASE_DN_ATTRIBUTE "nsslapd-ldapientrysearchbase"
 #define CONFIG_LDAPI_AUTO_DN_SUFFIX_ATTRIBUTE "nsslapd-ldapiautodnsuffix"
+#define CONFIG_SLAPI_COUNTER_ATTRIBUTE "nsslapd-counters"
 #define CONFIG_SECURITY_ATTRIBUTE "nsslapd-security"
 #define CONFIG_SSL3CIPHERS_ATTRIBUTE "nsslapd-SSL3ciphers"
 #define CONFIG_ACCESSLOG_ATTRIBUTE "nsslapd-accesslog"
@@ -1979,6 +1980,7 @@
   char *ldapi_gidnumber_type;   /* type that contains gid number */
   char *ldapi_search_base_dn;   /* base dn to search for mapped entries */
   char *ldapi_auto_dn_suffix;   /* suffix to be appended to auto gen DNs */
+  int slapi_counters;            /* switch to turn slapi_counters on/off */
 #ifndef _WIN32
   struct passwd *localuserinfo; /* userinfo of localuser */
 #endif /* _WIN32 */


Index: slapi-private.h
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/slapi-private.h,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -r1.27 -r1.28
--- slapi-private.h	3 Oct 2008 04:28:22 -0000	1.27
+++ slapi-private.h	24 Oct 2008 22:36:58 -0000	1.28
@@ -1208,14 +1208,6 @@
 #define PRLDAP_SET_PORT(myaddr,myport) \
     ((myaddr)->raw.family == PR_AF_INET6 ? ((myaddr)->ipv6.port = PR_htons(myport)) : ((myaddr)->inet.port = PR_htons(myport)))
 
-/*
- * snmp_collator.c
- * wrapper functions to ease the cast burdon between net-snmp APIs which expect 
- * unsigned int and PR_AtomicIncrement/PR_AtomicSet which expect signed int.
- */ 
-void snmp_increment_counter(PRUint32 *counter);
-void snmp_set_counter(PRUint32 *counter, PRInt32 newval);
-
 #ifdef __cplusplus
 }
 #endif


Index: snmp_collator.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/snmp_collator.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- snmp_collator.c	17 Oct 2008 22:12:47 -0000	1.15
+++ snmp_collator.c	24 Oct 2008 22:36:58 -0000	1.16
@@ -48,6 +48,7 @@
 #include <sys/ipc.h>
 #include <sys/msg.h>
 #include <dirent.h>
+#include <semaphore.h>
 #endif
 #include <time.h>
 #include <signal.h>
@@ -62,6 +63,14 @@
 #include "prcvar.h"
 #include "plstr.h"
 
+#ifdef HPUX
+/* HP-UX doesn't define SEM_FAILED like other platforms, so
+ * we define it ourselves. */
+#define SEM_FAILED ((sem_t *)(-1))
+#endif
+
+#define SNMP_NUM_SEM_WAITS 10
+
 #include "snmp_collator.h" 
 #include "../snmp/ntagt/nslagtcom_nt.h"
 
@@ -70,12 +79,18 @@
 /* strlen of url portions ie "ldap://:/" */
 #define URL_CHARS_LEN 9 
 
-char *make_ds_url(char *host, int port);
-void print_snmp_interaction_table();
-int search_interaction_table(char *dsURL, int *isnew);
+static char *make_ds_url(char *host, int port);
+static void print_snmp_interaction_table();
+static int search_interaction_table(char *dsURL, int *isnew);
 static void loadConfigStats();
 static Slapi_Entry *getConfigEntry( Slapi_Entry **e );
 static void freeConfigEntry( Slapi_Entry **e );
+static void snmp_update_ops_table();
+static void snmp_update_entries_table();
+static void snmp_update_interactions_table();
+static void snmp_update_cache_stats();
+static void snmp_collator_create_semaphore();
+static void snmp_collator_sem_wait();
 
 /* snmp stats stuff */
 struct agt_stats_t *stats=NULL;
@@ -94,12 +109,14 @@
 static TCHAR szSpoolRootDir[_MAX_PATH];
 #else
 static char szStatsFile[_MAX_PATH];
+static char stats_sem_name[_MAX_PATH];
 #endif /* _WIN32*/
 static Slapi_Eq_Context snmp_eq_ctx;
 static int snmp_collator_stopped = 0;
 
-/* lock stuff */
+/* synchronization stuff */
 static PRLock 		*interaction_table_mutex;
+static sem_t		*stats_sem;
 
 
 /***********************************************************************************
@@ -110,88 +127,80 @@
 *
 ************************************************************************************/
 
-int snmp_collator_init(){
- int i;
+static int snmp_collator_init(){
+	int i;
+
+	/*
+	 * Create the global SNMP counters
+	 */
+	g_get_global_snmp_vars()->ops_tbl.dsAnonymousBinds		= slapi_counter_new();
+	g_get_global_snmp_vars()->ops_tbl.dsUnAuthBinds			= slapi_counter_new();
+	g_get_global_snmp_vars()->ops_tbl.dsSimpleAuthBinds		= slapi_counter_new();
+	g_get_global_snmp_vars()->ops_tbl.dsStrongAuthBinds		= slapi_counter_new();
+	g_get_global_snmp_vars()->ops_tbl.dsBindSecurityErrors		= slapi_counter_new();
+	g_get_global_snmp_vars()->ops_tbl.dsInOps			= slapi_counter_new();
+	g_get_global_snmp_vars()->ops_tbl.dsReadOps			= slapi_counter_new();
+	g_get_global_snmp_vars()->ops_tbl.dsCompareOps			= slapi_counter_new();
+	g_get_global_snmp_vars()->ops_tbl.dsAddEntryOps			= slapi_counter_new();
+	g_get_global_snmp_vars()->ops_tbl.dsRemoveEntryOps		= slapi_counter_new();
+	g_get_global_snmp_vars()->ops_tbl.dsModifyEntryOps		= slapi_counter_new();
+	g_get_global_snmp_vars()->ops_tbl.dsModifyRDNOps		= slapi_counter_new();
+	g_get_global_snmp_vars()->ops_tbl.dsListOps			= slapi_counter_new();
+	g_get_global_snmp_vars()->ops_tbl.dsSearchOps			= slapi_counter_new();
+	g_get_global_snmp_vars()->ops_tbl.dsOneLevelSearchOps		= slapi_counter_new();
+	g_get_global_snmp_vars()->ops_tbl.dsWholeSubtreeSearchOps	= slapi_counter_new();
+	g_get_global_snmp_vars()->ops_tbl.dsReferrals			= slapi_counter_new();
+	g_get_global_snmp_vars()->ops_tbl.dsChainings			= slapi_counter_new();
+	g_get_global_snmp_vars()->ops_tbl.dsSecurityErrors		= slapi_counter_new();
+	g_get_global_snmp_vars()->ops_tbl.dsErrors			= slapi_counter_new();
+	g_get_global_snmp_vars()->ops_tbl.dsConnections			= slapi_counter_new();
+	g_get_global_snmp_vars()->ops_tbl.dsConnectionSeq		= slapi_counter_new();
+	g_get_global_snmp_vars()->ops_tbl.dsBytesRecv			= slapi_counter_new();
+	g_get_global_snmp_vars()->ops_tbl.dsBytesSent			= slapi_counter_new();
+	g_get_global_snmp_vars()->ops_tbl.dsEntriesReturned		= slapi_counter_new();
+	g_get_global_snmp_vars()->ops_tbl.dsReferralsReturned		= slapi_counter_new();
+	g_get_global_snmp_vars()->entries_tbl.dsMasterEntries		= slapi_counter_new();
+	g_get_global_snmp_vars()->entries_tbl.dsCopyEntries		= slapi_counter_new();
+	g_get_global_snmp_vars()->entries_tbl.dsCacheEntries		= slapi_counter_new();
+	g_get_global_snmp_vars()->entries_tbl.dsCacheHits		= slapi_counter_new();
+	g_get_global_snmp_vars()->entries_tbl.dsSlaveHits		= slapi_counter_new();
+
+	/* Initialize the global interaction table */
+	for(i=0; i < NUM_SNMP_INT_TBL_ROWS; i++)
+	{
+		g_get_global_snmp_vars()->int_tbl[i].dsIntIndex                    = i + 1;
+		strncpy(g_get_global_snmp_vars()->int_tbl[i].dsName, "Not Available",
+			sizeof(g_get_global_snmp_vars()->int_tbl[i].dsName));
+		g_get_global_snmp_vars()->int_tbl[i].dsTimeOfCreation              = 0;
+		g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastAttempt           = 0;
+		g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastSuccess           = 0;
+		g_get_global_snmp_vars()->int_tbl[i].dsFailuresSinceLastSuccess    = 0;
+		g_get_global_snmp_vars()->int_tbl[i].dsFailures                    = 0;
+		g_get_global_snmp_vars()->int_tbl[i].dsSuccesses                   = 0;
+		strncpy(g_get_global_snmp_vars()->int_tbl[i].dsURL, "Not Available",
+			sizeof(g_get_global_snmp_vars()->int_tbl[i].dsURL));
+	}
+
+	/* Get the semaphore */
+	snmp_collator_sem_wait();
 
-	/* 
-	* Initialize the mmap structure 
-	*/
+	/* Initialize the mmap structure */
 	memset((void *) stats, 0, sizeof(*stats));
+
+	/* Load header stats table */
 	strncpy(stats->hdr_stats.dsVersion, SLAPD_VERSION_STR,
                 (sizeof(stats->hdr_stats.dsVersion)/sizeof(char)) - 1);
 	stats->hdr_stats.restarted = 0;			 
 	stats->hdr_stats.startTime = time(0);		/* This is a bit off, hope it's ok */
-
-	/* load config stats */
 	loadConfigStats();
 
-	/* point these at the mmaped data */
-	g_get_global_snmp_vars()->ops_tbl.dsAnonymousBinds		= &(stats->ops_stats.dsAnonymousBinds);
-        g_get_global_snmp_vars()->ops_tbl.dsUnAuthBinds			= &(stats->ops_stats.dsUnAuthBinds);
-	g_get_global_snmp_vars()->ops_tbl.dsSimpleAuthBinds		= &(stats->ops_stats.dsSimpleAuthBinds);
-	g_get_global_snmp_vars()->ops_tbl.dsStrongAuthBinds		= &(stats->ops_stats.dsStrongAuthBinds);
-	g_get_global_snmp_vars()->ops_tbl.dsBindSecurityErrors	        = &(stats->ops_stats.dsBindSecurityErrors);
-	g_get_global_snmp_vars()->ops_tbl.dsInOps			= &(stats->ops_stats.dsInOps);
-    g_get_global_snmp_vars()->ops_tbl.dsReadOps			= &(stats->ops_stats.dsReadOps);
-    g_get_global_snmp_vars()->ops_tbl.dsCompareOps			= &(stats->ops_stats.dsCompareOps);
-	g_get_global_snmp_vars()->ops_tbl.dsAddEntryOps			= &(stats->ops_stats.dsAddEntryOps);
-	g_get_global_snmp_vars()->ops_tbl.dsRemoveEntryOps		= &(stats->ops_stats.dsRemoveEntryOps); 
-	g_get_global_snmp_vars()->ops_tbl.dsModifyEntryOps		= &(stats->ops_stats.dsModifyEntryOps);
-	g_get_global_snmp_vars()->ops_tbl.dsModifyRDNOps		= &(stats->ops_stats.dsModifyRDNOps);
-	g_get_global_snmp_vars()->ops_tbl.dsListOps			= &(stats->ops_stats.dsListOps);
-	g_get_global_snmp_vars()->ops_tbl.dsSearchOps			= &(stats->ops_stats.dsSearchOps);
-	g_get_global_snmp_vars()->ops_tbl.dsOneLevelSearchOps		= &(stats->ops_stats.dsOneLevelSearchOps);
-	g_get_global_snmp_vars()->ops_tbl.dsWholeSubtreeSearchOps       = &(stats->ops_stats.dsWholeSubtreeSearchOps);
-	g_get_global_snmp_vars()->ops_tbl.dsReferrals			= &(stats->ops_stats.dsReferrals);
-	g_get_global_snmp_vars()->ops_tbl.dsChainings			= &(stats->ops_stats.dsChainings);
-	g_get_global_snmp_vars()->ops_tbl.dsSecurityErrors	        = &(stats->ops_stats.dsSecurityErrors);
-	g_get_global_snmp_vars()->ops_tbl.dsErrors			= &(stats->ops_stats.dsErrors);
-	g_get_global_snmp_vars()->ops_tbl.dsConnections			= &(stats->ops_stats.dsConnections);
-	g_get_global_snmp_vars()->ops_tbl.dsConnectionSeq			= &(stats->ops_stats.dsConnectionSeq);
-	g_get_global_snmp_vars()->ops_tbl.dsBytesRecv			= &(stats->ops_stats.dsBytesRecv);
-	g_get_global_snmp_vars()->ops_tbl.dsBytesSent			= &(stats->ops_stats.dsBytesSent);
-	g_get_global_snmp_vars()->ops_tbl.dsEntriesReturned			= &(stats->ops_stats.dsEntriesReturned);
-	g_get_global_snmp_vars()->ops_tbl.dsReferralsReturned			= &(stats->ops_stats.dsReferralsReturned);
-
-	/* entries table */
-
-	g_get_global_snmp_vars()->entries_tbl.dsMasterEntries		= &(stats->entries_stats.dsMasterEntries);
-	g_get_global_snmp_vars()->entries_tbl.dsCopyEntries		= &(stats->entries_stats.dsCopyEntries);
-	g_get_global_snmp_vars()->entries_tbl.dsCacheEntries		= &(stats->entries_stats.dsCacheEntries);
-	g_get_global_snmp_vars()->entries_tbl.dsCacheHits		= &(stats->entries_stats.dsCacheHits);
-	g_get_global_snmp_vars()->entries_tbl.dsSlaveHits		= &(stats->entries_stats.dsSlaveHits);
-
-	/* interaction table */
+	/* update the mmap'd tables */
+	snmp_update_ops_table();
+	snmp_update_entries_table();
+	snmp_update_interactions_table();
 
-	/* set pointers to table */
-	for(i=0; i < NUM_SNMP_INT_TBL_ROWS; i++)
-	{
-	    stats->int_stats[i].dsIntIndex=i;
-	    g_get_global_snmp_vars()->int_tbl[i].dsIntIndex		 = &(stats->int_stats[i].dsIntIndex);
-	    g_get_global_snmp_vars()->int_tbl[i].dsName			 = stats->int_stats[i].dsName;
-	    g_get_global_snmp_vars()->int_tbl[i].dsTimeOfCreation	 = &(stats->int_stats[i].dsTimeOfCreation);     
-	    g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastAttempt	 = &(stats->int_stats[i].dsTimeOfLastAttempt);
-	    g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastSuccess	 = &(stats->int_stats[i].dsTimeOfLastSuccess);
-	    g_get_global_snmp_vars()->int_tbl[i].dsFailuresSinceLastSuccess
-	      = &(stats->int_stats[i].dsFailuresSinceLastSuccess);
-	    g_get_global_snmp_vars()->int_tbl[i].dsFailures		 = &(stats->int_stats[i].dsFailures);
-	    g_get_global_snmp_vars()->int_tbl[i].dsSuccesses		 = &(stats->int_stats[i].dsSuccesses);
-	    g_get_global_snmp_vars()->int_tbl[i].dsURL			 = stats->int_stats[i].dsURL;
-	}
-
-	/* initialize table contents */
-	for(i=0; i < NUM_SNMP_INT_TBL_ROWS; i++)
-	{
-            *(g_get_global_snmp_vars()->int_tbl[i].dsIntIndex)                    = i + 1;
-            strcpy(g_get_global_snmp_vars()->int_tbl[i].dsName, "Not Available");
-            *(g_get_global_snmp_vars()->int_tbl[i].dsTimeOfCreation)              = 0;
-            *(g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastAttempt)           = 0;
-            *(g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastSuccess)           = 0;
-            *(g_get_global_snmp_vars()->int_tbl[i].dsFailuresSinceLastSuccess)    = 0;
-            *(g_get_global_snmp_vars()->int_tbl[i].dsFailures)                    = 0;
-            *(g_get_global_snmp_vars()->int_tbl[i].dsSuccesses)                   = 0;
-	    strcpy(g_get_global_snmp_vars()->int_tbl[i].dsURL, "Not Available");
-	}
+	/* Release the semaphore */
+	sem_post(stats_sem);
 
 	/* create lock for interaction table */
         interaction_table_mutex = PR_NewLock();
@@ -202,7 +211,7 @@
 
 
 /***********************************************************************************
- * given the name, wether or not it was successfull and the URL updates snmp 
+ * given the name, whether or not it was successful and the URL updates snmp 
  * interaction table appropriately
  *
  *
@@ -231,32 +240,34 @@
   
       if(isnew){
           /* fillin the new row from scratch*/
-          *(g_get_global_snmp_vars()->int_tbl[index].dsIntIndex)	                  = index;
-          strcpy(g_get_global_snmp_vars()->int_tbl[index].dsName, dsName);
-          *(g_get_global_snmp_vars()->int_tbl[index].dsTimeOfCreation)	          = time(0);
-          *(g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastAttempt)	          = time(0);
+          g_get_global_snmp_vars()->int_tbl[index].dsIntIndex	                  = index;
+          strncpy(g_get_global_snmp_vars()->int_tbl[index].dsName, dsName,
+                  sizeof(g_get_global_snmp_vars()->int_tbl[index].dsName));
+          g_get_global_snmp_vars()->int_tbl[index].dsTimeOfCreation	          = time(0);
+          g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastAttempt	          = time(0);
           if(error == 0){
-              *(g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastSuccess)	  = time(0);
-              *(g_get_global_snmp_vars()->int_tbl[index].dsFailuresSinceLastSuccess)  = 0;
-              *(g_get_global_snmp_vars()->int_tbl[index].dsFailures)	          = 0;
-              *(g_get_global_snmp_vars()->int_tbl[index].dsSuccesses)		  = 1;
+              g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastSuccess	  = time(0);
+              g_get_global_snmp_vars()->int_tbl[index].dsFailuresSinceLastSuccess = 0;
+              g_get_global_snmp_vars()->int_tbl[index].dsFailures	          = 0;
+              g_get_global_snmp_vars()->int_tbl[index].dsSuccesses		  = 1;
           }else{
-              *(g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastSuccess)	  = 0;
-              *(g_get_global_snmp_vars()->int_tbl[index].dsFailuresSinceLastSuccess)  = 1;
-              *(g_get_global_snmp_vars()->int_tbl[index].dsFailures)		  = 1;
-              *(g_get_global_snmp_vars()->int_tbl[index].dsSuccesses)		  = 0;
+              g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastSuccess	  = 0;
+              g_get_global_snmp_vars()->int_tbl[index].dsFailuresSinceLastSuccess = 1;
+              g_get_global_snmp_vars()->int_tbl[index].dsFailures		  = 1;
+              g_get_global_snmp_vars()->int_tbl[index].dsSuccesses		  = 0;
           }
-          strcpy(g_get_global_snmp_vars()->int_tbl[index].dsURL, dsURL);		         
+          strncpy(g_get_global_snmp_vars()->int_tbl[index].dsURL, dsURL,
+                  sizeof(g_get_global_snmp_vars()->int_tbl[index].dsURL));		         
       }else{
         /* just update the appropriate fields */
-           *(g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastAttempt)	          = time(0);
+           g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastAttempt	         = time(0);
           if(error == 0){
-             *(g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastSuccess)	  = time(0);
-             *(g_get_global_snmp_vars()->int_tbl[index].dsFailuresSinceLastSuccess)   = 0;
-             *(g_get_global_snmp_vars()->int_tbl[index].dsSuccesses)                  += 1;
+             g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastSuccess        = time(0);
+             g_get_global_snmp_vars()->int_tbl[index].dsFailuresSinceLastSuccess = 0;
+             g_get_global_snmp_vars()->int_tbl[index].dsSuccesses                += 1;
           }else{
-             *(g_get_global_snmp_vars()->int_tbl[index].dsFailuresSinceLastSuccess)   +=1;
-             *(g_get_global_snmp_vars()->int_tbl[index].dsFailures)                   +=1;
+             g_get_global_snmp_vars()->int_tbl[index].dsFailuresSinceLastSuccess +=1;
+             g_get_global_snmp_vars()->int_tbl[index].dsFailures                 +=1;
           }
 
       }
@@ -274,7 +285,7 @@
  * 
  *    this should point to root DSE 
 ************************************************************************************/
-char *make_ds_url(char *host, int port){
+static char *make_ds_url(char *host, int port){
 
   char *url;
   
@@ -291,14 +302,14 @@
  * so caller can rewrite this row
 ************************************************************************************/
 
-int search_interaction_table(char *dsURL, int *isnew)
+static int search_interaction_table(char *dsURL, int *isnew)
 {
   int i;
   int index = 0;
   time_t oldestattempt;
   time_t currentattempt;
    
-   oldestattempt = *(g_get_global_snmp_vars()->int_tbl[0].dsTimeOfLastAttempt);
+   oldestattempt = g_get_global_snmp_vars()->int_tbl[0].dsTimeOfLastAttempt;
    *isnew = 1;
    
    for(i=0; i < NUM_SNMP_INT_TBL_ROWS; i++){
@@ -314,7 +325,7 @@
 	   break;
        }else{
           /* not found so figure out oldest row */ 
-          currentattempt = *(g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastAttempt);
+          currentattempt = g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastAttempt;
 	 
           if(currentattempt <= oldestattempt){
               index=i;
@@ -328,19 +339,19 @@
 
 }
 /* for debuging until subagent part working, print contents of interaction table */
-void print_snmp_interaction_table()
+static void print_snmp_interaction_table()
 { 
   int i;
   for(i=0; i < NUM_SNMP_INT_TBL_ROWS; i++)
   {
-    fprintf(stderr, "                dsIntIndex: %d \n", *(g_get_global_snmp_vars()->int_tbl[i].dsIntIndex));
+    fprintf(stderr, "                dsIntIndex: %d \n", g_get_global_snmp_vars()->int_tbl[i].dsIntIndex);
     fprintf(stderr, "                    dsName: %s \n",   g_get_global_snmp_vars()->int_tbl[i].dsName);
-    fprintf(stderr, "          dsTimeOfCreation: %ld \n", *(g_get_global_snmp_vars()->int_tbl[i].dsTimeOfCreation));
-    fprintf(stderr, "       dsTimeOfLastAttempt: %ld \n", *(g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastAttempt));
-    fprintf(stderr, "       dsTimeOfLastSuccess: %ld \n", *(g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastSuccess));
-    fprintf(stderr, "dsFailuresSinceLastSuccess: %d \n", *(g_get_global_snmp_vars()->int_tbl[i].dsFailuresSinceLastSuccess));
-    fprintf(stderr, "                dsFailures: %d \n", *(g_get_global_snmp_vars()->int_tbl[i].dsFailures));
-    fprintf(stderr, "               dsSuccesses: %d \n", *(g_get_global_snmp_vars()->int_tbl[i].dsSuccesses));
+    fprintf(stderr, "          dsTimeOfCreation: %ld \n", g_get_global_snmp_vars()->int_tbl[i].dsTimeOfCreation);
+    fprintf(stderr, "       dsTimeOfLastAttempt: %ld \n", g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastAttempt);
+    fprintf(stderr, "       dsTimeOfLastSuccess: %ld \n", g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastSuccess);
+    fprintf(stderr, "dsFailuresSinceLastSuccess: %d \n", g_get_global_snmp_vars()->int_tbl[i].dsFailuresSinceLastSuccess);
+    fprintf(stderr, "                dsFailures: %d \n", g_get_global_snmp_vars()->int_tbl[i].dsFailures);
+    fprintf(stderr, "               dsSuccesses: %d \n", g_get_global_snmp_vars()->int_tbl[i].dsSuccesses);
     fprintf(stderr, "                     dsURL: %s \n", g_get_global_snmp_vars()->int_tbl[i].dsURL);
     fprintf(stderr, "\n");
   }
@@ -418,6 +429,8 @@
   }
   PR_snprintf(szStatsFile, sizeof(szStatsFile), "%s/%s%s",
               statspath, instname, AGT_STATS_EXTENSION);
+  PR_snprintf(stats_sem_name, sizeof(stats_sem_name), "%s%s",
+              instname, AGT_STATS_EXTENSION);
   tmpstatsfile = szStatsFile;
   slapi_ch_free_string(&statspath);
   slapi_ch_free_string(&instdir);
@@ -427,27 +440,22 @@
   {
     if (err != EEXIST)      /* Ignore if file already exists */
     {
-      printf("Failed to open stats file (%s) (error %d).\n", 
-                                         szStatsFile, err);
+      LDAPDebug( LDAP_DEBUG_ANY, "Failed to open stats file (%s) (error %d).\n",
+                         szStatsFile, err, 0 );
       exit(1);
     }
   }
 
-/* read config entry for entity table data */
+  /* Create semaphore for stats file access */
+  snmp_collator_create_semaphore();
 
-/* point stats struct at mmap data */
+  /* point stats struct at mmap data */
   stats = (struct agt_stats_t *) mmap_tbl [hdl].fp;
 
-/* initialize stats data */
-
+  /* initialize stats data */
   snmp_collator_init();
-/*
-*  now that memmap is open and things point the right way
-*  an atomic set or increment anywhere in slapd should set
-*  the snmp memmap vars correctly and be able to be polled by snmp
-*/
 
-  /* Arrange to be called back periodically */
+  /* Arrange to be called back periodically to update the mmap'd stats file. */
   snmp_eq_ctx = slapi_eq_repeat(snmp_collator_update, NULL, (time_t)0,
                                 SLAPD_SNMP_UPDATE_INTERVAL);
   return 0;
@@ -472,6 +480,9 @@
 	slapi_eq_cancel(snmp_eq_ctx);
 	snmp_collator_stopped = 1;
 
+   /* acquire the semaphore */
+   snmp_collator_sem_wait();
+
    /* close the memory map */
    if ((err = agt_mclose_stats(hdl)) != 0)
    {
@@ -485,6 +496,10 @@
             tmpstatsfile, errno);
    }
 
+   /* close and delete semaphore */
+   sem_close(stats_sem);
+   sem_unlink(stats_sem_name);
+
    /* delete lock */
    PR_DestroyLock(interaction_table_mutex);
 
@@ -498,166 +513,304 @@
 return 0;
 }
 
+/*
+ * snmp_collator_create_semaphore()
+ *
+ * Create a semaphore to synchronize access to the stats file with
+ * the SNMP sub-agent.  NSPR doesn't support a trywait function
+ * for semaphores, so we just use POSIX semaphores directly.
+ */
+static void
+snmp_collator_create_semaphore()
+{
+    /* First just try to create the semaphore.  This should usually just work. */
+    if ((stats_sem = sem_open(stats_sem_name, O_CREAT | O_EXCL, SLAPD_DEFAULT_FILE_MODE, 1)) == SEM_FAILED) {
+        if (errno == EEXIST) {
+            /* It appears that we didn't exit cleanly last time and left the semaphore
+             * around.  Recreate it since we don't know what state it is in. */
+            sem_unlink(stats_sem_name);
+            if ((stats_sem = sem_open(stats_sem_name, O_CREAT | O_EXCL, SLAPD_DEFAULT_FILE_MODE, 1)) == SEM_FAILED) {
+                /* No dice */
+                LDAPDebug( LDAP_DEBUG_ANY, "Failed to create semaphore for stats file (%s). Error %d.\n",
+                         szStatsFile, errno, 0 );
+                exit(1);
+            }
+        } else {
+            /* Some other problem occurred creating the semaphore. */
+            LDAPDebug( LDAP_DEBUG_ANY, "Failed to create semaphore for stats file (%s). Error %d.\n",
+                     szStatsFile, errno, 0 );
+            exit(1);
+        }
+    }
+
+    /* If we've reached this point, everything should be good. */
+    return;
+}
+
+/*
+ * snmp_collator_sem_wait()
+ *
+ * A wrapper used to get the semaphore.  We don't want to block,
+ * but we want to retry a specified number of times in case the
+ * semaphore is help by the sub-agent.
+ */
+static void
+snmp_collator_sem_wait()
+{
+    int i = 0;
+    int got_sem = 0;
+
+    for (i=0; i < SNMP_NUM_SEM_WAITS; i++) {
+        if (sem_trywait(stats_sem) == 0) {
+            got_sem = 1;
+            break;
+        }
+        PR_Sleep(PR_SecondsToInterval(1));
+    }
+
+    if (!got_sem) {
+        /* If we've been unable to get the semaphore, there's
+         * something wrong (likely the sub-agent went out to
+         * lunch).  We remove the old semaphore and recreate
+         * a new one to avoid hanging up the server. */
+        sem_close(stats_sem);
+        sem_unlink(stats_sem_name);
+        snmp_collator_create_semaphore();
+    }
+}
+
 
 
 /***********************************************************************************
 *
 * int snmp_collator_update()
 *
-*    our architecture changed from mail server and we right to mmapped 
-*    area as soon as operation completed, rather than maintining the same data twice  
-*    and doing a polled update. However, to keep traps working correctly (as they depend)
-*    on the time in the header, it is more efficient to write the header info
-*    in a polled fashion (ever 1 sec)
+* Event callback function that updates the mmap'd stats file
+* for the SNMP sub-agent.  This will use a semaphore while
+* updating the stats file to prevent the SNMP sub-agent from
+* reading it in the middle of an update.
 *
 ************************************************************************************/
 
 void
 snmp_collator_update(time_t start_time, void *arg)
 {
-    Slapi_Backend	*be, *be_next;
-    char			*cookie = NULL;
-    Slapi_PBlock	*search_result_pb = NULL;
-    Slapi_Entry     **search_entries;
-    Slapi_Attr      *attr  = NULL;
-    Slapi_Value     *sval = NULL;
-    int             search_result;
-    
-	if (snmp_collator_stopped) {
-		return;
-	}
+    if (snmp_collator_stopped) {
+        return;
+    }
+
+    /* force an update of the backend cache stats. */
+    snmp_update_cache_stats();
+
+    /* get the semaphore */
+    snmp_collator_sem_wait();
 
     /* just update the update time in the header */
     if( stats != NULL){
         stats->hdr_stats.updateTime = time(0);		
     }
 
+    /* update the mmap'd tables */
+    snmp_update_ops_table();
+    snmp_update_entries_table();
+    snmp_update_interactions_table();
+
+    /* release the semaphore */
+    sem_post(stats_sem);
+}
+
+/*
+ * snmp_update_ops_table()
+ *
+ * Updates the mmap'd operations table.  The semaphore
+ * should be acquired before you call this.
+ */
+static void
+snmp_update_ops_table()
+{
+    stats->ops_stats.dsAnonymousBinds = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsAnonymousBinds);
+    stats->ops_stats.dsUnAuthBinds = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsUnAuthBinds);
+    stats->ops_stats.dsSimpleAuthBinds = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsSimpleAuthBinds);
+    stats->ops_stats.dsStrongAuthBinds = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsStrongAuthBinds);
+    stats->ops_stats.dsBindSecurityErrors = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsBindSecurityErrors);
+    stats->ops_stats.dsInOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsInOps);
+    stats->ops_stats.dsReadOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsReadOps);
+    stats->ops_stats.dsCompareOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsCompareOps);
+    stats->ops_stats.dsAddEntryOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsAddEntryOps);
+    stats->ops_stats.dsRemoveEntryOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsRemoveEntryOps);
+    stats->ops_stats.dsModifyEntryOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsModifyEntryOps);
+    stats->ops_stats.dsModifyRDNOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsModifyRDNOps);
+    stats->ops_stats.dsListOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsListOps);
+    stats->ops_stats.dsSearchOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsSearchOps);
+    stats->ops_stats.dsOneLevelSearchOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsOneLevelSearchOps);
+    stats->ops_stats.dsWholeSubtreeSearchOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsWholeSubtreeSearchOps);
+    stats->ops_stats.dsReferrals = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsReferrals);
+    stats->ops_stats.dsChainings = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsChainings);
+    stats->ops_stats.dsSecurityErrors = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsSecurityErrors);
+    stats->ops_stats.dsErrors = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsErrors);
+    stats->ops_stats.dsConnections = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsConnections);
+    stats->ops_stats.dsConnectionSeq = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsConnectionSeq);
+    stats->ops_stats.dsBytesRecv = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsBytesRecv);
+    stats->ops_stats.dsBytesSent = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsBytesSent);
+    stats->ops_stats.dsEntriesReturned = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsEntriesReturned);
+    stats->ops_stats.dsReferralsReturned = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsReferralsReturned);
+}
+
+/*
+ * snmp_update_entries_table()
+ *
+ * Updated the mmap'd entries table.  The semaphore should
+ * be acquired before you call this.
+ */
+static void
+snmp_update_entries_table()
+{
+    stats->entries_stats.dsMasterEntries = slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsMasterEntries);
+    stats->entries_stats.dsCopyEntries = slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsCopyEntries);
+    stats->entries_stats.dsCacheEntries = slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsCacheEntries);
+    stats->entries_stats.dsCacheHits = slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsCacheHits);
+    stats->entries_stats.dsSlaveHits = slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsSlaveHits);
+}
+
+/*
+ * snmp_update_interactions_table()
+ *
+ * Updates the mmap'd interactions table.  The semaphore should
+ * be acquired before you call this.
+ */
+static void
+snmp_update_interactions_table()
+{
+    int i;
+
+    for(i=0; i < NUM_SNMP_INT_TBL_ROWS; i++) {
+        stats->int_stats[i].dsIntIndex = i;
+        strncpy(stats->int_stats[i].dsName, g_get_global_snmp_vars()->int_tbl[i].dsName,
+                sizeof(stats->int_stats[i].dsName));
+        stats->int_stats[i].dsTimeOfCreation = g_get_global_snmp_vars()->int_tbl[i].dsTimeOfCreation;
+        stats->int_stats[i].dsTimeOfLastAttempt = g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastAttempt;
+        stats->int_stats[i].dsTimeOfLastSuccess = g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastSuccess;
+        stats->int_stats[i].dsFailuresSinceLastSuccess = g_get_global_snmp_vars()->int_tbl[i].dsFailuresSinceLastSuccess;
+        stats->int_stats[i].dsFailures = g_get_global_snmp_vars()->int_tbl[i].dsFailures;
+        stats->int_stats[i].dsSuccesses = g_get_global_snmp_vars()->int_tbl[i].dsSuccesses;
+        strncpy(stats->int_stats[i].dsURL, g_get_global_snmp_vars()->int_tbl[i].dsURL,
+                sizeof(stats->int_stats[i].dsURL));
+    }
+}
+
+/*
+ * snmp_update_cache_stats()
+ *
+ * Reads the backend cache stats from the backend monitor entry and 
+ * updates the global counter used by the SNMP sub-agent as well as
+ * the SNMP monitor entry.
+ */
+static void
+snmp_update_cache_stats()
+{
+    Slapi_Backend       *be, *be_next;
+    char                *cookie = NULL;
+    Slapi_PBlock        *search_result_pb = NULL;
+    Slapi_Entry         **search_entries;
+    int                 search_result;
+
     /* set the cache hits/cache entries info */
-	be = slapi_get_first_backend(&cookie);
-	if (!be)
-		return;
+    be = slapi_get_first_backend(&cookie);
+    if (!be)
+        return;
 
-	be_next = slapi_get_next_backend(cookie);
+    be_next = slapi_get_next_backend(cookie);
 
-	slapi_ch_free ((void **) &cookie);
+    slapi_ch_free ((void **) &cookie);
 
-	/* for now, only do it if there is only 1 backend, otherwise don't know 
-       which backend to pick */
+    /* for now, only do it if there is only 1 backend, otherwise don't know 
+     * which backend to pick */
     if(be_next == NULL)
     {
-	    Slapi_DN monitordn;
-		slapi_sdn_init(&monitordn);
-		be_getmonitordn(be,&monitordn);
+        Slapi_DN monitordn;
+        slapi_sdn_init(&monitordn);
+        be_getmonitordn(be,&monitordn);
    
-	  /* do a search on the monitor dn to get info */
+        /* do a search on the monitor dn to get info */
         search_result_pb = slapi_search_internal( slapi_sdn_get_dn(&monitordn),
-				    LDAP_SCOPE_BASE,
-				    "objectclass=*", 
-				    NULL,
-				    NULL,
-				    0);
-		slapi_sdn_done(&monitordn);
-
-		slapi_pblock_get( search_result_pb, SLAPI_PLUGIN_INTOP_RESULT, &search_result);
-
-		if(search_result == 0)
-		{
-		    const struct berval *val = NULL;
-            /* get the entrycachehits */
-		    slapi_pblock_get( search_result_pb,SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES,
-				    &search_entries);
-		    if(slapi_entry_attr_find( search_entries[0], "entrycachehits", &attr)  == 0 )
-		    {
-		        /* get the values out of the attribute */
-				val = NULL;
-				slapi_attr_first_value( attr, &sval );
-				if(NULL != sval)
-				{
-				    val= slapi_value_get_berval( sval );
-				}
-		    }		       
-
-		    /* if we got a value for entrycachehits, then set it */
-		    if(val != NULL)
-		    {
-		        snmp_set_counter(g_get_global_snmp_vars()->entries_tbl.dsCacheHits, atoi(val->bv_val));
-
-		    }
+                LDAP_SCOPE_BASE,
+                "objectclass=*", 
+                NULL,
+                NULL,
+                0);
+        slapi_sdn_done(&monitordn);
+
+        slapi_pblock_get( search_result_pb, SLAPI_PLUGIN_INTOP_RESULT, &search_result);
+
+        if(search_result == 0)
+        {
+            slapi_pblock_get( search_result_pb,SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES,
+                    &search_entries);
+
+            /* set the entrycachehits */
+            slapi_counter_set_value(g_get_global_snmp_vars()->entries_tbl.dsCacheHits,
+                    slapi_entry_attr_get_ulonglong(search_entries[0], "entrycachehits"));
 		    
-		    /* get the currententrycachesize */
-		    attr = NULL;
-		    val = NULL;
-		    sval = NULL;
-		    if(slapi_entry_attr_find( search_entries[0], "currententrycachesize", &attr)  == 0 )
-		    {
-		        /* get the values out of the attribute */
-		        slapi_attr_first_value( attr,&sval );
-				if(NULL != sval) {
-				    val= slapi_value_get_berval( sval );
-				}
-		    }		       
-
-		    /* if we got a value for currententrycachesize, then set it */
-		    if(val != NULL)
-		    {
-		        snmp_set_counter(g_get_global_snmp_vars()->entries_tbl.dsCacheEntries, atoi(val->bv_val));
-
-		    }
-
-		}
-		
-		slapi_free_search_results_internal(search_result_pb);
-	    slapi_pblock_destroy(search_result_pb);
+            /* set the currententrycachesize */
+            slapi_counter_set_value(g_get_global_snmp_vars()->entries_tbl.dsCacheEntries,
+                    slapi_entry_attr_get_ulonglong(search_entries[0], "currententrycachesize"));
+        }
+
+        slapi_free_search_results_internal(search_result_pb);
+        slapi_pblock_destroy(search_result_pb);
     }
 }
 
-/* NGK - We should not be using a plain int here.  All of these counters
- * are PRUint32 types for now, but they will be PRUint64 once converted
- * to use Slapi_Counter. */
 static void
-add_counter_to_value(Slapi_Entry *e, const char *type, int countervalue)
+add_counter_to_value(Slapi_Entry *e, const char *type, PRUint64 countervalue)
 {
 	char value[40];
-	sprintf(value,"%d",countervalue);
+	sprintf(value,"%" PRIu64, countervalue);
 	slapi_entry_attr_set_charptr( e, type, value);
 }
 
 void
 snmp_as_entry(Slapi_Entry *e)
 {
-	add_counter_to_value(e,"AnonymousBinds",stats->ops_stats.dsAnonymousBinds);
-	add_counter_to_value(e,"UnAuthBinds",stats->ops_stats.dsUnAuthBinds);
-	add_counter_to_value(e,"SimpleAuthBinds",stats->ops_stats.dsSimpleAuthBinds);
-	add_counter_to_value(e,"StrongAuthBinds",stats->ops_stats.dsStrongAuthBinds);
-	add_counter_to_value(e,"BindSecurityErrors",stats->ops_stats.dsBindSecurityErrors);
-	add_counter_to_value(e,"InOps",stats->ops_stats.dsInOps);
-	add_counter_to_value(e,"ReadOps",stats->ops_stats.dsReadOps);
-	add_counter_to_value(e,"CompareOps",stats->ops_stats.dsCompareOps);
-	add_counter_to_value(e,"AddEntryOps",stats->ops_stats.dsAddEntryOps);
-	add_counter_to_value(e,"RemoveEntryOps",stats->ops_stats.dsRemoveEntryOps);
-	add_counter_to_value(e,"ModifyEntryOps",stats->ops_stats.dsModifyEntryOps);
-	add_counter_to_value(e,"ModifyRDNOps",stats->ops_stats.dsModifyRDNOps);
-	add_counter_to_value(e,"ListOps",stats->ops_stats.dsListOps);
-	add_counter_to_value(e,"SearchOps",stats->ops_stats.dsSearchOps);
-	add_counter_to_value(e,"OneLevelSearchOps",stats->ops_stats.dsOneLevelSearchOps);
-	add_counter_to_value(e,"WholeSubtreeSearchOps",stats->ops_stats.dsWholeSubtreeSearchOps);
-	add_counter_to_value(e,"Referrals",stats->ops_stats.dsReferrals);
-	add_counter_to_value(e,"Chainings",stats->ops_stats.dsChainings);
-	add_counter_to_value(e,"SecurityErrors",stats->ops_stats.dsSecurityErrors);
-	add_counter_to_value(e,"Errors",stats->ops_stats.dsErrors);
-	add_counter_to_value(e,"Connections",stats->ops_stats.dsConnections);
-	add_counter_to_value(e,"ConnectionSeq",stats->ops_stats.dsConnectionSeq);
-	add_counter_to_value(e,"BytesRecv",stats->ops_stats.dsBytesRecv);
-	add_counter_to_value(e,"BytesSent",stats->ops_stats.dsBytesSent);
-	add_counter_to_value(e,"EntriesReturned",stats->ops_stats.dsEntriesReturned);
-	add_counter_to_value(e,"ReferralsReturned",stats->ops_stats.dsReferralsReturned);
-	add_counter_to_value(e,"MasterEntries",stats->entries_stats.dsMasterEntries);
-	add_counter_to_value(e,"CopyEntries",stats->entries_stats.dsCopyEntries);
-	add_counter_to_value(e,"CacheEntries",stats->entries_stats.dsCacheEntries);
-	add_counter_to_value(e,"CacheHits",stats->entries_stats.dsCacheHits);
-	add_counter_to_value(e,"SlaveHits",stats->entries_stats.dsSlaveHits);
+	add_counter_to_value(e,"AnonymousBinds", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsAnonymousBinds));
+	add_counter_to_value(e,"UnAuthBinds", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsUnAuthBinds));
+	add_counter_to_value(e,"SimpleAuthBinds", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsSimpleAuthBinds));
+	add_counter_to_value(e,"StrongAuthBinds", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsStrongAuthBinds));
+	add_counter_to_value(e,"BindSecurityErrors", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsBindSecurityErrors));
+	add_counter_to_value(e,"InOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsInOps));
+	add_counter_to_value(e,"ReadOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsReadOps));
+	add_counter_to_value(e,"CompareOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsCompareOps));
+	add_counter_to_value(e,"AddEntryOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsAddEntryOps));
+	add_counter_to_value(e,"RemoveEntryOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsRemoveEntryOps));
+	add_counter_to_value(e,"ModifyEntryOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsModifyEntryOps));
+	add_counter_to_value(e,"ModifyRDNOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsModifyRDNOps));
+	add_counter_to_value(e,"ListOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsListOps));
+	add_counter_to_value(e,"SearchOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsSearchOps));
+	add_counter_to_value(e,"OneLevelSearchOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsOneLevelSearchOps));
+	add_counter_to_value(e,"WholeSubtreeSearchOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsWholeSubtreeSearchOps));
+	add_counter_to_value(e,"Referrals", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsReferrals));
+	add_counter_to_value(e,"Chainings", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsChainings));
+	add_counter_to_value(e,"SecurityErrors", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsSecurityErrors));
+	add_counter_to_value(e,"Errors", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsErrors));
+	add_counter_to_value(e,"Connections", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsConnections));
+	add_counter_to_value(e,"ConnectionSeq", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsConnectionSeq));
+	add_counter_to_value(e,"BytesRecv", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsBytesRecv));
+	add_counter_to_value(e,"BytesSent", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsBytesSent));
+	add_counter_to_value(e,"EntriesReturned", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsEntriesReturned));
+	add_counter_to_value(e,"ReferralsReturned", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsReferralsReturned));
+	add_counter_to_value(e,"MasterEntries", slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsMasterEntries));
+	add_counter_to_value(e,"CopyEntries", slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsCopyEntries));
+	add_counter_to_value(e,"CacheEntries", slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsCacheEntries));
+	add_counter_to_value(e,"CacheHits", slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsCacheHits));
+	add_counter_to_value(e,"SlaveHits", slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsSlaveHits));
 }
 
+/*
+ * loadConfigStats()
+ *
+ * Reads the header table SNMP settings and sets them in the mmap'd stats
+ * file.  This should be done only when the semaphore is held.
+ */
 static void
 loadConfigStats() {
 	Slapi_Entry *entry = NULL;
@@ -726,20 +879,3 @@
         }
 }
 
-/*
- * wrapper functions to ease the cast burdon between net=snmp APIs which expect
- * unsigned int and PR_AtomicIncrement/PR_AtomicSet which expect signed int.
- * NSPR_API(PRInt32) PR_AtomicSet(PRInt32 *val, PRInt32 newval);
- * NSPR_API(PRInt32) PR_AtomicIncrement(PRInt32 *val);
- */
-void
-snmp_increment_counter(PRUint32 *counter)
-{
-	PR_AtomicIncrement((PRInt32 *)counter);
-}
-
-void snmp_set_counter(PRUint32 *counter, PRInt32 newval)
-{
-	PR_AtomicSet((PRInt32 *)counter, newval);
-}
-




More information about the Fedora-directory-commits mailing list