diff options
author | antirez <antirez@gmail.com> | 2018-04-09 11:54:44 +0200 |
---|---|---|
committer | antirez <antirez@gmail.com> | 2018-04-09 11:54:44 +0200 |
commit | 49e098234abc2c5cc7042c931e3d611b0ae2055d (patch) | |
tree | 8bb82295918cf5e49f312109aa67e9ae04a1ab37 | |
parent | b2868c7b9cfed0e517547768d2bb9178d409daef (diff) | |
download | redis-49e098234abc2c5cc7042c931e3d611b0ae2055d.tar.gz |
Modules API: blocked client free callback modified to get a context.
Note that this was an experimental API that can only be enabled with
REIDSMODULE_EXPERIMENTAL_API, so it is subject to change until its
promoted to stable API. Sorry for the breakage, it is trivial to
resolve btw. This change will not be back ported to Redis 4.0.
-rw-r--r-- | src/module.c | 25 | ||||
-rw-r--r-- | src/modules/helloblock.c | 3 | ||||
-rw-r--r-- | src/modules/hellocluster.c | 1 | ||||
-rw-r--r-- | src/redismodule.h | 53 |
4 files changed, 51 insertions, 31 deletions
diff --git a/src/module.c b/src/module.c index 7cf1a24bd..3a494a203 100644 --- a/src/module.c +++ b/src/module.c @@ -127,6 +127,7 @@ typedef struct RedisModuleCtx RedisModuleCtx; #define REDISMODULE_CTX_BLOCKED_REPLY (1<<3) #define REDISMODULE_CTX_BLOCKED_TIMEOUT (1<<4) #define REDISMODULE_CTX_THREAD_SAFE (1<<5) +#define REDISMODULE_CTX_BLOCKED_DISCONNECTED (1<<6) /* This represents a Redis key opened with RM_OpenKey(). */ struct RedisModuleKey { @@ -200,7 +201,7 @@ typedef struct RedisModuleBlockedClient { RedisModule *module; /* Module blocking the client. */ RedisModuleCmdFunc reply_callback; /* Reply callback on normal completion.*/ RedisModuleCmdFunc timeout_callback; /* Reply callback on timeout. */ - void (*free_privdata)(void *); /* privdata cleanup callback. */ + void (*free_privdata)(RedisModuleCtx*,void*);/* privdata cleanup callback.*/ void *privdata; /* Module private data that may be used by the reply or timeout callback. It is set via the RedisModule_UnblockClient() API. */ @@ -3449,7 +3450,7 @@ void unblockClientFromModule(client *c) { * free_privdata: called in order to free the privata data that is passed * by RedisModule_UnblockClient() call. */ -RedisModuleBlockedClient *RM_BlockClient(RedisModuleCtx *ctx, RedisModuleCmdFunc reply_callback, RedisModuleCmdFunc timeout_callback, void (*free_privdata)(void*), long long timeout_ms) { +RedisModuleBlockedClient *RM_BlockClient(RedisModuleCtx *ctx, RedisModuleCmdFunc reply_callback, RedisModuleCmdFunc timeout_callback, void (*free_privdata)(RedisModuleCtx*,void*), long long timeout_ms) { client *c = ctx->client; int islua = c->flags & CLIENT_LUA; int ismulti = c->flags & CLIENT_MULTI; @@ -3553,8 +3554,16 @@ void moduleHandleBlockedClients(void) { } /* Free privdata if any. */ - if (bc->privdata && bc->free_privdata) - bc->free_privdata(bc->privdata); + if (bc->privdata && bc->free_privdata) { + RedisModuleCtx ctx = REDISMODULE_CTX_INIT; + if (c == NULL) + ctx.flags |= REDISMODULE_CTX_BLOCKED_DISCONNECTED; + ctx.blocked_privdata = bc->privdata; + ctx.module = bc->module; + ctx.client = bc->client; + bc->free_privdata(&ctx,bc->privdata); + moduleFreeContext(&ctx); + } /* It is possible that this blocked client object accumulated * replies to send to the client in a thread safe context. @@ -3625,6 +3634,13 @@ void *RM_GetBlockedClientPrivateData(RedisModuleCtx *ctx) { return ctx->blocked_privdata; } +/* Return true if when the free callback of a blocked client is called, + * the reason for the client to be unblocked is that it disconnected + * while it was blocked. */ +int RM_BlockedClientDisconnected(RedisModuleCtx *ctx) { + return (ctx->flags & REDISMODULE_CTX_BLOCKED_DISCONNECTED) != 0; +} + /* -------------------------------------------------------------------------- * Thread Safe Contexts * -------------------------------------------------------------------------- */ @@ -4596,4 +4612,5 @@ void moduleRegisterCoreAPI(void) { REGISTER_API(GetClusterSize); REGISTER_API(GetRandomBytes); REGISTER_API(GetRandomHexChars); + REGISTER_API(BlockedClientDisconnected); } diff --git a/src/modules/helloblock.c b/src/modules/helloblock.c index c74fcd30f..cabaeff6c 100644 --- a/src/modules/helloblock.c +++ b/src/modules/helloblock.c @@ -54,7 +54,8 @@ int HelloBlock_Timeout(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) } /* Private data freeing callback for HELLO.BLOCK command. */ -void HelloBlock_FreeData(void *privdata) { +void HelloBlock_FreeData(RedisModuleCtx *ctx, void *privdata) { + REDISMODULE_NOT_USED(ctx); RedisModule_Free(privdata); } diff --git a/src/modules/hellocluster.c b/src/modules/hellocluster.c index 4cc40a17f..75d18f3e2 100644 --- a/src/modules/hellocluster.c +++ b/src/modules/hellocluster.c @@ -30,6 +30,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#define REDISMODULE_EXPERIMENTAL_API #include "../redismodule.h" #include <stdio.h> #include <stdlib.h> diff --git a/src/redismodule.h b/src/redismodule.h index f663006ab..4ba4be3b9 100644 --- a/src/redismodule.h +++ b/src/redismodule.h @@ -268,23 +268,10 @@ long long REDISMODULE_API_FUNC(RedisModule_Milliseconds)(void); void REDISMODULE_API_FUNC(RedisModule_DigestAddStringBuffer)(RedisModuleDigest *md, unsigned char *ele, size_t len); void REDISMODULE_API_FUNC(RedisModule_DigestAddLongLong)(RedisModuleDigest *md, long long ele); void REDISMODULE_API_FUNC(RedisModule_DigestEndSequence)(RedisModuleDigest *md); -void REDISMODULE_API_FUNC(RedisModule_RegisterClusterMessageReceiver)(RedisModuleCtx *ctx, uint8_t type, RedisModuleClusterMessageReceiver callback); -int REDISMODULE_API_FUNC(RedisModule_SendClusterMessage)(RedisModuleCtx *ctx, char *target_id, uint8_t type, unsigned char *msg, uint32_t len); -int REDISMODULE_API_FUNC(RedisModule_GetClusterNodeInfo)(RedisModuleCtx *ctx, const char *id, char *ip, char *master_id, int *port, int *flags); -char **REDISMODULE_API_FUNC(RedisModule_GetClusterNodesList)(RedisModuleCtx *ctx, size_t *numnodes); -void REDISMODULE_API_FUNC(RedisModule_FreeClusterNodesList)(char **ids); -RedisModuleTimerID REDISMODULE_API_FUNC(RedisModule_CreateTimer)(RedisModuleCtx *ctx, mstime_t period, RedisModuleTimerProc callback, void *data); -int REDISMODULE_API_FUNC(RedisModule_StopTimer)(RedisModuleCtx *ctx, RedisModuleTimerID id, void **data); -int REDISMODULE_API_FUNC(RedisModule_GetTimerInfo)(RedisModuleCtx *ctx, RedisModuleTimerID id, uint64_t *remaining, void **data); -const char *REDISMODULE_API_FUNC(RedisModule_GetMyClusterID)(void); -size_t REDISMODULE_API_FUNC(RedisModule_GetClusterSize)(void); -void REDISMODULE_API_FUNC(RedisModule_GetRandomBytes)(unsigned char *dst, size_t len); -void REDISMODULE_API_FUNC(RedisModule_GetRandomHexChars)(char *dst, size_t len); - /* Experimental APIs */ #ifdef REDISMODULE_EXPERIMENTAL_API -RedisModuleBlockedClient *REDISMODULE_API_FUNC(RedisModule_BlockClient)(RedisModuleCtx *ctx, RedisModuleCmdFunc reply_callback, RedisModuleCmdFunc timeout_callback, void (*free_privdata)(void*), long long timeout_ms); +RedisModuleBlockedClient *REDISMODULE_API_FUNC(RedisModule_BlockClient)(RedisModuleCtx *ctx, RedisModuleCmdFunc reply_callback, RedisModuleCmdFunc timeout_callback, void (*free_privdata)(RedisModuleCtx*,void*), long long timeout_ms); int REDISMODULE_API_FUNC(RedisModule_UnblockClient)(RedisModuleBlockedClient *bc, void *privdata); int REDISMODULE_API_FUNC(RedisModule_IsBlockedReplyRequest)(RedisModuleCtx *ctx); int REDISMODULE_API_FUNC(RedisModule_IsBlockedTimeoutRequest)(RedisModuleCtx *ctx); @@ -295,6 +282,19 @@ void REDISMODULE_API_FUNC(RedisModule_FreeThreadSafeContext)(RedisModuleCtx *ctx void REDISMODULE_API_FUNC(RedisModule_ThreadSafeContextLock)(RedisModuleCtx *ctx); void REDISMODULE_API_FUNC(RedisModule_ThreadSafeContextUnlock)(RedisModuleCtx *ctx); int REDISMODULE_API_FUNC(RedisModule_SubscribeToKeyspaceEvents)(RedisModuleCtx *ctx, int types, RedisModuleNotificationFunc cb); +int REDISMODULE_API_FUNC(RedisModule_BlockedClientDisconnected)(RedisModuleCtx *ctx); +void REDISMODULE_API_FUNC(RedisModule_RegisterClusterMessageReceiver)(RedisModuleCtx *ctx, uint8_t type, RedisModuleClusterMessageReceiver callback); +int REDISMODULE_API_FUNC(RedisModule_SendClusterMessage)(RedisModuleCtx *ctx, char *target_id, uint8_t type, unsigned char *msg, uint32_t len); +int REDISMODULE_API_FUNC(RedisModule_GetClusterNodeInfo)(RedisModuleCtx *ctx, const char *id, char *ip, char *master_id, int *port, int *flags); +char **REDISMODULE_API_FUNC(RedisModule_GetClusterNodesList)(RedisModuleCtx *ctx, size_t *numnodes); +void REDISMODULE_API_FUNC(RedisModule_FreeClusterNodesList)(char **ids); +RedisModuleTimerID REDISMODULE_API_FUNC(RedisModule_CreateTimer)(RedisModuleCtx *ctx, mstime_t period, RedisModuleTimerProc callback, void *data); +int REDISMODULE_API_FUNC(RedisModule_StopTimer)(RedisModuleCtx *ctx, RedisModuleTimerID id, void **data); +int REDISMODULE_API_FUNC(RedisModule_GetTimerInfo)(RedisModuleCtx *ctx, RedisModuleTimerID id, uint64_t *remaining, void **data); +const char *REDISMODULE_API_FUNC(RedisModule_GetMyClusterID)(void); +size_t REDISMODULE_API_FUNC(RedisModule_GetClusterSize)(void); +void REDISMODULE_API_FUNC(RedisModule_GetRandomBytes)(unsigned char *dst, size_t len); +void REDISMODULE_API_FUNC(RedisModule_GetRandomHexChars)(char *dst, size_t len); #endif /* This is included inline inside each Redis module. */ @@ -404,18 +404,6 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int REDISMODULE_GET_API(DigestAddStringBuffer); REDISMODULE_GET_API(DigestAddLongLong); REDISMODULE_GET_API(DigestEndSequence); - REDISMODULE_GET_API(RegisterClusterMessageReceiver); - REDISMODULE_GET_API(SendClusterMessage); - REDISMODULE_GET_API(GetClusterNodeInfo); - REDISMODULE_GET_API(GetClusterNodesList); - REDISMODULE_GET_API(FreeClusterNodesList); - REDISMODULE_GET_API(CreateTimer); - REDISMODULE_GET_API(StopTimer); - REDISMODULE_GET_API(GetTimerInfo); - REDISMODULE_GET_API(GetMyClusterID); - REDISMODULE_GET_API(GetClusterSize); - REDISMODULE_GET_API(GetRandomBytes); - REDISMODULE_GET_API(GetRandomHexChars); #ifdef REDISMODULE_EXPERIMENTAL_API REDISMODULE_GET_API(GetThreadSafeContext); @@ -429,6 +417,19 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int REDISMODULE_GET_API(GetBlockedClientPrivateData); REDISMODULE_GET_API(AbortBlock); REDISMODULE_GET_API(SubscribeToKeyspaceEvents); + REDISMODULE_GET_API(BlockedClientDisconnected); + REDISMODULE_GET_API(RegisterClusterMessageReceiver); + REDISMODULE_GET_API(SendClusterMessage); + REDISMODULE_GET_API(GetClusterNodeInfo); + REDISMODULE_GET_API(GetClusterNodesList); + REDISMODULE_GET_API(FreeClusterNodesList); + REDISMODULE_GET_API(CreateTimer); + REDISMODULE_GET_API(StopTimer); + REDISMODULE_GET_API(GetTimerInfo); + REDISMODULE_GET_API(GetMyClusterID); + REDISMODULE_GET_API(GetClusterSize); + REDISMODULE_GET_API(GetRandomBytes); + REDISMODULE_GET_API(GetRandomHexChars); #endif if (RedisModule_IsModuleNameBusy && RedisModule_IsModuleNameBusy(name)) return REDISMODULE_ERR; |