From 5b4bff9c175a0189672d95eb953df5704c891d0c Mon Sep 17 00:00:00 2001 From: antirez Date: Mon, 12 Jul 2010 12:01:15 +0200 Subject: [PATCH] WATCH is now affected only when write commands actually modify the key content --- TODO | 2 ++ src/db.c | 4 +--- src/sort.c | 1 + src/t_hash.c | 5 +++++ src/t_list.c | 10 ++++++++++ src/t_set.c | 11 ++++++++++- src/t_string.c | 6 +++++- src/t_zset.c | 6 ++++++ 8 files changed, 40 insertions(+), 5 deletions(-) diff --git a/TODO b/TODO index 5d9736a9..dbde9bb5 100644 --- a/TODO +++ b/TODO @@ -4,7 +4,9 @@ Redis TODO and Roadmap VERSION 2.2 TODO (Optimizations and latency) ============================================ +* SETNX when failing should not affect WATCH * Support for syslog(3). +* Document ZCOUNT. * Change the implementation of ZCOUNT to use the augmented skiplist in order to be much faster. * Add an explicit test for MULTI/EXEC reloaded in the AOF. diff --git a/src/db.c b/src/db.c index d5e0d1e8..958a9f6b 100644 --- a/src/db.c +++ b/src/db.c @@ -46,7 +46,6 @@ robj *lookupKeyRead(redisDb *db, robj *key) { robj *lookupKeyWrite(redisDb *db, robj *key) { deleteIfVolatile(db,key); - touchWatchedKey(db,key); return lookupKey(db,key); } @@ -332,6 +331,7 @@ void renameGenericCommand(redisClient *c, int nx) { dbReplace(c->db,c->argv[2],o); } dbDelete(c->db,c->argv[1]); + touchWatchedKey(c->db,c->argv[1]); touchWatchedKey(c->db,c->argv[2]); server.dirty++; addReply(c,nx ? shared.cone : shared.ok); @@ -506,5 +506,3 @@ void ttlCommand(redisClient *c) { } addReplySds(c,sdscatprintf(sdsempty(),":%d\r\n",ttl)); } - - diff --git a/src/sort.c b/src/sort.c index 0bc86b47..4295a6ec 100644 --- a/src/sort.c +++ b/src/sort.c @@ -364,6 +364,7 @@ void sortCommand(redisClient *c) { * SORT result is empty a new key is set and maybe the old content * replaced. */ server.dirty += 1+outputlen; + touchWatchedKey(c->db,storekey); addReplySds(c,sdscatprintf(sdsempty(),":%d\r\n",outputlen)); } diff --git a/src/t_hash.c b/src/t_hash.c index 3f5fd6e1..b6be284f 100644 --- a/src/t_hash.c +++ b/src/t_hash.c @@ -224,6 +224,7 @@ void hsetCommand(redisClient *c) { hashTypeTryObjectEncoding(o,&c->argv[2], &c->argv[3]); update = hashTypeSet(o,c->argv[2],c->argv[3]); addReply(c, update ? shared.czero : shared.cone); + touchWatchedKey(c->db,c->argv[1]); server.dirty++; } @@ -238,6 +239,7 @@ void hsetnxCommand(redisClient *c) { hashTypeTryObjectEncoding(o,&c->argv[2], &c->argv[3]); hashTypeSet(o,c->argv[2],c->argv[3]); addReply(c, shared.cone); + touchWatchedKey(c->db,c->argv[1]); server.dirty++; } } @@ -258,6 +260,7 @@ void hmsetCommand(redisClient *c) { hashTypeSet(o,c->argv[i],c->argv[i+1]); } addReply(c, shared.ok); + touchWatchedKey(c->db,c->argv[1]); server.dirty++; } @@ -284,6 +287,7 @@ void hincrbyCommand(redisClient *c) { hashTypeSet(o,c->argv[2],new); decrRefCount(new); addReplyLongLong(c,value); + touchWatchedKey(c->db,c->argv[1]); server.dirty++; } @@ -330,6 +334,7 @@ void hdelCommand(redisClient *c) { if (hashTypeDelete(o,c->argv[2])) { if (hashTypeLength(o) == 0) dbDelete(c->db,c->argv[1]); addReply(c,shared.cone); + touchWatchedKey(c->db,c->argv[1]); server.dirty++; } else { addReply(c,shared.czero); diff --git a/src/t_list.c b/src/t_list.c index 0568fff1..2a981033 100644 --- a/src/t_list.c +++ b/src/t_list.c @@ -273,12 +273,14 @@ void pushGenericCommand(redisClient *c, int where) { return; } if (handleClientsWaitingListPush(c,c->argv[1],c->argv[2])) { + touchWatchedKey(c->db,c->argv[1]); addReply(c,shared.cone); return; } } listTypePush(lobj,c->argv[2],where); addReplyLongLong(c,listTypeLength(lobj)); + touchWatchedKey(c->db,c->argv[1]); server.dirty++; } @@ -327,6 +329,7 @@ void pushxGenericCommand(redisClient *c, robj *refval, robj *val, int where) { if (subject->encoding == REDIS_ENCODING_ZIPLIST && ziplistLen(subject->ptr) > server.list_max_ziplist_entries) listTypeConvert(subject,REDIS_ENCODING_LINKEDLIST); + touchWatchedKey(c->db,c->argv[1]); server.dirty++; } else { /* Notify client of a failed insert */ @@ -335,6 +338,7 @@ void pushxGenericCommand(redisClient *c, robj *refval, robj *val, int where) { } } else { listTypePush(subject,val,where); + touchWatchedKey(c->db,c->argv[1]); server.dirty++; } @@ -419,6 +423,7 @@ void lsetCommand(redisClient *c) { o->ptr = ziplistInsert(o->ptr,p,value->ptr,sdslen(value->ptr)); decrRefCount(value); addReply(c,shared.ok); + touchWatchedKey(c->db,c->argv[1]); server.dirty++; } } else if (o->encoding == REDIS_ENCODING_LINKEDLIST) { @@ -430,6 +435,7 @@ void lsetCommand(redisClient *c) { listNodeValue(ln) = value; incrRefCount(value); addReply(c,shared.ok); + touchWatchedKey(c->db,c->argv[1]); server.dirty++; } } else { @@ -448,6 +454,7 @@ void popGenericCommand(redisClient *c, int where) { addReplyBulk(c,value); decrRefCount(value); if (listTypeLength(o) == 0) dbDelete(c->db,c->argv[1]); + touchWatchedKey(c->db,c->argv[1]); server.dirty++; } } @@ -546,6 +553,7 @@ void ltrimCommand(redisClient *c) { redisPanic("Unknown list encoding"); } if (listTypeLength(o) == 0) dbDelete(c->db,c->argv[1]); + touchWatchedKey(c->db,c->argv[1]); server.dirty++; addReply(c,shared.ok); } @@ -587,6 +595,7 @@ void lremCommand(redisClient *c) { if (listTypeLength(subject) == 0) dbDelete(c->db,c->argv[1]); addReplySds(c,sdscatprintf(sdsempty(),":%d\r\n",removed)); + if (removed) touchWatchedKey(c->db,c->argv[1]); } /* This is the semantic of this command: @@ -635,6 +644,7 @@ void rpoplpushcommand(redisClient *c) { /* Delete the source list when it is empty */ if (listTypeLength(sobj) == 0) dbDelete(c->db,c->argv[1]); + touchWatchedKey(c->db,c->argv[1]); server.dirty++; } } diff --git a/src/t_set.c b/src/t_set.c index 808ef268..94b97633 100644 --- a/src/t_set.c +++ b/src/t_set.c @@ -19,6 +19,7 @@ void saddCommand(redisClient *c) { } if (dictAdd(set->ptr,c->argv[2],NULL) == DICT_OK) { incrRefCount(c->argv[2]); + touchWatchedKey(c->db,c->argv[1]); server.dirty++; addReply(c,shared.cone); } else { @@ -34,6 +35,7 @@ void sremCommand(redisClient *c) { if (dictDelete(set->ptr,c->argv[2]) == DICT_OK) { server.dirty++; + touchWatchedKey(c->db,c->argv[1]); if (htNeedsResize(set->ptr)) dictResize(set->ptr); if (dictSize((dict*)set->ptr) == 0) dbDelete(c->db,c->argv[1]); addReply(c,shared.cone); @@ -67,6 +69,8 @@ void smoveCommand(redisClient *c) { } if (dictSize((dict*)srcset->ptr) == 0 && srcset != dstset) dbDelete(c->db,c->argv[1]); + touchWatchedKey(c->db,c->argv[1]); + touchWatchedKey(c->db,c->argv[2]); server.dirty++; /* Add the element to the destination set */ if (!dstset) { @@ -118,6 +122,7 @@ void spopCommand(redisClient *c) { dictDelete(set->ptr,ele); if (htNeedsResize(set->ptr)) dictResize(set->ptr); if (dictSize((dict*)set->ptr) == 0) dbDelete(c->db,c->argv[1]); + touchWatchedKey(c->db,c->argv[1]); server.dirty++; } } @@ -161,8 +166,10 @@ void sinterGenericCommand(redisClient *c, robj **setskeys, unsigned long setsnum if (!setobj) { zfree(dv); if (dstkey) { - if (dbDelete(c->db,dstkey)) + if (dbDelete(c->db,dstkey)) { + touchWatchedKey(c->db,dstkey); server.dirty++; + } addReply(c,shared.czero); } else { addReply(c,shared.emptymultibulk); @@ -229,6 +236,7 @@ void sinterGenericCommand(redisClient *c, robj **setskeys, unsigned long setsnum decrRefCount(dstset); addReply(c,shared.czero); } + touchWatchedKey(c->db,dstkey); server.dirty++; } else { lenobj->ptr = sdscatprintf(sdsempty(),"*%lu\r\n",cardinality); @@ -327,6 +335,7 @@ void sunionDiffGenericCommand(redisClient *c, robj **setskeys, int setsnum, robj decrRefCount(dstset); addReply(c,shared.czero); } + touchWatchedKey(c->db,dstkey); server.dirty++; } zfree(dv); diff --git a/src/t_string.c b/src/t_string.c index eaaec05b..281bd6be 100644 --- a/src/t_string.c +++ b/src/t_string.c @@ -17,7 +17,6 @@ void setGenericCommand(redisClient *c, int nx, robj *key, robj *val, robj *expir } } - touchWatchedKey(c->db,key); if (nx) deleteIfVolatile(c->db,key); retval = dbAdd(c->db,key,val); if (retval == REDIS_ERR) { @@ -31,6 +30,7 @@ void setGenericCommand(redisClient *c, int nx, robj *key, robj *val, robj *expir } else { incrRefCount(val); } + touchWatchedKey(c->db,key); server.dirty++; removeExpire(c->db,key); if (expire) setExpire(c->db,key,time(NULL)+seconds); @@ -72,6 +72,7 @@ void getsetCommand(redisClient *c) { if (getGenericCommand(c) == REDIS_ERR) return; dbReplace(c->db,c->argv[1],c->argv[2]); incrRefCount(c->argv[2]); + touchWatchedKey(c->db,c->argv[1]); server.dirty++; removeExpire(c->db,c->argv[1]); } @@ -120,6 +121,7 @@ void msetGenericCommand(redisClient *c, int nx) { dbReplace(c->db,c->argv[j],c->argv[j+1]); incrRefCount(c->argv[j+1]); removeExpire(c->db,c->argv[j]); + touchWatchedKey(c->db,c->argv[j]); } server.dirty += (c->argc-1)/2; addReply(c, nx ? shared.cone : shared.ok); @@ -144,6 +146,7 @@ void incrDecrCommand(redisClient *c, long long incr) { value += incr; o = createStringObjectFromLongLong(value); dbReplace(c->db,c->argv[1],o); + touchWatchedKey(c->db,c->argv[1]); server.dirty++; addReply(c,shared.colon); addReply(c,o); @@ -207,6 +210,7 @@ void appendCommand(redisClient *c) { } totlen = sdslen(o->ptr); } + touchWatchedKey(c->db,c->argv[1]); server.dirty++; addReplySds(c,sdscatprintf(sdsempty(),":%lu\r\n",(unsigned long)totlen)); } diff --git a/src/t_zset.c b/src/t_zset.c index 26a80e99..0fcd6ea3 100644 --- a/src/t_zset.c +++ b/src/t_zset.c @@ -379,6 +379,7 @@ void zaddGenericCommand(redisClient *c, robj *key, robj *ele, double scoreval, i incrRefCount(ele); /* added to hash */ zslInsert(zs->zsl,*score,ele); incrRefCount(ele); /* added to skiplist */ + touchWatchedKey(c->db,c->argv[1]); server.dirty++; if (doincrement) addReplyDouble(c,*score); @@ -402,6 +403,7 @@ void zaddGenericCommand(redisClient *c, robj *key, robj *ele, double scoreval, i incrRefCount(ele); /* Update the score in the hash table */ dictReplace(zs->dict,ele,score); + touchWatchedKey(c->db,c->argv[1]); server.dirty++; } else { zfree(score); @@ -452,6 +454,7 @@ void zremCommand(redisClient *c) { dictDelete(zs->dict,c->argv[2]); if (htNeedsResize(zs->dict)) dictResize(zs->dict); if (dictSize(zs->dict) == 0) dbDelete(c->db,c->argv[1]); + touchWatchedKey(c->db,c->argv[1]); server.dirty++; addReply(c,shared.cone); } @@ -473,6 +476,7 @@ void zremrangebyscoreCommand(redisClient *c) { deleted = zslDeleteRangeByScore(zs->zsl,min,max,zs->dict); if (htNeedsResize(zs->dict)) dictResize(zs->dict); if (dictSize(zs->dict) == 0) dbDelete(c->db,c->argv[1]); + if (deleted) touchWatchedKey(c->db,c->argv[1]); server.dirty += deleted; addReplyLongLong(c,deleted); } @@ -511,6 +515,7 @@ void zremrangebyrankCommand(redisClient *c) { deleted = zslDeleteRangeByRank(zs->zsl,start+1,end+1,zs->dict); if (htNeedsResize(zs->dict)) dictResize(zs->dict); if (dictSize(zs->dict) == 0) dbDelete(c->db,c->argv[1]); + if (deleted) touchWatchedKey(c->db,c->argv[1]); server.dirty += deleted; addReplyLongLong(c, deleted); } @@ -702,6 +707,7 @@ void zunionInterGenericCommand(redisClient *c, robj *dstkey, int op) { if (dstzset->zsl->length) { dbAdd(c->db,dstkey,dstobj); addReplyLongLong(c, dstzset->zsl->length); + touchWatchedKey(c->db,dstkey); server.dirty++; } else { decrRefCount(dstobj);