|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+use std::collections::VecDeque;
|
|
1
|
2
|
use std::sync::Arc;
|
|
|
3
|
+use std::path::Path;
|
|
2
|
4
|
|
|
|
5
|
+use inotify::{Inotify, WatchMask};
|
|
3
|
6
|
use tokio::sync::{mpsc, oneshot, Mutex};
|
|
|
7
|
+use tokio::task;
|
|
4
|
8
|
|
|
5
|
9
|
use super::{Error, FileTree};
|
|
6
|
10
|
|
|
|
@@ -38,7 +42,7 @@ impl FileSystemWatcher {
|
|
38
|
42
|
}
|
|
39
|
43
|
|
|
40
|
44
|
async fn task_paused(
|
|
41
|
|
- _file_tree: Arc<Mutex<FileTree>>,
|
|
|
45
|
+ mut file_tree: Arc<Mutex<FileTree>>,
|
|
42
|
46
|
mut state_receive: mpsc::Receiver<(StateChange, oneshot::Sender<()>)>,
|
|
43
|
47
|
) {
|
|
44
|
48
|
let mut paused = true;
|
|
|
@@ -56,7 +60,59 @@ impl FileSystemWatcher {
|
|
56
|
60
|
} else {
|
|
57
|
61
|
// We were unpaused, initialize the file system watcher and start waiting for
|
|
58
|
62
|
// that as well.
|
|
|
63
|
+ let next_state = Self::task_unpaused(&mut file_tree, &mut state_receive).await;
|
|
|
64
|
+ match next_state {
|
|
|
65
|
+ StateChange::Pause => paused = true,
|
|
|
66
|
+ StateChange::Unpause => paused = false,
|
|
|
67
|
+ StateChange::Terminate => break,
|
|
|
68
|
+ }
|
|
|
69
|
+ }
|
|
|
70
|
+ }
|
|
|
71
|
+ }
|
|
|
72
|
+
|
|
|
73
|
+ async fn task_unpaused(
|
|
|
74
|
+ file_tree: &mut Arc<Mutex<FileTree>>,
|
|
|
75
|
+ _state_receive: &mut mpsc::Receiver<(StateChange, oneshot::Sender<()>)>,
|
|
|
76
|
+ ) -> StateChange {
|
|
|
77
|
+ let mut inotify = Inotify::init().expect("Failed to initialize inotify");
|
|
|
78
|
+ let mut new_directories = VecDeque::new();
|
|
|
79
|
+ new_directories.push_back(file_tree.lock().await.root_path().to_owned());
|
|
|
80
|
+
|
|
|
81
|
+ let mut inotify_buffer = InotifyBuffer { data: [0; 1024] };
|
|
|
82
|
+ let _inotify_stream = inotify.event_stream(&mut inotify_buffer).unwrap();
|
|
|
83
|
+ //let watches_by_path = BTreeMap::new();
|
|
|
84
|
+ //let paths_by_watch = HashMap::new();
|
|
|
85
|
+
|
|
|
86
|
+ loop {
|
|
|
87
|
+ if new_directories.is_empty() {
|
|
|
88
|
+ // If all the inotify watches are up-to-date, simply wait for any events.
|
|
59
|
89
|
// TODO
|
|
|
90
|
+ } else {
|
|
|
91
|
+ // Install an inotify watch for the directory and check the directory contents
|
|
|
92
|
+ // against the database.
|
|
|
93
|
+ let new_directory = new_directories.pop_front().unwrap();
|
|
|
94
|
+ // TODO: Do not follow links!
|
|
|
95
|
+ // TODO: Is ONLYDIR correct?
|
|
|
96
|
+ // TODO: We want to delay events for 2-3 seconds, so that we limit the rate of
|
|
|
97
|
+ // modification events and so that we are maybe able to detect moved
|
|
|
98
|
+ // files/directories across different directories!
|
|
|
99
|
+ if Path::new(&new_directory).is_dir() {
|
|
|
100
|
+ let watch = inotify.add_watch(new_directory, WatchMask::ATTRIB | WatchMask::CLOSE_WRITE | WatchMask::CREATE | WatchMask::DELETE | WatchMask::DELETE_SELF | WatchMask::MODIFY | WatchMask::MOVE | WatchMask::EXCL_UNLINK | WatchMask::ONLYDIR);
|
|
|
101
|
+ // TODO
|
|
|
102
|
+ }
|
|
|
103
|
+
|
|
|
104
|
+ // Proceed recursively at the next loop iteration.
|
|
|
105
|
+ // TODO
|
|
|
106
|
+
|
|
|
107
|
+ // Poll for events (without blocking, so that we immediately process the next
|
|
|
108
|
+ // directory if nothing happened).
|
|
|
109
|
+ // TODO
|
|
|
110
|
+
|
|
|
111
|
+ // Yield to other parts of the program to minimize the impact of scanning large
|
|
|
112
|
+ // directory trees.
|
|
|
113
|
+ // TODO: Check whether this is really necessary and how large the impact on
|
|
|
114
|
+ // performance is.
|
|
|
115
|
+ task::yield_now().await;
|
|
60
|
116
|
}
|
|
61
|
117
|
}
|
|
62
|
118
|
}
|
|
|
@@ -75,6 +131,22 @@ impl Drop for FileSystemWatcher {
|
|
75
|
131
|
}
|
|
76
|
132
|
}
|
|
77
|
133
|
|
|
|
134
|
+struct InotifyBuffer {
|
|
|
135
|
+ data: [u8; 1024],
|
|
|
136
|
+}
|
|
|
137
|
+
|
|
|
138
|
+impl AsMut<[u8]> for InotifyBuffer {
|
|
|
139
|
+ fn as_mut<'a>(&'a mut self) -> &'a mut [u8] {
|
|
|
140
|
+ &mut self.data
|
|
|
141
|
+ }
|
|
|
142
|
+}
|
|
|
143
|
+
|
|
|
144
|
+impl AsRef<[u8]> for InotifyBuffer {
|
|
|
145
|
+ fn as_ref<'a>(&'a self) -> &'a [u8] {
|
|
|
146
|
+ &self.data
|
|
|
147
|
+ }
|
|
|
148
|
+}
|
|
|
149
|
+
|
|
78
|
150
|
#[derive(Debug)]
|
|
79
|
151
|
enum StateChange {
|
|
80
|
152
|
Pause,
|