Improve RDB type correctness

It's possible large objects could be larger than 'int', so let's
upgrade all size counters to ssize_t.

This also fixes rdbSaveObject serialized bytes calculation.
Since entire serializations of data structures can be large,
so we don't want to limit their calculated size to a 32 bit signed max.

This commit increases object size calculation and
cascades the change back up to serializedlength printing.

Before:
127.0.0.1:6379> debug object hihihi
... encoding:quicklist serializedlength:-2147483559 ...

After:
127.0.0.1:6379> debug object hihihi
... encoding:quicklist serializedlength:2147483737 ...
This commit is contained in:
Matt Stancliff 2015-01-18 15:54:30 -05:00
parent cf76af6b9f
commit f704360462
3 changed files with 17 additions and 18 deletions

View File

@ -336,10 +336,10 @@ void debugCommand(redisClient *c) {
addReplyStatusFormat(c, addReplyStatusFormat(c,
"Value at:%p refcount:%d " "Value at:%p refcount:%d "
"encoding:%s serializedlength:%lld " "encoding:%s serializedlength:%zu "
"lru:%d lru_seconds_idle:%llu%s", "lru:%d lru_seconds_idle:%llu%s",
(void*)val, val->refcount, (void*)val, val->refcount,
strenc, (long long) rdbSavedObjectLen(val), strenc, rdbSavedObjectLen(val),
val->lru, estimateObjectIdleTime(val)/1000, extra); val->lru, estimateObjectIdleTime(val)/1000, extra);
} else if (!strcasecmp(c->argv[1]->ptr,"sdslen") && c->argc == 3) { } else if (!strcasecmp(c->argv[1]->ptr,"sdslen") && c->argc == 3) {
dictEntry *de; dictEntry *de;

View File

@ -222,10 +222,10 @@ int rdbTryIntegerEncoding(char *s, size_t len, unsigned char *enc) {
return rdbEncodeInteger(value,enc); return rdbEncodeInteger(value,enc);
} }
int rdbSaveLzfBlob(rio *rdb, void *data, size_t compress_len, ssize_t rdbSaveLzfBlob(rio *rdb, void *data, size_t compress_len,
size_t original_len) { size_t original_len) {
unsigned char byte; unsigned char byte;
int n, nwritten = 0; ssize_t n, nwritten = 0;
/* Data compressed! Let's save it on disk */ /* Data compressed! Let's save it on disk */
byte = (REDIS_RDB_ENCVAL<<6)|REDIS_RDB_ENC_LZF; byte = (REDIS_RDB_ENCVAL<<6)|REDIS_RDB_ENC_LZF;
@ -247,7 +247,7 @@ writeerr:
return -1; return -1;
} }
int rdbSaveLzfStringObject(rio *rdb, unsigned char *s, size_t len) { ssize_t rdbSaveLzfStringObject(rio *rdb, unsigned char *s, size_t len) {
size_t comprlen, outlen; size_t comprlen, outlen;
void *out; void *out;
@ -260,7 +260,7 @@ int rdbSaveLzfStringObject(rio *rdb, unsigned char *s, size_t len) {
zfree(out); zfree(out);
return 0; return 0;
} }
size_t nwritten = rdbSaveLzfBlob(rdb, out, comprlen, len); ssize_t nwritten = rdbSaveLzfBlob(rdb, out, comprlen, len);
zfree(out); zfree(out);
return nwritten; return nwritten;
} }
@ -305,9 +305,9 @@ err:
/* Save a string object as [len][data] on disk. If the object is a string /* Save a string object as [len][data] on disk. If the object is a string
* representation of an integer value we try to save it in a special form */ * representation of an integer value we try to save it in a special form */
int rdbSaveRawString(rio *rdb, unsigned char *s, size_t len) { ssize_t rdbSaveRawString(rio *rdb, unsigned char *s, size_t len) {
int enclen; int enclen;
int n, nwritten = 0; ssize_t n, nwritten = 0;
/* Try integer encoding */ /* Try integer encoding */
if (len <= 11) { if (len <= 11) {
@ -338,9 +338,9 @@ int rdbSaveRawString(rio *rdb, unsigned char *s, size_t len) {
} }
/* Save a long long value as either an encoded string or a string. */ /* Save a long long value as either an encoded string or a string. */
int rdbSaveLongLongAsStringObject(rio *rdb, long long value) { ssize_t rdbSaveLongLongAsStringObject(rio *rdb, long long value) {
unsigned char buf[32]; unsigned char buf[32];
int n, nwritten = 0; ssize_t n, nwritten = 0;
int enclen = rdbEncodeInteger(value,buf); int enclen = rdbEncodeInteger(value,buf);
if (enclen > 0) { if (enclen > 0) {
return rdbWriteRaw(rdb,buf,enclen); return rdbWriteRaw(rdb,buf,enclen);
@ -532,8 +532,8 @@ int rdbLoadObjectType(rio *rdb) {
} }
/* Save a Redis object. Returns -1 on error, number of bytes written on success. */ /* Save a Redis object. Returns -1 on error, number of bytes written on success. */
int rdbSaveObject(rio *rdb, robj *o) { ssize_t rdbSaveObject(rio *rdb, robj *o) {
int n = 0, nwritten = 0; ssize_t n = 0, nwritten = 0;
if (o->type == REDIS_STRING) { if (o->type == REDIS_STRING) {
/* Save a string value */ /* Save a string value */
@ -654,8 +654,8 @@ int rdbSaveObject(rio *rdb, robj *o) {
* the rdbSaveObject() function. Currently we use a trick to get * the rdbSaveObject() function. Currently we use a trick to get
* this length with very little changes to the code. In the future * this length with very little changes to the code. In the future
* we could switch to a faster solution. */ * we could switch to a faster solution. */
off_t rdbSavedObjectLen(robj *o) { size_t rdbSavedObjectLen(robj *o) {
int len = rdbSaveObject(NULL,o); ssize_t len = rdbSaveObject(NULL,o);
redisAssertWithInfo(NULL,o,len != -1); redisAssertWithInfo(NULL,o,len != -1);
return len; return len;
} }

View File

@ -109,9 +109,8 @@ int rdbSaveBackground(char *filename);
int rdbSaveToSlavesSockets(void); int rdbSaveToSlavesSockets(void);
void rdbRemoveTempFile(pid_t childpid); void rdbRemoveTempFile(pid_t childpid);
int rdbSave(char *filename); int rdbSave(char *filename);
int rdbSaveObject(rio *rdb, robj *o); ssize_t rdbSaveObject(rio *rdb, robj *o);
off_t rdbSavedObjectLen(robj *o); size_t rdbSavedObjectLen(robj *o);
off_t rdbSavedObjectPages(robj *o);
robj *rdbLoadObject(int type, rio *rdb); robj *rdbLoadObject(int type, rio *rdb);
void backgroundSaveDoneHandler(int exitcode, int bysignal); void backgroundSaveDoneHandler(int exitcode, int bysignal);
int rdbSaveKeyValuePair(rio *rdb, robj *key, robj *val, long long expiretime, long long now); int rdbSaveKeyValuePair(rio *rdb, robj *key, robj *val, long long expiretime, long long now);