Skip to content

Commit 20038e7

Browse files
authored
Add support for running module unload code (#107)
* Can now run de-init code, similarly to how init code can be specified for a module. * Added an example module to demonstrate the functionality. * Also, fixed paths in macros, so that they can compile regardless of which identifiers the caller has brought into scope.
1 parent 7109d5c commit 20038e7

File tree

3 files changed

+77
-8
lines changed

3 files changed

+77
-8
lines changed

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ required-features = ["experimental-api"]
3636
name = "data_type"
3737
crate-type = ["cdylib"]
3838

39+
40+
[[example]]
41+
name = "load_unload"
42+
crate-type = ["cdylib"]
43+
3944
[dependencies]
4045
bitflags = "1.2"
4146
libc = "0.2"

examples/load_unload.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#[macro_use]
2+
extern crate redis_module;
3+
4+
use redis_module::{Context, LogLevel, RedisResult, raw};
5+
use std::os::raw::c_int;
6+
7+
static mut GLOBAL_STATE: Option<String> = None;
8+
9+
pub extern "C" fn init(ctx: *mut raw::RedisModuleCtx) -> c_int {
10+
let ctx = Context::new(ctx);
11+
let (before, after) = unsafe {
12+
let before = GLOBAL_STATE.clone();
13+
GLOBAL_STATE.replace("GLOBAL DATA".to_string());
14+
let after = GLOBAL_STATE.clone();
15+
(before, after)
16+
};
17+
ctx.log(LogLevel::Warning,
18+
&format!("Update global state on LOAD. BEFORE: {:?}, AFTER: {:?}",
19+
before, after));
20+
21+
return raw::Status::Ok as c_int;
22+
}
23+
24+
pub extern "C" fn deinit(ctx: *mut raw::RedisModuleCtx) -> c_int {
25+
let ctx = Context::new(ctx);
26+
let (before, after) = unsafe {
27+
let before = GLOBAL_STATE.take();
28+
let after = GLOBAL_STATE.clone();
29+
(before, after)
30+
};
31+
ctx.log(LogLevel::Warning,
32+
&format!("Update global state on UNLOAD. BEFORE: {:?}, AFTER: {:?}",
33+
before, after));
34+
35+
raw::Status::Ok as c_int
36+
}
37+
38+
//////////////////////////////////////////////////////
39+
40+
redis_module! {
41+
name: "load_unload",
42+
version: 1,
43+
data_types: [],
44+
init: init,
45+
deinit: deinit,
46+
commands: [],
47+
}
48+

src/macros.rs

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,20 @@ macro_rules! redis_command {
1212

1313
/////////////////////
1414
extern "C" fn do_command(
15-
ctx: *mut raw::RedisModuleCtx,
16-
argv: *mut *mut raw::RedisModuleString,
15+
ctx: *mut $crate::raw::RedisModuleCtx,
16+
argv: *mut *mut $crate::raw::RedisModuleString,
1717
argc: c_int,
1818
) -> c_int {
1919
let context = Context::new(ctx);
2020

21-
let args_decoded: Result<Vec<_>, RedisError> =
21+
let args_decoded: Result<Vec<_>, $crate::RedisError> =
2222
unsafe { slice::from_raw_parts(argv, argc as usize) }
2323
.into_iter()
2424
.map(|&arg| {
25-
RedisString::from_ptr(arg)
25+
$crate::RedisString::from_ptr(arg)
2626
.map(|v| v.to_owned())
27-
.map_err(|_| RedisError::Str("UTF8 encoding error in handler args"))
27+
.map_err(|_|$crate::RedisError::Str(
28+
"UTF8 encoding error in handler args"))
2829
})
2930
.collect();
3031

@@ -37,7 +38,7 @@ macro_rules! redis_command {
3738
/////////////////////
3839

3940
if unsafe {
40-
raw::RedisModule_CreateCommand.unwrap()(
41+
$crate::raw::RedisModule_CreateCommand.unwrap()(
4142
$ctx,
4243
name.as_ptr(),
4344
Some(do_command),
@@ -46,9 +47,9 @@ macro_rules! redis_command {
4647
$lastkey,
4748
$keystep,
4849
)
49-
} == raw::Status::Err as c_int
50+
} == $crate::raw::Status::Err as c_int
5051
{
51-
return raw::Status::Err as c_int;
52+
return $crate::raw::Status::Err as c_int;
5253
}
5354
}};
5455
}
@@ -62,6 +63,7 @@ macro_rules! redis_module {
6263
$($data_type:ident),* $(,)*
6364
],
6465
$(init: $init_func:ident,)* $(,)*
66+
$(deinit: $deinit_func:ident,)* $(,)*
6567
commands: [
6668
$([
6769
$name:expr,
@@ -126,5 +128,19 @@ macro_rules! redis_module {
126128

127129
raw::Status::Ok as c_int
128130
}
131+
132+
#[no_mangle]
133+
#[allow(non_snake_case)]
134+
pub extern "C" fn RedisModule_OnUnload(
135+
ctx: *mut $crate::raw::RedisModuleCtx
136+
) -> std::os::raw::c_int {
137+
$(
138+
if $deinit_func(ctx) == raw::Status::Err as c_int {
139+
return $crate::raw::Status::Err as c_int;
140+
}
141+
)*
142+
143+
$crate::raw::Status::Ok as std::os::raw::c_int
144+
}
129145
}
130146
}

0 commit comments

Comments
 (0)