Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
d38d82af
Commit
d38d82af
authored
Dec 20, 2018
by
antirez
Browse files
Modules shared API: initial core functions.
Based on ideas and code in PR #5560 by @MeirShpilraien.
parent
4d747bb8
Changes
2
Hide whitespace changes
Inline
Side-by-side
src/module.c
View file @
d38d82af
...
@@ -47,9 +47,21 @@ struct RedisModule {
...
@@ -47,9 +47,21 @@ struct RedisModule {
int
ver
;
/* Module version. We use just progressive integers. */
int
ver
;
/* Module version. We use just progressive integers. */
int
apiver
;
/* Module API version as requested during initialization.*/
int
apiver
;
/* Module API version as requested during initialization.*/
list
*
types
;
/* Module data types. */
list
*
types
;
/* Module data types. */
list
*
usedby
;
/* List of modules using APIs from this one. */
list
*
using
;
/* List of modules we use some APIs of. */
};
};
typedef
struct
RedisModule
RedisModule
;
typedef
struct
RedisModule
RedisModule
;
/* This represents a shared API. Shared APIs will be used to populate
* the server.sharedapi dictionary, mapping names of APIs exported by
* modules for other modules to use, to their structure specifying the
* function pointer that can be called. */
struct
RedisModuleSharedAPI
{
void
*
func
;
RedisModule
*
module
;
};
typedef
struct
RedisModuleSharedAPI
RedisModuleSharedAPI
;
static
dict
*
modules
;
/* Hash table of modules. SDS -> RedisModule ptr.*/
static
dict
*
modules
;
/* Hash table of modules. SDS -> RedisModule ptr.*/
/* Entries in the context->amqueue array, representing objects to free
/* Entries in the context->amqueue array, representing objects to free
...
@@ -700,6 +712,8 @@ void RM_SetModuleAttribs(RedisModuleCtx *ctx, const char *name, int ver, int api
...
@@ -700,6 +712,8 @@ void RM_SetModuleAttribs(RedisModuleCtx *ctx, const char *name, int ver, int api
module
->
ver
=
ver
;
module
->
ver
=
ver
;
module
->
apiver
=
apiver
;
module
->
apiver
=
apiver
;
module
->
types
=
listCreate
();
module
->
types
=
listCreate
();
module
->
usedby
=
listCreate
();
module
->
using
=
listCreate
();
ctx
->
module
=
module
;
ctx
->
module
=
module
;
}
}
...
@@ -4621,6 +4635,77 @@ void RM_GetRandomHexChars(char *dst, size_t len) {
...
@@ -4621,6 +4635,77 @@ void RM_GetRandomHexChars(char *dst, size_t len) {
getRandomHexChars
(
dst
,
len
);
getRandomHexChars
(
dst
,
len
);
}
}
/* --------------------------------------------------------------------------
* Modules API exporting / importing
* -------------------------------------------------------------------------- */
/* This function is called by a module in order to export some API with a
* given name. Other modules will be able to use this API by calling the
* symmetrical function RM_GetSharedAPI() and casting the return value to
* the right function pointer.
*
* The function will return REDISMODULE_OK if the name is not already taken,
* otherwise REDISMODULE_ERR will be returned and no operation will be
* performed.
*
* IMPORTANT: the apiname argument should be a string literal with static
* lifetime. The API relies on the fact that it will always be valid in
* the future. */
int
RM_ExportSharedAPI
(
RedisModuleCtx
*
ctx
,
const
char
*
apiname
,
void
*
func
)
{
RedisModuleSharedAPI
*
sapi
=
zmalloc
(
sizeof
(
*
sapi
));
sapi
->
module
=
ctx
->
module
;
sapi
->
func
=
func
;
if
(
dictAdd
(
server
.
sharedapi
,
(
char
*
)
apiname
,
sapi
)
!=
DICT_OK
)
{
zfree
(
sapi
);
return
REDISMODULE_ERR
;
}
return
REDISMODULE_OK
;
}
/* Request an exported API pointer. The return value is just a void pointer
* that the caller of this function will be required to cast to the right
* function pointer, so this is a private contract between modules.
*
* If the requested API is not available then NULL is returned. Because
* modules can be loaded at different times with different order, this
* function calls should be put inside some module generic API registering
* step, that is called every time a module attempts to execute a
* command that requires external APIs: if some API cannot be resolved, the
* command should return an error.
*
* Here is an exmaple:
*
* int ... myCommandImplementation() {
* if (getExternalAPIs() == 0) {
* reply with an error here if we cannot have the APIs
* }
* // Use the API:
* myFunctionPointer(foo);
* }
*
* And the function registerAPI() is:
*
* int getExternalAPIs(void) {
* static int api_loaded = 0;
* if (api_loaded != 0) return 1; // APIs already resolved.
*
* myFunctionPointer = RedisModule_GetOtherModuleAPI("...");
* if (myFunctionPointer == NULL) return 0;
*
* return 1;
* }
*/
void
*
RM_GetSharedAPI
(
RedisModuleCtx
*
ctx
,
const
char
*
apiname
)
{
dictEntry
*
de
=
dictFind
(
server
.
sharedapi
,
apiname
);
if
(
de
==
NULL
)
return
NULL
;
RedisModuleSharedAPI
*
sapi
=
dictGetVal
(
de
);
if
(
listSearchKey
(
sapi
->
module
->
usedby
,
ctx
->
module
)
==
NULL
)
{
listAddNodeTail
(
sapi
->
module
->
usedby
,
ctx
->
module
);
listAddNodeTail
(
ctx
->
module
->
using
,
sapi
->
module
);
}
return
sapi
->
func
;
}
/* --------------------------------------------------------------------------
/* --------------------------------------------------------------------------
* Modules API internals
* Modules API internals
* -------------------------------------------------------------------------- */
* -------------------------------------------------------------------------- */
...
@@ -4900,6 +4985,7 @@ size_t moduleCount(void) {
...
@@ -4900,6 +4985,7 @@ size_t moduleCount(void) {
* file so that's easy to seek it to add new entries. */
* file so that's easy to seek it to add new entries. */
void
moduleRegisterCoreAPI
(
void
)
{
void
moduleRegisterCoreAPI
(
void
)
{
server
.
moduleapi
=
dictCreate
(
&
moduleAPIDictType
,
NULL
);
server
.
moduleapi
=
dictCreate
(
&
moduleAPIDictType
,
NULL
);
server
.
sharedapi
=
dictCreate
(
&
moduleAPIDictType
,
NULL
);
REGISTER_API
(
Alloc
);
REGISTER_API
(
Alloc
);
REGISTER_API
(
Calloc
);
REGISTER_API
(
Calloc
);
REGISTER_API
(
Realloc
);
REGISTER_API
(
Realloc
);
...
...
src/server.h
View file @
d38d82af
...
@@ -954,7 +954,9 @@ struct redisServer {
...
@@ -954,7 +954,9 @@ struct redisServer {
size_t
initial_memory_usage
;
/* Bytes used after initialization. */
size_t
initial_memory_usage
;
/* Bytes used after initialization. */
int
always_show_logo
;
/* Show logo even for non-stdout logging. */
int
always_show_logo
;
/* Show logo even for non-stdout logging. */
/* Modules */
/* Modules */
dict
*
moduleapi
;
/* Exported APIs dictionary for modules. */
dict
*
moduleapi
;
/* Exported core APIs dictionary for modules. */
dict
*
sharedapi
;
/* Like moduleapi but containing the APIs that
modules share with each other. */
list
*
loadmodule_queue
;
/* List of modules to load at startup. */
list
*
loadmodule_queue
;
/* List of modules to load at startup. */
int
module_blocked_pipe
[
2
];
/* Pipe used to awake the event loop if a
int
module_blocked_pipe
[
2
];
/* Pipe used to awake the event loop if a
client blocked on a module command needs
client blocked on a module command needs
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment