]> git.saurik.com Git - redis.git/commitdiff
more work done for diskstore without trying to compile, more work needed to build...
authorantirez <antirez@gmail.com>
Thu, 30 Dec 2010 15:41:36 +0000 (16:41 +0100)
committerantirez <antirez@gmail.com>
Thu, 30 Dec 2010 15:41:36 +0000 (16:41 +0100)
src/config.c
src/db.c
src/diskstore.c
src/dscache.c
src/rdb.c
src/redis.c
src/redis.h

index 75b1365b5125e92a83720b065a2e2ff8fec81596..a4060631c3b95aab658fcab25686350343140140 100644 (file)
@@ -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) {
index f0701c2a5685f7d7aad9c4b3ee1912085e53360b..cf99bbb299780f3ac81e8e53b908d6d0afc28235 100644 (file)
--- a/src/db.c
+++ b/src/db.c
@@ -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;
     }
 }
index ae23b8ed981c65d3066bdde7670c247bf1017423..08c747a71585c7686c6a7bfc8a7a572e182b3540 100644 (file)
@@ -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);
 }
 
index d24ec77cd3478dd8dd9f55793be39f283c2118eb..f1ffe49123f2f01e292e0195d0e91396cecf4e83 100644 (file)
@@ -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)
index acec829a6322a2ed2d28d4fd658dc8d5f5ca0027..9129056d3dbec5dfb82a9abc91fd8b08a22dfd6b 100644 (file)
--- a/src/rdb.c
+++ b/src/rdb.c
@@ -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);
     }
index 36b7c853ec8c493c8a7c6cde146761714bf66bba..13fe0f3c6d6a71828993d4c1dbf11888b51c98a4 100644 (file)
@@ -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;
index d9a4b912398156f395586f0900808edc658aa2b1..183b06b0f80f0c54a57ce3c762e625feb439675b 100644 (file)
@@ -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);