Created
May 3, 2017 21:15
-
-
Save antirez/c07a6fdbd408f260aff14ab6d2ab5024 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* The thread entry point that actually executes the blocking part | |
* of the command HELLO.KEYS. | |
* | |
* Note: this implementation is very simple on purpose, so no duplicated | |
* keys (returned by SCAN) are filtered. However adding such a functionality | |
* would be trivial just using any data structure implementing a dictionary | |
* in order to filter the duplicated items. */ | |
void *HelloKeys_ThreadMain(void *arg) { | |
RedisModuleBlockedClient *bc = arg; | |
RedisModuleCtx *ctx = RedisModule_GetThreadSafeContext(bc); | |
long long cursor = 0; | |
size_t replylen = 0; | |
RedisModule_ReplyWithArray(ctx,REDISMODULE_POSTPONED_ARRAY_LEN); | |
do { | |
RedisModule_ThreadSafeContextLock(ctx); | |
RedisModuleCallReply *reply = RedisModule_Call(ctx, | |
"SCAN","l",(long long)cursor); | |
RedisModule_ThreadSafeContextUnlock(ctx); | |
RedisModuleCallReply *cr_cursor = | |
RedisModule_CallReplyArrayElement(reply,0); | |
RedisModuleCallReply *cr_keys = | |
RedisModule_CallReplyArrayElement(reply,1); | |
RedisModuleString *s = RedisModule_CreateStringFromCallReply(cr_cursor); | |
RedisModule_StringToLongLong(s,&cursor); | |
RedisModule_FreeString(ctx,s); | |
size_t items = RedisModule_CallReplyLength(cr_keys); | |
for (size_t j = 0; j < items; j++) { | |
RedisModuleCallReply *ele = | |
RedisModule_CallReplyArrayElement(cr_keys,j); | |
RedisModule_ReplyWithCallReply(ctx,ele); | |
replylen++; | |
} | |
RedisModule_FreeCallReply(reply); | |
} while (cursor != 0); | |
RedisModule_ReplySetArrayLength(ctx,replylen); | |
RedisModule_FreeThreadSafeContext(ctx); | |
RedisModule_UnblockClient(bc,NULL); | |
return NULL; | |
} | |
/* HELLO.KEYS -- Return all the keys in the current database without blocking | |
* the server. The keys do not represent a point-in-time state so only the keys | |
* that were in the database from the start to the end are guaranteed to be | |
* there. */ | |
int HelloKeys_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { | |
REDISMODULE_NOT_USED(argv); | |
if (argc != 1) return RedisModule_WrongArity(ctx); | |
pthread_t tid; | |
/* Note that when blocking the client we do not set any callback: no | |
* timeout is possible since we passed '0', nor we need a reply callback | |
* because we'll use the thread safe context to accumulate a reply. */ | |
RedisModuleBlockedClient *bc = RedisModule_BlockClient(ctx,NULL,NULL,NULL,0); | |
/* Now that we setup a blocking client, we need to pass the control | |
* to the thread. However we need to pass arguments to the thread: | |
* the reference to the blocked client handle. */ | |
if (pthread_create(&tid,NULL,HelloKeys_ThreadMain,bc) != 0) { | |
RedisModule_AbortBlock(bc); | |
return RedisModule_ReplyWithError(ctx,"-ERR Can't start thread"); | |
} | |
return REDISMODULE_OK; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment