use errors::*;
use PersistentCache;
use PREFIX;
#[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) => {
extern crate bincode as pers_f_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, &pers_f_bincode::serialize(&res).unwrap()).unwrap();
return res;
},
_ => return pers_f_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) => {
(||{
extern crate bincode as pers_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).unwrap();
let res;
match result.len() {
0 => {
res = $func($($x),*);
$storage.set(&var_name, &pers_bincode::serialize(&res).unwrap()).unwrap();
res
},
_ => {
res = pers_bincode::deserialize(&result).unwrap();
res
}
}
})()
}
}