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
102
103
#[macro_use] extern crate serde_derive;
extern crate fuse_mt;
use self::fuse_mt::*;
extern crate crossbeam;
use std::io::{Error, ErrorKind};
use std::ffi::{OsStr};
use std::time;
use std::mem;
use std::sync::mpsc;
use std::path::Path;
mod filesystem;
mod backingstore;
mod settings;
mod rwhashes;
pub mod config;
use settings::*;
use config::*;
use self::backingstore::BackingStore;
use self::filesystem::FS;
fn fix_lifetime<'a>(t: FS<'a>) -> FS<'static> {
unsafe { mem::transmute(t) }
}
struct BackgroundThread {
handle: crossbeam::ScopedJoinHandle<()>,
tx: std::sync::mpsc::Sender<u8>,
}
impl BackgroundThread {
fn new<'a, F: 'a>(scope: &crossbeam::Scope<'a>, secs: u64, closure: F) -> Self
where F: Fn()+Send {
let (tx, rx) = mpsc::channel();
let handle = scope.spawn(move || {
let dur = time::Duration::from_secs(secs);
loop {
match rx.recv_timeout(dur) {
Err(mpsc::RecvTimeoutError::Timeout) => {
closure();
},
_ => break,
}
}
});
Self {
handle,
tx,
}
}
fn join(self) {
self.tx.send(0).unwrap();
self.handle.join();
}
}
pub fn run(source: &Path, mount: &Path, conf: &Config) -> Result<(), Error> {
if conf.formatversion < FORMATVERSION {
let message = format!("Trying to mount old format (version {} vs {})",
conf.formatversion, FORMATVERSION);
return Err(Error::new(ErrorKind::Other, message));
}
let bs = match BackingStore::new(&conf.peerid, source, &conf.server, conf.maxbytes) {
Ok(bs) => bs,
Err(_) => return Err(Error::new(ErrorKind::Other, "Couldn't create the backing store")),
};
let fs = match filesystem::FS::new(&bs) {
Ok(fs) => fs,
Err(_) => return Err(Error::new(ErrorKind::Other, "Couldn't create the filesystem")),
};
let fs = fix_lifetime(fs);
let bsref = &bs;
crossbeam::scope(|scope| {
let sync = BackgroundThread::new(&scope, 60, move || bsref.sync_all().unwrap());
let upload = BackgroundThread::new(&scope, 10, move || bsref.do_uploads());
let nodes = BackgroundThread::new(&scope, 10, move || bsref.do_uploads_nodes());
let remove = BackgroundThread::new(&scope, 10, move || bsref.do_removals());
let fshandle = scope.spawn(move || {
let fs_mt = FuseMT::new(fs, 16);
let options = [OsStr::new("-o"), OsStr::new("auto_unmount,default_permissions")];
fuse_mt::mount(fs_mt, &mount, &options[..])
});
let ret = fshandle.join();
sync.join();
upload.join();
nodes.join();
remove.join();
ret
})
}