|
|
@@ -1,57 +1,122 @@
|
|
1
|
1
|
use std::io;
|
|
2
|
|
-use std::sync::{Arc, Mutex};
|
|
3
|
2
|
|
|
4
|
|
-pub struct SynchronizedDirectory {
|
|
5
|
|
- db: Arc<Mutex<Database>>,
|
|
6
|
|
- master: bool,
|
|
7
|
|
- // TODO
|
|
8
|
|
-}
|
|
|
3
|
+mod database;
|
|
|
4
|
+mod filetree;
|
|
9
|
5
|
|
|
10
|
|
-impl SynchronizedDirectory {
|
|
11
|
|
- pub fn open(
|
|
12
|
|
- db: Arc<Mutex<Database>>,
|
|
13
|
|
- _path: &str,
|
|
14
|
|
- master: bool,
|
|
15
|
|
- ) -> Result<SynchronizedDirectory, Error> {
|
|
16
|
|
- // TODO
|
|
17
|
|
- Ok(SynchronizedDirectory { db, master })
|
|
18
|
|
- }
|
|
|
6
|
+pub use database::Database;
|
|
|
7
|
+pub use filetree::FileTree;
|
|
19
|
8
|
|
|
20
|
|
- // TODO: Login information.
|
|
21
|
|
- pub fn new(
|
|
22
|
|
- db: Arc<Mutex<Database>>,
|
|
23
|
|
- local_path: &str,
|
|
24
|
|
- remote_path: &str,
|
|
25
|
|
- master: bool,
|
|
26
|
|
- ) -> Result<SynchronizedDirectory, Error> {
|
|
27
|
|
- // TODO
|
|
28
|
|
- Ok(SynchronizedDirectory { db, master })
|
|
29
|
|
- }
|
|
30
|
|
-}
|
|
|
9
|
+// Sketch of the synchronization algorithm:
|
|
|
10
|
+//
|
|
|
11
|
+// if (filesystem_change) {
|
|
|
12
|
+// if the change is already represented in the mode in the database, ignore it;
|
|
|
13
|
+// scan the directory/file for changes (recalculate hashes if necessary);
|
|
|
14
|
+// if necessary, update the local version;
|
|
|
15
|
+// notify client connections about the change, push the change to server connections;
|
|
|
16
|
+// if a server rejects the change, copy contents to a conflict file and revert;
|
|
|
17
|
+// }
|
|
|
18
|
+// if (new_version_notification_from_server) {
|
|
|
19
|
+// the server sent us a path and a version for each element in the path;
|
|
|
20
|
+// if the path is a file, download the hashes for the file and start downloading
|
|
|
21
|
+// content;
|
|
|
22
|
+// if the path is a directory, list the directory (recursively) and download changes;
|
|
|
23
|
+// update the version whenever an element was locally updated;
|
|
|
24
|
+// update the version of directories when all files/directories below it were updated;
|
|
|
25
|
+// notify clients;
|
|
|
26
|
+// }
|
|
|
27
|
+// if (update_from_client) {
|
|
|
28
|
+// compare the client's server version with our version, if different, early reject;
|
|
|
29
|
+// download file information and store in temporary file;
|
|
|
30
|
+// check whether our version changed, if so, late reject;
|
|
|
31
|
+// move file and update;
|
|
|
32
|
+// update database version and hashes;
|
|
|
33
|
+// push update to server, similar to local file system change;
|
|
|
34
|
+// }
|
|
|
35
|
+//
|
|
|
36
|
+// Synchronization issues between the three code paths:
|
|
|
37
|
+// - File system operations (except for temporary files) and database changes (final
|
|
|
38
|
+// conflict checks as well as hash updates?) need to be synchronized.
|
|
|
39
|
+// - If any operation locks a directory, operations to the files within the directory can
|
|
|
40
|
+// be delayed due to locking, and have to re-check whether the file in question is still
|
|
|
41
|
+// the same file (version check + ID check?).
|
|
31
|
42
|
|
|
32
|
|
-pub struct SyncEvent {
|
|
33
|
|
- // TODO
|
|
34
|
|
-}
|
|
35
|
|
-
|
|
36
|
|
-impl SyncEvent {
|
|
37
|
|
- // TODO
|
|
38
|
|
-}
|
|
|
43
|
+// Sketch of the database structure:
|
|
|
44
|
+// (TODO: Rework and adapt to reality?)
|
|
|
45
|
+//
|
|
|
46
|
+// The server-side database has a list of synchronization roots and stores a file tree for each.
|
|
|
47
|
+// It also stores all recent/valid synchronization "connection" declarations, to be able to prune
|
|
|
48
|
+// synchronization roots periodically.
|
|
|
49
|
+//
|
|
|
50
|
+// The client-side databse has a list of synchronization roots and stores a file tree for each.
|
|
|
51
|
+// It also stores one synchronization "connection" for each root, which contains the server address,
|
|
|
52
|
+// login information and the mode of synchronization.
|
|
|
53
|
+//
|
|
|
54
|
+// FileTree:
|
|
|
55
|
+// - path
|
|
|
56
|
+// Object (file or directory):
|
|
|
57
|
+// - path
|
|
|
58
|
+// - type
|
|
|
59
|
+// - version
|
|
|
60
|
+// - remote version
|
|
|
61
|
+// - remote author (connection which created the last remote version)
|
|
|
62
|
+// - modification time
|
|
|
63
|
+// - size
|
|
|
64
|
+// - checksum
|
|
|
65
|
+// - content-id (points to file contents, can stay the same for file move)
|
|
|
66
|
+// Content (for files, one per ):
|
|
|
67
|
+// - content-id
|
|
|
68
|
+// - offset
|
|
|
69
|
+// - length
|
|
|
70
|
+// - checksum
|
|
|
71
|
+//
|
|
|
72
|
+// Synchronization connection:
|
|
|
73
|
+// - id
|
|
|
74
|
+// - key
|
|
|
75
|
+// - path
|
|
|
76
|
+// - address (only for client)
|
|
|
77
|
+// - direction
|
|
|
78
|
+// - last logged in
|
|
|
79
|
+// - conflict (only for server, a second upload-only client logged in since the last logout)
|
|
39
|
80
|
|
|
40
|
|
-pub struct Database {
|
|
41
|
|
- // TODO
|
|
42
|
|
-}
|
|
43
|
|
-
|
|
44
|
|
-impl Database {
|
|
45
|
|
- pub fn create_or_open(_path: &str) -> Result<Database, Error> {
|
|
46
|
|
- // TODO
|
|
47
|
|
- Ok(Database {})
|
|
48
|
|
- }
|
|
49
|
|
-
|
|
50
|
|
- pub fn synchronized_directories(&self) -> Vec<String> {
|
|
51
|
|
- // TODO
|
|
52
|
|
- Vec::new()
|
|
53
|
|
- }
|
|
54
|
|
-}
|
|
|
81
|
+//use std::sync::{Arc, Mutex};
|
|
|
82
|
+//
|
|
|
83
|
+//pub mod protocol;
|
|
|
84
|
+//
|
|
|
85
|
+//pub struct SynchronizedDirectory {
|
|
|
86
|
+// db: Arc<Mutex<Database>>,
|
|
|
87
|
+// master: bool,
|
|
|
88
|
+// // TODO
|
|
|
89
|
+//}
|
|
|
90
|
+//
|
|
|
91
|
+//impl SynchronizedDirectory {
|
|
|
92
|
+// pub fn open(
|
|
|
93
|
+// db: Arc<Mutex<Database>>,
|
|
|
94
|
+// _path: &str,
|
|
|
95
|
+// master: bool,
|
|
|
96
|
+// ) -> Result<SynchronizedDirectory, Error> {
|
|
|
97
|
+// // TODO
|
|
|
98
|
+// Ok(SynchronizedDirectory { db, master })
|
|
|
99
|
+// }
|
|
|
100
|
+//
|
|
|
101
|
+// // TODO: Login information.
|
|
|
102
|
+// pub fn new(
|
|
|
103
|
+// db: Arc<Mutex<Database>>,
|
|
|
104
|
+// local_path: &str,
|
|
|
105
|
+// remote_path: &str,
|
|
|
106
|
+// master: bool,
|
|
|
107
|
+// ) -> Result<SynchronizedDirectory, Error> {
|
|
|
108
|
+// // TODO
|
|
|
109
|
+// Ok(SynchronizedDirectory { db, master })
|
|
|
110
|
+// }
|
|
|
111
|
+//}
|
|
|
112
|
+//
|
|
|
113
|
+//pub struct SyncEvent {
|
|
|
114
|
+// // TODO
|
|
|
115
|
+//}
|
|
|
116
|
+//
|
|
|
117
|
+//impl SyncEvent {
|
|
|
118
|
+// // TODO
|
|
|
119
|
+//}
|
|
55
|
120
|
|
|
56
|
121
|
#[derive(Debug)]
|
|
57
|
122
|
pub enum Error {
|