diff --git a/src/db.c b/src/db.c index f360607765cbec7fe21371eea58272ad0d6b6d2e..d545345cb9fdf893ad4546f99bfa4b1c8ccb364d 100644 --- a/src/db.c +++ b/src/db.c @@ -205,10 +205,22 @@ void delCommand(redisClient *c) { int deleted = 0, j; for (j = 1; j < c->argc; j++) { + if (server.ds_enabled) { + lookupKeyRead(c->db,c->argv[j]); + /* FIXME: this can be optimized a lot, no real need to load + * a possibly huge value. */ + } if (dbDelete(c->db,c->argv[j])) { signalModifiedKey(c->db,c->argv[j]); server.dirty++; deleted++; + } else if (server.ds_enabled) { + if (cacheKeyMayExist(c->db,c->argv[j]) && + dsExists(c->db,c->argv[j])) + { + cacheScheduleForFlush(c->db,c->argv[j]); + deleted = 1; + } } } addReplyLongLong(c,deleted); diff --git a/src/diskstore.c b/src/diskstore.c index 35c591d755110429fb8a2ece81ee2192a47c7cc4..6e59bc679cf704678945830b0d69b91ddef98fc1 100644 --- a/src/diskstore.c +++ b/src/diskstore.c @@ -262,6 +262,10 @@ int dsDel(redisDb *db, robj *key) { } int dsExists(redisDb *db, robj *key) { + char buf[1024]; + + dsKeyToPath(db,buf,key); + return access(buf,R_OK) == 0; } int dsFlushDb(int dbid) { diff --git a/src/dscache.c b/src/dscache.c index 05112cbb7303e2b7510f3bfc8e1661f8638dc2cb..9fc0f5e58f7c309aec380beb038eff2dc91e30e6 100644 --- a/src/dscache.c +++ b/src/dscache.c @@ -304,8 +304,10 @@ void vmThreadedIOCompletedJob(aeEventLoop *el, int fd, void *privdata, handleClientsBlockedOnSwappedKey(j->db,j->key); freeIOJob(j); } else if (j->type == REDIS_IOJOB_SAVE) { - redisAssert(j->val->storage == REDIS_DS_SAVING); - j->val->storage = REDIS_DS_MEMORY; + if (j->val) { + redisAssert(j->val->storage == REDIS_DS_SAVING); + j->val->storage = REDIS_DS_MEMORY; + } freeIOJob(j); } processed++; @@ -362,11 +364,12 @@ void *IOThreadEntryPoint(void *arg) { 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) + if (j->val) { + redisAssert(j->val->storage == REDIS_DS_SAVING); dsSet(j->db,j->key,j->val); - else + } else { dsDel(j->db,j->key); + } } /* Done: insert the job into the processed queue */ @@ -540,6 +543,15 @@ void cacheCron(void) { } } +/* ============ Negative caching for diskstore objects ====================== */ +/* Since accesses to keys that don't exist with disk store cost us a disk + * access, we need to cache names of keys that do not exist but are frequently + * accessed. */ +int cacheKeyMayExist(redisDb *db, robj *key) { + /* FIXME: for now we just always return true. */ + return 1; +} + /* ============ Virtual Memory - Blocking clients on missing keys =========== */ /* This function makes the clinet 'c' waiting for the key 'key' to be loaded. diff --git a/src/redis.h b/src/redis.h index bb9aee7a991f3d4946746c51225902f62e15390f..15c192cfa02c6a2a72b2c098451047a6ef8b2146 100644 --- a/src/redis.h +++ b/src/redis.h @@ -808,6 +808,7 @@ void handleClientsBlockedOnSwappedKey(redisDb *db, robj *key); int cacheFreeOneEntry(void); void cacheScheduleForFlush(redisDb *db, robj *key); void cacheCron(void); +int cacheKeyMayExist(redisDb *db, robj *key); /* Set data type */ robj *setTypeCreate(robj *value);