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(-)
New commits:
commit 591055105f700ceb0b40cccb76ccd55d0370f63c
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Wed Nov 16 17:34:46 2011 -0700
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.
Reviewed by: nkinder (Thanks!)
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;
+}