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