Commit 8620a434 authored by Dvir Volk's avatar Dvir Volk
Browse files

Added keyspace miss notifications support

parent 3eaa2cdc
...@@ -83,6 +83,7 @@ robj *lookupKey(redisDb *db, robj *key, int flags) { ...@@ -83,6 +83,7 @@ robj *lookupKey(redisDb *db, robj *key, int flags) {
* 1. A key gets expired if it reached it's TTL. * 1. A key gets expired if it reached it's TTL.
* 2. The key last access time is updated. * 2. The key last access time is updated.
* 3. The global keys hits/misses stats are updated (reported in INFO). * 3. The global keys hits/misses stats are updated (reported in INFO).
* 4. If keyspace notifications are enabled, a "miss" notification is fired.
* *
* This API should not be used when we write to the key after obtaining * This API should not be used when we write to the key after obtaining
* the object linked to the key, but only for read only operations. * the object linked to the key, but only for read only operations.
...@@ -106,6 +107,7 @@ robj *lookupKeyReadWithFlags(redisDb *db, robj *key, int flags) { ...@@ -106,6 +107,7 @@ robj *lookupKeyReadWithFlags(redisDb *db, robj *key, int flags) {
* to return NULL ASAP. */ * to return NULL ASAP. */
if (server.masterhost == NULL) { if (server.masterhost == NULL) {
server.stat_keyspace_misses++; server.stat_keyspace_misses++;
notifyKeyspaceEvent(NOTIFY_GENERIC, "miss", key, db->id);
return NULL; return NULL;
} }
...@@ -127,12 +129,15 @@ robj *lookupKeyReadWithFlags(redisDb *db, robj *key, int flags) { ...@@ -127,12 +129,15 @@ robj *lookupKeyReadWithFlags(redisDb *db, robj *key, int flags) {
server.current_client->cmd->flags & CMD_READONLY) server.current_client->cmd->flags & CMD_READONLY)
{ {
server.stat_keyspace_misses++; server.stat_keyspace_misses++;
notifyKeyspaceEvent(NOTIFY_GENERIC, "miss", key, db->id);
return NULL; return NULL;
} }
} }
val = lookupKey(db,key,flags); val = lookupKey(db,key,flags);
if (val == NULL) if (val == NULL) {
server.stat_keyspace_misses++; server.stat_keyspace_misses++;
notifyKeyspaceEvent(NOTIFY_GENERIC, "miss", key, db->id);
}
else else
server.stat_keyspace_hits++; server.stat_keyspace_hits++;
return val; return val;
......
...@@ -109,9 +109,9 @@ int TestStringPrintf(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { ...@@ -109,9 +109,9 @@ int TestStringPrintf(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
if (argc < 3) { if (argc < 3) {
return RedisModule_WrongArity(ctx); return RedisModule_WrongArity(ctx);
} }
RedisModuleString *s = RedisModule_CreateStringPrintf(ctx, RedisModuleString *s = RedisModule_CreateStringPrintf(ctx,
"Got %d args. argv[1]: %s, argv[2]: %s", "Got %d args. argv[1]: %s, argv[2]: %s",
argc, argc,
RedisModule_StringPtrLen(argv[1], NULL), RedisModule_StringPtrLen(argv[1], NULL),
RedisModule_StringPtrLen(argv[2], NULL) RedisModule_StringPtrLen(argv[2], NULL)
); );
...@@ -133,7 +133,7 @@ int TestUnlink(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { ...@@ -133,7 +133,7 @@ int TestUnlink(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
RedisModuleKey *k = RedisModule_OpenKey(ctx, RedisModule_CreateStringPrintf(ctx, "unlinked"), REDISMODULE_WRITE | REDISMODULE_READ); RedisModuleKey *k = RedisModule_OpenKey(ctx, RedisModule_CreateStringPrintf(ctx, "unlinked"), REDISMODULE_WRITE | REDISMODULE_READ);
if (!k) return failTest(ctx, "Could not create key"); if (!k) return failTest(ctx, "Could not create key");
if (REDISMODULE_ERR == RedisModule_StringSet(k, RedisModule_CreateStringPrintf(ctx, "Foobar"))) { if (REDISMODULE_ERR == RedisModule_StringSet(k, RedisModule_CreateStringPrintf(ctx, "Foobar"))) {
return failTest(ctx, "Could not set string value"); return failTest(ctx, "Could not set string value");
} }
...@@ -152,7 +152,7 @@ int TestUnlink(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { ...@@ -152,7 +152,7 @@ int TestUnlink(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
return failTest(ctx, "Could not verify key to be unlinked"); return failTest(ctx, "Could not verify key to be unlinked");
} }
return RedisModule_ReplyWithSimpleString(ctx, "OK"); return RedisModule_ReplyWithSimpleString(ctx, "OK");
} }
int NotifyCallback(RedisModuleCtx *ctx, int type, const char *event, int NotifyCallback(RedisModuleCtx *ctx, int type, const char *event,
...@@ -188,6 +188,10 @@ int TestNotifications(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { ...@@ -188,6 +188,10 @@ int TestNotifications(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
RedisModule_Call(ctx, "LPUSH", "cc", "l", "y"); RedisModule_Call(ctx, "LPUSH", "cc", "l", "y");
RedisModule_Call(ctx, "LPUSH", "cc", "l", "y"); RedisModule_Call(ctx, "LPUSH", "cc", "l", "y");
/* Miss some keys intentionally so we will get a "miss" notification. */
RedisModule_Call(ctx, "GET", "c", "nosuchkey");
RedisModule_Call(ctx, "SMEMBERS", "c", "nosuchkey");
size_t sz; size_t sz;
const char *rep; const char *rep;
RedisModuleCallReply *r = RedisModule_Call(ctx, "HGET", "cc", "notifications", "foo"); RedisModuleCallReply *r = RedisModule_Call(ctx, "HGET", "cc", "notifications", "foo");
...@@ -225,6 +229,16 @@ int TestNotifications(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { ...@@ -225,6 +229,16 @@ int TestNotifications(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
FAIL("Wrong reply for l"); FAIL("Wrong reply for l");
} }
r = RedisModule_Call(ctx, "HGET", "cc", "notifications", "nosuchkey");
if (r == NULL || RedisModule_CallReplyType(r) != REDISMODULE_REPLY_STRING) {
FAIL("Wrong or no reply for nosuchkey");
} else {
rep = RedisModule_CallReplyStringPtr(r, &sz);
if (sz != 1 || *rep != '2') {
FAIL("Got reply '%.*s'. expected '2'", sz, rep);
}
}
RedisModule_Call(ctx, "FLUSHDB", ""); RedisModule_Call(ctx, "FLUSHDB", "");
return RedisModule_ReplyWithSimpleString(ctx, "OK"); return RedisModule_ReplyWithSimpleString(ctx, "OK");
...@@ -423,7 +437,7 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) ...@@ -423,7 +437,7 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
if (RedisModule_CreateCommand(ctx,"test.ctxflags", if (RedisModule_CreateCommand(ctx,"test.ctxflags",
TestCtxFlags,"readonly",1,1,1) == REDISMODULE_ERR) TestCtxFlags,"readonly",1,1,1) == REDISMODULE_ERR)
return REDISMODULE_ERR; return REDISMODULE_ERR;
if (RedisModule_CreateCommand(ctx,"test.unlink", if (RedisModule_CreateCommand(ctx,"test.unlink",
TestUnlink,"write deny-oom",1,1,1) == REDISMODULE_ERR) TestUnlink,"write deny-oom",1,1,1) == REDISMODULE_ERR)
return REDISMODULE_ERR; return REDISMODULE_ERR;
...@@ -435,7 +449,8 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) ...@@ -435,7 +449,8 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
RedisModule_SubscribeToKeyspaceEvents(ctx, RedisModule_SubscribeToKeyspaceEvents(ctx,
REDISMODULE_NOTIFY_HASH | REDISMODULE_NOTIFY_HASH |
REDISMODULE_NOTIFY_SET | REDISMODULE_NOTIFY_SET |
REDISMODULE_NOTIFY_STRING, REDISMODULE_NOTIFY_STRING |
REDISMODULE_NOTIFY_GENERIC,
NotifyCallback); NotifyCallback);
if (RedisModule_CreateCommand(ctx,"test.notify", if (RedisModule_CreateCommand(ctx,"test.notify",
TestNotifications,"write deny-oom",1,1,1) == REDISMODULE_ERR) TestNotifications,"write deny-oom",1,1,1) == REDISMODULE_ERR)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment