"doc/MgetCommand.html" did not exist on "73287b2b576fa6a1ff1b61467286cbd5458881d2"
Commit 4ab98823 authored by antirez's avatar antirez
Browse files

more work done for diskstore without trying to compile, more work needed to build again.

parent 1609a1c4
......@@ -246,8 +246,8 @@ void loadServerConfig(char *filename) {
err = "argument must be 'yes' or 'no'"; goto loaderr;
}
} else if (!strcasecmp(argv[0],"diskstore-path") && argc == 2) {
zfree(server.ds_path);
server.ds_path = zstrdup(argv[1]);
sdsfree(server.ds_path);
server.ds_path = sdsnew(argv[1]);
} else if (!strcasecmp(argv[0],"cache-max-memory") && argc == 2) {
server.cache_max_memory = memtoll(argv[1],NULL);
} else if (!strcasecmp(argv[0],"hash-max-zipmap-entries") && argc == 2) {
......
......@@ -66,6 +66,9 @@ int dbAdd(redisDb *db, robj *key, robj *val) {
} else {
sds copy = sdsdup(key->ptr);
dictAdd(db->dict, copy, val);
if (server.ds_enabled) {
/* FIXME: remove entry from negative cache */
}
return REDIS_OK;
}
}
......
......@@ -70,6 +70,7 @@
*/
#include "redis.h"
#include "sha1.h"
#include <fcntl.h>
#include <sys/stat.h>
......@@ -138,10 +139,62 @@ int dsClose(void) {
return REDIS_OK;
}
/* Convert key into full path for this object. Dirty but hopefully
* is fast enough. */
void dsKeyToPath(redisDb *db, unsigned char *buf, robj *key) {
SHA1_CTX ctx;
unsigned char hash[20];
char *hex, digits[] = "0123456789abcdef";
int j, l;
SHA1Init(&ctx);
SHA1Update(&ctx,key->ptr,sdslen(key->ptr));
SHA1Final(hash,&ctx);
/* Convert the hash into hex format */
for (j = 0; j < 20; j++) {
hex[j*2] = digits[(hash[j]&0xF0)>>4];
hex[(j*2)+1] = digits[hash[j]&0x0F];
}
/* Create the object path. Start with server.ds_path that's the root dir */
l = sdslen(server.ds_path);
memcpy(buf,server.ds_path,l);
buf += l;
*buf++ = '/';
/* Then add xx/yy/ that is the two level directories */
buf[0] = hex[0];
buf[1] = hex[1];
buf[2] = '/';
buf[3] = hex[2];
buf[4] = hex[3];
buf[5] = '/';
buf += 6;
/* Add the database number followed by _ and finall the SHA1 hex */
l = ll2string(buf,64,db->id);
buf += l;
buf[0] = '_';
memcpy(buf+1,hex,40);
buf[41] = '\0';
}
int dsSet(redisDb *db, robj *key, robj *val) {
char buf[1024];
FILE *fp;
int retval;
dsKeyToPath(buf,key);
fp = fopen(buf,"w");
if ((retval = rdbSaveKeyValuePair(fp,db,key,val,time(NULL))) == -1)
return REDIS_ERR;
fclose(fp);
if (retval == 0) unlink(buf); /* Expired key */
return REDIS_OK;
}
robj *dsGet(redisDb *db, robj *key) {
robj *dsGet(redisDb *db, robj *key, time_t *expire) {
return createStringObject("foo",3);
}
......
......@@ -84,6 +84,9 @@
* - What happens with MULTI/EXEC?
*
* Good question.
*
* - If dsSet() fails on the write thread log the error and reschedule the
* key for flush.
*/
/* Virtual Memory is composed mainly of two subsystems:
......@@ -285,8 +288,15 @@ void vmThreadedIOCompletedJob(aeEventLoop *el, int fd, void *privdata,
(unsigned char*)j->key->ptr);
if (j->type == REDIS_IOJOB_LOAD) {
/* Create the key-value pair in the in-memory database */
dbAdd(j->db,j->key,j->val);
incrRefCount(j->val);
if (j->val != NULL) {
dbAdd(j->db,j->key,j->val);
incrRefCount(j->val);
setExpire(j->db,j->key,j->expire);
} else {
/* The key does not exist. Create a negative cache entry
* for this key. */
/* FIXME: add this entry into the negative cache */
}
/* Handle clients waiting for this key to be loaded. */
handleClientsBlockedOnSwappedKey(j->db,j->key);
freeIOJob(j);
......@@ -342,8 +352,10 @@ void *IOThreadEntryPoint(void *arg) {
/* Process the Job */
if (j->type == REDIS_IOJOB_LOAD) {
j->val = dsGet(j->db,j->key);
redisAssert(j->val != NULL);
time_t expire;
j->val = dsGet(j->db,j->key,&expire);
if (j->val) j->expire = expire;
} else if (j->type == REDIS_IOJOB_SAVE) {
redisAssert(j->val->storage == REDIS_DS_SAVING);
if (j->val)
......
......@@ -395,6 +395,31 @@ off_t rdbSavedObjectLen(robj *o) {
return len;
}
/* Save a key-value pair, with expire time, type, key, value.
* On error -1 is returned.
* On success if the key was actaully saved 1 is returned, otherwise 0
* is returned (the key was already expired). */
int rdbSaveKeyValuePair(FILE *fp, redisDb *db, robj *key, robj *val,
time_t now)
{
time_t expiretime;
expiretime = getExpire(db,&key);
/* Save the expire time */
if (expiretime != -1) {
/* If this key is already expired skip it */
if (expiretime < now) return 0;
if (rdbSaveType(fp,REDIS_EXPIRETIME) == -1) return -1;
if (rdbSaveTime(fp,expiretime) == -1) return -1;
}
/* Save type, key, value */
if (rdbSaveType(fp,val->type) == -1) return -1;
if (rdbSaveStringObject(fp,&key) == -1) return -1;
if (rdbSaveObject(fp,val) == -1) return -1;
return 1;
}
/* Save the DB on disk. Return REDIS_ERR on error, REDIS_OK on success */
int rdbSave(char *filename) {
dictIterator *di = NULL;
......@@ -432,22 +457,9 @@ int rdbSave(char *filename) {
while((de = dictNext(di)) != NULL) {
sds keystr = dictGetEntryKey(de);
robj key, *o = dictGetEntryVal(de);
time_t expiretime;
initStaticStringObject(key,keystr);
expiretime = getExpire(db,&key);
/* Save the expire time */
if (expiretime != -1) {
/* If this key is already expired skip it */
if (expiretime < now) continue;
if (rdbSaveType(fp,REDIS_EXPIRETIME) == -1) goto werr;
if (rdbSaveTime(fp,expiretime) == -1) goto werr;
}
/* Save type, key, value */
if (rdbSaveType(fp,o->type) == -1) goto werr;
if (rdbSaveStringObject(fp,&key) == -1) goto werr;
if (rdbSaveObject(fp,o) == -1) goto werr;
if (rdbSaveKeyValuePair(fp,db,key,o,now) == -1) goto werr;
}
dictReleaseIterator(di);
}
......
......@@ -769,7 +769,7 @@ void initServerConfig() {
server.maxmemory_policy = REDIS_MAXMEMORY_VOLATILE_LRU;
server.maxmemory_samples = 3;
server.ds_enabled = 0;
server.ds_path = zstrdup("/tmp/redis.ds");
server.ds_path = sdsnew("/tmp/redis.ds");
server.cache_max_memory = 64LL*1024*1024; /* 64 MB of RAM */
server.cache_blocked_clients = 0;
server.hash_max_zipmap_entries = REDIS_HASH_MAX_ZIPMAP_ENTRIES;
......
......@@ -554,6 +554,7 @@ typedef struct iojob {
robj *key; /* This I/O request is about this key */
robj *val; /* the value to swap for REDIS_IOJOB_SAVE, otherwise this
* field is populated by the I/O thread for REDIS_IOJOB_LOAD. */
time_t expire; /* Expire time for this key on REDIS_IOJOB_LOAD */
} iojob;
/* When diskstore is enabled and a flush operation is requested we push
......@@ -746,6 +747,7 @@ off_t rdbSavedObjectLen(robj *o);
off_t rdbSavedObjectPages(robj *o);
robj *rdbLoadObject(int type, FILE *fp);
void backgroundSaveDoneHandler(int statloc);
int rdbSaveKeyValuePair(FILE *fp, redisDb *db, robj *key, robj *val, time_t now);
/* AOF persistence */
void flushAppendOnlyFile(void);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment