Skip to content

Instantly share code, notes, and snippets.

@bohford
Created December 21, 2010 14:44
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bohford/749997 to your computer and use it in GitHub Desktop.
Save bohford/749997 to your computer and use it in GitHub Desktop.
ZPOP and ZREVPOP for Redis 2.2.0 series
diff --git a/src/help.h b/src/help.h
index 51613c9..196f90e 100644
--- a/src/help.h
+++ b/src/help.h
@@ -632,7 +632,17 @@ struct commandHelp {
"destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]",
"Add multiple sorted sets and store the resulting sorted set in a new key",
4,
- "1.3.10" }
+ "1.3.10" },
+ { "ZPOP",
+ "key [score]",
+ "Remove and get the highest ranked member of a sorted set",
+ 4,
+ "2.1.8" },
+ { "ZREVPOP",
+ "key [score]",
+ "Remove and get the lowest ranked member of a sorted set",
+ 4,
+ "2.1.8" }
};
#endif
diff --git a/src/redis.c b/src/redis.c
index 6e667f2..c0a77f1 100644
--- a/src/redis.c
+++ b/src/redis.c
@@ -132,6 +132,8 @@ struct redisCommand readonlyCommandTable[] = {
{"zscore",zscoreCommand,3,0,NULL,1,1,1},
{"zrank",zrankCommand,3,0,NULL,1,1,1},
{"zrevrank",zrevrankCommand,3,0,NULL,1,1,1},
+ {"zpop",zpopCommand,-2,0,NULL,1,1,1},
+ {"zrevpop",zrevpopCommand,-2,0,NULL,1,1,1},
{"hset",hsetCommand,4,REDIS_CMD_DENYOOM,NULL,1,1,1},
{"hsetnx",hsetnxCommand,4,REDIS_CMD_DENYOOM,NULL,1,1,1},
{"hget",hgetCommand,3,0,NULL,1,1,1},
diff --git a/src/redis.h b/src/redis.h
index bc1a58c..9b6aae9 100644
--- a/src/redis.h
+++ b/src/redis.h
@@ -998,6 +998,8 @@ void hlenCommand(redisClient *c);
void zremrangebyrankCommand(redisClient *c);
void zunionstoreCommand(redisClient *c);
void zinterstoreCommand(redisClient *c);
+void zpopCommand(redisClient *c);
+void zrevpopCommand(redisClient *c);
void hkeysCommand(redisClient *c);
void hvalsCommand(redisClient *c);
void hgetallCommand(redisClient *c);
diff --git a/src/t_zset.c b/src/t_zset.c
index 8139b53..7965320 100644
--- a/src/t_zset.c
+++ b/src/t_zset.c
@@ -1058,3 +1058,59 @@ void zrankCommand(redisClient *c) {
void zrevrankCommand(redisClient *c) {
zrankGenericCommand(c, 1);
}
+
+void zpopGenericCommand(redisClient *c, int reverse) {
+ robj *o;
+ zset *zs;
+ zskiplist *zsl;
+ zskiplistNode *ln;
+ int withminscore = 0;
+ double minscore;
+
+ o = lookupKeyWriteOrReply(c,c->argv[1],shared.nullbulk);
+ if (o == NULL || checkType(c,o,REDIS_ZSET)) return;
+
+ if(c->argc == 3) {
+ withminscore = 1;
+ if (getDoubleFromObjectOrReply(c, c->argv[2], &minscore, NULL) != REDIS_OK) return;
+ } else if (c->argc > 3) {
+ addReply(c,shared.syntaxerr);
+ return;
+ }
+
+ zs = o->ptr;
+ zsl = zs->zsl;
+ if (reverse) {
+ ln = zsl->header->level[0].forward;
+ } else {
+ ln = zsl->tail;
+ };
+
+ if (ln == NULL) {
+ addReply(c,shared.nullbulk);
+ } else if (withminscore && (reverse ? ln->score > minscore : ln->score < minscore)) {
+ addReply(c,shared.nullbulk);
+ } else {
+ addReplyBulk(c,ln->obj);
+
+ long deleted;
+ deleted = zslDelete(zsl,ln->score,ln->obj);
+ redisAssert(deleted != 0);
+
+ /* Delete from the hash table */
+ dictDelete(zs->dict,ln->obj);
+ 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++;
+ }
+}
+
+void zpopCommand(redisClient *c) {
+ zpopGenericCommand(c, 0);
+}
+
+void zrevpopCommand(redisClient *c) {
+ zpopGenericCommand(c, 1);
+}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment