+#include "redis.h"
+#include "lzf.h" /* LZF compression library */
+
#include <math.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <sys/stat.h>
-#include "rdb.h"
-#include "lzf.h" /* LZF compression library */
static int rdbWriteRaw(rio *rdb, void *p, size_t len) {
if (rdb && rioWrite(rdb,p,len) == 0)
return (time_t)t32;
}
+int rdbSaveMillisecondTime(rio *rdb, long long t) {
+ int64_t t64 = (int64_t) t;
+ return rdbWriteRaw(rdb,&t64,8);
+}
+
+long long rdbLoadMillisecondTime(rio *rdb) {
+ int64_t t64;
+ if (rioRead(rdb,&t64,8) == 0) return -1;
+ return (long long)t64;
+}
+
/* Saves an encoded length. The first two bits in the first byte are used to
* hold the encoding type. See the REDIS_RDB_* definitions for more information
* on the types of encoding. */
nwritten += n;
while((de = dictNext(di)) != NULL) {
- robj *eleobj = dictGetEntryKey(de);
+ robj *eleobj = dictGetKey(de);
if ((n = rdbSaveStringObject(rdb,eleobj)) == -1) return -1;
nwritten += n;
}
nwritten += n;
while((de = dictNext(di)) != NULL) {
- robj *eleobj = dictGetEntryKey(de);
- double *score = dictGetEntryVal(de);
+ robj *eleobj = dictGetKey(de);
+ double *score = dictGetVal(de);
if ((n = rdbSaveStringObject(rdb,eleobj)) == -1) return -1;
nwritten += n;
nwritten += n;
while((de = dictNext(di)) != NULL) {
- robj *key = dictGetEntryKey(de);
- robj *val = dictGetEntryVal(de);
+ robj *key = dictGetKey(de);
+ robj *val = dictGetVal(de);
if ((n = rdbSaveStringObject(rdb,key)) == -1) return -1;
nwritten += n;
* On success if the key was actaully saved 1 is returned, otherwise 0
* is returned (the key was already expired). */
int rdbSaveKeyValuePair(rio *rdb, robj *key, robj *val,
- time_t expiretime, time_t now)
+ long long expiretime, long long now)
{
/* Save the expire time */
if (expiretime != -1) {
/* If this key is already expired skip it */
if (expiretime < now) return 0;
- if (rdbSaveType(rdb,REDIS_RDB_OPCODE_EXPIRETIME) == -1) return -1;
- if (rdbSaveTime(rdb,expiretime) == -1) return -1;
+ if (rdbSaveType(rdb,REDIS_RDB_OPCODE_EXPIRETIME_MS) == -1) return -1;
+ if (rdbSaveMillisecondTime(rdb,expiretime) == -1) return -1;
}
/* Save type, key, value */
dictEntry *de;
char tmpfile[256];
int j;
- time_t now = time(NULL);
+ long long now = mstime();
FILE *fp;
rio rdb;
}
rioInitWithFile(&rdb,fp);
- if (rdbWriteRaw(&rdb,"REDIS0002",9) == -1) goto werr;
+ if (rdbWriteRaw(&rdb,"REDIS0003",9) == -1) goto werr;
for (j = 0; j < server.dbnum; j++) {
redisDb *db = server.db+j;
/* Iterate this DB writing every entry */
while((de = dictNext(di)) != NULL) {
- sds keystr = dictGetEntryKey(de);
- robj key, *o = dictGetEntryVal(de);
- time_t expire;
+ sds keystr = dictGetKey(de);
+ robj key, *o = dictGetVal(de);
+ long long expire;
initStaticStringObject(key,keystr);
expire = getExpire(db,&key);
int type, rdbver;
redisDb *db = server.db+0;
char buf[1024];
- time_t expiretime, now = time(NULL);
+ long long expiretime, now = mstime();
long loops = 0;
FILE *fp;
rio rdb;
fp = fopen(filename,"r");
- if (!fp) return REDIS_ERR;
+ if (!fp) {
+ errno = ENOENT;
+ return REDIS_ERR;
+ }
rioInitWithFile(&rdb,fp);
if (rioRead(&rdb,buf,9) == 0) goto eoferr;
buf[9] = '\0';
if (memcmp(buf,"REDIS",5) != 0) {
fclose(fp);
redisLog(REDIS_WARNING,"Wrong signature trying to load DB from file");
+ errno = EINVAL;
return REDIS_ERR;
}
rdbver = atoi(buf+5);
- if (rdbver < 1 || rdbver > 2) {
+ if (rdbver < 1 || rdbver > 3) {
fclose(fp);
redisLog(REDIS_WARNING,"Can't handle RDB format version %d",rdbver);
+ errno = EINVAL;
return REDIS_ERR;
}
if ((expiretime = rdbLoadTime(&rdb)) == -1) goto eoferr;
/* We read the time so we need to read the object type again. */
if ((type = rdbLoadType(&rdb)) == -1) goto eoferr;
+ /* the EXPIRETIME opcode specifies time in seconds, so convert
+ * into milliesconds. */
+ expiretime *= 1000;
+ } else if (type == REDIS_RDB_OPCODE_EXPIRETIME_MS) {
+ /* Milliseconds precision expire times introduced with RDB
+ * version 3. */
+ if ((expiretime = rdbLoadMillisecondTime(&rdb)) == -1) goto eoferr;
+ /* We read the time so we need to read the object type again. */
+ if ((type = rdbLoadType(&rdb)) == -1) goto eoferr;
}
if (type == REDIS_RDB_OPCODE_EOF)