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
100
101
use lazy_static::lazy_static;
use std::collections::HashMap;
use std::io;
use std::path::PathBuf;
use wasmer_runtime::cache::Cache;
use wasmer_runtime::cache::FileSystemCache;
use wasmer_runtime::cache::WasmHash;
use wasmer_runtime::error::CacheError;
use wasmer_runtime::Backend;
use wasmer_runtime::Module;
use std::sync::Mutex;
lazy_static! {
static ref HASHCACHE: Mutex<HashMap<String, HashMap<WasmHash, Module>>> =
Mutex::new(HashMap::new());
}
pub struct MemoryFallbackFileSystemCache {
fs_fallback: Option<FileSystemCache>,
}
impl MemoryFallbackFileSystemCache {
pub fn new<P: Into<PathBuf>>(
maybe_fallback_path: Option<P>,
) -> io::Result<MemoryFallbackFileSystemCache> {
Ok(MemoryFallbackFileSystemCache {
fs_fallback: match maybe_fallback_path {
Some(fallback_path) => Some(unsafe { FileSystemCache::new(fallback_path) }?),
None => None,
},
})
}
fn load_with_backend_mem(&self, key: WasmHash, backend: Backend) -> Result<Module, CacheError> {
let cache = HASHCACHE.lock().unwrap();
let backend_key = backend.to_string();
match cache.get(backend_key) {
Some(module_cache) => match module_cache.get(&key) {
Some(module) => Ok(module.to_owned()),
_ => Err(CacheError::InvalidatedCache),
},
_ => Err(CacheError::InvalidatedCache),
}
}
fn load_with_backend_fs(&self, key: WasmHash, backend: Backend) -> Result<Module, CacheError> {
if let Some(fs_fallback) = &self.fs_fallback {
match fs_fallback.load_with_backend(key, backend) {
Ok(module) => {
self.store_mem(key, module.clone())?;
Ok(module)
}
Err(e) => Err(e),
}
} else {
Err(CacheError::InvalidatedCache)
}
}
fn store_mem(&self, key: WasmHash, module: Module) -> Result<(), CacheError> {
let mut cache = HASHCACHE.lock().unwrap();
let backend_key = module.info().backend.to_string();
let backend_map = cache.entry(backend_key).or_insert_with(HashMap::new);
backend_map.entry(key).or_insert(module);
Ok(())
}
fn store_fs(&mut self, key: WasmHash, module: Module) -> Result<(), CacheError> {
if let Some(fs_fallback) = &mut self.fs_fallback {
fs_fallback.store(key, module)?;
}
Ok(())
}
}
impl Cache for MemoryFallbackFileSystemCache {
type LoadError = CacheError;
type StoreError = CacheError;
fn load(&self, key: WasmHash) -> Result<Module, CacheError> {
self.load_with_backend(key, Backend::default())
}
fn load_with_backend(&self, key: WasmHash, backend: Backend) -> Result<Module, CacheError> {
match self.load_with_backend_mem(key, backend) {
Ok(module) => Ok(module),
Err(_) => self.load_with_backend_fs(key, backend),
}
}
fn store(&mut self, key: WasmHash, module: Module) -> Result<(), CacheError> {
self.store_fs(key, module.clone())?;
self.store_mem(key, module)?;
Ok(())
}
}