mirror of
http://github.com/valkey-io/valkey
synced 2024-11-22 18:54:58 +00:00
adc3183cd2
* Introduce a new API's: RM_GetContextFlagsAll, and RM_GetKeyspaceNotificationFlagsAll that will return the full flags mask of each feature. The module writer can check base on this value if the Flags he needs are supported or not. * For each flag, introduce a new value on redismodule.h, this value represents the LAST value and should be there as a reminder to update it when a new value is added, also it will be used in the code to calculate the full flags mask (assuming flags are incrementally increasing). In addition, stated that the module writer should not use the LAST flag directly and he should use the GetFlagAll API's. * Introduce a new API: RM_IsSubEventSupported, that returns for a given event and subevent, whether or not the subevent supported. * Introduce a new macro RMAPI_FUNC_SUPPORTED(func) that returns whether or not a function API is supported by comparing it to NULL. * Introduce a new API: int RM_GetServerVersion();, that will return the current Redis version in the format 0x00MMmmpp; e.g. 0x00060008; * Changed unstable version from 999.999.999 to 255.255.255 Co-authored-by: Oran Agra <oran@redislabs.com> Co-authored-by: Yossi Gottlieb <yossigo@gmail.com>
94 lines
2.6 KiB
C
94 lines
2.6 KiB
C
#define REDISMODULE_EXPERIMENTAL_API
|
|
#include "redismodule.h"
|
|
#include <assert.h>
|
|
#include <stdio.h>
|
|
#include <pthread.h>
|
|
|
|
#define UNUSED(V) ((void) V)
|
|
|
|
void *sub_worker(void *arg) {
|
|
// Get Redis module context
|
|
RedisModuleCtx *ctx = (RedisModuleCtx *)arg;
|
|
|
|
// Try acquiring GIL
|
|
int res = RedisModule_ThreadSafeContextTryLock(ctx);
|
|
|
|
// GIL is already taken by the calling thread expecting to fail.
|
|
assert(res != REDISMODULE_OK);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void *worker(void *arg) {
|
|
// Retrieve blocked client
|
|
RedisModuleBlockedClient *bc = (RedisModuleBlockedClient *)arg;
|
|
|
|
// Get Redis module context
|
|
RedisModuleCtx *ctx = RedisModule_GetThreadSafeContext(bc);
|
|
|
|
// Acquire GIL
|
|
RedisModule_ThreadSafeContextLock(ctx);
|
|
|
|
// Create another thread which will try to acquire the GIL
|
|
pthread_t tid;
|
|
int res = pthread_create(&tid, NULL, sub_worker, ctx);
|
|
assert(res == 0);
|
|
|
|
// Wait for thread
|
|
pthread_join(tid, NULL);
|
|
|
|
// Release GIL
|
|
RedisModule_ThreadSafeContextUnlock(ctx);
|
|
|
|
// Reply to client
|
|
RedisModule_ReplyWithSimpleString(ctx, "OK");
|
|
|
|
// Unblock client
|
|
RedisModule_UnblockClient(bc, NULL);
|
|
|
|
// Free the Redis module context
|
|
RedisModule_FreeThreadSafeContext(ctx);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
int acquire_gil(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
|
|
{
|
|
UNUSED(argv);
|
|
UNUSED(argc);
|
|
|
|
int flags = RedisModule_GetContextFlags(ctx);
|
|
int allFlags = RedisModule_GetContextFlagsAll();
|
|
if ((allFlags & REDISMODULE_CTX_FLAGS_MULTI) &&
|
|
(flags & REDISMODULE_CTX_FLAGS_MULTI)) {
|
|
RedisModule_ReplyWithSimpleString(ctx, "Blocked client is not supported inside multi");
|
|
return REDISMODULE_OK;
|
|
}
|
|
|
|
/* This command handler tries to acquire the GIL twice
|
|
* once in the worker thread using "RedisModule_ThreadSafeContextLock"
|
|
* second in the sub-worker thread
|
|
* using "RedisModule_ThreadSafeContextTryLock"
|
|
* as the GIL is already locked. */
|
|
RedisModuleBlockedClient *bc = RedisModule_BlockClient(ctx, NULL, NULL, NULL, 0);
|
|
|
|
pthread_t tid;
|
|
int res = pthread_create(&tid, NULL, worker, bc);
|
|
assert(res == 0);
|
|
|
|
return REDISMODULE_OK;
|
|
}
|
|
|
|
int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
|
|
REDISMODULE_NOT_USED(argv);
|
|
REDISMODULE_NOT_USED(argc);
|
|
|
|
if (RedisModule_Init(ctx, "blockedclient", 1, REDISMODULE_APIVER_1)== REDISMODULE_ERR)
|
|
return REDISMODULE_ERR;
|
|
|
|
if (RedisModule_CreateCommand(ctx, "acquire_gil", acquire_gil, "", 0, 0, 0) == REDISMODULE_ERR)
|
|
return REDISMODULE_ERR;
|
|
|
|
return REDISMODULE_OK;
|
|
}
|