|
|
@@ -1,11 +1,11 @@
|
|
1
|
|
-use std::collections::{VecDeque, HashMap};
|
|
2
|
1
|
use std::sync::Arc;
|
|
3
|
|
-use std::path::Path;
|
|
4
|
2
|
use std::time::Duration;
|
|
5
|
3
|
|
|
|
4
|
+use fswatcher::{FileEventDelay, FileSystemEvent};
|
|
|
5
|
+use futures::future::{self, Either};
|
|
|
6
|
+use tokio::stream::StreamExt;
|
|
6
|
7
|
use tokio::sync::{mpsc, oneshot, Mutex};
|
|
7
|
8
|
use tokio::task;
|
|
8
|
|
-use fswatcher::FileEventDelay;
|
|
9
|
9
|
|
|
10
|
10
|
use super::{Error, FileTree};
|
|
11
|
11
|
|
|
|
@@ -73,45 +73,78 @@ impl FileSystemWatcher {
|
|
73
|
73
|
|
|
74
|
74
|
async fn task_unpaused(
|
|
75
|
75
|
file_tree: &mut Arc<Mutex<FileTree>>,
|
|
76
|
|
- _state_receive: &mut mpsc::Receiver<(StateChange, oneshot::Sender<()>)>,
|
|
|
76
|
+ state_receive: &mut mpsc::Receiver<(StateChange, oneshot::Sender<()>)>,
|
|
77
|
77
|
) -> StateChange {
|
|
78
|
78
|
let root_path = file_tree.lock().await.root_path().to_owned();
|
|
79
|
79
|
// TODO: Proper error handling.
|
|
80
|
|
- let file_events = FileEventDelay::new(fswatcher::FileSystemWatcher::new(&root_path).unwrap(), Duration::from_secs(3));
|
|
|
80
|
+ let mut file_events = FileEventDelay::new(
|
|
|
81
|
+ fswatcher::FileSystemWatcher::new(&root_path).unwrap(),
|
|
|
82
|
+ Duration::from_secs(3),
|
|
|
83
|
+ );
|
|
81
|
84
|
|
|
82
|
85
|
loop {
|
|
83
|
|
- /*if new_directories.is_empty() {
|
|
84
|
|
- // If all the inotify watches are up-to-date, simply wait for any events.
|
|
85
|
|
- let event = file_events.next(&paths_by_watch).await;
|
|
86
|
|
- // TODO
|
|
87
|
|
- } else {
|
|
88
|
|
- // Install an inotify watch for the directory and check the directory contents
|
|
89
|
|
- // against the database.
|
|
90
|
|
- let new_directory = new_directories.pop_front().unwrap();
|
|
91
|
|
- // TODO: Do not follow links!
|
|
92
|
|
- // TODO: Is ONLYDIR correct?
|
|
93
|
|
- // TODO: We want to delay events for 2-3 seconds, so that we limit the rate of
|
|
94
|
|
- // modification events and so that we are maybe able to detect moved
|
|
95
|
|
- // files/directories across different directories!
|
|
96
|
|
- if Path::new(&new_directory).is_dir() {
|
|
97
|
|
- 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);
|
|
98
|
|
- // TODO
|
|
|
86
|
+ match future::select(Box::pin(file_events.next()), Box::pin(state_receive.recv())).await
|
|
|
87
|
+ {
|
|
|
88
|
+ Either::Left((event, _state_future)) => {
|
|
|
89
|
+ // TODO: Error handling, handle None event.
|
|
|
90
|
+ Self::handle_file_event(file_tree, event.unwrap()).await;
|
|
99
|
91
|
}
|
|
|
92
|
+ Either::Right((next_state, _file_event_future)) => {
|
|
|
93
|
+ match next_state.unwrap() {
|
|
|
94
|
+ (StateChange::Unpause, send) => send.send(()).unwrap(),
|
|
|
95
|
+ (StateChange::Pause, send) => {
|
|
|
96
|
+ send.send(()).unwrap();
|
|
|
97
|
+ return StateChange::Pause;
|
|
|
98
|
+ }
|
|
|
99
|
+ (StateChange::Terminate, _) => return StateChange::Pause,
|
|
|
100
|
+ };
|
|
|
101
|
+ }
|
|
|
102
|
+ };
|
|
|
103
|
+ }
|
|
|
104
|
+ }
|
|
100
|
105
|
|
|
101
|
|
- // Proceed recursively at the next loop iteration.
|
|
|
106
|
+ async fn handle_file_event(_file_tree: &mut Arc<Mutex<FileTree>>, event: FileSystemEvent) {
|
|
|
107
|
+ match event {
|
|
|
108
|
+ FileSystemEvent::Stopped(_reason) => {
|
|
102
|
109
|
// TODO
|
|
103
|
|
-
|
|
104
|
|
- // Poll for events (without blocking, so that we immediately process the next
|
|
105
|
|
- // directory if nothing happened).
|
|
|
110
|
+ }
|
|
|
111
|
+ FileSystemEvent::DirectoryWatched(_path) => {
|
|
106
|
112
|
// TODO
|
|
107
|
|
-
|
|
108
|
|
- // Yield to other parts of the program to minimize the impact of scanning large
|
|
109
|
|
- // directory trees.
|
|
110
|
|
- // TODO: Check whether this is really necessary and how large the impact on
|
|
111
|
|
- // performance is.
|
|
112
|
|
- task::yield_now().await;
|
|
113
|
|
- }*/
|
|
|
113
|
+ }
|
|
|
114
|
+ FileSystemEvent::DirectoryCreated(_path) => {
|
|
|
115
|
+ // TODO
|
|
|
116
|
+ }
|
|
|
117
|
+ FileSystemEvent::DirectoryModified(_path) => {
|
|
|
118
|
+ // TODO
|
|
|
119
|
+ }
|
|
|
120
|
+ FileSystemEvent::DirectoryRemoved(_path) => {
|
|
|
121
|
+ // TODO
|
|
|
122
|
+ }
|
|
|
123
|
+ FileSystemEvent::DirectoryMoved(_from, _to) => {
|
|
|
124
|
+ // TODO
|
|
|
125
|
+ }
|
|
|
126
|
+ FileSystemEvent::FileCreated(_path) => {
|
|
|
127
|
+ // TODO
|
|
|
128
|
+ }
|
|
|
129
|
+ FileSystemEvent::FileModified(_path) => {
|
|
|
130
|
+ // TODO
|
|
|
131
|
+ }
|
|
|
132
|
+ FileSystemEvent::FileRemoved(_path) => {
|
|
|
133
|
+ // TODO
|
|
|
134
|
+ }
|
|
|
135
|
+ FileSystemEvent::FileMoved(_from, _to) => {
|
|
|
136
|
+ // TODO
|
|
|
137
|
+ }
|
|
|
138
|
+ FileSystemEvent::Error(_e) => {
|
|
|
139
|
+ // TODO
|
|
|
140
|
+ }
|
|
114
|
141
|
}
|
|
|
142
|
+
|
|
|
143
|
+ // Yield to other parts of the program to minimize the impact of scanning large
|
|
|
144
|
+ // directory trees.
|
|
|
145
|
+ // TODO: Check whether this is really necessary and how large the impact on
|
|
|
146
|
+ // performance is.
|
|
|
147
|
+ task::yield_now().await;
|
|
115
|
148
|
}
|
|
116
|
149
|
}
|
|
117
|
150
|
|