[389-devel] Please review: csn_init_as_string should not use sscanf

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




From ce59c808793ff858bb0771830e000eb54982035c Mon Sep 17 00:00:00 2001
From: Rich Megginson <rmeggins@xxxxxxxxxx>
Date: Wed, 16 Nov 2011 17:34:46 -0700
Subject: [PATCH] csn_init_as_string should not use sscanf

Added new slapi functions to convert decimal/hex strings to their integral
values.  Use these in csn_init_as_string to convert the csn string values
to their integral values.  Similar to removing sprintf, using these functions
instead of sscanf provides a large performance gain.
I also got rid of the use of PR_Counter in favor of slapi_counter, and
only use the counters if DEBUG is set.
---
 ldap/servers/slapd/csn.c          |   64 +++++++++++-----------------
 ldap/servers/slapd/slapi-plugin.h |   47 +++++++++++++++++++++
 ldap/servers/slapd/util.c         |   83 +++++++++++++++++++++++++++++++++++++
 3 files changed, 155 insertions(+), 39 deletions(-)

diff --git a/ldap/servers/slapd/csn.c b/ldap/servers/slapd/csn.c
index 0480036..9fb5b4a 100644
--- a/ldap/servers/slapd/csn.c
+++ b/ldap/servers/slapd/csn.c
@@ -47,19 +47,6 @@
 
 #include <string.h>
 #include "slap.h"
-#include <prcountr.h>
-
-#define _CSN_TSTAMP_STRSIZE_STR "8"
-#define _CSN_SEQNUM_STRSIZE_STR "4"
-#define _CSN_REPLID_STRSIZE_STR "4"
-#define _CSN_SUBSEQNUM_STRSIZE_STR "4"
-
-#define _CSN_TSTAMP_SCANSTR "%"_CSN_TSTAMP_STRSIZE_STR"lx"
-#define _CSN_SEQNUM_SCANSTR "%"_CSN_SEQNUM_STRSIZE_STR"hx"
-#define _CSN_REPLID_SCANSTR "%"_CSN_REPLID_STRSIZE_STR"hx"
-#define _CSN_SUBSEQNUM_SCANSTR "%"_CSN_SUBSEQNUM_STRSIZE_STR"hx" 
-
-#define _CSN_TSORDER_SPRINTSTR "%08x%04x%04x%04x"
 
 #define _CSN_TSORDER_TSTAMP_OFFSET 0
 #define _CSN_TSORDER_SEQNUM_OFFSET 8
@@ -71,10 +58,12 @@ static PRBool _csnIsValidString(const char *csnStr);
 /*
  * Debugging counters.
  */
+#ifdef DEBUG
 static int counters_created= 0;
-PR_DEFINE_COUNTER(slapi_csn_counter_created);
-PR_DEFINE_COUNTER(slapi_csn_counter_deleted);
-PR_DEFINE_COUNTER(slapi_csn_counter_exist);
+static Slapi_Counter *slapi_csn_counter_created;
+static Slapi_Counter *slapi_csn_counter_deleted;
+static Slapi_Counter *slapi_csn_counter_exist;
+#endif
 
 /*
  * **************************************************************************
@@ -82,23 +71,27 @@ PR_DEFINE_COUNTER(slapi_csn_counter_exist);
  * **************************************************************************
  */
 
+#ifdef DEBUG
 static void
 csn_create_counters()
 {
-	PR_CREATE_COUNTER(slapi_csn_counter_created,"Slapi_CSN","created","");
-	PR_CREATE_COUNTER(slapi_csn_counter_deleted,"Slapi_CSN","deleted","");
-	PR_CREATE_COUNTER(slapi_csn_counter_exist,"Slapi_CSN","exist","");
+	slapi_csn_counter_created = slapi_counter_new();
+	slapi_csn_counter_deleted = slapi_counter_new();
+	slapi_csn_counter_exist = slapi_counter_new();
 	counters_created= 1;
 }
+#endif
 
 CSN *csn_new()
 {
+#ifdef DEBUG
 	if(!counters_created)
 	{
 		csn_create_counters();
 	}
-	PR_INCREMENT_COUNTER(slapi_csn_counter_created);
-	PR_INCREMENT_COUNTER(slapi_csn_counter_exist);
+	slapi_counter_increment(slapi_csn_counter_created);
+	slapi_counter_increment(slapi_csn_counter_exist);
+#endif
 	return (CSN*)slapi_ch_calloc(sizeof(CSN),1);
 }
 
@@ -138,22 +131,13 @@ void csn_init_by_csn(CSN *csn1,const CSN *csn2)
 
 void csn_init_by_string(CSN *csn, const char *s)
 {
-	time_t csnTime= 0;
-	PRUint16 csnSeqNum= 0;
-	ReplicaId rid= 0;
-	PRUint16 csnSubSeqNum= 0;
-
-    if(_csnIsValidString(s))
-    {
-		/* JCM - char2hex faster */
-		sscanf((s+_CSN_TSORDER_TSTAMP_OFFSET), _CSN_TSTAMP_SCANSTR, &csnTime); /* JCM - scanf is very slow */
-		sscanf((s+_CSN_TSORDER_SEQNUM_OFFSET), _CSN_SEQNUM_SCANSTR, &csnSeqNum);/* JCM - scanf is very slow */
-		sscanf((s+_CSN_TSORDER_REPLID_OFFSET), _CSN_REPLID_SCANSTR, &rid);/* JCM - scanf is very slow */
-	    sscanf((s+_CSN_TSORDER_SUBSEQNUM_OFFSET), _CSN_SUBSEQNUM_SCANSTR, &csnSubSeqNum);/* JCM - scanf is very slow */
-	    csn->tstamp= csnTime;
-	    csn->seqnum= csnSeqNum;
-	    csn->rid= rid;
-		csn->subseqnum= csnSubSeqNum;
+	if(_csnIsValidString(s)) {
+		/* yes - time_t is long - but the CSN will only ever store the lowest 4 bytes of
+		   the timestamp */
+		csn->tstamp = slapi_str_to_u32(s+_CSN_TSORDER_TSTAMP_OFFSET);
+		csn->seqnum = slapi_str_to_u16(s+_CSN_TSORDER_SEQNUM_OFFSET);
+		csn->rid = slapi_str_to_u16(s+_CSN_TSORDER_REPLID_OFFSET);
+		csn->subseqnum = slapi_str_to_u16(s+_CSN_TSORDER_SUBSEQNUM_OFFSET);
 	}
 }
 
@@ -176,12 +160,14 @@ void csn_free(CSN **csn)
 {
 	if(csn!=NULL && *csn!=NULL)
 	{
+#ifdef DEBUG
 		if(!counters_created)
 		{
 			csn_create_counters();
 		}
-		PR_INCREMENT_COUNTER(slapi_csn_counter_deleted);
-		PR_DECREMENT_COUNTER(slapi_csn_counter_exist);
+		slapi_counter_increment(slapi_csn_counter_deleted);
+		slapi_counter_increment(slapi_csn_counter_exist);
+#endif
 	    slapi_ch_free((void **)csn);
 	}
     return;
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index 446c5f7..cc19777 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -6826,6 +6826,53 @@ char *slapi_u32_to_hex(uint32_t val, char *s, uint8_t upper);
  */
 char *slapi_u64_to_hex(uint64_t val, char *s, uint8_t upper);
 
+/**
+ * Convert a char to its integral hex value e.g. '0' -> 0 or 'a' -> 10.
+ * This only works on one caller at a time.  If you want to convert a string
+ * of decimal/hex numbers to its integral value, see slapi_str_to_u8 et. al.
+ * This uses a lookup table so it should be extremely fast.
+ *
+ * \param c character value to convert
+ * \return integral value of the given char or -1 if not a valid decimal/hex digit
+ */
+int slapi_hexchar2int(char c);
+
+/**
+ * Convert a string of 2 decimal/hex characters to a 1 byte (8-bit) unsigned value.
+ * This function does no checking - it assumes s is non-NULL and well-formed.
+ *
+ * \param s convert the first 2 chars of this decimal/hex char string to its integral value
+ * \return the integral value
+ */
+uint8_t slapi_str_to_u8(const char *s);
+
+/**
+ * Convert a string of 4 decimal/hex characters to a 2 byte (16-bit) unsigned value.
+ * This function does no checking - it assumes s is non-NULL and well-formed.
+ *
+ * \param s convert the first 4 chars of this decimal/hex char string to its integral value
+ * \return the integral value
+ */
+uint16_t slapi_str_to_u16(const char *s);
+
+/**
+ * Convert a string of 8 decimal/hex characters to a 4 byte (32-bit) unsigned value.
+ * This function does no checking - it assumes s is non-NULL and well-formed.
+ *
+ * \param s convert the first 8 chars of this decimal/hex char string to its integral value
+ * \return the integral value
+ */
+uint32_t slapi_str_to_u32(const char *s);
+
+/**
+ * Convert a string of 16 decimal/hex characters to a 8 byte (64-bit) unsigned value.
+ * This function does no checking - it assumes s is non-NULL and well-formed.
+ *
+ * \param s convert the first 16 chars of this decimal/hex char string to its integral value
+ * \return the integral value
+ */
+uint64_t slapi_str_to_u64(const char *s);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/ldap/servers/slapd/util.c b/ldap/servers/slapd/util.c
index e2970b4..58d4dfa 100644
--- a/ldap/servers/slapd/util.c
+++ b/ldap/servers/slapd/util.c
@@ -1004,3 +1004,86 @@ slapi_u64_to_hex(uint64_t val, char *s, uint8_t upper) {
 	s[15] = digits[val & 0xf];
 	return &s[16];
 }
+
+static const int char2intarray[] = {
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
+	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+};
+
+static const int char2intarray_size = sizeof(char2intarray)/sizeof(char2intarray[0]);
+
+int
+slapi_hexchar2int(char c)
+{
+	return char2intarray[(unsigned char)c];
+}
+    
+uint8_t
+slapi_str_to_u8(const char *s)
+{
+	uint8_t v0 = (uint8_t)slapi_hexchar2int(s[0]);
+	uint8_t v1 = (uint8_t)slapi_hexchar2int(s[1]);
+	return (v0 << 4) | v1;
+}
+
+uint16_t
+slapi_str_to_u16(const char *s)
+{
+	uint16_t v0 = (uint16_t)slapi_hexchar2int(s[0]);
+	uint16_t v1 = (uint16_t)slapi_hexchar2int(s[1]);
+	uint16_t v2 = (uint16_t)slapi_hexchar2int(s[2]);
+	uint16_t v3 = (uint16_t)slapi_hexchar2int(s[3]);
+	return (v0 << 12) | (v1 << 8) | (v2 << 4) | v3;
+}
+
+uint32_t
+slapi_str_to_u32(const char *s)
+{
+	uint32_t v0 = (uint32_t)slapi_hexchar2int(s[0]);
+	uint32_t v1 = (uint32_t)slapi_hexchar2int(s[1]);
+	uint32_t v2 = (uint32_t)slapi_hexchar2int(s[2]);
+	uint32_t v3 = (uint32_t)slapi_hexchar2int(s[3]);
+	uint32_t v4 = (uint32_t)slapi_hexchar2int(s[4]);
+	uint32_t v5 = (uint32_t)slapi_hexchar2int(s[5]);
+	uint32_t v6 = (uint32_t)slapi_hexchar2int(s[6]);
+	uint32_t v7 = (uint32_t)slapi_hexchar2int(s[7]);
+	return (v0 << 28) | (v1 << 24) | (v2 << 20) | (v3 << 16) | (v4 << 12) | (v5 << 8) | (v6 << 4) | v7;
+}
+
+uint64_t
+slapi_str_to_u64(const char *s)
+{
+	uint64_t v0 = (uint64_t)slapi_hexchar2int(s[0]);
+	uint64_t v1 = (uint64_t)slapi_hexchar2int(s[1]);
+	uint64_t v2 = (uint64_t)slapi_hexchar2int(s[2]);
+	uint64_t v3 = (uint64_t)slapi_hexchar2int(s[3]);
+	uint64_t v4 = (uint64_t)slapi_hexchar2int(s[4]);
+	uint64_t v5 = (uint64_t)slapi_hexchar2int(s[5]);
+	uint64_t v6 = (uint64_t)slapi_hexchar2int(s[6]);
+	uint64_t v7 = (uint64_t)slapi_hexchar2int(s[7]);
+	uint64_t v8 = (uint64_t)slapi_hexchar2int(s[8]);
+	uint64_t v9 = (uint64_t)slapi_hexchar2int(s[9]);
+	uint64_t v10 = (uint64_t)slapi_hexchar2int(s[10]);
+	uint64_t v11 = (uint64_t)slapi_hexchar2int(s[11]);
+	uint64_t v12 = (uint64_t)slapi_hexchar2int(s[12]);
+	uint64_t v13 = (uint64_t)slapi_hexchar2int(s[13]);
+	uint64_t v14 = (uint64_t)slapi_hexchar2int(s[14]);
+	uint64_t v15 = (uint64_t)slapi_hexchar2int(s[15]);
+	return (v0 << 60) | (v1 << 56) | (v2 << 52) | (v3 << 48) | (v4 << 44) | (v5 << 40) |
+		(v6 << 36) | (v7 << 32) | (v8 << 28) | (v9 << 24) | (v10 << 20) | (v11 << 16) |
+		(v12 << 12) | (v13 << 8) | (v14 << 4) | v15;
+}
-- 
1.7.1

--
389-devel mailing list
389-devel@xxxxxxxxxxxxxxxxxxxxxxx
https://admin.fedoraproject.org/mailman/listinfo/389-devel

[Index of Archives]     [Fedora Directory Announce]     [Fedora Users]     [Older Fedora Users Mail]     [Fedora Advisory Board]     [Fedora Security]     [Fedora Devel Java]     [Fedora Desktop]     [ATA RAID]     [Fedora Marketing]     [Fedora Mentors]     [Fedora Package Review]     [Fedora Art]     [Fedora Music]     [Fedora Packaging]     [CentOS]     [Fedora SELinux]     [Big List of Linux Books]     [KDE Users]     [Fedora Art]     [Fedora Docs]

  Powered by Linux