Browse Source

Add ClientSideSync type for network synchtonization logic.

Mathias Gottschlag 5 years ago
parent
commit
b4dd70bc78
2 changed files with 118 additions and 0 deletions
  1. 116
    0
      src/client_side_sync.rs
  2. 2
    0
      src/lib.rs

+ 116
- 0
src/client_side_sync.rs View File

@@ -0,0 +1,116 @@
1
+use std::sync::Arc;
2
+
3
+use tokio::sync::{mpsc, oneshot, Mutex};
4
+
5
+use super::file_tree::{FileTree, NewVersionSource};
6
+use super::{Error, SynchronizationError};
7
+
8
+pub struct ClientSideSync {
9
+    state_send: mpsc::Sender<(StateChange, oneshot::Sender<()>)>,
10
+    new_version_source: NewVersionSource,
11
+}
12
+
13
+// TODO: Parametrize the server protocol!
14
+// TODO: Can one directory be synchronized to multiple servers? Cycles are then possible!
15
+impl ClientSideSync {
16
+    // TODO: Restrict the size of the files downloaded by the synchronization client?
17
+    pub async fn new(
18
+        file_tree: Arc<Mutex<FileTree>>,
19
+        errors: mpsc::Sender<SynchronizationError>,
20
+    ) -> Result<ClientSideSync, Error> {
21
+        let new_version_source = file_tree.lock().await.new_version_source();
22
+        // Spawn the task that connects to the server as soon as unpause() is called.
23
+        let (state_send, pause_receive) = mpsc::channel(1);
24
+        tokio::spawn(async move {
25
+            let mut sync_task = ClientSideSyncTask {
26
+                file_tree,
27
+                errors,
28
+                new_version_source,
29
+            };
30
+            sync_task.task_paused(pause_receive).await;
31
+        });
32
+
33
+        Ok(ClientSideSync{
34
+            state_send,
35
+            new_version_source,
36
+        })
37
+    }
38
+
39
+    // TODO: Deduplicate this code.
40
+    pub async fn pause(&mut self) {
41
+        let (send, receive) = oneshot::channel();
42
+        self.state_send
43
+            .send((StateChange::Pause, send))
44
+            .await
45
+            .unwrap();
46
+        receive.await.unwrap();
47
+    }
48
+
49
+    pub async fn unpause(&mut self) {
50
+        let (send, receive) = oneshot::channel();
51
+        self.state_send
52
+            .send((StateChange::Unpause, send))
53
+            .await
54
+            .unwrap();
55
+        receive.await.unwrap();
56
+    }
57
+}
58
+
59
+struct ClientSideSyncTask {
60
+    file_tree: Arc<Mutex<FileTree>>,
61
+    errors: mpsc::Sender<SynchronizationError>,
62
+    new_version_source: NewVersionSource,
63
+}
64
+
65
+impl ClientSideSyncTask {
66
+    async fn task_paused(
67
+        &mut self,
68
+        mut state_receive: mpsc::Receiver<(StateChange, oneshot::Sender<()>)>,
69
+    ) {
70
+        let mut paused = true;
71
+
72
+        loop {
73
+            if paused {
74
+                // If we are paused, we only need to wait for state changes.
75
+                let (new_state, send) = state_receive.recv().await.unwrap();
76
+                match new_state {
77
+                    StateChange::Pause => paused = true,
78
+                    StateChange::Unpause => paused = false,
79
+                    StateChange::Terminate => break, // No reply, see drop().
80
+                }
81
+                send.send(()).unwrap();
82
+            } else {
83
+                // We were unpaused, initialize the file system watcher and start waiting for
84
+                // that as well.
85
+                let next_state = self.task_unpaused(&mut state_receive).await;
86
+                match next_state {
87
+                    StateChange::Pause => paused = true,
88
+                    StateChange::Unpause => paused = false,
89
+                    StateChange::Terminate => break,
90
+                }
91
+            }
92
+        }
93
+    }
94
+
95
+    async fn task_unpaused(
96
+        &mut self,
97
+        state_receive: &mut mpsc::Receiver<(StateChange, oneshot::Sender<()>)>,
98
+    ) -> StateChange {
99
+        // Connect to the server.
100
+        // TODO
101
+
102
+        // Start listening to local events, remote events and pause commands.
103
+        // TODO
104
+
105
+        // Disconnect again.
106
+        // TODO
107
+        panic!("Not yet implemented.");
108
+    }
109
+}
110
+
111
+#[derive(Debug)]
112
+enum StateChange {
113
+    Pause,
114
+    Unpause,
115
+    Terminate,
116
+}

+ 2
- 0
src/lib.rs View File

@@ -2,12 +2,14 @@ extern crate rmp_serde as rmps;
2 2
 
3 3
 use std::io;
4 4
 
5
+mod client_side_sync;
5 6
 mod database;
6 7
 mod file_system_watcher;
7 8
 mod file_tree;
8 9
 pub mod network;
9 10
 pub mod protocol;
10 11
 
12
+pub use client_side_sync::ClientSideSync;
11 13
 pub use database::Database;
12 14
 pub use file_system_watcher::FileSystemWatcher;
13 15
 pub use file_tree::FileTree;

Loading…
Cancel
Save