diff --git a/src/rdb.c b/src/rdb.c index 57b759278..7d696b201 100644 --- a/src/rdb.c +++ b/src/rdb.c @@ -95,7 +95,7 @@ long long rdbLoadMillisecondTime(rio *rdb) { /* Saves an encoded length. The first two bits in the first byte are used to * hold the encoding type. See the RDB_* definitions for more information * on the types of encoding. */ -int rdbSaveLen(rio *rdb, uint32_t len) { +int rdbSaveLen(rio *rdb, uint64_t len) { unsigned char buf[2]; size_t nwritten; @@ -110,13 +110,20 @@ int rdbSaveLen(rio *rdb, uint32_t len) { buf[1] = len&0xFF; if (rdbWriteRaw(rdb,buf,2) == -1) return -1; nwritten = 2; - } else { + } else if (len <= UINT32_MAX) { /* Save a 32 bit len */ - buf[0] = (RDB_32BITLEN<<6); + buf[0] = RDB_32BITLEN; if (rdbWriteRaw(rdb,buf,1) == -1) return -1; - len = htonl(len); - if (rdbWriteRaw(rdb,&len,4) == -1) return -1; + uint32_t len32 = htonl(len); + if (rdbWriteRaw(rdb,&len32,4) == -1) return -1; nwritten = 1+4; + } else { + /* Save a 64 bit len */ + buf[0] = RDB_64BITLEN; + if (rdbWriteRaw(rdb,buf,1) == -1) return -1; + len = htonu64(len); + if (rdbWriteRaw(rdb,&len,8) == -1) return -1; + nwritten = 1+8; } return nwritten; } @@ -124,9 +131,8 @@ int rdbSaveLen(rio *rdb, uint32_t len) { /* Load an encoded length. The "isencoded" argument is set to 1 if the length * is not actually a length but an "encoding type". See the RDB_ENC_* * definitions in rdb.h for more information. */ -uint32_t rdbLoadLen(rio *rdb, int *isencoded) { +uint64_t rdbLoadLen(rio *rdb, int *isencoded) { unsigned char buf[2]; - uint32_t len; int type; if (isencoded) *isencoded = 0; @@ -143,10 +149,19 @@ uint32_t rdbLoadLen(rio *rdb, int *isencoded) { /* Read a 14 bit len. */ if (rioRead(rdb,buf+1,1) == 0) return RDB_LENERR; return ((buf[0]&0x3F)<<8)|buf[1]; - } else { + } else if (buf[0] == RDB_32BITLEN) { /* Read a 32 bit len. */ + uint32_t len; if (rioRead(rdb,&len,4) == 0) return RDB_LENERR; return ntohl(len); + } else if (buf[0] == RDB_64BITLEN) { + /* Read a 64 bit len. */ + uint64_t len; + if (rioRead(rdb,&len,8) == 0) return RDB_LENERR; + return ntohu64(len); + } else { + rdbExitReportCorruptRDB("Unknown length encoding in rdbLoadLen()"); + return 0; /* Never reached. */ } } diff --git a/src/rdb.h b/src/rdb.h index 48a064a19..754bea9e8 100644 --- a/src/rdb.h +++ b/src/rdb.h @@ -38,16 +38,17 @@ /* The current RDB version. When the format changes in a way that is no longer * backward compatible this number gets incremented. */ -#define RDB_VERSION 7 +#define RDB_VERSION 8 /* Defines related to the dump file format. To store 32 bits lengths for short * keys requires a lot of space, so we check the most significant 2 bits of * the first byte to interpreter the length: * - * 00|000000 => if the two MSB are 00 the len is the 6 bits of this byte - * 01|000000 00000000 => 01, the len is 14 byes, 6 bits + 8 bits of next byte - * 10|000000 [32 bit integer] => if it's 01, a full 32 bit len will follow - * 11|000000 this means: specially encoded object will follow. The six bits + * 00|XXXXXX => if the two MSB are 00 the len is the 6 bits of this byte + * 01|XXXXXX XXXXXXXX => 01, the len is 14 byes, 6 bits + 8 bits of next byte + * 10|000000 [32 bit integer] => A full 32 bit len in net byte order will follow + * 10|000001 [64 bit integer] => A full 64 bit len in net byte order will follow + * 11|OBKIND this means: specially encoded object will follow. The six bits * number specify the kind of object that follows. * See the RDB_ENC_* defines. * @@ -55,12 +56,13 @@ * values, will fit inside. */ #define RDB_6BITLEN 0 #define RDB_14BITLEN 1 -#define RDB_32BITLEN 2 +#define RDB_32BITLEN 0x80 +#define RDB_64BITLEN 0x81 #define RDB_ENCVAL 3 #define RDB_LENERR UINT_MAX /* When a length of a string object stored on disk has the first two bits - * set, the remaining two bits specify a special encoding for the object + * set, the remaining six bits specify a special encoding for the object * accordingly to the following defines: */ #define RDB_ENC_INT8 0 /* 8 bit signed integer */ #define RDB_ENC_INT16 1 /* 16 bit signed integer */ @@ -100,8 +102,8 @@ int rdbSaveType(rio *rdb, unsigned char type); int rdbLoadType(rio *rdb); int rdbSaveTime(rio *rdb, time_t t); time_t rdbLoadTime(rio *rdb); -int rdbSaveLen(rio *rdb, uint32_t len); -uint32_t rdbLoadLen(rio *rdb, int *isencoded); +int rdbSaveLen(rio *rdb, uint64_t len); +uint64_t rdbLoadLen(rio *rdb, int *isencoded); int rdbSaveObjectType(rio *rdb, robj *o); int rdbLoadObjectType(rio *rdb); int rdbLoad(char *filename); diff --git a/src/server.h b/src/server.h index 521cfa6b7..07cada62e 100644 --- a/src/server.h +++ b/src/server.h @@ -195,33 +195,6 @@ typedef long long mstime_t; /* millisecond time type. */ #define CMD_MODULE_GETKEYS (1<<14) /* Use the modules getkeys interface. */ #define CMD_MODULE_NO_CLUSTER (1<<15) /* Deny on Redis Cluster. */ -/* Defines related to the dump file format. To store 32 bits lengths for short - * keys requires a lot of space, so we check the most significant 2 bits of - * the first byte to interpreter the length: - * - * 00|000000 => if the two MSB are 00 the len is the 6 bits of this byte - * 01|000000 00000000 => 01, the len is 14 byes, 6 bits + 8 bits of next byte - * 10|000000 [32 bit integer] => if it's 10, a full 32 bit len will follow - * 11|000000 this means: specially encoded object will follow. The six bits - * number specify the kind of object that follows. - * See the RDB_ENC_* defines. - * - * Lengths up to 63 are stored using a single byte, most DB keys, and may - * values, will fit inside. */ -#define RDB_6BITLEN 0 -#define RDB_14BITLEN 1 -#define RDB_32BITLEN 2 -#define RDB_ENCVAL 3 -#define RDB_LENERR UINT_MAX - -/* When a length of a string object stored on disk has the first two bits - * set, the remaining two bits specify a special encoding for the object - * accordingly to the following defines: */ -#define RDB_ENC_INT8 0 /* 8 bit signed integer */ -#define RDB_ENC_INT16 1 /* 16 bit signed integer */ -#define RDB_ENC_INT32 2 /* 32 bit signed integer */ -#define RDB_ENC_LZF 3 /* string compressed with FASTLZ */ - /* AOF states */ #define AOF_OFF 0 /* AOF is off */ #define AOF_ON 1 /* AOF is on */