1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
use PREFIX;
use PersistentCache;
use errors::*;
#[macro_export]
macro_rules! cache_func {
(Redis, $host:expr, fn $f:ident($($x:ident : $t:ty),*) -> $r:ty $b:block) => {
cache_func!(Redis, $host, "DEF", fn $f($($x : $t),*) -> $r $b);
};
(File, $dir:expr, fn $f:ident($($x:ident : $t:ty),*) -> $r:ty $b:block) => {
cache_func!(File, $dir, "DEF", fn $f($($x : $t),*) -> $r $b);
};
(Redis, $host:expr, $prefix:expr, fn $f:ident($($x:ident : $t:ty),*) -> $r:ty $b:block) => {
fn $f($($x: $t),*) -> $r {
lazy_static!{
static ref S: ::std::sync::Mutex<::storage::redis::RedisStorage> = ::std::sync::Mutex::new(::storage::redis::RedisStorage::new($host).unwrap());
};
cache_func!($f($($x),*), $b, $prefix);
}
};
(File, $dir:expr, $prefix:expr, fn $f:ident($($x:ident : $t:ty),*) -> $r:ty $b:block) => {
fn $f($($x: $t),*) -> $r {
lazy_static!{
static ref S: ::std::sync::Mutex<::storage::file::FileStorage> = ::std::sync::Mutex::new(::storage::file::FileStorage::new($dir).unwrap());
};
cache_func!($f($($x),*), $b, $prefix);
}
};
($f:ident($($x:ident),*), $b:block, $prefix:expr) => {
use bincode;
use ::std::hash::{Hash, Hasher};
let mut s = ::std::collections::hash_map::DefaultHasher::new();
for item in &[&($($x),*)] {
item.hash(&mut s);
}
let var_name = format!("{}_{}_{}_{:?}", PREFIX, $prefix, stringify!($f), s.finish());
let result: Vec<u8> = S.lock().unwrap().get(&var_name).unwrap();
match result.len() {
0 => {
let res = {$b};
S.lock().unwrap().set(&var_name, &bincode::serialize(&res, bincode::Infinite).unwrap()).unwrap();
return res;
},
_ => return bincode::deserialize(&result).unwrap(),
}
}
}
#[macro_export]
macro_rules! cache {
($storage:ident, $func:ident($($x:expr),*)) => {
cache!($storage, $func($($x),*), "DEF")
};
($storage:ident, $func:ident($($x:expr),*), $prefix:expr) => {
(||{
use bincode;
use ::std::hash::{Hash, Hasher};
let mut s = ::std::collections::hash_map::DefaultHasher::new();
for item in &[&($($x),*)] {
item.hash(&mut s);
}
let var_name = format!("{}_{}_{}_{:?}", PREFIX, $prefix, stringify!($func), s.finish());
let result: Vec<u8> = $storage.get(&var_name)?;
match result.len() {
0 => {
match $func($($x),*) {
Ok(res) => {
$storage.set(&var_name, &bincode::serialize(&res, bincode::Infinite)?)?;
Ok(res)
}
Err(e) => Err(e)
}
},
_ => match bincode::deserialize(&result) {
Ok(res) => Ok(res),
Err(e) => Err(e.into()),
}
}
})()
}
}