X-Git-Url: https://git.saurik.com/redis.git/blobdiff_plain/4e941ecacb976ec88c04561e2251f01db87146b3..c15a3887e08d468b96d4313cc19862b5e4b09977:/src/db.c?ds=sidebyside diff --git a/src/db.c b/src/db.c index 1b0289bc..ae40d204 100644 --- a/src/db.c +++ b/src/db.c @@ -17,20 +17,44 @@ robj *lookupKey(redisDb *db, robj *key) { if (server.bgsavechildpid == -1 && server.bgrewritechildpid == -1) val->lru = server.lruclock; - if (server.ds_enabled && val->storage == REDIS_DS_SAVING) { - /* FIXME: change this code to just wait for our object to - * get out of the IO Job. */ + if (server.ds_enabled && + cacheScheduleIOGetFlags(db,key) & REDIS_IO_SAVEINPROG) + { + /* There is a save in progress for this object! + * Wait for it to get out. */ waitEmptyIOJobsQueue(); processAllPendingIOJobs(); - redisAssert(val->storage != REDIS_DS_SAVING); + redisAssert(!(cacheScheduleIOGetFlags(db,key) & REDIS_IO_SAVEINPROG)); } server.stat_keyspace_hits++; return val; } else { - /* FIXME: Check if the object is on disk, if it is, load it - * in a blocking way now. If we are sure there are no collisions - * it would be cool to load this directly here without IO thread - * help. */ + time_t expire; + robj *val; + + /* Key not found in the in memory hash table, but if disk store is + * enabled we may have this key on disk. If so load it in memory + * in a blocking way. */ + if (server.ds_enabled && cacheKeyMayExist(db,key)) { + if (cacheScheduleIOGetFlags(db,key) & REDIS_IO_SAVEINPROG) { + /* There is a save in progress for this object! + * Wait for it to get out. */ + waitEmptyIOJobsQueue(); + processAllPendingIOJobs(); + redisAssert((cacheScheduleIOGetFlags(db,key) & REDIS_IO_SAVEINPROG) == 0); + } + + redisLog(REDIS_DEBUG,"Force loading key %s via lookup", + key->ptr); + val = dsGet(db,key,&expire); + if (val) { + int retval = dbAdd(db,key,val); + redisAssert(retval == REDIS_OK); + if (expire != -1) setExpire(db,key,expire); + server.stat_keyspace_hits++; + return val; + } + } server.stat_keyspace_misses++; return NULL; } @@ -69,9 +93,7 @@ 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 */ - } + if (server.ds_enabled) cacheSetKeyMayExist(db,key); return REDIS_OK; } } @@ -81,14 +103,19 @@ int dbAdd(redisDb *db, robj *key, robj *val) { * * On update (key already existed) 0 is returned. Otherwise 1. */ int dbReplace(redisDb *db, robj *key, robj *val) { - if (dictFind(db->dict,key->ptr) == NULL) { + robj *oldval; + int retval; + + if ((oldval = dictFetchValue(db->dict,key->ptr)) == NULL) { sds copy = sdsdup(key->ptr); dictAdd(db->dict, copy, val); - return 1; + retval = 1; } else { dictReplace(db->dict, key->ptr, val); - return 0; + retval = 0; } + if (server.ds_enabled) cacheSetKeyMayExist(db,key); + return retval; } int dbExists(redisDb *db, robj *key) { @@ -123,14 +150,13 @@ robj *dbRandomKey(redisDb *db) { /* Delete a key, value, and associated expiration entry if any, from the DB */ int dbDelete(redisDb *db, robj *key) { - /* If VM is enabled make sure to awake waiting clients for this key: - * deleting the key will kill the I/O thread bringing the key from swap - * to memory, so the client will never be notified and unblocked if we - * don't do it now. */ - if (server.ds_enabled) handleClientsBlockedOnSwappedKey(db,key); - - /* FIXME: we need to delete the IO Job loading the key, or simply we can - * wait for it to finish. */ + /* If diskstore is enabled make sure to awake waiting clients for this key + * as it is not really useful to wait for a key already deleted to be + * loaded from disk. */ + if (server.ds_enabled) { + handleClientsBlockedOnSwappedKey(db,key); + cacheSetKeyDoesNotExist(db,key); + } /* Deleting an entry from the expires dict will not free the sds of * the key, because it is shared with the main dictionary. */ @@ -170,13 +196,11 @@ int selectDb(redisClient *c, int id) { void signalModifiedKey(redisDb *db, robj *key) { touchWatchedKey(db,key); if (server.ds_enabled) - cacheScheduleForFlush(db,key); + cacheScheduleIO(db,key,REDIS_IO_SAVE); } void signalFlushedDb(int dbid) { touchWatchedKeysOnFlush(dbid); - if (server.ds_enabled) - dsFlushDb(dbid); } /*----------------------------------------------------------------------------- @@ -188,6 +212,7 @@ void flushdbCommand(redisClient *c) { signalFlushedDb(c->db->id); dictEmpty(c->db->dict); dictEmpty(c->db->expires); + if (server.ds_enabled) dsFlushDb(c->db->id); addReply(c,shared.ok); } @@ -199,7 +224,10 @@ void flushallCommand(redisClient *c) { kill(server.bgsavechildpid,SIGKILL); rdbRemoveTempFile(server.bgsavechildpid); } - rdbSave(server.dbfilename); + if (server.ds_enabled) + dsFlushDb(-1); + else + rdbSave(server.dbfilename); server.dirty++; } @@ -220,7 +248,7 @@ void delCommand(redisClient *c) { if (cacheKeyMayExist(c->db,c->argv[j]) && dsExists(c->db,c->argv[j])) { - cacheScheduleForFlush(c->db,c->argv[j]); + cacheScheduleIO(c->db,c->argv[j],REDIS_IO_SAVE); deleted = 1; } }