Lazyfree: Hash converted to use plain SDS WIP 2.

This commit is contained in:
antirez 2015-09-15 14:43:14 +02:00
parent 1c247556c6
commit 777396aeba
4 changed files with 64 additions and 37 deletions

View File

@ -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);
}

View File

@ -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) {

View File

@ -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

View File

@ -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);