summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2015-09-15 14:43:14 +0200
committerantirez <antirez@gmail.com>2015-10-01 13:02:24 +0200
commit777396aeba81c2346041d5d1a4b507693d6177e2 (patch)
tree84eac56d26fbb2b5ebee038b53d337d5900b94b1
parent1c247556c691bb61be65734be0670d50512f710c (diff)
downloadredis-777396aeba81c2346041d5d1a4b507693d6177e2.tar.gz
Lazyfree: Hash converted to use plain SDS WIP 2.
-rw-r--r--src/object.c32
-rw-r--r--src/t_hash.c16
-rw-r--r--src/util.c52
-rw-r--r--src/util.h1
4 files changed, 64 insertions, 37 deletions
diff --git a/src/object.c b/src/object.c
index 5d72abb8c..43c371ead 100644
--- a/src/object.c
+++ b/src/object.c
@@ -135,37 +135,7 @@ robj *createStringObjectFromLongLong(long long value) {
* The 'humanfriendly' option is used for INCRBYFLOAT and HINCRBYFLOAT. */
robj *createStringObjectFromLongDouble(long double value, int humanfriendly) {
char buf[256];
- int len;
-
- if (isinf(value)) {
- /* Libc in odd systems (Hi Solaris!) will format infinite in a
- * different way, so better to handle it in an explicit way. */
- if (value > 0) {
- memcpy(buf,"inf",3);
- len = 3;
- } else {
- memcpy(buf,"-inf",4);
- len = 4;
- }
- } else if (humanfriendly) {
- /* We use 17 digits precision since with 128 bit floats that precision
- * after rounding is able to represent most small decimal numbers in a
- * way that is "non surprising" for the user (that is, most small
- * decimal numbers will be represented in a way that when converted
- * back into a string are exactly the same as what the user typed.) */
- len = snprintf(buf,sizeof(buf),"%.17Lf", value);
- /* Now remove trailing zeroes after the '.' */
- if (strchr(buf,'.') != NULL) {
- char *p = buf+len-1;
- while(*p == '0') {
- p--;
- len--;
- }
- if (*p == '.') len--;
- }
- } else {
- len = snprintf(buf,sizeof(buf),"%.17Lg", value);
- }
+ int len = ld2string(buf,sizeof(buf),value,humanfriendly);
return createStringObject(buf,len);
}
diff --git a/src/t_hash.c b/src/t_hash.c
index 9019112e1..eaf4d245c 100644
--- a/src/t_hash.c
+++ b/src/t_hash.c
@@ -545,10 +545,12 @@ void hincrbyCommand(client *c) {
server.dirty++;
}
+/* XXX From here. */
+
void hincrbyfloatCommand(client *c) {
double value, incr;
long long ll;
- robj *o, *doubleobj;
+ robj *o;
sds new;
unsigned char *vstr;
unsigned int *lven;
@@ -569,10 +571,12 @@ void hincrbyfloatCommand(client *c) {
}
value += incr;
- doubleobj = createStringObjectFromLongDouble(value,1);
- decrRefCount(doubleobj);
+
+ char buf[256];
+ int len = ld2string(buf,sizeof(buf),value,humanfriendly);
+ new = sdsnewlen(buf,len);
hashTypeSet(o,c->argv[2],new);
- addReplyBulk(c,new);
+ addReplyBulkSds(c,new);
signalModifiedKey(c->db,c->argv[1]);
notifyKeyspaceEvent(NOTIFY_HASH,"hincrbyfloat",c->argv[1],c->db->id);
server.dirty++;
@@ -580,11 +584,13 @@ void hincrbyfloatCommand(client *c) {
/* Always replicate HINCRBYFLOAT as an HSET command with the final value
* in order to make sure that differences in float pricision or formatting
* will not create differences in replicas or after an AOF restart. */
+ robj *aux, *newobj;
aux = createStringObject("HSET",4);
+ newobj = createRawStringObject(buf,len);
rewriteClientCommandArgument(c,0,aux);
decrRefCount(aux);
rewriteClientCommandArgument(c,3,new);
- decrRefCount(new);
+ decrRefCount(newobj);
}
static void addHashFieldToReply(client *c, robj *o, robj *field) {
diff --git a/src/util.c b/src/util.c
index 4a000bc61..80e316c9c 100644
--- a/src/util.c
+++ b/src/util.c
@@ -444,7 +444,10 @@ int string2d(const char *s, size_t slen, double *dp) {
}
/* Convert a double to a string representation. Returns the number of bytes
- * required. The representation should always be parsable by strtod(3). */
+ * required. The representation should always be parsable by strtod(3).
+ * This function does not support human-friendly formatting like ld2string
+ * does. It is intented mainly to be used inside t_zset.c when writing scores
+ * into a ziplist representing a sorted set. */
int d2string(char *buf, size_t len, double value) {
if (isnan(value)) {
len = snprintf(buf,len,"nan");
@@ -482,6 +485,53 @@ int d2string(char *buf, size_t len, double value) {
return len;
}
+/* Convert a long double into a string. If humanfriendly is non-zero
+ * it does not use exponential format and trims trailing zeroes at the end,
+ * however this results in loss of precision. Otherwise exp format is used
+ * and the output of snprintf() is not modified.
+ *
+ * The function returns the length of the string or zero if there was not
+ * enough buffer room to store it. */
+int ld2string(char *buf, size_t len, long double value, int humanfriendly) {
+ char buf[256];
+ size_t l;
+
+ if (isinf(value)) {
+ /* Libc in odd systems (Hi Solaris!) will format infinite in a
+ * different way, so better to handle it in an explicit way. */
+ if (len < 5) return 0; /* No room. 5 is "-inf\0" */
+ if (value > 0) {
+ memcpy(buf,"inf",3);
+ l = 3;
+ } else {
+ memcpy(buf,"-inf",4);
+ l = 4;
+ }
+ } else if (humanfriendly) {
+ /* We use 17 digits precision since with 128 bit floats that precision
+ * after rounding is able to represent most small decimal numbers in a
+ * way that is "non surprising" for the user (that is, most small
+ * decimal numbers will be represented in a way that when converted
+ * back into a string are exactly the same as what the user typed.) */
+ l = snprintf(buf,len,"%.17Lf", value);
+ if (l+1 > len) return 0; /* No room. */
+ /* Now remove trailing zeroes after the '.' */
+ if (strchr(buf,'.') != NULL) {
+ char *p = buf+len-1;
+ while(*p == '0') {
+ p--;
+ len--;
+ }
+ if (*p == '.') len--;
+ }
+ } else {
+ l = snprintf(buf,len,"%.17Lg", value);
+ if (l+1 > len) return 0; /* No room. */
+ }
+ buf[l] = '\0';
+ return l;
+}
+
/* Generate the Redis "Run ID", a SHA1-sized random number that identifies a
* given execution of Redis, so that if you are talking with an instance
* having run_id == A, and you reconnect and it has run_id == B, you can be
diff --git a/src/util.h b/src/util.h
index 8ec4228fd..d28049eaf 100644
--- a/src/util.h
+++ b/src/util.h
@@ -43,6 +43,7 @@ int string2ll(const char *s, size_t slen, long long *value);
int string2l(const char *s, size_t slen, long *value);
int string2d(const char *s, size_t slen, double *dp);
int d2string(char *buf, size_t len, double value);
+int ld2string(char *buf, size_t len, long double value, int humanfriendly);
sds getAbsolutePath(char *filename);
int pathIsBaseName(char *path);