Skip to content

Commit 414a81b

Browse files
committed
Compute server storage account hashes in db upgrade.
1 parent d809978 commit 414a81b

File tree

11 files changed

+190
-71
lines changed

11 files changed

+190
-71
lines changed

Cargo.lock

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/database/src/error.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
11
use sos_core::{commit::CommitHash, VaultId};
2-
use std::path::PathBuf;
32
use thiserror::Error;
43

54
/// Errors generated by the database library.
65
#[derive(Debug, Error)]
76
pub enum Error {
8-
/// Database file already exists.
9-
#[error("database '{0}' already exists")]
10-
DatabaseExists(PathBuf),
11-
127
/// Error generated when a folder could not be found in the database.
138
#[cfg(feature = "sqlite")]
149
#[error("folder '{0}' not found in the database")]

crates/database_upgrader/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,16 @@ rustdoc-args = ["--cfg", "docsrs"]
1313

1414
[dependencies]
1515
sos-core.workspace = true
16+
sos-backend.workspace = true
1617
sos-external-files.workspace = true
1718
sos-client-storage = { workspace = true, features = ["full"] }
1819
sos-database = { workspace = true, features = ["full"] }
1920
sos-filesystem = { workspace = true, features = ["full"] }
2021
sos-audit.workspace = true
2122
sos-preferences.workspace = true
2223
sos-system-messages.workspace = true
24+
sos-server-storage = { workspace = true, features = ["full"] }
25+
sos-sync.workspace = true
2326
sos-vault.workspace = true
2427
sos-vfs.workspace = true
2528

crates/database_upgrader/src/error.rs

Lines changed: 6 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use sos_core::{commit::CommitHash, VaultId};
21
use std::path::PathBuf;
32
use thiserror::Error;
43

@@ -9,25 +8,6 @@ pub enum Error {
98
#[error("database '{0}' already exists")]
109
DatabaseExists(PathBuf),
1110

12-
/// Error generated when a folder could not be found in the database.
13-
#[error("folder '{0}' not found in the database")]
14-
DatabaseFolderNotFound(VaultId),
15-
16-
/// Error generated when a target commit hash could not be found.
17-
#[error("commit '{0}' could not be found")]
18-
CommitNotFound(CommitHash),
19-
20-
/// Error generated when replacing events in an event log
21-
/// does not compute the same root hash as the expected
22-
/// checkpoint.
23-
#[error("checkpoint verification failed, expected root hash '{checkpoint}' but computed '{computed}')")]
24-
CheckpointVerification {
25-
/// Checkpoint root hash.
26-
checkpoint: CommitHash,
27-
/// Computed root hash.
28-
computed: CommitHash,
29-
},
30-
3111
/// Errors generated by the core library.
3212
#[error(transparent)]
3313
Core(#[from] sos_core::Error),
@@ -44,21 +24,17 @@ pub enum Error {
4424
#[error(transparent)]
4525
FileSystem(#[from] sos_filesystem::Error),
4626

47-
/// Errors generated by the filesystem archive module.
48-
#[error(transparent)]
49-
BackupArchive(#[from] sos_filesystem::archive::Error),
50-
51-
/// Error generated converting to fixed length slice.
27+
/// Errors generated by the client storage library.
5228
#[error(transparent)]
53-
TryFromSlice(#[from] std::array::TryFromSliceError),
29+
ClientStorage(#[from] sos_client_storage::Error),
5430

55-
/// Error generated converting integers.
31+
/// Errors generated by the server storage library.
5632
#[error(transparent)]
57-
TryFromInt(#[from] std::num::TryFromIntError),
33+
ServerStorage(#[from] sos_server_storage::Error),
5834

59-
/// Errors generated by the UUID library.
35+
/// Errors generated by the filesystem archive module.
6036
#[error(transparent)]
61-
Uuid(#[from] uuid::Error),
37+
BackupArchive(#[from] sos_filesystem::archive::Error),
6238

6339
/// Errors generated by the IO module.
6440
#[error(transparent)]
@@ -68,25 +44,11 @@ pub enum Error {
6844
#[error(transparent)]
6945
Json(#[from] serde_json::Error),
7046

71-
/// Errors generated by the URL library.
72-
#[error(transparent)]
73-
UrlParse(#[from] url::ParseError),
74-
7547
/// Errors generated by the async sqlite library.
7648
#[error(transparent)]
7749
AsyncSqlite(#[from] sos_database::async_sqlite::Error),
7850

7951
/// Errors generated by the rusqlite library.
8052
#[error(transparent)]
8153
Rusqlite(#[from] sos_database::async_sqlite::rusqlite::Error),
82-
/*
83-
/// Errors generated by refinery migration library.
84-
#[error(transparent)]
85-
Refinery(#[from] refinery::Error),
86-
87-
88-
/// Errors generated by the URN library.
89-
#[error(transparent)]
90-
Urn(#[from] urn::Error),
91-
*/
9254
}

crates/database_upgrader/src/upgrader/mod.rs

Lines changed: 96 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
//! Import filesystem backed accounts into a database.
22
use crate::{Error, Result};
33
use serde::{Deserialize, Serialize};
4+
use sos_backend::BackendTarget;
5+
use sos_client_storage::ClientStorage;
46
use sos_core::{Paths, PublicIdentity};
5-
use sos_database::{migrations::migrate_client, open_file, open_memory};
7+
use sos_database::{
8+
async_sqlite::Client, migrations::migrate_client, open_file, open_memory,
9+
};
610
use sos_external_files::list_external_files;
711
use sos_filesystem::archive::AccountBackup;
12+
use sos_server_storage::ServerStorage;
13+
use sos_sync::{StorageEventLogs, SyncStatus, SyncStorage};
814
use sos_vault::list_accounts;
915
use sos_vfs::{self as vfs, File};
1016
use std::path::{Path, PathBuf};
@@ -82,7 +88,7 @@ impl UpgradeResult {
8288
/// Import all accounts found on disc.
8389
async fn import_accounts(
8490
options: &UpgradeOptions,
85-
) -> Result<Vec<PublicIdentity>> {
91+
) -> Result<(Vec<PublicIdentity>, Vec<(SyncStatus, SyncStatus)>)> {
8692
let mut client = if !options.dry_run {
8793
let db_file = options
8894
.db_file
@@ -98,23 +104,78 @@ async fn import_accounts(
98104
db_import::import_globals(&mut client, &options.paths).await?;
99105

100106
let accounts = list_accounts(Some(&options.paths)).await?;
107+
let mut sync_status = Vec::new();
101108
for account in &accounts {
102109
let account_paths =
103110
options.paths.with_account_id(account.account_id());
104-
let account_status =
105-
compute_account_status(&account_paths, account).await?;
111+
let fs_status =
112+
compute_fs_account_status(&account_paths, account).await?;
113+
106114
db_import::import_account(&mut client, &account_paths, &account)
107115
.await?;
116+
let db_status =
117+
compute_db_account_status(&account_paths, account, &client)
118+
.await?;
119+
120+
sync_status.push((fs_status, db_status));
108121
}
109-
Ok(accounts)
122+
Ok((accounts, sync_status))
110123
}
111124

112125
/// Compute the account status for the input file system account.
113-
async fn compute_account_status(
126+
async fn compute_fs_account_status(
114127
account_paths: &Paths,
115128
account: &PublicIdentity,
116-
) -> Result<()> {
117-
Ok(())
129+
) -> Result<SyncStatus> {
130+
let sync_status = if account_paths.is_server() {
131+
let storage = ServerStorage::new(
132+
account_paths.documents_dir(),
133+
account.account_id(),
134+
BackendTarget::FileSystem(account_paths.clone()),
135+
)
136+
.await?;
137+
storage.load_all_event_commits().await?;
138+
storage.sync_status().await?
139+
} else {
140+
let storage = ClientStorage::new_unauthenticated(
141+
*account.account_id(),
142+
BackendTarget::FileSystem(account_paths.clone()),
143+
)
144+
.await?;
145+
storage.load_all_event_commits().await?;
146+
storage.sync_status().await?
147+
};
148+
Ok(sync_status)
149+
}
150+
151+
/// Compute the account status for the output database account.
152+
async fn compute_db_account_status(
153+
account_paths: &Paths,
154+
account: &PublicIdentity,
155+
client: &Client,
156+
) -> Result<SyncStatus> {
157+
let sync_status = if account_paths.is_server() {
158+
let storage = ServerStorage::new(
159+
account_paths.documents_dir(),
160+
account.account_id(),
161+
BackendTarget::Database(client.clone()),
162+
)
163+
.await?;
164+
storage.sync_status().await?
165+
} else {
166+
todo!("compute for client accounts");
167+
/*
168+
let storage = ClientFileSystemStorage::new_unauthenticated(
169+
*account.account_id(),
170+
account_paths.clone(),
171+
)
172+
.await?;
173+
174+
storage.load_all_event_commits().await?;
175+
storage.sync_status().await?
176+
*/
177+
};
178+
Ok(sync_status)
118179
}
119180

120181
/// Upgrade all accounts found on disc.
@@ -146,7 +207,33 @@ pub async fn upgrade_accounts(
146207

147208
tracing::debug!("upgrade_accounts::import_accounts");
148209

149-
let accounts = import_accounts(&options).await?;
210+
let (accounts, sync_status) = import_accounts(&options).await?;
211+
212+
/*
213+
for status in &sync_status {
214+
println!("{} <-> {}", status.0.root, status.1.root);
215+
216+
if status.0.identity != status.1.identity {
217+
println!("{:#?} != {:#?}", status.0.identity, status.1.identity);
218+
}
219+
220+
if status.0.account != status.1.account {
221+
println!("{:#?} != {:#?}", status.0.account, status.1.account);
222+
}
223+
224+
if status.0.device != status.1.device {
225+
println!("{:#?} != {:#?}", status.0.device, status.1.device);
226+
}
227+
228+
if status.0.files != status.1.files {
229+
println!("{:#?} != {:#?}", status.0.files, status.1.files);
230+
}
231+
232+
if status.0.folders != status.1.folders {
233+
println!("{:#?} != {:#?}", status.0.folders, status.1.folders);
234+
}
235+
}
236+
*/
150237

151238
if options.copy_file_blobs {
152239
tracing::debug!("upgrade_accounts::copy_file_blobs");

crates/server/src/backend.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use super::{Error, Result};
2+
use sos_backend::BackendTarget;
23
use sos_core::{device::DevicePublicKey, AccountId, Paths};
34
use sos_server_storage::{ServerAccountStorage, ServerStorage};
45
use sos_signer::ed25519::{self, Verifier, VerifyingKey};
@@ -79,9 +80,12 @@ impl Backend {
7980
"server_backend::read_dir",
8081
);
8182

82-
let account = ServerStorage::new_fs(
83+
let account = ServerStorage::new(
8384
&self.directory,
8485
&account_id,
86+
BackendTarget::FileSystem(
87+
Paths::new_global_server(&self.directory),
88+
),
8589
)
8690
.await?;
8791

crates/storage/server/src/database/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,9 @@ impl ServerDatabaseStorage {
115115
let (device_log, devices) =
116116
Self::initialize_device_log(&client, &account_id).await?;
117117

118-
let file_log =
118+
let mut file_log =
119119
FileEventLog::new_db_file(client.clone(), account_id).await?;
120+
file_log.load_tree().await?;
120121

121122
Ok(Self {
122123
account_id,

crates/storage/server/src/filesystem/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ impl ServerFileStorage {
6161
/// Create folder storage for server-side access.
6262
pub async fn new(
6363
account_id: AccountId,
64-
data_dir: Option<PathBuf>,
6564
identity_log: Arc<RwLock<FolderEventLog>>,
65+
data_dir: Option<PathBuf>,
6666
) -> Result<Self> {
6767
let data_dir = if let Some(data_dir) = data_dir {
6868
data_dir

crates/storage/server/src/storage.rs

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ use crate::{
55
use async_trait::async_trait;
66
use indexmap::IndexSet;
77
use sos_backend::{
8-
AccountEventLog, DeviceEventLog, FileEventLog, FolderEventLog,
8+
AccountEventLog, BackendTarget, DeviceEventLog, FileEventLog,
9+
FolderEventLog,
910
};
1011
use sos_core::{
1112
commit::{CommitState, Comparison},
@@ -39,8 +40,24 @@ pub enum ServerStorage {
3940
}
4041

4142
impl ServerStorage {
43+
/// Create new server storage.
44+
pub async fn new(
45+
directory: impl AsRef<Path>,
46+
account_id: &AccountId,
47+
target: BackendTarget,
48+
) -> Result<Self> {
49+
match target {
50+
BackendTarget::FileSystem(_) => {
51+
Self::new_fs(directory, account_id).await
52+
}
53+
BackendTarget::Database(client) => {
54+
Self::new_db(directory, account_id, client).await
55+
}
56+
}
57+
}
58+
4259
/// Create new file system storage.
43-
pub async fn new_fs(
60+
async fn new_fs(
4461
directory: impl AsRef<Path>,
4562
account_id: &AccountId,
4663
) -> Result<Self> {
@@ -56,8 +73,8 @@ impl ServerStorage {
5673
Ok(Self::FileSystem(
5774
ServerFileStorage::new(
5875
*account_id,
59-
Some(directory.as_ref().to_owned()),
6076
identity_log,
77+
Some(directory.as_ref().to_owned()),
6178
)
6279
.await?,
6380
))
@@ -81,8 +98,8 @@ impl ServerStorage {
8198

8299
let mut storage = ServerFileStorage::new(
83100
*account_id,
84-
Some(directory.as_ref().to_owned()),
85101
Arc::new(RwLock::new(identity_log)),
102+
Some(directory.as_ref().to_owned()),
86103
)
87104
.await?;
88105
storage.import_account(&account_data).await?;
@@ -91,10 +108,10 @@ impl ServerStorage {
91108
}
92109

93110
/// Create new database storage.
94-
pub async fn new_db(
95-
client: Client,
96-
account_id: &AccountId,
111+
async fn new_db(
97112
directory: impl AsRef<Path>,
113+
account_id: &AccountId,
114+
client: Client,
98115
) -> Result<Self> {
99116
let folder_account_id = *account_id;
100117

0 commit comments

Comments
 (0)